From GLB to JSX: Integrating 3D Models into Your React App

React three fiber

Transform and Display 3D Models in React with GLTFJSX and React Three Fiber

react
drei
react three fiber

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

  1. Use the CLI to navigate to the model folder. Ideally, the model should be inside the public > 3d Model folder.
  2. 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 the GLTF file to [fileName]-transformed.glb

    The [fileName].jsx file will also be generated inside the folder.

    If you don’t need to compress the texture, then remove the --draco flag.

    or run the following command if you are inside gltf model folder
    npx gltfjsx .\scene.gltf --draco

    This will only generate a jsx file inside the folder

  3. 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");
  4. Change the model name to something meaningful export function FlyingCar(props) Then move the *.jsx file to src>components>3dModel>FlyingCar.jsx
  5. 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");
  6. 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;
  7. 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;