• Create Account

## Decompressing Quaternion Problem

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

13 replies to this topic

### #1IggyPop  Members

Posted 04 July 2012 - 08:34 PM

Hi,

I'm a little bit stuck with decompressing my Quaternions used in key frame animation. Angles that are close to 180 are some times negative when they should not and vise versa.

Instead of -179.6 it should be 179.6 which causes a whole ~360 degree rotation when translating between say frame 5-10 since I drop certain frames.

My compression code:

[source lang="cpp"] if(q.w < 0) q.Flip(); // positive so i don't have to store sign double scale = sqrt( q.v.x * q.v.x + q.v.y * q.v.y + q.v.z * q.v.z + q.w * q.w); scale = (32767.0 / scale ) + 0.5; floor(q.v.x * scale); floor(q.v.y * scale); floor(q.v.z * scale);[/source]

Which gives me 3 signed __int16 values.

My Decompression code:
[source lang="cpp"] static double scale = 32767.0 - 0.5; q.v.x /= scale; q.v.y /= scale; q.v.z /= scale; double temp = ( (q.v.x * q.v.x) + (q.v.y * q.v.y) + (q.v.z * q.v.z) ); if(temp > 1) { // wtf } q.w = sqrt(1 - temp);[/source]

Also I sometimes get values of 'temp' that are > 1 which makes no sense (to me).

So if anyone can spot the error that would be great, I'm still learning

Results of my searching around before making a topic:

I came across a post on here that seamed relevant but I'm unsure as to what extra checks are required.
(Snip of post)

There are a couple of issues with this. First you need an additional sign bit to distinguish between w being posive and negative, both of which are possible. You can avoid this though by checking the sign of w before compressing and if it's negative multiply the whole quaternion by -1, so w is always positive and you take the positive square root when decompressing. But this can cause problems for some data - e.g. by introducing jumps into a sequence of keyframes of an animation, requiring extra checks when interpolating them.

Original Topic: http://www.gamedev.n...ed-quaternions/

I've also read: Game Programming Gems 3: Section 2.4 on quaternion compression be to no avial.

### #2Álvaro  Members

Posted 04 July 2012 - 09:05 PM

You seem to be partially aware of the fact that q and -q both represent the same rotation. When you try to interpolate between two rotations, make sure the dot product of the two is positive, and flip one of them if it isn't.

Also, this seems wrong to me:
scale = (32767.0 / scale ) + 0.5;

floor(q.v.x * scale);
//...

You probably meant this:
scale = 32767.0 / scale;

floor(q.v.x * scale + 0.5); // Add 0.5 so effectively we round, instead of flooring (can be implemented as a round' function)
//...

### #3IggyPop  Members

Posted 04 July 2012 - 11:38 PM

You seem to be partially aware of the fact that q and -q both represent the same rotation. When you try to interpolate between two rotations, make sure the dot product of the two is positive, and flip one of them if it isn't.

Yer I'm aware that both (-x, -y, -z, -w) and (x, y, z ,w) are the same angle.

And I flip it so I can take the postive square root.

When you try to interpolate between two rotations, make sure the dot product of the two is positive, and flip one of them if it isn't.

My code works fine in terms of correct angle just when translating between 2 animation key frames it gets messed up.

Also, this seems wrong to me:

scale = (32767.0 / scale ) + 0.5;

floor(q.v.x * scale);
//...

You probably meant this:
scale = 32767.0 / scale;

floor(q.v.x * scale + 0.5); // Add 0.5 so effectively we round, instead of flooring (can be implemented as a round' function)
//...

In my code I have the later I just made fails when removing my rnd() macro when posting topic, it makes no sense why i added 0.5 on the end of scale reading it myself lol.

### #4Álvaro  Members

Posted 05 July 2012 - 05:42 AM

When you try to interpolate between two rotations, make sure the dot product of the two is positive, and flip one of them if it isn't.

Neither.

My code works fine in terms of correct angle just when translating between 2 animation key frames it gets messed up.

This is what I am talking about. I don't know what "translating between 2 animation key frames" means, but one typically needs to fill in the frames between key frames, and does so by interpolating the data. When you interpolate between two rotations that are represented as quaternions, you need to do what I said: Check that the dot product of the two quaternions is positive, and flip one of them if it isn't.

In my code I have the later I just made fails when removing my rnd() macro when posting topic, it makes no sense why i added 0.5 on the end of scale reading it myself lol.

It's kind of annoying when people post edited code instead of what they are actually using, because very frequently they introduce new mistakes. I understand the need to simplify the code to show the problem more clearly, but you need to make sure the code you are posting still behaves the way you describe, so compile it and test it.

Particularly if you need help figuring out something like why sometimes the length is more than 1, post real code.

### #5IggyPop  Members

Posted 05 July 2012 - 09:20 AM

This is what I am talking about. I don't know what "translating between 2 animation key frames" means, but one typically needs to fill in the frames between key frames, and does so by interpolating the data. When you interpolate between two rotations that are represented as quaternions, you need to do what I said: Check that the dot product of the two quaternions is positive, and flip one of them if it isn't.

A thanks that might be the tip I needed.

I'll be more clear about what I'm doing interms of "translating between 2 animation key frames"

I'm reading the compressed quaternion and then converting it to Euler so that I can set a bones rotation via MEL in Maya.

For example sake I have rotation data for frames 1, 5, 10

Frame 1: -90, 0 , 179.2
Frame 5: -85, 2, - 179.8
Frame 10: -88, 3, 178.4

When the animation is played the bone rotates allmost 360 between the two keyframes when there should only be 2-3 degrees of rotation.

It's kind of annoying when people post edited code instead of what they are actually using, because very frequently they introduce new mistakes. I understand the need to simplify the code to show the problem more clearly, but you need to make sure the code you are posting still behaves the way you describe, so compile it and test it.

Particularly if you need help figuring out something like why sometimes the length is more than 1, post real code.

no problem I won't post edited code again, also was not a good idear to edit it after been awake for 26hrs lmao.

### #6Álvaro  Members

Posted 05 July 2012 - 10:06 AM

I'll be more clear about what I'm doing interms of "translating between 2 animation key frames"

I'm reading the compressed quaternion and then converting it to Euler so that I can set a bones rotation via MEL in Maya.

[...]

When the animation is played the bone rotates allmost 360 between the two keyframes when there should only be 2-3 degrees of rotation.

Well, Euler angles are a notoriously bad representation to interpolate, so you shouldn't do that regardless. Interpolate the quaternions (look up slerp and nlerp), then convert to Euler angles if you really have to because of the particularities of some API.

### #7IggyPop  Members

Posted 06 July 2012 - 08:59 AM

I'll be more clear about what I'm doing interms of "translating between 2 animation key frames"

I'm reading the compressed quaternion and then converting it to Euler so that I can set a bones rotation via MEL in Maya.

[...]

When the animation is played the bone rotates allmost 360 between the two keyframes when there should only be 2-3 degrees of rotation.

Well, Euler angles are a notoriously bad representation to interpolate, so you shouldn't do that regardless. Interpolate the quaternions (look up slerp and nlerp), then convert to Euler angles if you really have to because of the particularities of some API.

Would that not require the quaternions to be correct ?

Since if I slerp it's just going to give me values between frame 1 - 5 which is not what I need but frames 5 angles to be correct.

### #8Álvaro  Members

Posted 06 July 2012 - 11:24 AM

I don't think you understand what the problem is. Or perhaps I don't. It's not that the angles at frame 5 are incorrect, but it's that interpolating angles doesn't do what you want. So interpolate quaternions instead, which behaves much much better.

### #9IggyPop  Members

Posted 07 July 2012 - 04:00 AM

I don't think you understand what the problem is. Or perhaps I don't. It's not that the angles at frame 5 are incorrect, but it's that interpolating angles doesn't do what you want. So interpolate quaternions instead, which behaves much much better.

Ok I explain again just to make sure, thanks for you help so far.

Some frames have angles that are negative for example -179.9 when THEY should be 179.9 in order for the animation to be correct.

So when I key frame 1 as 179.9 and frame 5 as -179.9(the incorrect angle) maya translates between frames rotating 360 degrees (to get from -179 to 179) instead of there been very little rotation if the correct angles are used.

-179.9 is the same as 180.1 which would only cause 0.2 degress of rotation between frames like it should be.
Is there a reason the anlge is negative when it shouldn't be, maybe it's todo with been so close to 180.

Edited by IggyPop, 07 July 2012 - 04:11 AM.

### #10Álvaro  Members

Posted 07 July 2012 - 07:04 AM

-179.9 and 180.1 are the same angle. So the angle isn't "incorrect" in any meaningful way. If the point is that it should be 179.9 and not 180.1, you need to make your code more robust.

Again, if you use quaternions during the interpolation, many problems will go away.

Edited by alvaro, 07 July 2012 - 07:06 AM.

### #11IggyPop  Members

Posted 07 July 2012 - 08:06 AM

-179.9 and 180.1 are the same angle. So the angle isn't "incorrect" in any meaningful way. If the point is that it should be 179.9 and not 180.1, you need to make your code more robust.

Again, if you use quaternions during the interpolation, many problems will go away.

yes they are the same angle but Maya requires Euler angles. so the problem arises when maya translates between them.

The top is what I want but the bottom is what happens: (since it dose a whole 360 spin to get from negative 180 to postivie 180)

### #12Álvaro  Members

Posted 07 July 2012 - 08:31 AM

Can you tell Maya what the angles are at every frame, instead of letting it interpolate?

### #13IggyPop  Members

Posted 09 July 2012 - 01:23 AM

Can you tell Maya what the angles are at every frame, instead of letting it interpolate?

Yes I can Id need to generate the values myself tho.

I've been looking into the curve editor in Maya and wrote the basias of a c++ plugin for maya gonna have a play with that see what happens.

### #14IggyPop  Members

Posted 10 July 2012 - 12:27 PM

Ok After more and more time spent on google, I finaly stumble apon this:

This now makes animation curves take the shortest route to the next angle, fixing the 359 degress of rotation, instead of the 1 degree intended.

Thanks for all your input alvaro

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.