Converting a 3DMax matrix to a OpenGL matrix

Started by
12 comments, last by timw 18 years ago
After many weeks of banging my head on the wall, im still trying to get skeletal animation working with my new Collada converter. Ironically i have in the past gotten skeletal animation to work twice in the past with my own exporters. Much of this has to do with the way Collada represents data differently and also overcomplicates retrieval of simple data, e.g for vertices get it from reference pos, for pos get it from reference whatever, for normals get it from another reference, stores geometry in object space,etc.. Anyway i think i have overcome most of these differences and exporting of static meshes has been working well for the past month. Part of my current woes stem from the fact that the mesh/skin is exported in object space, meaning it is centered at the origin without any transformations. The bones are exported with their world transformations, so i need to transform my skin/mesh to their correct transformation at the time it was bound to the bones. The data is represented in the form of a matrix under a tag called, <bind_shape_matrix>. Unfortunately the matrix is in native Max form and obviously cannot be used in my code where the coordinate system is similar to OpenGL. I tried looking around the net for any help, but have not been able to find anything which works. The closest was this

//============================================================================
// FixCoordSys(Matrix3 &tm) - Similarity Transformation
// similarity transformation consists of swapping the 2nd and 3rd rows, then
// swapping the the 2nd and 3rd columns as above, and THEN negating all
// the elements of the 1st row, then negating all the elements of the 1st
// column (with the result that the 11 element is unchanged).
// ----------------------------------------------------------------------------
//void FixCoordSys(Matrix3 &tm)
//{
//	// swap 2nd and 3rd rows
//	Point3 row = tm.GetRow(1);
//	tm.SetRow(1, tm.GetRow(2));
//	tm.SetRow(2, row);
//
//	// swap 2nd and 3rd columns
//	Point4 column = tm.GetColumn(1);
//	tm.SetColumn(1, tm.GetColumn(2));
//	tm.SetColumn(2, column);
//
//	// negate 1rst row and column
//	tm.SetRow(0, -(tm.GetRow(0)));
//	tm.SetColumn(0, -(tm.GetColumn(0)));
//}


But the rotations are a little screwed up in the x-axis and the x/z translations need to be negated. Does anyone know of a way to convert max matrices into OpenGL matrices?
Advertisement
hint: rotations in max are backwards... meaning max is right handed, but the rotations are left handed, so you need to convert from left to right, and some people will tell you that all you got to is swap rows or some crap like that. these people obviously have never written a max exporter.

look closely at this code... this is from the max exporter for an older version of my engine (when i was still storing node rotations as a quat). Note that i'm inverting the quaternion... that's the key there. The quaternion is backwards! WTF you ask? As it turns out all quaternions are left handed.

Matrix3 matrix = node->GetNodeTM( time ) * Inverse( node->GetParentTM( time ) );AffineParts parts;decomp_affine( matrix, &parts );screamNode->SetTranslate( zeus::Vector3f(	parts.t.x,	parts.t.y,	parts.t.z ) );parts.q = parts.q.Inverse();zeus::Quaternionf rot( parts.q.w, parts.q.x, parts.q.y, parts.q.z );rot = rot * parts.f * zeus::Quaternionf( 1, 0, 0, 0);screamNode->SetRotate( rot );

this question has been answerd many times here lol. here is a link to a pervious post where I go over how to do it. and what to think about when you're doing ANY change of basis.

http://www.gamedev.net/community/forums/topic.asp?topic_id=361664&whichpage=1
Quote:Original post by Anonymous Poster
As it turns out all quaternions are left handed.
Can you clarify what you mean by 'all quaternions are left handed'? Just curious.
Probably that positive rotation is defined as CW rotation when looking along the normal down to the plane of rotation, from the positive half-space of the plane.
CW comes from the direction your fingers would curl when aligning your left thumb with the normal.
Quote:Original post by someusername
Probably that positive rotation is defined as CW rotation when looking along the normal down to the plane of rotation, from the positive half-space of the plane.
CW comes from the direction your fingers would curl when aligning your left thumb with the normal.
To clarify, I wasn't asking what 'left handed' means, but rather what the AP meant by the statement 'all quaternions are left handed'.
Quote:Original post by jyk
Quote:Original post by someusername
Probably that positive rotation is defined as CW rotation when looking along the normal down to the plane of rotation, from the positive half-space of the plane.
CW comes from the direction your fingers would curl when aligning your left thumb with the normal.
To clarify, I wasn't asking what 'left handed' means, but rather what the AP meant by the statement 'all quaternions are left handed'.


