Sign in to follow this  
Raeldor

Does a Quaternion Care about Left or Right Handedness?

Recommended Posts

jyk    2094
Quote:
Or is it the same irrespective of the co-ordinate system?
Hey again,

It's the same, just like with matrices. But again, the direction of positive rotation changes with handedness.

Think of it this way. Let's say I present you with the matrix:
[1 0 0]
[0 1 0]
[0 0 1]
What is the handedness of this system? (And by this I mean 'spatial' handedness, such as differs between OpenGL and D3D.)

The answer is, you don't know - it's just a bunch of numbers. Now let's say you apply some rotations to it. No information is added that 'gives away' the handedness. No matter what you do to it, it's still just numbers. Same with a quaternion.

The system only takes on handedness when you visualize it. That is, given the matrix above, you hold out your left or right hand and extend your thumb, first finger, and second finger along the x, y, and z axes respectively. If you compare your two hands, you can now see a difference. The numbers have taken on a particular spatial meaning.

Here are some things that change with handedness:

1. Positive rotation is in the direction that the fingers curl around the thumb if the thumb is the rotation axis.

2. Specifically, positive rotation is CW in a LH system and CCW in a RH system.

3. aXb points in the direction of the thumb if bending your fingers follows the shortest arc from a to b.

4. Number 3 leads to polygons typically being wound CW in LH and CCW in RH.

5. +z is into the screen in LH and out of the screen in RH, leading to different projection and view matrices.

6. And maybe some other things I haven't thought of.

'Hope that helps clear things up.

Share this post


Link to post
Share on other sites
Raeldor    254
Thanks, jyk. It's slowly beginning to make a bit more sense. I think my main problem is that I have a quaternion which I convert into a matrix, but if I take the seperate XYZ values and build a matrix by multiplying individual rotation matrices based on the same values the matrix is different. My test code is...

Quaternion test;
if (fread(&test, sizeof(Quaternion), 1, in_file) != 1)
return FALSE;
float test2=NWEulerXFromQuat(test);
float test3=NWEulerYFromQuat(test);
float test4=NWEulerZFromQuat(test);
NWMatrix mat=test.ToMatrix();
NWMatrix mat2=NWMatrixMultiply(NWMatrixRotateX(test2),NWMatrixRotateY(test3));
mat2=NWMatrixMultiply(mat2,NWMatrixRotateZ(test4));



The values for test2, test3 and test4 are correct and match what is the rotation angles in Max, but when I try and build a matrix using the quaternion, it is different from a matrix built from the individual parts. To add to the problem, neither are the same as the matrix in Max.

My code for these routines is as follows

Matrix functions...

// build matrix to rotate around y
__forceinline NWMatrix NWMatrixRotateY(float in_angle)
{
NWMatrix newMatrix;
newMatrix._11=cos(in_angle);
newMatrix._13=-sin(in_angle);
newMatrix._22=1.0f;
newMatrix._31=sin(in_angle);
newMatrix._33=cos(in_angle);
newMatrix._44=1.0f;
return newMatrix;
}

// build matrix to rotate around x
__forceinline NWMatrix NWMatrixRotateX(float in_angle)
{
NWMatrix newMatrix;
newMatrix._11=1.0f;
newMatrix._22=cos(in_angle);
newMatrix._23=sin(in_angle);
newMatrix._32=-sin(in_angle);
newMatrix._33=cos(in_angle);
newMatrix._44=1.0f;
return newMatrix;
}

// build matrix to rotate around z
__forceinline NWMatrix NWMatrixRotateZ(float in_angle)
{
NWMatrix newMatrix;
newMatrix._11=cos(in_angle);
newMatrix._12=sin(in_angle);
newMatrix._21=-sin(in_angle);
newMatrix._22=cos(in_angle);
newMatrix._33=1.0f;
newMatrix._44=1.0f;
return newMatrix;
}



Quaternion functions...

