Loading Models
3D Software to the web!
All the models in this page were created by Sara Vieira and are freely available to download from any of the sandboxes.
There are many types of 3D model extensions, in this page we will focus on loading the three most common ones: GLTF
, FBX
and OBJ
. All of these will use the useLoader
function but in slightly different ways.
This whole section will assume you have placed your models in the public folder or in a place in your application where you can import them easily.
Loading GLTF models
Starting with the open standard and the one that has more support in React Three Fiber we will load a .gltf
model.
Let's start by importing the two things we need:
import { useLoader } from '@react-three/fiber'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
With this we can create a Model component and place it in our scene like so:
function Scene() {
const gltf = useLoader(GLTFLoader, '/Poimandres.gltf')
return (
<Suspense fallback={null}>
<primitive object={gltf.scene} />
</Suspense>
)
}
You can play with the sandbox and see how it looks here after I added an HDRI background:
Loading GLTF models as JSX Components
Here comes the really fancy part, you can transform these models into React components and then use them as your would any React component.
To do this, grab your GLTF
model and head over to https://gltf.pmnd.rs/ and drop your GLTF
, after that you should see something like:
Let's now copy the code and move it over to Model.js
:
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
*/
import React, { useRef } from 'react'
import { useGLTF } from '@react-three/drei'
export default function Model(props) {
const group = useRef()
const { nodes, materials } = useGLTF('/Poimandres.gltf')
return (
<group ref={group} {...props} dispose={null}>
<mesh
castShadow
receiveShadow
geometry={nodes.Curve007_1.geometry}
material={materials['Material.001']}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.Curve007_2.geometry}
material={materials['Material.002']}
/>
</group>
)
}
useGLTF.preload('/Poimandres.gltf')
Now we can import our model like we would import any React component and use it in our app:
import { Suspense } from 'react'
import { Canvas } from '@react-three/fiber'
import { Environment } from '@react-three/drei'
import Model from './Model'
export default function App() {
return (
<div className="App">
<Canvas>
<Suspense fallback={null}>
<Model />
<Environment preset="sunset" background />
</Suspense>
</Canvas>
</div>
)
}
You can play with the sandbox here:
Loading OBJ models
In this case, we will use the trusted useLoader
hook but in combination with three.js
OBJLoader
.
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'
import { useLoader } from '@react-three/fiber'
With these imported let's get the mesh into our scene:
function Scene() {
const obj = useLoader(OBJLoader, '/Poimandres.obj')
return <primitive object={obj} />
}
And here we go, we have an OBJ model showing on the web! Pretty cool ah?
You can play with the sandbox here:
Loading FBX models
Let's again use the trusted useLoader
but this time with the FBXLoader
that comes from three.js
import { useLoader } from '@react-three/fiber'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'
To create our scene we can get the FBX as a return value of the useLoader by passing the FBXloader
and the location of our file like so:
function Scene() {
const fbx = useLoader(FBXLoader, '/Poimandres.fbx')
return <primitive object={fbx} />
}
You can play with the sandbox here:
Loading FBX models using useFBX
@react-three/drei exports a very useful helper when it comes to loading FBX models and it's called useFBX
, in this case there is no need to import anything from three.js
as it is all done behind the scenes and we can just pass the location of the file to useFBX
like so:
function Scene() {
const fbx = useFBX('/Poimandres.fbx')
return <primitive object={fbx} />
}
You can play with the sandbox here:
Showing a loader
If your model is big and takes a while to load, it's always good to show a small loader of how much is already is loaded and again @react-three/drei is here to help with Html
and useProgress
.
Html
allows you place plain ol' HTML in your canvas and render it like you would a normal DOM element.useProgress
is a hook that gives you a bunch of information about the loading status of your model.
With these two things, we can create a very bare-bones loading component like so:
import { Html, useProgress } from '@react-three/drei'
function Loader() {
const { progress } = useProgress()
return <Html center>{progress} % loaded</Html>
}
We can then wrap our model in it using Suspense
like so:
export default function App() {
return (
<Canvas>
<Suspense fallback={<Loader />}>
<Model />
</Suspense>
</Canvas>
)
}
The hook returns much more than just the progress so there is a lot you can do there to give the user more information about the loading status of the application. You can play with all of them in this sandbox: