I am using Three.js to create an animation, but my animate()
function is not working properly. Simplified code below:
let obj;
let camera = new THREE.PerspectiveCamera(fov, asp, near, far);
let scene = new THREE.Scene();
const loader = new THREE.GLTFLoader();
async function init() {
obj = await loader.loadAsync("./public/modelo/scene.gltf");
scene.add(obj.scene);
animate(obj.scene.children[0]);
renderer.render(scene, camera);
function animate(objeto){
console.log(objeto);
requestAnimationFrame(animate);
objeto.rotation.z = 0.005;
renderer.render(scene, camera);
}
}
init();
The function works for the first call, but after that I can see things going wrong via my console.log()
statement. On the first run of animate()
, the line prints out the object, as expected. But, on all ensuing calls, the statement just returns a floating point number that increases greatly with each successive call. I checked and made sure that the object was intact at the end of the first function call, so I'm not sure what's going on here. Any suggestions?
CodePudding user response:
The problem is in this one line in your code:
requestAnimationFrame(animate);
From the MDN documentation for requestAnimationFrame
, the callback you pass it - here animate
, is:
The function to call when it's time to update your animation for the next repaint. The callback function is passed one single argument, a DOMHighResTimeStamp similar to the one returned by performance.now(), indicating the point in time when requestAnimationFrame() starts to execute callback functions.
In other words, your animate
is getting called with a timestamp - which in some ways I imagine behaves much like a number (I'm not personally familiar with what a DOMHighResTimeStamp
is), and explains what you're seeing. It certainly won't be getting called with your "objeto" as argument.
To ensure that, just pass in as a callback a function will calls animate
with the correct argument. Replace the call above with
requestAnimationFrame(() => { animate(objeto); });
EDIT: or as @Bergi suggests, we can avoid needing an argument at all by simply defining objeto
outside animate
, in the init
function. Since you always call animate
with this same argument there's no need to specifically pass it, so your code can just be:
async function init() {
obj = await loader.loadAsync("./public/modelo/scene.gltf");
const objeto = obj.scene.children[0];
scene.add(obj.scene);
animate();
renderer.render(scene, camera);
function animate(){
console.log(objeto);
requestAnimationFrame(animate);
objeto.rotation.z = 0.005;
renderer.render(scene, camera);
}
}