__forceinline NWMatrix ToMatrix()
{
NWMatrix mat;
mat._11=1.0f-2.0f*(v.y*v.y)-2.0f*(v.z*v.z);
mat._12=2.0f*v.x*v.y+2.0f*w*v.z;
mat._13=2.0f*v.x*v.z-2.0f*w*v.y;
mat._14=0.0f;
mat._21=2.0f*v.x*v.y-2.0f*w*v.z;
mat._22=1.0f-2.0f*(v.x*v.x)-2.0f*(v.z*v.z);
mat._23=2.0f*v.y*v.z+2.0f*w*v.x;
mat._24=0.0f;
mat._31=2.0f*v.x*v.z+2.0f*w*v.y;
mat._32=2.0f*v.y*v.z-2.0f*w*v.x;
mat._33=1.0f-2.0f*(v.x*v.x)-2.0f*(v.y*v.y);
mat._34=0.0f;
mat._41=0.0f;
mat._42=0.0f;
mat._43=0.0f;
mat._44=1.0f;
return mat;
}
__forceinline float NWEulerXFromQuat(Quaternion in_quat)
{
float p,h,b;
float sp=-2.0f*(in_quat.v.y*in_quat.v.z+in_quat.w*in_quat.v.x);

// compute angles
p=asin(sp);
h=atan2(in_quat.v.x*in_quat.v.z-in_quat.w*in_quat.v.y, 0.5f-in_quat.v.x*in_quat.v.x-in_quat.v.y*in_quat.v.y);
b=atan2(in_quat.v.x*in_quat.v.y-in_quat.w*in_quat.v.z, 0.5f-in_quat.v.x*in_quat.v.x-in_quat.v.z*in_quat.v.z);

// return heading
return h;
}
__forceinline float NWEulerYFromQuat(Quaternion in_quat)
{
float p,h,b;
float sp=-2.0f*(in_quat.v.y*in_quat.v.z+in_quat.w*in_quat.v.x);

// compute angles
p=asin(sp);
h=atan2(in_quat.v.x*in_quat.v.z-in_quat.w*in_quat.v.y, 0.5f-in_quat.v.x*in_quat.v.x-in_quat.v.y*in_quat.v.y);
b=atan2(in_quat.v.x*in_quat.v.y-in_quat.w*in_quat.v.z, 0.5f-in_quat.v.x*in_quat.v.x-in_quat.v.z*in_quat.v.z);

// return pitch
return p;
}
__forceinline float NWEulerZFromQuat(Quaternion in_quat)
{
float p,h,b;
float sp=-2.0f*(in_quat.v.y*in_quat.v.z+in_quat.w*in_quat.v.x);

// compute angles
p=asin(sp);
h=atan2(in_quat.v.x*in_quat.v.z-in_quat.w*in_quat.v.y, 0.5f-in_quat.v.x*in_quat.v.x-in_quat.v.y*in_quat.v.y);
b=atan2(in_quat.v.x*in_quat.v.y-in_quat.w*in_quat.v.z, 0.5f-in_quat.v.x*in_quat.v.x-in_quat.v.z*in_quat.v.z);

// return bank
return b;
}



They look ok to me, and I am pretty sure my matrix functions are good as they are used elsewhere. Maybe the problem lies in my quaternion functions?

Share this post


Link to post
Share on other sites
jyk    2094
Hm, I don't know. Your matrix rotation and quat->matrix functions look correct for row vectors. I'd have to examine the quat->Euler functions more carefully, but you say they're returning the results you expect. The fact that you have three different results - the Max matrix, your quat matrix, and your Euler matrix - that should be the same gives you several ways to debug. For example, you could start by trying to figure out why your quat matrix doesn't match the Max matrix. Are they transposes of each other? Maybe Max is using column vectors. Or perhaps it's an issue of matrix majorness. If they're not transposes of each other, then something else must be wrong.

As for the Euler angles, maybe Max is composing them in a different order than you are.

Sorry I can't give you more specific answers...

Share this post


Link to post
Share on other sites
Raeldor    254
Quote:
Original post by jyk
Hm, I don't know. Your matrix rotation and quat->matrix functions look correct for row vectors. I'd have to examine the quat->Euler functions more carefully, but you say they're returning the results you expect. The fact that you have three different results - the Max matrix, your quat matrix, and your Euler matrix - that should be the same gives you several ways to debug. For example, you could start by trying to figure out why your quat matrix doesn't match the Max matrix. Are they transposes of each other? Maybe Max is using column vectors. Or perhaps it's an issue of matrix majorness. If they're not transposes of each other, then something else must be wrong.

As for the Euler angles, maybe Max is composing them in a different order than you are.

Sorry I can't give you more specific answers...


Ok, I think this is working now or at least the matrices are the same ignoring some small floating point rounding issues.

I still seem to be having a problem with my rotations though. If my max scene is in a right handed system, then how do I convert my rotations to be usable in DirectX? Do I need to negate all of the euler angles because the rotation is reversed? Will the fact that the axis in max has y into the screen and z up, as opposed to D3D having z into the screen and y up also screw up my rotations?

Thanks


Share this post


Link to post
Share on other sites
timw    598
Quote:

still seem to be having a problem with my rotations though. If my max scene is in a right handed system, then how do I convert my rotations to be usable in DirectX? Do I need to negate all of the euler angles because the rotation is reversed? Will the fact that the axis in max has y into the screen and z up, as opposed to D3D having z into the screen and y up also screw up my rotations?


you just need one matrix to do it all, whatever matrix you're using to convert your point set, use it to convert your matrix's as well

M = matrix in RHS
L = matrix Max->D3D

New matrix = L*M order is important obviously.
new points = L*p for each vertex
new normals = L*n for each normals

//edit, I'm assuming column major format here, if it's row major
reverse all the respective orderings


Tim

Share this post


Link to post
Share on other sites
timw    598
you know I dont have much experience with maya, but it seems to me like something like that would have some options regarding the output no? like what type of coordinate systems the points/matrix are in?

Tim

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this