Rotate an animation (or blend with a static Quaternion)

I have a SkinnedMesh with animations and everything works fine, but now we want the character to be able to track the cursor with his head while performing normal animations. We’ve been able to get the cursor tracking while no animations are playing but can’t figure out how to blend the static quaternion applied to our bone, it just gets overwritten by the animation.

Is there any way to rotate all the animation clip quaternions (performantly?) or blend this static quaternion?

Are we approaching this wrong and there’s another feature we should be using? I’m not super familiar with morph targets but maybe that’s the correct route.

I’d still like some feedback, but as it turns out, I’m able to make a dummy animation with a quaternion blended between itself and then just play it and it works!

        //this is the rotation we want to set it to
        let quat = new THREE.Quaternion()
            .setFromAxisAngle(new THREE.Vector3(1,0,0),Math.PI/4 * ndc.x)
            .premultiply(new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,0,1),Math.PI/6 * -ndc.y));
        let bone = this.gg.bones.SheKNeck2;
        //to blend with the animations make a dummy animation clip
        let clip = new THREE.AnimationClip("MOUSE_LOOK", 1.0, [
                //Will apply to the quaternion property
                new THREE.QuaternionKeyframeTrack(`${bone.uuid}.quaternion`, [0.0,1.0], quat.toArray().concat(quat.toArray()))
            ]);
        let action = this.gg.mixer.clipAction(clip);
        action.play();
        if(this._oldAction) {
            this._oldAction.stop();
        }   
        this._oldAction = action;

Your presented approach seems valid to me, I can’t think of a better one^^. The good thing is that the animation system will automatically ensure that your animations are correctly mixed which is actually a nice feature.

Making a new action I believe works, but trying to reuse the animation and setting the animation tracks does not. I believe internally it is doing some sort of caching (in _bindAction) so it might not be as doable as I originally thought.

I also found that setting the Quaternion after the animation mixer has updated works too but then I dont get any blending on the given bone, which might work for my case.

Do the rotation after mixer update. Save its value after mixer update. Use lookAt, then use the slerp method of a quaternion to blend with the saved value.

1 Like