如何使用 react 和 three.js 在网站渲染自己的3D模型

在本文中,我将介绍如何在 react 项目中使用 react-three-fiber 创建的一个3D 软件程序,配置3D 参数(如Blender或Maya) 。在本文结束时,您将能够在您的网站上渲染一个3D模型 (gltf / glb)。
获取自己的3D模型
为了获得自己的 3D模型,我们使用 Ready Player Me 这个网站,一个免费的3D形象创建器来自 Wolf3D,允许任何人在几分钟内创建自己的外观表现,不需要3D建模经验,你需要做的只是快速自拍,然后等待程序根据你的肖像自动生成自定义3D形象。
然后你可以自由地使用一系列合适的发型、肤色、面部特征、服装选择和其他可定制的属性对自己的角色进行调整。
登录这个网站后 Ready Player Me, 你只需要遵循以下步骤,你就可以开始进行。
选择体型

上传你自己的照片

定制您的外观

下载您的模型

在React中渲染模型
为了在react 程序中渲染这个模型,我们将使用 react-three-fiber 一个Threejs React 渲染器
项目开发
首先让我们创建一个项目
npx create-react-app my-3d-model
#or
yarn create react-app my-3d-model
然后安装 @react-three/fiber 和 @react-three/drei
npm install three @react-three/fiber @react-three/drei
#or
yarn add three @react-three/fiber @react-three/drei
将模型转换为React组件
完成之后,继续并运行以下命令,使用 gltfjsx 转换成 react 组件格式文件。
npx gltfjsx model.glb
转换后的内容类似于以下代码
import React, { useRef } from 'react';
import { useGLTF } from '@react-three/drei';
export default function Model({ ...props }) {
const group = useRef();
const { nodes, materials } = useGLTF('/model.glb');
return (
<group ref={group} {...props} dispose={null}>
<primitive object={nodes.Hips} />
<skinnedMesh
geometry={nodes.Wolf3D_Body.geometry}
material={materials.Wolf3D_Body}
skeleton={nodes.Wolf3D_Body.skeleton}
/>
<skinnedMesh
geometry={nodes.Wolf3D_Glasses.geometry}
material={materials.Wolf3D_Glasses}
skeleton={nodes.Wolf3D_Glasses.skeleton}
/>
<skinnedMesh
geometry={nodes.Wolf3D_Hair.geometry}
material={materials.Wolf3D_Hair}
skeleton={nodes.Wolf3D_Hair.skeleton}
/>
<skinnedMesh
geometry={nodes.Wolf3D_Outfit_Bottom.geometry}
material={materials.Wolf3D_Outfit_Bottom}
skeleton={nodes.Wolf3D_Outfit_Bottom.skeleton}
/>
<skinnedMesh
geometry={nodes.Wolf3D_Outfit_Footwear.geometry}
material={materials.Wolf3D_Outfit_Footwear}
skeleton={nodes.Wolf3D_Outfit_Footwear.skeleton}
/>
<skinnedMesh
geometry={nodes.Wolf3D_Outfit_Top.geometry}
material={materials.Wolf3D_Outfit_Top}
skeleton={nodes.Wolf3D_Outfit_Top.skeleton}
/>
<skinnedMesh
name="EyeLeft"
geometry={nodes.EyeLeft.geometry}
material={nodes.EyeLeft.material}
skeleton={nodes.EyeLeft.skeleton}
morphTargetDictionary={nodes.EyeLeft.morphTargetDictionary}
morphTargetInfluences={nodes.EyeLeft.morphTargetInfluences}
/>
<skinnedMesh
name="EyeRight"
geometry={nodes.EyeRight.geometry}
material={nodes.EyeRight.material}
skeleton={nodes.EyeRight.skeleton}
morphTargetDictionary={nodes.EyeRight.morphTargetDictionary}
morphTargetInfluences={nodes.EyeRight.morphTargetInfluences}
/>
<skinnedMesh
name="Wolf3D_Head"
geometry={nodes.Wolf3D_Head.geometry}
material={materials.Wolf3D_Skin}
skeleton={nodes.Wolf3D_Head.skeleton}
morphTargetDictionary={nodes.Wolf3D_Head.morphTargetDictionary}
morphTargetInfluences={nodes.Wolf3D_Head.morphTargetInfluences}
/>
<skinnedMesh
name="Wolf3D_Teeth"
geometry={nodes.Wolf3D_Teeth.geometry}
material={materials.Wolf3D_Teeth}
skeleton={nodes.Wolf3D_Teeth.skeleton}
morphTargetDictionary={nodes.Wolf3D_Teeth.morphTargetDictionary}
morphTargetInfluences={nodes.Wolf3D_Teeth.morphTargetInfluences}
/>
group>
);
}
useGLTF.preload('/model.glb');
创建场景
import React, { Suspense } from 'react';
import { Canvas } from '@react-three/fiber';
import { OrbitControls } from '@react-three/drei';
export default function App() {
return (
<Canvas
camera={{ position: [2, 0, 12.25], fov: 15 }}
style={{
backgroundColor: '#111a21',
width: '100vw',
height: '100vh',
}}
>
<ambientLight intensity={1.25} />
<ambientLight intensity={0.1} />
<directionalLight intensity={0.4} />
<Suspense fallback={null}>
// your model here
Suspense>
<OrbitControls />
Canvas>
);
}
将模型添加到场景中
首先将模型 (glb文件) 添加到 **public **文件夹,使用 gltfjsx 生成的文件将其放入src 下的components 文件夹
import React, { Suspense } from 'react';
import { Canvas } from '@react-three/fiber';
import { OrbitControls } from '@react-three/drei';
import Model from './Model'; /* highlight-line */
export default function App() {
return (
<Canvas
camera={{ position: [2, 0, 12.25], fov: 15 }}
style={{
backgroundColor: '#111a21',
width: '100vw',
height: '100vh',
}}
>
<ambientLight intensity={1.25} />
<ambientLight intensity={0.1} />
<directionalLight intensity={0.4} />
<Suspense fallback={null}>
<Model position={[0.025, -0.9, 0]} /> /* highlight-line */
Suspense>
<OrbitControls />
Canvas>
);
}
修改 app.js
body {
margin: 0;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
}
添加 css
结果展示codesandbox.io
给模型添加动画
给3D模型添加动画, 需要在你的电脑上安装 blender
将模型导入到 blender
Blender 是免费的开源3D软件.它支持整个3D管道建模、索具、动画、模拟、渲染、合成和运动跟踪,甚至视频编辑和游戏创作。了解更多信息
创建一个新的blender项目

