This topic is 5394 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm still trying to grasp the whole quaternion deal. To be honest, I despise them [lol] -They never do what I expect them to do, but they are really the only acceptable means of interpolating rotations that I've tried. This is what I'm trying to do now. I have a quaternion called "motion". This motion is filled from keyframes from an animation that is playing. Every motion frame of the animation is relative to the previous frame. I do a simular thing with translation:
VECTOR translation_motion_buffer = 0;
.....
VECTOR key_translation = NextAnimationKeyframeVector;
FLOAT frame_time_laps = NumberOfMillisecondsPassedThisGameFrame;
FLOAT TimeToNextKey = NextAnimationKeyTime - PreviousAnimationKeyTime;

// Calculate the percentage of distance we've covered
perc = frame_time_laps / TimeToNextKey;

// Get Motion Amount (Motion values are relative)
translation_motion_buffer += key_translation * perc;


The above code may execute several times before translation_motion_buffer is used. Then my character's current position is updated right after by adding translation_motion_buffer to his current position, and reseting translation_motion_buffer back to zero. Does anyone know how I can do something just like this with quaternion rotations? The math is not the same, is it? 1) What would key_rotation * perc actually represent? Will it actually pull the percentage of that rotation quaternion out of the key? Or will it mess up the axis as well? Do I have to do something weird like factor the rotation quaternion with an identity quaternion to pull a percentage of it's rotations out? In other words, SLERP with identity and the key? 2) And after I do this, I can't simply add the amount to rotation_motion_buffer, right? How can I add an amount of rotation (quat) to another rotation (quat)? Each rotation may be around different axes. Does this matter? I know I sound pretty dumb. But that's okay, I feel the same way [lol] Any help is appreciated [smile]

##### Share on other sites
Just a quick reply, which may or may not address any of the issues you mentioned.

Quaternions, like matrices, can be used to concatenate rotations. If your object's orientation is represented by one quaternion, you can multiply it by another quaternion that represents, say, a roll around your object's z axis. The resulting quat represents your orientation after applying the roll.

For keyframe interpolation, I think you will want to use slerp, which, given two quats and a parametric value should return the appropriate intermediate quat. I don't think this can be done linearly for any but very small differences in orientation.

##### Share on other sites
It sounds like one would never want to simply multiply the rotations? I've noticed a lot of jerking when I simply multiply the quaternions rather than SLERP. And the differences between my keyframes are not drastic. -Medium paced rotations with 33.333 milliseconds between keys.

And thanks, that would cover everything except for factoring. What is the best way to use a specific amount of a rotation quaternion? Say I have a quat (Buffer) which represents 90 degree rotation around (0.5, 0.5, 0.0) axis. What rotation does Buffer * 0.7 represent? And if this will work, will it also cause the same problems as interpolating without SLERP? Would my best bet be to SLERP between an identity quat and the main rotation by factor 0.7? Does Rotation == (Rotation * 0.5) * (Rotation * 0.5) ?

Thanks again [smile]

##### Share on other sites
Quote:
 It sounds like one would never want to simply multiply the rotations? I've noticed a lot of jerking when I simply multiply the quaternions rather than SLERP. And the differences between my keyframes are not drastic. -Medium paced rotations with 33.333 milliseconds between keys.

It's not that you don't want to multiply quats. It's that multiplying them and slerping them do two different things.

Multiplying quats has the same effect as multiplying matrices. It's what you do when you want to change the orientation of your object. You have one quat representing your orientation, and another representing your change in orientation. You mult them together to get the new orientation.

Slerping is what you do when you want to interpolate two quats, i.e. for keyframe animation. So if you have quat1 and quat2 which are the keyframe quats, and you are at .33 between the frames, then newquat = slerp(.33, quat1, quat2).

Quote:
 What is the best way to use a specific amount of a rotation quaternion? Say I have a quat (Buffer) which represents 90 degree rotation around (0.5, 0.5, 0.0) axis. What rotation does Buffer * 0.7 represent?

First of all, keep in mind that the axis needs to be normalized (I think) for the quat representation to make sense. So .5, .5, 0 wouldn't give you the results you were looking for.

I'd have to look in my books to see if scaling a quat (like by 0.7) has any useful meaning, but I'm fairly certain it doesn't do what you expect it to. That's what slerp is for - it uses quaternion calculus to give you a meaningful parametric interpolation between two quats.

In summary, use multiplication for cumulative changes in orientation, and slerp for interpolation, such as between keyframes.

