Quaternions

I’ve added quaternions to my application for the benefits they offer.

I have a problem however that I can’t quite figure out.

My application needs to set keyframes with rotational values greater than 360.
I’m currently relying on extracting the Euler angles from the quaternion defining my rotation before and after any rotation is done with the mouse. This gives me the delta of how much rotation was done along what axis and the idea is to add this delta to the key frame value of the rotation along that axis.

The problem with this method is that quaternions will suddenly do a rotation of 180 on some axis from time to time and also never return a representation of a rotation with a value greater than 360 (actually I think it’s more like -180 to 180).

As you can tell from my post, I’m no quaternion expert…what’s a simple way to use quaternions and also track rotations so I can properly set keyframes (much like is done in 3D Studio Max)?

I hope at least some of that came across clearly.

I’d greatly appreciate any help on this, thanks.

Quaternions do behave a bit strangely from what people are used to. Using a single quaternion to deal with wrapping issues is somewhat hard.

There are two things you might do to simplify your life a bit. One is you can store your key-frame rotations as raw “axis + angle” and convert to a Quat when you need to concatenate.

The angle can then use the full float range, not just the normalized quat range. You could similarly store a regular Quat plus an extra “quadrature” value to remember how many windings need to be done or undone. It’s still a pain if you want to, say, slerp between two such quats that are not on the same axis.

So the other method is to scale your quats. I’ve used that more for storing rotational velocities, which naturally can go above +/- 1 revolution. But it might also work for your needs.

In this case, you’d pre-multiply your quats by a common scale factor, which is fine for velocity because you generally need to multiply ‘dt’ (delta time) anyway – one extra 1/1000 scale won’t hurt, except to lose some precision in the float range. You’d then de-scale the result back to the normal range. A scale factor of 2 or 3 might be enough to handle most of your winding cases, though I’ve never tried it for this purpose.

But if, for example, you store the delta or velocity between keyframes instead of the keyframes themselves, then it should work the same way as I described. [edit: if you can guarantee that the delta angle between keyframes is never > 180 degrees, then you don’t even need to scale the quats – just storing the deltas should give you the correct wrapping you want]

You should not use Euler angles at all. That way you loose nearly all advantages of quaternions. Axis-angle is propably the best way for deltas between keyframes, when you need to calculate in-between steps. Everything else should propably be stored as quaternions only, and also calculated as quaternions.