3D Rotations with Quaternions

I am having trouble with rotating models using quaternions/matrices.

The model has three vectors to determine which way it is facing and a quaternion to store the rotation of the model. It also has a vector to store its position.

When I rotate the model around the x axis the direction vector rotates clockwise and the quaternion rotates anti-clockwise.

If I use negative x values for the direction vector then when I rotate the model around the y axis sometimes the vector and the quaternion rotate the same way and some times opposite ways.

Can anyone give me any ideas as to why this happens?

Thanks a ton - Gareth

I don’t know anything about quaternions but then you shouldn’t need them. It sounds as though you are tracking your current orientation in space (x’, y’, z’) relative to global coordinate space (x, y, z). All you have to do is create a 4 x 4 matrix as such:

| x’(x) x’(y) x’(z) 0 |
| y’(x) y’(y) y’(z) 0 |
| z’(x) z’(y) z’(z) 0 |
| 0 0 0 1 |

then load the matrix and use glTranslate to change your location. I have used this method and it works perfectly without any Gimbel lock or any other problems. Although you may need to verify that your algorithm for tracking the local coordinate vectors works properly. I had one equation with the wrong sign causing the x and z axes to move in opposite directions when rotating about y axis causing lock to occur at 90 degrees because they ended up parallel. Took me days to finally figure it out.

Hope this helps. If you really really really want to use quaternions I am certain someone else will respond. Personally I think this works as well and probably requires less calculation. But again I know nothing of quaternions so maybe there is actually less calculation or is in some way more robust. I mean what is better than knowing that your local coordinate unit vectors (relative to the global coordinate system) can be used to directly create your rotation matrix.


[This message has been edited by shinpaughp (edited 01-27-2003).]

If you have 3 orientation vectors and a position, that is essentially the whole transformation matrix, as the last guy suggested. You dont need to use quaternions to avoid gimbal lock in this situation, but if you want quaternions, look up the formula for converting your matrix to a quaternion.

Really the only advantage to quaternions over matrices is that it takes less memory, and therefore can be sent faster over a network. If you arent doing any networking stuff you can get a slight memory optimization if use quaternions instead of matrices, but that is negated if you store both.

[This message has been edited by ioquan (edited 01-27-2003).]

Thanks for your help. I have tried using matrices but I find that when I rotate around a given axis the model will “shrink” in the other two axis.

For example if I rotate around the y axis then the model begin to appear tall and thin. It eventually becomes a line and disappears.

If that is the case you are applying the rotation incorrectly to the matrix. You can lift a load of quaternian code from my site if you like have a look at
c code -> opengl Kalman Filter
Use quaternians for trackball etc in there. But there is also the code for quat->matrix and so on

Yeah, it sounds as if your vectors are not normalized (ie length = 1.0) or your 3 base vectors(x’, y’, z’) are not properly in sync where a rotation around y’ results in both x’ and z’ rotating the same angle about y’. Like I said, I had a problem where my x and z were rotating oppositely about y. Took awhile.

But, guaranteed that this should work as long as your 3 base vectors are in sync and properly calculated. Best way is by vector addition and then normalization as long as angle of rotation for any single frame is less than 90 degrees (and probably better if less than 80 or 85 only because of floating point error) and the need to use tangent (or better than using sine or cosine in this particular case - less calculation).

Anyway, whatever you decide… good luck.

Yes, your object will begin to distort after a while using the three vector system, due to floating point precision errors.

The solution is to make the vectors orthogonal again after applying your rotations. To do this, you take the cross product of two of the vectors, which will give you the third vector. Then take the cross product of the third vector and one of the first two to get the other one. Do this every time after applying your rotations and the vectors will stay orthogonal, and your object will not get distorted.

In the same sense you will have to normalise you quaternians anyway!

Not sure what you mean by “and the quaternion rotates anti-clockwise”, a quaternion can’t really rotate… it is a rotation. Sounds like you are rotating your model a bit each frame. Try and work out it’s total rotation at each frame and rotate the same static model through different rotations each frame rather then rotating the already rotated. This is where quaternions may be handy cause you can add them.



If I have three vectors - forwards, left and normal for example and a rotation matrix which stores the current orientation of the model. I can get the three vectors from the matrix and make them orthagonal as suggested above do I need to update the rotation matrix with the orthagonal vectors? If so how do I do this?

Use glLoadMatrix so long as your 3 vectors are in matrix form.

I don’t understand what you mean by matrix form. How do I get the vectors in and out of the matrix then?

Sorry if I’m being a bit slow :wink:

| a b c d |
| e f g h |
| i j k l |
| m n o p |

Vector axis X would be (a, b, c)
Vector axis Y would be (e, f, g)
Vector axis Z would be (i, j, k)

or is it the columns? I’m never sure.

I would still use quaternions over the matrices. personnal taste.

[This message has been edited by oliii (edited 03-19-2003).]

It would be your columns since ogl uses column ordering.

I would suggest you use quaternions. They are nice, simple, and accurate, if all you are doing is axis_angle to quaternion using unit quaternions to then build the rotation matrix. Besides, you will be very happy when it comes to skinning a model.

Also, invert the signs when you are computing your quaternion.
e.g. if your roll is zero:

X = cosYawsinPitch;
Y = sinYaw
Z = -sinYawsinPitch;
W = cosYaw

Or in general:

W = cosYawcosPitchcosRoll + sinYawsinPitchsinRoll;
X = cosYawsinPitchcosRoll + sinYawcosPitchsinRoll;
Y = cosYawsinPitchsinRoll - sinYawcosPitchcosRoll;
Z = cosYawcosPitchsinRoll - sinYawsinPitchcosRoll;

I am going to put up on my site a quick quaternion demo sometime tonight or tomorrow. I will let you know.

Miguel Castillo

Originally posted by oliii:
[b]| a b c d |
| e f g h |
| i j k l |
| m n o p |

Vector axis X would be (a, b, c)
Vector axis Y would be (e, f, g)
Vector axis Z would be (i, j, k)

or is it the columns? I’m never sure.

[This message has been edited by mancha (edited 03-19-2003).]

[This message has been edited by mancha (edited 03-19-2003).]

Yes, Mancha is correct. It is columns. I guess I didn’t check my code when I wrote that stuff up top. Oh, well.

Rows… columns… what’s the difference!!!

Jezz, I dont know, I have never seen a matrix before!

Originally posted by shinpaughp:
Rows… columns… what’s the difference!!!

I’ve sussed it out now :slight_smile:

Thanks for all your help

In the end I used quaternions. I found a few +'s and -'s which were the wrong way round (_8(|) DOH