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

程序源代码

共 3660字,需浏览 8分钟

 · 2022-03-15


在本文中,我将介绍如何在 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 ModeCopy, 然后点击 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');

最终展示效果

效果.gif

源码地址:

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




浏览 30
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报