From Blender I have exported an animated model(spaceship) and an animated camera as a .glb using the gltfExporter, when I drop the .glb file into the glTF viewer (gltf-viewer.donmccurdy.com) everything works, so I know the issue is not with the model/Blender.
The problem is when I try and play the animation in my script. I can either have the model animate perfectly OR I can have the camera animate perfectly, but when I try and do both camera and model go crazy. I think it might be my lack of understanding with Animation Mixers? Perhaps I only need to utilize one Mixer for the one file? Anyway this is what I'm doing in brief:
I create two separate animation mixers, one for the spaceship and one for camera:
gltfStore.mixer = new THREE.AnimationMixer(gltf.cameras[0]);
gltfStore.mixerShip = new THREE.AnimationMixer(gltf.scene.children[2]);
I play the animations using clipAction:
gltfStore.mixer.clipAction(gltfStore.animations[0]).play();
gltfStore.mixerShip.clipAction(gltfStore.animations[0]).play();
In my loop, I render the animations:
gltfStore.mixer.update(clock.getDelta());
gltfStore.mixerShip.update(clock.getDelta());
Separately they work, but together they do not. Something that I noticed is that the animation data imported in the glTF animation object includes the animation for both camera and model under gltf.animations[0]. What I mean is gltf.animations[0]
has a tracks
array with 6
items, the position, quaternion and scale for each item. is that right?
For your convenience, here is the main js file:
var scene = new THREE.Scene();
var mixer, animationClip;
var clock = new THREE.Clock();
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
//LIGHTS
var light = new THREE.PointLight( 0xffffff, 1, 200 );
light.position.set( 10, -10, 0 );
scene.add( light )
//OBJECT TO STORE THE GLTF ASSETS WHEN LOADED
var gltfStore = {};
var loader = new THREE.GLTFLoader();
// LOAD GLTF ASSETS
var gltfCamera = loader.load(
'spaceship.glb',
function ( gltf ) {
scene.add( gltf.scene );
gltfStore.animations = gltf.animations;
gltfStore.ship = gltf.scene.children[2];
gltfStore.cam = gltf.cameras[0];
gltfStore.mixer = new THREE.AnimationMixer(gltf.cameras[0]);
gltfStore.mixerShip = new THREE.AnimationMixer(gltf.scene.children[2]);
gltfStore.mixer.clipAction(gltfStore.animations[0]).play();
gltfStore.mixerShip.clipAction(gltfStore.animations[0]).play();
}
);
function animate() {
requestAnimationFrame( animate );
if(gltfStore.mixer && gltfStore.cam){
//gltfStore.mixer.update(clock.getDelta());
gltfStore.mixerShip.update(clock.getDelta());
renderer.render(scene, gltfStore.cam);
}
};
animate();
Thank you for any help/ideas!
So after further examining examples I found my answer.
Simply put, there was no need to extract and attempt to animate the model and camera individually, all what was required was to create an AnimatioMixer
from the scene itself:
gltfStore.mixer = new THREE.AnimationMixer(gltf.scene);
gltfStore.mixer.clipAction(gltfStore.animations[0]).play();
The above animated all elements perfectly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With