0

I’m building a next.js app (v.15 with app router) and I’m having some issues with my glb file/model after building/deploying my app. I have a CI that deploys my app to GCP using docker(artifact registry) cloud run. But I don’t think the issue is with the deploy. If I check my builded/deployed app in devtools>network I can see my glb file there, also if I type myExampleUrl.com/myglbfile.glb in the browser my file starts to download. So the file is there.

I have added this to my next.config.ts

transpilePackages: ['three', '@react-three/fiber', '@react-three/drei'], 

The model is in my frontpage hero component. I have devided it in 2 components: scene and model.

Here is my ThreeScene/ThreeScenetsx

import {useEffect} from 'react'; import {Canvas} from '@react-three/fiber' import Model from './Model' import {Environment} from "@react-three/drei"; export default function ThreeScene() { useEffect(() => { if (!window.WebGLRenderingContext) { console.error("WebGL not supported"); } else { console.log("WebGL supported"); } }, []); return ( <Canvas> <directionalLight intensity={.1} position={[0, 3, 2]}/> <Environment preset="city"/> <Model/> </Canvas> ) } 

And here is my ThreeScene/Model.tsx

import {useGLTF} from "@react-three/drei";
import {useFrame, useThree} from "@react-three/fiber";
import React, {useRef, useState, useEffect} from "react";
import {Group, Vector2} from "three";
import gsap from "gsap";
import {useGSAP} from "@gsap/react";

export default function Model() {
    const groupRef = useRef<Group>(null);
    const [pointer] = useState(new Vector2());
    const {nodes, materials} = useGLTF("/heroobject.glb");
    const {viewport, size} = useThree(); // Här läggs size till i destructuring
    const [isAnimating, setIsAnimating] = useState(true);
    const [isInitialized, setIsInitialized] = useState(false);

    const getScaleFactor = (width: number) => {
        if (width <= 768) {
            return 1.2; // mobile
        } else if (width <= 1024) {
            return 2.3; // tablet
        } else {
            return 3.2; //desktop
        }
    };

    useGSAP(() => {
        if (groupRef.current && !isInitialized) {
            setIsInitialized(true);

            groupRef.current.scale.set(0, 0, 0);
            groupRef.current.rotation.set(0, 0, 0);
            groupRef.current.position.y = 0;

            const scaleFactor = getScaleFactor(size.width);

            gsap.to(groupRef.current.scale, {
                x: viewport.width / scaleFactor,
                y: viewport.width / scaleFactor,
                z: viewport.width / scaleFactor,
                delay: .5,
                duration: 1.5,
                ease: "elastic.out(1, 0.5)",
                "onComplete": () => setIsAnimating(false)
            });

            gsap.to(groupRef.current.position, {
                y: 0.75,
                duration: 1.5,
                ease: "power3.out"
            });

            gsap.to(groupRef.current.rotation, {
                y: Math.PI * 2,
                duration: 2,
                ease: "power2.inOut"
            });
        }
    }, [isInitialized, size.width, viewport.width]);

    useEffect(() => {
        if (groupRef.current && isInitialized && !isAnimating) {
            const scaleFactor = getScaleFactor(size.width);

            gsap.to(groupRef.current.scale, {
                x: viewport.width / scaleFactor,
                y: viewport.width / scaleFactor,
                z: viewport.width / scaleFactor,
                duration: 0.5,
                ease: "power2.out"
            });
        }
    }, [size.width, viewport.width, isInitialized, isAnimating]);

    useFrame((state) => {
        pointer.set(state.pointer.x, state.pointer.y);

        if (groupRef.current && !isAnimating) {
            groupRef.current.rotation.y += 0.004;

            const targetRotationX = pointer.y * 0.2;
            const targetRotationZ = pointer.x * 0.2;

            groupRef.current.rotation.x += (targetRotationX - groupRef.current.rotation.x) * 0.05;
            groupRef.current.rotation.z += (targetRotationZ - groupRef.current.rotation.z) * 0.05;
        }
    });

    const cylinderNames = [
        "Cylinder", "Cylinder001", "Cylinder002", "Cylinder003",
        "Cylinder004", "Cylinder005", "Cylinder006"
    ];

    return (
        <group ref={groupRef} position={[0, 0, 0]}>
            {cylinderNames.map((name: string) => (
                <primitive
                    key={name}
                    object={nodes[name]}
                    material={materials["Material.001"]}
                />
            ))}
        </group>
    );

I’m then importing ThreeScene in my hero component.

Any ideas? If anyone wants to take a closer look I would love to invite you to my gitlab repo.

I have tried to use next/dynamic and imported ThreeScene with ssr:false, I have tried several different config settings. The file is there I just can’t see the model.

3
  • Do you see your model instance when you console.log the scene tree? Do you have lights activated? No need to issue invitations to your gitlab repo, people don't like to be redirected here and there. Just post the relevant pieces of your code involved with your model loading & rendering. Relevant pieces, I insist, not boilerplate code. Commented Mar 11 at 8:14
  • Yes, i can see the instance when console.log the scene tree. Lights is activated. Well its a lot of code. I have my file in root/public/ Im using useGLTF like this: const {scene} = useGLTF("/heroobject.glb"); , importing the object then using a primitve setting object={scene}. im also importing my three component dynamic with next/dynamic. At first i could only see my object when running my app on dev server with npm run dev. If i tried to build the app and run npm run start the object didnt show. Now i have figrued out the build issue but still cant see my object after deploying to. Commented Mar 12 at 9:11
  • I have created a demo here. codesandbox.io/p/devbox/r3f-demo-4pc293 Commented Mar 15 at 9:52

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.