DEV Community

Cover image for How to Use Three.js And React to Render a 3D Model of Your Self

How to Use Three.js And React to Render a 3D Model of Your Self

Nourdine Labib on March 04, 2022

In this article, we’ll cover how to render and configure 3D assets created in a 3D software program like Blender or Maya in a React project using r...
Collapse
 
martinlundqvist profile image
MartinLundqvist • Edited

Nice one! Only issue I have is that I lose the textures when exporting the fbx animation to glb from Blender in the final step.

  • I can see the textures in Mixamo and in Blender, so they are "there" so to speak.
  • Also, if I just use the ReadyPlayerMe model without adding any animations to it, then the textures also show.

Any advice?

Collapse
 
nourdinedev profile image
Nourdine Labib

When you export the model as glb make sure you use this configurations.


I hope this fixes the problem.

Collapse
 
martinlundqvist profile image
MartinLundqvist

Now only one problem remains.. the "position" property of the Model component doesn't seem to affect the position once the model is animating. Whenever I reload the app, the position will go back to the bottom of the model being in the center of the canvas.

Thread Thread
 
nourdinedev profile image
Nourdine Labib

I'm sorry I didn't understand what problem you are having with the Model position, If you still didn't figure it out, provide me with some more feedback, and I will try my best to help.

Thread Thread
 
martinlundqvist profile image
MartinLundqvist • Edited

The "Model position={[0.2, -0.9, 0]}" positions the model as it should, when the model is not animating. However, as soon as I replace with the animated model, the position is somehow overridden and becomes [0,0,0]. I can see this behavior when I console.log(group.current.position).

Thread Thread
 
martinlundqvist profile image
MartinLundqvist

Problem solved. By wrapping the group in a new parent group, and setting the position on the parent - I could solve the problem. The animation clearly reset the position of its group.

Thread Thread
 
nourdinedev profile image
Nourdine Labib

I never had a problem like that before, glad you solved it.

Collapse
 
martinlundqvist profile image
MartinLundqvist

Indeed it did. The only config that differed was "Selected Objects". When I checked this option, it started working.

Thanks!

Collapse
 
jhonrios85 profile image
jhonrios85 • Edited

