Hello everyone! I'm working with React+Three.js + GSAP. I'm trying to animate a 3D model to make it rotate infinitely around its Y axis. The animation itself is applied, but I encounter a bug. The issue is that the animation randomly stops (does not complete a full rotation), and to restart it, I have to either drag the model again or move it (change its coordinates); otherwise, the model just remains stationary. So, it does not seem like a loading issue since otherwise, it would continue rotating on its own.
I've tried animating using GSAP and useFrame. I've attempted importing the model as .jsx, as .glb, but I get the same effect everywhere.
I also made a rotation animation in Blender and imported it, but I have the same error.
I also used other models. But I'm getting the same error.
This is the first time I'm encountering such an issue. Please advise on what might be the problem.
Here is a GIF demonstrating the operation: https://drive.google.com/file/d/14pjIwIL-RqjsGepeEYC2owZ97dopJgDC/view?usp=drive_link
This is the code of my component with a 3D model. I've shortened it for convenience. The comments indicate functions that I also tried. It didn't work.
import React, { useRef, useEffect } from 'react'
import { useAnimations, useGLTF } from '@react-three/drei'
import * as THREE from 'three';
import { useGSAP } from '@gsap/react';
import gsap from 'gsap';
import { useFrame } from '@react-three/fiber';
export function Model(props) {
const group = useRef()
const { nodes, materials, animations } = useGLTF('models/bmw_m4_csl_2023.glb')
const { actions, names } = useAnimations(animations, group)
/*useEffect(()=>{
actions[names[0]].reset().fadeIn(3).play()
},[])
*/
gsap.registerPlugin(useGSAP)
/*useGSAP(()=>{
let ctx = gsap.context(() => {
gsap.to(group.current.rotation,{
y: "+=1", repeat: -1, ease: 'none', repeatRefresh: true, duration: 4
}),group})
return () => ctx.revert();
},[]);*/
/*
useFrame(() => {
group.current.rotation.y += 0.01
})*/
useEffect(() => {
if (!group.current) return;
gsap.to(group.current.rotation, {
duration: 2,
repeat:-1,
y:2*Math.PI
});
}, []);
return (
<group ref={group} {...props} dispose={null}>
<group scale={0.01}>
<group rotation={[-Math.PI / 2, 0, 0]} scale={100}>
<mesh
castShadow
receiveShadow
geometry={nodes.M4xNME_exhaust_M4xNME_mechanical_0.geometry}
material={materials.M4xNME_mechanical}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.M4xNME_exhaust_M4xNME_silver_0.geometry}
material={materials.M4xNME_silver}
/>
</group>
<group rotation={[-Math.PI / 2, 0, 0]} scale={100}>
<mesh
castShadow
receiveShadow
geometry={nodes.M4xNME_radiator_M4xNME_Black_0.geometry}
material={materials.M4xNME_Black}
/>
<mesh
castShadow
receiveShadow
geometry={nodes.M4xNME_radiator_M4xNME_Grille7_0.geometry}
material={materials.M4xNME_Grille7}
/>
</group>
</group>
)
}
useGLTF.preload('models/bmw_m4_csl_2023.glb')
export default Model;
Here is the component where the component with the 3D model is called.
import React, { useEffect, useRef } from 'react';
import Model from './Model';
import { OrbitControls } from '@react-three/drei';
import { Canvas } from '@react-three/fiber';
const ModelView = () => {
return (
<Canvas frameloop='demand' camera={{ position: [20, 10, 20], fov: 12 }}>
<directionalLight position={[-19.772, 15.337, -0.439]} intensity={3.5} color="white"></directionalLight>
<directionalLight position={[21.998, 14.051, -3.370]} intensity={2.46} color="white"></directionalLight>
<directionalLight position={[-0.069, 13.752, -21.463]} intensity={5.08} color="white"></directionalLight>
<directionalLight position={[4.116, 16.240, 20.387]} intensity={2.4} color="white"></directionalLight>
<ambientLight intensity={2.12}></ambientLight>
<directionalLight position={[0.009, 0.076, 7.499]} intensity={1.6} color="white"></directionalLight>
<OrbitControls enableZoom={false} maxPolarAngle={Math.PI / 2} minPolarAngle={Math.PI / 2} />
<Model />
</Canvas>
);
};
export default ModelView;