How To Mirror Animation Key Frames

How do i MIRROR a keyframe animation key.

I tried flipping like this

Position.x *= -1


QuaternionRotation.x *= -1
QuaternionRotation.w *= -1

But its not quite working :frowning:

1 Like

Weird. This looks good to me. Can you share a PG?

1 Like

I cant really put on playground yet. So i made a video trying to show what i am doing:

Test Mirror Video

1 Like

For the quaternion, try to negate the y and z components instead of the x / w.

A quaternion is a rotation around an axis ((ax, ay, az) is the axis, angle is the angle of ration):

qx = ax * sin(angle/2)
qy = ay * sin(angle/2)
qz = az * sin(angle/2)
qw = cos(angle/2)

Now you want to mirror against the X plane, I think you need to negate the angle and the axis x component:

q2x = -ax * sin(-angle/2) = qx
q2y = ay * sin(-angle/2) = -qy
q2z = az * sin(-angle/2) = -qz
q2w = cos(-angle/2) = qw

So the y and z components should be negated.

I tried the Y and the Z

public static SampleAnimationQuaternion(animation:BABYLON.Animation, frame: number, mirror:boolean, loopMode:number, result:BABYLON.Quaternion): void {
    if (animation != null && animation.dataType === BABYLON.Animation.ANIMATIONTYPE_QUATERNION) {
        const keys:BABYLON.IAnimationKey[] = animation.getKeys();
        if (frame < keys[0].frame) {
            frame = keys[0].frame;
        } else if (frame > keys[keys.length - 1].frame) {
            frame = keys[keys.length - 1].frame;
        BABYLON.Utilities.FastQuaternionInterpolate(animation, frame, loopMode, result);
        if (mirror === true) {
            //result.x *= -1;
            result.y *= -1;
            result.z *= -1;
            //result.w *= -1;

Still looks funny with the arms


I wonder why you have problems with the harms and not the legs / torso / head…

Also, did you change the side orientation of the materials when mirroring? You should set it to clock-wise (I think) as the winding of the vertices does change under mirroring.

not familiar with the source code but I think the scaling should be applied after the other operations e.g. rotating for the bone matrix?
and, the arm bones are nested, so is there a mechanism in BJS that we need to update the child bones as well when we modify the parent bone?