I had the same problem, when I exported from Blender to FBX I lost the textures, what I did is:

  • Export the to FBX using blender
  • Add the animation in Mixamo and export the "Animated Version FBX" (Doesn't matter that the FBX have not textures, this is only to generate the animation)
  • Import the "Animated Version FBX" and the original GLB (with textures) to Blender
  • And follow these instructions to copy the animation from "Animated Version FBX" to "Original GLB with textures" gachokistudios.com/how-to-copy-ani...
  • Once you copy the animation, you can delete the "Animated Version FBX" from blender and export the original one (animated) to GLB and continue with the tutorial to include it to the project
Collapse
 
irennalumbuun profile image
Irenna Nicole Lumbuun

Hope this is not too late; I got a similar error earlier:
You wanna uncomment the line console.log(action) and check the logs. It should show an object, mine looks something like this:

Armature.001|mixamo.com|Layer0: (...)
Armature.001|mixamo.com|Layer0.001: (...)
Enter fullscreen mode Exit fullscreen mode

Then you wanna change this line of code to match it

actions['Armature.001|mixamo.com|Layer0'].play(); 
Enter fullscreen mode Exit fullscreen mode
Collapse
 
itzcookiie profile image
Mayowa

Awesome awesome awesome! Ty for making this post was really helpful for me as I plan on making a personal portfolio and this will go a long way.

Just in case this helps anyone, I also encountered issues with the textures for the head not showing up in the final model export. This is how I fixed:

  • Downgrade blender to version 2.93.0
  • Follow all the steps up until where you import the exported .fbx asset file from mixamo (so up until the Import the animated model to blender step under Convert the animated model back to glb format section)
  • Click on the head of the exported .fbx asset file from mixamo, then click on the Material Properties tab in the bottom right. It should have this icon: Image description
  • A UI like so should open up Image description
  • Click on the following dropdown to select a material for your head Image description
  • Search for Wolf3D_Skin
  • Select that and you should see the correct head texture
  • Follow the remaining steps from Rendering the animated model in React
Collapse
 
tythos profile image
Brian Kirkpatrick

Cool stuff! I'll bet you could cut React out of this entirely and just use (say) ColladaLoader with THREE.js to port the same content.

Collapse
 
nourdinedev profile image
Nourdine Labib • Edited

Thanks!, I had used GLTFLoader outside of React but I never used the ColladaLoader, Over all if you have a collada model (.dae) you need to use the ColladaLoader, or if you have a model with other format you need to use a loader that supports the file type/format.

You are very much right, you can load any model with the power of Three.js only, thank you for pointing that out.

Collapse
 
leminhung profile image
Lê Minh Hưng • Edited

i just follow your steps. When i compile "yarn start" then i receive this animation (character has no color). I don't know why. Can you please help fix this!

Collapse
 
nourdinedev profile image
Nourdine Labib • Edited

can you provide me with a link of a public Github repo that have your Code, and I will see if I can help.

Collapse
 
leminhung profile image
Lê Minh Hưng • Edited

Repo: github.com/leminhung/my-3d-model
This is my public github repo, Can you please clone repo and run this app to see the problems with color of animations.
Thank you so much!

Thread Thread
 
nourdinedev profile image
Nourdine Labib • Edited

Apparently when you added the animation to the model, the names of the materials changed, you need to generate a new Model.js file using gltfjsx.

npx gltfjsx model-with-animations.glb
Enter fullscreen mode Exit fullscreen mode

or you can use the code I did generate using gltfjsx.

import React, { useRef, useEffect } from 'react';
import { useGLTF, useAnimations } from '@react-three/drei';

export default function Model({ ...props }) {
   const group = useRef();
   const { nodes, materials, animations } = useGLTF(
      '/model-with-animations.glb'
   );
   const { actions } = useAnimations(animations, group);

   useEffect(() => {
      actions['Armature|mixamo.com|Layer0'].play();
   });
   return (
      <group ref={group} {...props} dispose={null}>
         <primitive object={nodes.Hips} />
         <skinnedMesh
            geometry={nodes.Wolf3D_Body.geometry}
            material={materials['Wolf3D_Body.001']}
            skeleton={nodes.Wolf3D_Body.skeleton}
         />
         <skinnedMesh
            geometry={nodes.Wolf3D_Hair.geometry}
            material={materials['Wolf3D_Hair.001']}
            skeleton={nodes.Wolf3D_Hair.skeleton}
         />
         <skinnedMesh
            geometry={nodes.Wolf3D_Outfit_Bottom.geometry}
            material={materials['Wolf3D_Outfit_Bottom.001']}
            skeleton={nodes.Wolf3D_Outfit_Bottom.skeleton}
         />
         <skinnedMesh
            geometry={nodes.Wolf3D_Outfit_Footwear.geometry}
            material={materials['Wolf3D_Outfit_Footwear.001']}
            skeleton={nodes.Wolf3D_Outfit_Footwear.skeleton}
         />
         <skinnedMesh
            geometry={nodes.Wolf3D_Outfit_Top.geometry}
            material={materials['Wolf3D_Outfit_Top.001']}
            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.001']}
            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.001']}
            skeleton={nodes.Wolf3D_Teeth.skeleton}
            morphTargetDictionary={nodes.Wolf3D_Teeth.morphTargetDictionary}
            morphTargetInfluences={nodes.Wolf3D_Teeth.morphTargetInfluences}
         />
      </group>
   );
}

useGLTF.preload('/model-with-animations.glb');
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
leminhung profile image
Lê Minh Hưng

Ohh, problem was resolved. Thank you!

Collapse
 
nihaltuda profile image
nihal-tuda

Uncaught Could not load ../public/breakDance.glb: Unexpected token < in JSON at position 0.
I'm getting this error and can't find a way to parse it as html. Need help!
I guess there is some issue with useGLTF function cuz when i inserted my avatar link it worked but it wasn't working when i used the path of .glb file in the useGLTF().

Collapse
 
nourdinedev profile image
Nourdine Labib

can you upload it into a public git repo and give me the link so I can see what the problem is, or you can see my shared code on codesandbox at codesandbox.io/s/3d-model-animatio... and try to find if you missed any thing.

Collapse
 
maqi1520 profile image
Alex Ma

Thanks for sharing, May I translate this article into Chinese?

Collapse
 
nourdinedev profile image
Nourdine Labib

Yeah no problem, you can translate the article.

Collapse
 
maqi1520 profile image
Alex Ma
Collapse
 
robsonmuniz16 profile image
Robson Muniz

Nice content, thanks for sharing it!

Collapse
 
jzombie profile image
jzombie

This is radical! Thanks for sharing.

Collapse
 
nourdinedev profile image
Nourdine Labib

Thank you, I appreciate that.

Collapse
 
luisnomad profile image
Luis Serrano 🇪🇺

Genius. Thank you for this! It's simply awesome.

Collapse
 
nourdinedev profile image
Nourdine Labib

Thank you, I appreciate that.

Collapse
 
biomathcode profile image
Pratik sharma

This is solid and really helpful. Thanks !!

Collapse
 
nourdinedev profile image
Nourdine Labib

Thank you, glad this helped.

Collapse
 
doodz59 profile image
Doodz59 • Edited

Hello Nourdine,

Thank you for this tutorial, but I have a problem.
Following your directions, I find myself facing errors regarding MeshLineGeometry & raycast
``Attempted import error: 'MeshLineGeometry' is not exported from 'meshline' (imported as 'MeshLineGeometry').
WARNING in ./node_modules/meshline/dist/index.js
Module Warning (from ./node_modules/source-map-loader/dist/cjs.js):
Failed to parse source map from 'C:\Users\Edouard\Desktop\blender\3d\node_modules\meshline\src\index.ts' file: Error: ENOENT: no such file or directory, open 'C:\Users\Edouard\Desktop\blender\3d\node_modules\meshline\src\index.ts'

WARNING in [eslint]
src\Dd_text_withoutanim.js
Line 5:17: 'useRef' is defined but never used no-unused-vars

ERROR in ./node_modules/@react-three/drei/core/Trail.js 104:38-54
export 'MeshLineGeometry' (imported as 'MeshLineGeometry') was not found in 'meshline' (module has no exports)

ERROR in ./node_modules/@react-three/drei/core/Trail.js 107:18-34
export 'MeshLineMaterial' (imported as 'MeshLineMaterial') was not found in 'meshline' (module has no exports)

ERROR in ./node_modules/meshline/dist/index.js 1:0-35
Module not found: Error: Can't resolve './MeshLineGeometry' in 'C:\Users\Edouard\Desktop\blender\3d\node_modules\meshline\dist'
Did you mean 'MeshLineGeometry.js'?
BREAKING CHANGE: The request './MeshLineGeometry' failed to resolve only because it was resolved as fully specified
(probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '.mjs' file, or a '.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.

ERROR in ./node_modules/meshline/dist/index.js 2:0-35
Module not found: Error: Can't resolve './MeshLineMaterial' in 'C:\Users\Edouard\Desktop\blender\3d\node_modules\meshline\dist'
Did you mean 'MeshLineMaterial.js'?
BREAKING CHANGE: The request './MeshLineMaterial' failed to resolve only because it was resolved as fully specified
(probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '.mjs' file, or a '.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.

ERROR in ./node_modules/meshline/dist/index.js 3:0-26
Module not found: Error: Can't resolve './raycast' in 'C:\Users\Edouard\Desktop\blender\3d\node_modules\meshline\dist'
Did you mean 'raycast.js'?
BREAKING CHANGE: The request './raycast' failed to resolve only because it was resolved as fully specified
(probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '.mjs' file, or a '.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.``

Here is my packages : "dependencies": {
"@react-three/drei": "^9.46.4",
"@react-three/fiber": "^8.9.1",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"three": "^0.147.0",
"three.meshline": "^1.4.0", }

Do you know how to fix these errors?
When I put "type": "module" in package, I find myself faced with new errors.

Thank you reading me :)

Collapse
 
nurulasrulrojiajeye profile image
Nurul Arul Roji

Uncaught Could not load ../../../assets/model-with-animations.glb: Unexpected token < in JSON at position 0
Canvas @ react-three-fiber.esm.js:141
renderWithHooks @ react-dom.development.js:16305
updateForwardRef @ react-dom.development.js:19226
beginWork @ react-dom.development.js:21636
callCallback @ react-dom.development.js:4164
invokeGuardedCallbackDev @ react-dom.development.js:4213
invokeGuardedCallback @ react-dom.development.js:4277
beginWork$1 @ react-dom.development.js:27451
performUnitOfWork @ react-dom.development.js:26557
workLoopSync @ react-dom.development.js:26466
renderRootSync @ react-dom.development.js:26434
recoverFromConcurrentError @ react-dom.development.js:25850
performConcurrentWorkOnRoot @ react-dom.development.js:25750
workLoop @ scheduler.development.js:266
flushWork @ scheduler.development.js:239
performWorkUntilDeadline @ scheduler.development.js:533
react-dom.development.js:18687 The above error occurred in the component:

at Canvas (http://localhost:3000/static/js/bundle.js:22083:5)
at div
at Home (http://localhost:3000/static/js/bundle.js:417:88)
at Outlet (http://localhost:3000/static/js/bundle.js:85238:26)
at div
at div
at Layout
at Routes (http://localhost:3000/static/js/bundle.js:85330:5)
at App
at Router (http://localhost:3000/static/js/bundle.js:85263:15)
at BrowserRouter (http://localhost:3000/static/js/bundle.js:84072:5)
Enter fullscreen mode Exit fullscreen mode

Consider adding an error boundary to your tree to customize error handling behavior.
Visit reactjs.org/link/error-boundaries to learn more about error boundaries.

hallo, why cam't load model.glb sir

Collapse
 
gersonrto profile image
Gerson Toribio

are you using create-react-app? or is it a custom webpack project?

Collapse
 
nurulasrulrojiajeye profile image
Nurul Arul Roji

using CRA sir

Collapse
 
doodz59 profile image
Doodz59

Hey,
did you manage to solve your problem?

Collapse
 
xmannv profile image
Xman

I could not import FBX to Mixamo with textures, it lost textures. I already followed by your note about export fbx. Don't know what's wrong

Can you check on repo: github.com/xmannv/avatar3d

Collapse
 
gullerg profile image
Gustav Grimberg

I have the same issue...

Collapse
 
gullerg profile image
Gustav Grimberg

I resolved this by downgrading Blender to 2.93

Collapse
 
2773kartik profile image
Kartik Tiwari

Hey! My animated file just wont show up! I get the following error.
Uncaught TypeError: Cannot redefine property: Armature|mixamo.com|Layer0.001
I have tried generating new model.js file too. What could be the issue?
Thanks

Collapse
 
icewind profile image
icewind

Thanks for the article, it helps a lot. I'm totally new in threejs and webgl. So, if I want to replace some part of the glb model generated by Ready Player Me, to make a avatar customize game demo, could you please tell me how to change my code?
Here is my code demo: codesandbox.io/s/3d-model-animatio...

Collapse
 
gersonrto profile image
Gerson Toribio

I was trying your codesandbox, but It doesn't seem to work, can you update it?

Collapse
 
gersonrto profile image
Gerson Toribio • Edited

I have fixed all the issues, by my own, I will post my github repo with extra changes that I have done with a custom webpack 5 setup and with typescript.

Collapse
 
gersonrto profile image
Gerson Toribio

Hi guys, I have created repo using webpack 5, typescript and what Nourdine posted in this article. Thanks for this Nourdine , it was amazing :) . Btw, for those who has issues with texture, you have to use blender version 2.9.3, if not I will give you a different structure useGLTFfrom @react-three/drei is expecting.

Here is the repo: github.com/GRTO/avatar-three-js and this is how it looks avatar-three-js.vercel.app/

Collapse
 
vishwa_kolkar profile image
👨🏻‍💻🎧

I used 3D model to convey my goodbyes to colleagues during pandemic WFH days :)

vishwakolkar.netlify.app/

Code: github.com/visikolkar/lg-farewell

Collapse
 
ntamiegbe profile image
ntamiegbe

This was so thoughtful and nice.

Collapse
 
gonzalopmdev profile image
Gonzalo

I´m 3d artist and fullstack web developer....i think that idea it´s great, but, what happens with textures??? About animations, i recommend create them in Mixamo if the model had good topology.

Collapse
 
songhanpoo profile image
songhanpoo

great post. do you have any idea render floorplan by react ?

Collapse
 
rembertdesigns profile image
Richard Rembert

Great article! Thanks for sharing & going to try this out over the weekend!

Collapse
 
gullerg profile image
Gustav Grimberg

I lose the textures when I convert to fbx (the textures don't show in Mixamo...) - any idea why this happens?

Collapse
 
gullerg profile image
Gustav Grimberg

Okay I resolved this by downgrading Blender to 2.93

Collapse
 
athellan profile image
Jean-Baptiste CAMBILLARD

Hello Nourdine, thanks for this awesome tutorial.

I think everything is ok, but i have no render on my app, could you help me ?

github.com/Athellan/3d-model/

Thanks !

Collapse
 
yanisdevui profile image
Yanis AB

It's cool but is a framework really useful for this kind of use?