Oh ok, my bad. It wasn't clear.

Quote:
Original post by Anonymous Poster
hint: rotations in max are backwards... meaning max is right handed, but the rotations are left handed, so you need to convert from left to right, and some people will tell you that all you got to is swap rows or some crap like that. these people obviously have never written a max exporter.

What are you talking about? What does a co-ordinates' system's handedness have to do with using the transpose matrix to get a product right? Obviously, it's you who has never worked with more than one 3D API, because then you would probably know that some of them transform vectors as row-vectors (DX for instance) instead of column vectors (like openGL).
And -clearly- the way the vectors (x,y,z) and (x,y,z)T transform, has nothing to do with whether e.g. Z points to the positive or the negative half-space of XY. (I'm not sure whether half-space is the correct term, so please correct me if I'm wrong)
If you switched from right handed to left handed, you'd have to scale z by -1 and change the order of the vertices to an odd permutation of the original sequence. What does this have to do with whether you represent vectors as rows or columns?

To keep compatibility, one has to transpose all products when switching from one convention to another, as is obvious from the identity:
(M1*M1*...*Mn)T == MnT*Mn-1T*...*M1T

Personally I myself, as well as others in this forum, have suggested this quite a few times, so before you rush to deem anyone's suggestion "crap", next time I would advise you to be certain that you know what you're talking about.

If I'm mistaken somewhere, I'd be glad if you could point it out to me.
I think he's using the term right/left incorrectly. I have one x,y axis and another coord system with -x,y axis, the rotations will always be in reverse of the other. It certinaly doesn't mean that in one quats follow right hand rule and in another they follow left. I think that's what hes' getting at. quaternions follow the right hand rule to the tea, so I think he's talking about that. the right hand rule is the right had rule, regardless of the basis.
Quote:Original post by timw
this question has been answerd many times here lol. here is a link to a pervious post where I go over how to do it. and what to think about when you're doing ANY change of basis.

http://www.gamedev.net/community/forums/topic.asp?topic_id=361664&whichpage=1


Just another stupid question, im representing matrices as a float[16] array.

Your array is

M_Max_To_OGL =
[-1 0 0 ]
[ 0 0 -1]
[ 0 1 0 ]

if i make it into a 4x4 array it would become

-1 0 0 0
0 0 -1 0
0 1 0 0
0 0 0 1


While ive heard that if using float[16] it doesnt matter if the data is row-major or column major, it seems to make a difference for this case.

How would i define my MaxToGL matrix in this case?

float MaxToGL[16];
MaxToGL[0] = -1.0f;//this is pretty obvious
MaxToGL[6] = 1.0f;// or is it MaxToGL[9]
MaxToGL[9] = -1.0f// or is it MaxToGL[6]??
ya I think I constructed that matrix using row vectors, I think open gl is column vectors, so youd transpose it. just note the general logic I used to construct the array and make sure your thought is following the same lines. I would have to say take the matrix I gave and transpose it, that should work. also I dont know if max uses row or column vectors. if it uses row vectors, then youd have to transpose the matrix, to convert it into column vectors, then apply the transform to the matrix. ya I think I was in err, I'm reasonably sure ogl uses column vectors in which case that matrix should be transposed. does max use row/column vectors?



MaxToGL = transpose(MaxToGL); //first fix my error cuz ogl uses column vectors

say max uses column vectors then you do this
NewTransform = M*MaxToGL

if max uses row you do this
NewTransform = transpose(M)*MaxToGL

so the transpose of that MaxToGL would be
-1 0 0 0
0 0 1 0
0 -1 0 0
0 0 0 1

Quote:
While ive heard that if using float[16] it doesnt matter if the data is row-major or column major

it sure does matter. the only case where it wouldn't matter is where
M = transpose(M)

[Edited by - timw on March 22, 2006 12:54:39 AM]

This topic is closed to new replies.

Advertisement