1

I'm building a nextjs app with 3D animations using @react-three/drei.

I have a gltf file in the public folder, under the desktop_pc folder called scene. gltf.

The path from the project root is: /public/desktop_pc/scene.gltf.

When importing the gltf file into the useGLTF hook, I'm getting the error:

TypeError: Failed to parse URL from /desktop_pc/scene.gltf

Github Repository - nextjs & @react-three/drei - TypeError: Failed to parse URL

This is the component code:

import { useGLTF } from "@react-three/drei";
import React from "react";

const Computers = () => {
  const computer = useGLTF("/desktop_pc/scene.gltf");
  return <div>Computers</div>;
};

export default Computers;

These are my attempts so far (The links leads to the GitHub solution of them):

  1. Dynamic import - https://github.com/ItayTur/Portfolio/tree/invalid-url-error-dynamic-solution
  2. Lazy import - https://github.com/ItayTur/Portfolio/tree/invalid-url-error-lazy-solution
  3. Installing the Three & three-stdlib npm packages.
  4. Specify the exact path from the component to the file location.
  5. Adding a dot at the start of the path string.
Itay Tur
  • 683
  • 1
  • 15
  • 40

1 Answers1

1

Solution:

  1. Download three and react-three-fiber packages.
  2. Use the @react-three/fiber hook: useLoader.
  • NOT useGLTF from @react-three/drei
  1. Wrap the GLTF model component with a Canvas component.
import { Canvas } from "@react-three/fiber";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { useLoader } from "@react-three/fiber";

const Computers = ({ isMobile = false }) => {
  const gltf = useLoader(GLTFLoader, "/desktop_pc/scene.gltf");

  return (
    <group>
      <primitive
        scale={isMobile ? 0.7 : 0.75}
        position={isMobile ? [0, -3, -2.2] : [0, -3.25, -1.5]}
        rotation={[-0.01, -0.2, -0.1]}
        object={gltf.scene}
      />
    </group>
  );
};

const ComputersCanvas = () => {
  return (
    <Canvas>
      <Computers />
    </Canvas>
  );
};

export default ComputersCanvas;
  1. Use as any other component
const Hero = () => {
  return (
    <section className={`relative w-full h-screen mx-auto`}
      <ComputersCanvas />
    </section>
  );
};

export default Hero;
}

GitHub Links:

  1. First working commit
  2. Full PR
Itay Tur
  • 683
  • 1
  • 15
  • 40