In React, we can use tools like gltfjsx to convert 3D models from GLB
or GLTF
formats into *.jsx
components for rendering within a React application.
GLTF (GL Transmission Format): A JSON-based format for 3D scenes and models, including meshes, textures, and animations, designed for efficient web transmission as seperate files.
GLB: A compact, binary version of GLTF that includes all resources in a single file, ideal for efficient 3D content transfer and use in web applications.
To make it easier to understand, I'm going to use both GLB
and GLTF
files of the same model and explain how we can convert 3D files into JSX components in both cases
I have downloaded this 3d model Merc Hovercar from Sketchfab
- Use the
CLI
to navigate to themodel
folder. Ideally, themodel
should be inside thepublic > 3d Model
folder. - Now run the following command to generate a
jsx
file and compressed version of the model (the textures will be converted to webp)npx gltfjsx free_merc_hovercar.glb --draco
This command installs the
gltfjsx
npm package and converts theGLTF
file to[fileName]-transformed.glb
The
[fileName].jsx
file will also be generated inside the folder.
or run the following command if you are insideIf you don’t need to compress the texture, then remove the
--draco
flag.gltf
model foldernpx gltfjsx .\scene.gltf --draco
This will only generate a
jsx
file inside the folder - Let's take a look at the generated file.
import React, { useRef } from "react"; import { useGLTF } from "@react-three/drei"; export function Model(props) { const { nodes, materials } = useGLTF("/free_merc_hovercar.glb"); return ( <group {...props} dispose={null}> <group position={[0.019, -0.066, -0.047]} rotation={[-Math.PI / 2, 0, 0]} scale={0.496} > <mesh geometry={nodes.Plane006_0.geometry} material={materials["Material.001"]} /> <mesh geometry={nodes.Plane006_1.geometry} material={materials.Material_light} /> <mesh geometry={nodes.Plane_0.geometry} material={materials.Plane_0} position={[0, 0, -0.582]} scale={[1.187, 2, 1]} /> </group> </group> ); } useGLTF.preload("/free_merc_hovercar.glb");
- Change the model name to something meaningful
export function FlyingCar(props)
Then move the*.jsx
file tosrc>components>3dModel>FlyingCar.jsx
- Next, we need to update the file path.
In React, the default path for referencing any file starts from the public directory, and our model resides in this folder.
Therefore, we can specify the path as
3dModel/FlyingCar/free_merc_hovercar.glb
import React, { useRef } from "react"; import { useGLTF } from "@react-three/drei"; export function FlyingCar(props) { const { nodes, materials } = useGLTF( "3dModel/FlyingCar/free_merc_hovercar.glb" ); return ( <group {...props} dispose={null}> <group position={[0.019, -0.066, -0.047]} rotation={[-Math.PI / 2, 0, 0]} scale={0.496} > <mesh geometry={nodes.Plane006_0.geometry} material={materials["Material.001"]} /> <mesh geometry={nodes.Plane006_1.geometry} material={materials.Material_light} /> <mesh geometry={nodes.Plane_0.geometry} material={materials.Plane_0} position={[0, 0, -0.582]} scale={[1.187, 2, 1]} /> </group> </group> ); } useGLTF.preload("3dModel/FlyingCar/free_merc_hovercar.glb");
- We have to create a boilerplate code for displaying a 3d model using react three fiber
import "./App.css"; import { Canvas } from "@react-three/fiber"; import { CameraControls } from "@react-three/drei"; function App() { return ( <> <title>R3F GLTF</title> <Canvas> <PerspectiveCamera makeDefault fov={75} position={[0, 0, 2]} resolution={1024} /> <CameraControls/> <ambientLight intensity={0.5} /> </Canvas> </div> </> ); } export default App;
- Now, import the 3D model. Since the 3D model may load more slowly and asynchronously compared to the page, we also need to import
Suspense
from React.import "./App.css"; import { Suspense } from "react"; import { Canvas } from "@react-three/fiber"; import { FlyingCar } from "./components/3dModels/FlyingCar"; import { CameraControls } from "@react-three/drei"; function App() { return ( <> <title>R3F GLTF</title> <div className="h-[700px]"> <Canvas> <PerspectiveCamera makeDefault fov={75} position={[0, 0, 2]} resolution={1024} /> <CameraControls /> <ambientLight intensity={0.5} /> <Suspense> <FlyingCar></FlyingCar> </Suspense> </Canvas> </div> </> ); } export default App;