Mirroring a Quaternion

Started by
7 comments, last by JohnBolton 18 years, 6 months ago
I'm not very good with the use of these, yet. What I'm wanting to do is mirror a rotation-only quaternion on the x-axis. For a matrix, this would be as easy as flipping the x axis sign in all of the vectors of the matrix. But is this the case with quaternions? Do I just quat.x = -quat.x? Thanks for any help. Please let me know if I'm leaving something out. edit: Ack. I got a little confused there. To mirror the x-rotations, I believe I would need to negate both the y and the z values. Just to make sure I'm clear, I'm wanting to mirror skeletal bone rotations from one side to the other. The right forearm to the left forearm, for example. This is to mirror stances and allow the characters to swap sides through various attacks. [Edited by - Kest on October 5, 2005 11:37:17 AM]
Advertisement
You could always take the indirect approach, where you convert the quaternion to a matrix, mirror it, and then convert it back into a quaternion. Or, you could construct a rotation quaternion that rotates your original quaternion into a mirrored position. As long as you know how to extract the rotation vector out of the quaternion form, you can take the cross product between that and the x-axis to get such a rotation vector, then convert it back into a quaternion, make the rotation 90° (or -90°, not sure off the top of my head which direction would be the positive rotation) and multiply your original quaternion by this rotation quaternion. But unless this is just an exercise in understanding quaternions, if there's an operation that's trivial to perform in matrix form then it's best just to convert back and forth from a matrix.
This is a real feature I need to impliment into my game. Characters animate 40 bones every frame, and this mirroring would be applied to each of them every frame. I'm afraid converting to matrix and back would require too much processing. Another option would be to make copies of all of the mirror-able animations and process them on load up. But that would be a lot of animations.

This seems to work perfectly:

Quat.y = -Quat.y;
Quat.z = -Quat.z;

Is there something wrong with this approach that just isn't visible?

I appreciate your help.

edit: To be more clear, I've tested this under some pretty crazy conditions. Running around, jumping, fists swinging, etc. I apply right side bone animation states to the left side and vice versa, then flip the x rotations via the simple operation above. It seems to mirror the limbs perfectly. Still, I'd like to know if something will explode in the future.
Don't worry, it should work :) . x,y,z portion of quaternion (i.e. non-real part) specifies axis of rotation, and so, mirroring x,y,z part is equivalent to mirroring the axis of rotation. It is useful to think of quaternion as sort of axis and angle (instead of angle itself it stores sine and cosine of half angle (as length of vector part and real part respectively), so no trig is needed for transformation)
It definately will not blow up.

Flipping y and z to get mirrored rotation also makes sense: with symmetrical body doing symmetrical motion, left joint has axis of rotation that is mirror of right one. Also, it rotates in opposite direction (i.e. if right is clockwise, left must be counterclockwise). So, it is same as conjugate of quaternion that have x negated. That is, x,-y,-z,w
Thanks for that helpful information. The axis thing was really helpful :)

The hardest part was sorting out what axes my character's bones use. Like the left forearm lays where the x-axis is the length of it, and the z-axis is the elbow type rotation. This elbow type rotation is the only axis I don't want to negate when mirroring; it seems more suitable to me for the x-axis. But Character Studio seems to like laying the limb lengths out on the x-axis. But then there are custom max bones and weapon props, which use different coordinates. So I had to give each character type their own axes for every bone and create a lookup table to grab float indices from the quaternions. Lots of fun.

Thank you again.
If by "mirroring" you mean you want to rotate the same amount in the opposite direction, then the value you want is called the "conjugate". To get the conjugate, you negate the x, y, and z values of the quaternion.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
Well if I negate all of the values, I get broken elbows and knees (ostridge style). I definitely don't want to mirror those rotations. I want the effect of converting a left roundhouse kick into a right roundhouse kick.

Just out of curiousity, since the xyz components of a quaternion are like the axis, then w is kind of like the angle? Instead of negating y and z, could I negate x and w? Testing it seems to work, but I hate relying on test results. It is doing the exact same thing, right? This would be slightly easier to work with in my game, because the w component doesn't need converted to bone coordinates.

Anyway, thanks for all of the excellent advice.
Quote:Original post by Kest
Well if I negate all of the values, I get broken elbows and knees (ostridge style). I definitely don't want to mirror those rotations. I want the effect of converting a left roundhouse kick into a right roundhouse kick.

Just out of curiousity, since the xyz components of a quaternion are like the axis, then w is kind of like the angle? Instead of negating y and z, could I negate x and w? Testing it seems to work, but I hate relying on test results. It is doing the exact same thing, right? This would be slightly easier to work with in my game, because the w component doesn't need converted to bone coordinates.

Anyway, thanks for all of the excellent advice.

Yes, and another useful property of quaternions is that
w,x,y,z
and
-w,-x,-y,-z
defines same rotation.
I.e. w,x,-y,-z and -w,-x,y,z will rotate things the same.
How it could be proved: rotation is defined as Q*V*Qconj and if we negate Q, that is, multiply Q by -1 we get (Q*(-1))*V*(Q*(-1))conj . Multiplication by scalar is commutative so -1 could be moved out and we get (-1)^2*Q*V*Qconj , i.e. Q*V*Qconj

Actually, w is not very much like angle : it stores cosine of half angle, and sine of half angle is storen in length of xyz. So, in some sense xyz is more like angle. But negating w really negates the rotation itself. I actually use that instead of conjugate when i need "inverse" rotation.

By the way, that's why when doing quaternion interpolation you must ensure that it goes shortest path with if(a dotproduct b)a=-a;
Quote:Original post by Kest
Just out of curiousity, since the xyz components of a quaternion are like the axis, then w is kind of like the angle? Instead of negating y and z, could I negate x and w? Testing it seems to work, but I hate relying on test results. It is doing the exact same thing, right? This would be slightly easier to work with in my game, because the w component doesn't need converted to bone coordinates.

Indeed, a quaternion can be thought of as an encoded axis-angle form. I believe (though I haven't tried it) that to mirror around the yz plane, you would negate the x value and reverse the rotation. That means negating either x and w, or y and z.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!

This topic is closed to new replies.

Advertisement