删除对象中的物体

将glb文件导入blender


选择您的模型,然后单击 Import glTF 2.0

将模型转换为fbx格式
在任何动画添加到我们的模型之前,我们需要先将其转换为FBX格式。
选择模型
要在blender中选择3D模型,只需单击键盘a
或者您可以使用鼠标选择。

将模型导出为FBX


确保选择的 Path Mode
是 Copy
, 然后点击 Embed textures
这个选项。
添加动画 mixamo
Mixamo 是一项免费的在线服务,用于自动装配和动画3d角色,它由Mixamo公司开发, 由Adobe于2015年收购。 Mixamo 允许用户上传FBX、OBJ或Zip文件,然后网站尝试在两分钟内自动操纵角色。
将模型上传到 mixamo


选择动画并下载动画模型


将动画模型转换回glb格式
为了能够在react中使用需要转换回 glb 格式.
将动画模型导入blender

将动画模型导出为glb

在react中渲染动画模型
在public 文件夹下替换这个 model.glb
文件,使用动画模型 ,然后在 src/Model.js
修改以下代码
import React, { useRef, useEffect } from 'react'; /* highlight-line */
import { useGLTF, useAnimations } from '@react-three/drei'; /* highlight-line */
export default function Model({ ...props }) {
const group = useRef();
const { nodes, materials, animations } = useGLTF('/model.glb');
const { actions } = useAnimations(animations, group); /* highlight-line */
// 'Armature|mixamo.com|Layer0' is the name of the animation we need to run.
// console.log(actions);
useEffect(() => {/* highlight-line */
actions['Armature|mixamo.com|Layer0'].play(); /* highlight-line */
}); /* highlight-line */
return (
<group ref={group} {...props} dispose={null}>
<primitive object={nodes.Hips} />
<skinnedMesh
geometry={nodes.Wolf3D_Body.geometry}
material={materials.Wolf3D_Body}
skeleton={nodes.Wolf3D_Body.skeleton}
/>
<skinnedMesh
geometry={nodes.Wolf3D_Glasses.geometry}
material={materials.Wolf3D_Glasses}
skeleton={nodes.Wolf3D_Glasses.skeleton}
/>
<skinnedMesh
geometry={nodes.Wolf3D_Hair.geometry}
material={materials.Wolf3D_Hair}
skeleton={nodes.Wolf3D_Hair.skeleton}
/>
<skinnedMesh
geometry={nodes.Wolf3D_Outfit_Bottom.geometry}
material={materials.Wolf3D_Outfit_Bottom}
skeleton={nodes.Wolf3D_Outfit_Bottom.skeleton}
/>
<skinnedMesh
geometry={nodes.Wolf3D_Outfit_Footwear.geometry}
material={materials.Wolf3D_Outfit_Footwear}
skeleton={nodes.Wolf3D_Outfit_Footwear.skeleton}
/>
<skinnedMesh
geometry={nodes.Wolf3D_Outfit_Top.geometry}
material={materials.Wolf3D_Outfit_Top}
skeleton={nodes.Wolf3D_Outfit_Top.skeleton}
/>
<skinnedMesh
name="EyeLeft"
geometry={nodes.EyeLeft.geometry}
material={nodes.EyeLeft.material}
skeleton={nodes.EyeLeft.skeleton}
morphTargetDictionary={nodes.EyeLeft.morphTargetDictionary}
morphTargetInfluences={nodes.EyeLeft.morphTargetInfluences}
/>
<skinnedMesh
name="EyeRight"
geometry={nodes.EyeRight.geometry}
material={nodes.EyeRight.material}
skeleton={nodes.EyeRight.skeleton}
morphTargetDictionary={nodes.EyeRight.morphTargetDictionary}
morphTargetInfluences={nodes.EyeRight.morphTargetInfluences}
/>
<skinnedMesh
name="Wolf3D_Head"
geometry={nodes.Wolf3D_Head.geometry}
material={materials.Wolf3D_Skin}
skeleton={nodes.Wolf3D_Head.skeleton}
morphTargetDictionary={nodes.Wolf3D_Head.morphTargetDictionary}
morphTargetInfluences={nodes.Wolf3D_Head.morphTargetInfluences}
/>
<skinnedMesh
name="Wolf3D_Teeth"
geometry={nodes.Wolf3D_Teeth.geometry}
material={materials.Wolf3D_Teeth}
skeleton={nodes.Wolf3D_Teeth.skeleton}
morphTargetDictionary={nodes.Wolf3D_Teeth.morphTargetDictionary}
morphTargetInfluences={nodes.Wolf3D_Teeth.morphTargetInfluences}
/>
group>
);
}
useGLTF.preload('/model.glb');
最终展示效果

源码地址:
https://codesandbox.io/s/3d-model-animation-d41e9u?file=/src/Model.js:271-281
原文地址:https://dev.to/nourdinedev/how-to-use-threejs-and-react-to-render-a-3d-model-of-your-self-4kkf