Quaternions can be tricky, so ask more questions if you have them! I'm no math expert - I just understand them from a practical point of view. So others may chime in with more in-depth explanations.

##### Share on other sites
No, you pretty much answered everything. Everything except for using a specific amount of a rotation quaternion. Usually that amount would be based on time. I mean I know a SLERP between an identity and the rotation would pull this off, but is this what I should do? Is this what most do?

I appreciate your help. And I prefer practical experience explanations [smile]

##### Share on other sites
Quote:
 Usually that amount would be based on time. I mean I know a SLERP between an identity and the rotation would pull this off, but is this what I should do? Is this what most do?

Ah, I see what you mean. Yes, I'm not sure how you would do the equivalent of:

quat1 *= .7 * quat2;

I'm not sure if they can be used that way. I just do the scaling beforehand, like this:

angle = rotspeed * deltatime;
m_quat *= quat(angle, axis);

Perhaps someone else will give a more rigorous explanation. But that's how I do it.

##### Share on other sites
So I should extract the relative angle and axis from each quaternion keyframe? But then I would have to factor axes and angles. Not much difference is there?

What I'm trying to do is have my character's rotations controlled by his animations. If his animation turns him around 180 degrees, then stops, I want my character to actually turn around 180 degrees. But if I don't make each keyframe relative to the previous keyframe, he will turn around 180 degrees, then blast back to 0 degrees when he switches to another animation, or if that animation loops around to frame 0 (if it loops).

So if they are relative, and the animation turns him around 45 degrees, and it loops, he will turn around 45, then turn around another 45, etc. So if it loops twice, he will do a 90 degree turn.

So every frame update I add the current key's relative rotation (factored by time) to my character's rotation. If anyone can show me how to do this without slerp with an identity or such, that would be great. For some reason, it feels like a hack doing it that way.

Thanks again [smile]

[Edited by - Jiia on October 11, 2004 10:51:17 PM]

##### Share on other sites
Sorry, your question was clear from the beginning, but I just wasn't tracking.

So let me see if I'm understanding now. Your keyframe rotations are relative rather than absolute so, for example, you can be facing at 45 degrees, and start an animation which rotates you to the left *from that orientation* rather than snapping you back to 0 first.

The one thing I'm not quite clear on is whether, for example, an animation that rotates you 5 degrees per keyframe has successive keyframes of 5, 10, 15 degrees, etc., or whether they are all 5 and are performed relative to each other.

In any case, here's an off-the-top-of-my-head solution. I really don't know if this will work - I've never tried it.

I'm pretty sure this won't work:

buffer_quat += perc * key_quat;

But this might:

Quaternion goal_quat = buffer_quat * key_quat;buffer_quat = Slerp(buffer_quat, goal_quat, perc);

Again, that's just off the top of my head, so it may not work for some reason or another. But it seems like it should.

Anyway, let us know what happens :)

P.S. Note that you might have to change the quat mult order depending on how your quat mult function is set up.

##### Share on other sites
Ahh man, how did I totally miss that? It makes perfect sense. It does work, but I'm still unsure of the accuracy. I haven't measured the rotation under extreme time tests yet. So far it looks great. Thanks [smile]

Oh, and my animation keys are relative to each other. Not originally, but I convert them to that form. This lets me start playing an animation from the middle of it, and I never need to keep track of any previous frames.

Each animation file has settings such as X-Motion, Y-Motion, Z-Motion, and R-Motion. x,y and z are translation, and r rotation. If X-Motion is defined for an animation, I erase all X-movement from the base bone of my skeleton and convert what I erased into relative motion. That animation can still leave y and z movement to the base bone, which is better really in such animations as walking, where the motion is usually in a single direction.

By using motion in this way, a 30 frame walk animation can move the character infinitely in one direction by looping, and his movements exactly match his foot movement. Same for turning around. His feet have to push him around, none of that spinning stuff [smile]

##### Share on other sites

anyway, jyk 's post seems to do the job.
Quote:
 Oh, and my animation keys are relative to each other. Not originally, but I convert them to that form. This lets me start playing an animation from the middle of it, and I never need to keep track of any previous frames.

I don't get that. first sentence contradicts to second. If by relative you mean relative to previous frame.

If you need to start animation from the middle you need to store _absolute_ rotation quaternions, that is, quaternions that rotates from _initial_ position to position at that frame*, so previous frames doesn't matter. So there's no precision issues you'll surely sooner-or-later get with your method as i understand it.

* it's "goal_quat" in jyk post. In fact i think this goal_quat it's what you initially had from what you obtained.

• 18
• 29
• 11
• 21
• 16