Does a Quaternion Care about Left or Right Handedness?

Started by
5 comments, last by timw 18 years, 6 months ago
Or is it the same irrespective of the co-ordinate system? Thanks
Advertisement
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.
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?
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...
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


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
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

This topic is closed to new replies.

Advertisement