Search code examples
reactjsthree.jsreact-three-fiberreact-three-drei

How to animate a 3D model in threejs?


I am currently working on a project to show the 3D models in frontend. When you scroll it shows the next models. I am using gsap for scrolling, and three-fiber with React framework.

You may check the working version here.

I have created functional component to dynamically get the models and it returns


const { nodes, materials } = useGLTF(file);
<>
            <Environment files="/hdr/san_giuseppe_bridge_1k.hdr" />
            <directionalLight position={[3.3, 1.0, 4.4]} intensity={1} />
            {/* <OrbitControls enableZoom={false} /> */}
            <group>
              <mesh
                castShadow
                onPointerEnter={onHover}
                onPointerLeave={onHoverOut}
                onClick={handleClick}
                position={slide.position}
                ref={slideRef}
                geometry={nodes.Text.geometry}
                material={materials.Material}
                rotation={[Math.PI / 2, 0, 0]}
              >
              </mesh>
            </group>
          </>

and it is used in parent component dynamically for each file we get from backend.

I want to apply the animation to the models, but it should be simple animation, thus I think there is no need to create it in Blender. It basically should have "swinging" animation which is like here.

Would anyone help me with the idea of how that can be done? As I understand that animation is like a rotation within x and z axes.


Solution

  • I fixed it myself by using useFrame which acts like a update function.

    I have introduced several variables in order to calculate the rotation of x, y and z.

      useFrame(({ clock }) => {
        const t = clock.getElapsedTime();
        const swingSpeed = 0.1;
        const swingAmplitude = 0.01;
        const rotationSpeed = 0.4;
        const rotationAmplitude = 0.2;
        const swingY = Math.sin(t * swingSpeed) * swingAmplitude;
        const swingZ = Math.cos(t * swingSpeed) * swingAmplitude;
        const rotationX = Math.cos(t * rotationSpeed) * rotationAmplitude;
    
        modelRef.current.rotation.y = swingY;
        modelRef.current.rotation.x = Math.PI / 2 + rotationX;
    
        modelRef.current.rotation.z = swingZ;
      });