Quaternion Confusion

Started by
8 comments, last by AverageJoeSSU 13 years, 7 months ago
I have tried to implement quaternions and it seems there are a few holes in my implementation. I'm using them to represent the orientation of my core _3D objects.(ie camera, cube, etc;) so far all we manage to generate from our vectors in the lookat function is an identity quaternion.

1) If the identity quaternion is ( (0,0,0) 1 ) what does this mean? if it counts for a rotation around an axis wouldnt it be something like ( (0,1,0) 0) which to me means 0 rotation along the y axis?

2) How to construct the orient quaternion. my code uses matrices and the Look at function build the quaternion like so.

void _3DObject::SetLookTarget(glVector3& look, glVector3& up, float time)    {	look.Normalize();    glVector3 right = look.Cross(up);    glMatrix4x4 mat = glMatrix4x4(        //right.x, up.x, look.x, 0,        //right.y, up.y, look.y, 0,        //right.z, up.z, look.z, 0,        right.x, right.y, right.z, 0,        up.x, up.y, up.z, 0,        look.x, look.y, look.z, 0,        0, 0, 0, 1);	this->anim.orient = mat.GetQuat();}Get Quat -------- //Calculate the trace of the matrix T from the equation:    float t = 1 + this->m[0] + this->m[5] + this->m[10];      //          2     2     2      //T = 4 - 4x  - 4y  - 4z      //           2    2    2      //  = 4( 1 -x  - y  - z )      //  = 1 + mat[0] + mat[5] + mat[10]    //If the trace of the matrix is greater than zero, then    //perform an "instant" calculation.    //Important note wrt. rouning errors:    //Test if ( T > 0.00000001 ) to avoid large distortions!    //  S = sqrt(T) * 2;    //  X = ( mat[9] - mat[6] ) / S;    //  Y = ( mat[2] - mat[8] ) / S;    //  Z = ( mat[4] - mat[1] ) / S;    //  W = 0.25 * S;    if  (t > 0.00000001)        {        float s = sqrt(t) * 2;        return glQuaternion(            (this->m[9] - this->m[6]) / s,            (this->m[2] - this->m[8]) / s,            (this->m[4] - this->m[1]) / s,            0.25 * s);        }    //If the trace of the matrix is equal to zero then identify    //which major diagonal element has the greatest value.    //Depending on this, calculate the following:    if ( (this->m[0] > this->m[5]) && (this->m[0] > this->m[10]) )  {	// Column 0:         float s = sqrt( 1.0 + this->m[0] - this->m[5] - this->m[10] ) * 2;        return glQuaternion(            0.25 * s,            (this->m[4] + this->m[1] ) / s,            (this->m[2] + this->m[8] ) / s,            (this->m[9] - this->m[6] ) / s);    } else if ( this->m[5] > this->m[10] ) {			// Column 1:         float s = sqrt( 1.0 + this->m[5] - this->m[0] - this->m[10] ) * 2;        return glQuaternion(            (this->m[4] + this->m[1] ) / s,            0.25 * s,            (this->m[9] + this->m[6] ) / s,            (this->m[2] - this->m[8] ) / s);    } else {						// Column 2:        float s = sqrt( 1.0 + this->m[10] - this->m[0] - this->m[5] ) * 2;        return glQuaternion(            (this->m[2] + this->m[8] ) / s,            (this->m[9] + this->m[6] ) / s,            0.25 * s,            (this->m[4] - this->m[1] ) / s);    }     //The quaternion is then defined as:     //  Q = | X Y Z W |



One of the above functions was grabbed from a previous gamedev post but the equation is not well explained.

------------------------------

redwoodpixel.com

Advertisement
The quaternion for a rotation around an arbitrary axis (x, y, z) is (x sin(a/2), y sin (a/2), z sin(a / 2), cos(a / 2)). If the angle a is 0, you get (0, 0, 0, 1), not matter what axis you choose.
Quaternions are a rotation around an axis, but the rotation amount isn't straight up in degrees or radians. the rotation part is actually the cosine of the angle divide by 2.

Also, the x,y,z part isn't really just a vector, it's a vector multiplied by the sine of the angle divided by 2.

Something else, quaternions must always be normalized in the same way that a vector is so that w*w+x*x+y*y+z*z = 1. Basically to normalize it you just treat it like a 4 dimensional vector. Some people describe quaternions as 4d vectors on a 4d unit sphere.

Here's some pages you may or may not have already looked at :P
http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation
http://www.genesis3d.com/~kdtop/Quaternions-UsingToRepresentRotation.htm
Ah i see, the identity quaternion makes more sense now.

So the rotation matrix i use to generate my quaternion must be wrong or the matrix to quaternion calculations are off. (getQuat function above)

http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm

i found this which seems to explain things a little better.

------------------------------

redwoodpixel.com

Quote:Original post by Atrix256
Also, the x,y,z part isn't really just a vector, it's a vector multiplied by the sine of the angle divided by 2.


Not true. A vector multiplied by a scalar is still a vector. So yes, the XYZ part *IS* a vector.

Quote:Original post by Atrix256
Something else, quaternions must always be normalized in the same way that a vector is so that w*w+x*x+y*y+z*z = 1.


Not true. We use unit length quats because it's convenient, not because it's impossible to use quats of arbitrary length.

Quote:Original post by AverageJoeSSU
1) If the identity quaternion is ( (0,0,0) 1 ) what does this mean? if it counts for a rotation around an axis wouldnt it be something like ( (0,1,0) 0) which to me means 0 rotation along the y axis?


In matrix form....

A == A * MatrixIdentity
A == MatrixIdentity * A
MatrixIdentity = A * -A
MatrixIdentity = -A * A

Matrices are identical to quats in their usage and meaning..... thus:

A == A * QuatIdentity
A == QuatIdentity * A
QuatIdentity = A * -A
QuatIdentity = -A * A

The identity quaternion is a special case value in exactly the same way as the identity matrix is.

In axis angle form the identity quat would be Axis(0,0,0), Angle(0). The axis is 0,0,0 since the cross product of one vector with itself (i.e. a zero degree rotation difference) is always 0,0,0.

Quote:Original post by AverageJoeSSU
2) How to construct the orient quaternion. my code uses matrices and the Look at function build the quaternion like so.


