Skip to content

useGLTF Hook

Import

import { useGLTF } from '@react-three/drei'

Video Lecture

Section Video Links
useGLTF Hook : Part 1 useGLTF Hook useGLTF Hook : Part 1
useGLTF Hook : Part 2 useGLTF Hook useGLTF Hook : Part 2

Description

We will download some CC0 models, import them into Blender and export them as glTF suitable for our application.

We will load the models on demand as needed when the selection in the UI changes. They will then also be automatically cached in case they are selected in the UI again.

If you aren't able to download the models from Poly Haven, and then convert them in Blender, then you can download a zip of all the assets used in this video from assets_useGLTF.zip. Then extract all the contents into the ./public/ folder.

After extracting the zip, or conversion using Blender, the ./public/ folder structure should appear like,

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
|-- React-Three-Fiber-Boilerplate
    |-- node_modules
        // etc
    |-- public
        |-- img
            |-- workshop_1k.hdr
        |-- models
            |-- drill.glb
            |-- hammer.glb
            |-- tapeMeasure.glb
    |-- src
        // etc
    // etc

./src/styles.css

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
html,
body,
#root {
  height: 100%;
  margin: 0;
  background: #000000;
}

#info {
  position: absolute;
  top: 60px;
  left: 10px;
  background: #181c20;
  color: #8c92a4;
  padding: 10px 20px;
  border-radius: 5px;
  font-size: 32px;
  pointer-events: none;
}

./src/App.jsx

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import { Canvas } from '@react-three/fiber'
import { Stats, OrbitControls, Environment, useGLTF } from '@react-three/drei'
import { useControls } from 'leva'

const Models = [
  { title: 'Hammer', url: './models/hammer.glb' },
  { title: 'Drill', url: './models/drill.glb' },
  { title: 'Tape Measure', url: './models/tapeMeasure.glb' },
]

function Model({ url }) {
  const { scene } = useGLTF(url)
  return <primitive object={scene} />
}

export default function App() {
  const { title } = useControls({
    title: {
      options: Models.map(({ title }) => title),
    },
  })

  return (
    <>
      <Canvas camera={{ position: [0, 0, -0.2], near: 0.025 }}>
        <Environment files="./img/workshop_1k.hdr" background />
        <group>
          <Model
            url={Models[Models.findIndex((m) => m.title === title)].url}
          />
        </group>
        <OrbitControls autoRotate />
        <Stats />
      </Canvas>
      <span id="info">The {title} is selected.</span>
    </>
  )
}

Note that useGLTF also has a preload option. If you wanted to preload all the models in this example, you could add this line below, to the end of the ./src/App.jsx script.

useGLTF.preload(Models.map(({ url }) => url))

Mixing React-Dom elements with React Three Fiber

In this example, there is the HTML span tag. Note how this is placed outside the React Three Fiber Canvas tag.

Sometimes you want to add or control HTML elements within the HTML document outside the Three.js canvas.

If you try to add a standard HTML tag inside the React Three Fiber Canvas element, then you will get an error similar to Uncaught Error: R3F: Div is not part of the THREE namespace! Did you forget to extend?

The error happens because the React Three Fiber reconciler renders into a Three.js scene, and not the HTML document. So, a div, span, h1 or any other HTML tag will mean nothing to the Three.js renderer. Instead, you need to render it to the HTML document, and for that you use the React-DOM reconciler. This is a simple as putting your HTML tag outside the Canvas element.

I.e.,

bad

<Canvas>
  <div>Some Text</div>
  <axesHelper />
</Canvas>

good

<Canvas>
  <axesHelper />
</Canvas>
<div>Some Text</div>
useGLTF drei codesandbox.io
CC0 3D Models Poly Haven Models

Working Example