What's wrong with using a matrix here? Converting from matrix to quat, to then immediately convert back to a matrix for rendering is a bit redundant. Unless you want to smoothly transition between two orientations, you probably want to use matrices (not entirely true: a pos quat has a smaller memory footprint, and can be more efficient to multiply than a matrix. But that's about it unless as already mentioned, you need slerps/lerps)
Quote:Original post by RobTheBloke

Quote:Original post by AverageJoeSSU
2) How to construct the orient quaternion. my code uses matrices and the Look at function build the quaternion like so.


What's wrong with using a matrix here? Converting from matrix to quat, to then immediately convert back to a matrix for rendering is a bit redundant. Unless you want to smoothly transition between two orientations, you probably want to use matrices (not entirely true: a pos quat has a smaller memory footprint, and can be more efficient to multiply than a matrix. But that's about it unless as already mentioned, you need slerps/lerps)


well you're right... i am feeding this into an animator that slerps the two.

my example may look a bit un optimized, but that is because we are trying to get it to work, and converting a look at target to a quaternion only happens once, when you tell the object you want it to look at something.

once the animator receives the target orientation it slerps to it until done.

------------------------------

redwoodpixel.com

i have gone through some test cases and the matrix to quaternion code is actually working fine.

I have a look at target matrix of
[1 0 0 0 1 0 1 0 0 ]


the quaternion generated is xyz=0 w = 0.707 which is correct based on that site's calculator.

Normalizing this quaternion gives me the identity quaternion, which confuses me a bit, and not normalizing this quaternion causes slerp to go from xyz=0 w=4 and eventually w=-1.9. which im not sure is correct =(

when i normalize that quaternion i got the identity quaternion and thus get an identity matrix when i slerp and no rotation.

Any ideas?

------------------------------

redwoodpixel.com

Quote:Original post by AverageJoeSSU
i have gone through some test cases and the matrix to quaternion code is actually working fine.

I have a look at target matrix of
[1 0 0 0 1 0 1 0 0 ]



That matrix does not describe a rotation. It even has determinant 0! Any result you may get from trying to express this as a quaternion will be meaningless.
Interesting. Then i guess my problem boils down to constructing a quaternion based on a 3d point that i want an object to look at.

------------------------------

redwoodpixel.com

Nevermind.... i found another reference. thanks. took me long enough. There is so much stuff on quaternions its easy to get lost in it all =P

------------------------------

redwoodpixel.com

This topic is closed to new replies.

Advertisement