Converting a transformation matrix from Right-handed to Left-handed coord system

Started by
21 comments, last by gifaraj 18 years ago
pre-muptiplying top matrix should give you practically no extra cost whatsoever, and will work.

As for "doing it right": change of handness is like mirroring.
With hierarchies you have something like
a*b*c*d * v
where a,b,c,d is matrices and v is certex
and if all matrices mirror the space you get
a mirrors, a*b doesn't mirror, a*b*c mirror, a*b*c*d doesn't mirror.
You absolutely can not "evenly distribute" mirroring over several matrices.[lol] matrix either mirrors the space (has negative determinant) or it does not (has nonnegative determinant)

If you want to convert whole thing, that is, vertex coordinates(&normals), matrices, and everything else so that now whole thing is just like what'd happen if Maya would use same-handed coordinate system as your engine:

1:Negate all z coordinates of vertices and normals of model.(!)
2:In all matrices, negate following elements
  x  x -x  x  x  x -x  x -x -x  x -x  x  x -x  x

(maybe 3rd x on bottom row shouldn't matter as your matrices should all have zero there)

Note: I've derived that geometrically by imagining this thing (matrices is simple to visualize btw. just imagine 3 xyz vector arrows corresponding from columns. arrows should be drawn from point given by fourth point. when flipping coordinates, you need to flip z of all things, and also negate z arrow). I think it must work but haven't tried.

[Edited by - Dmytry on April 4, 2006 11:27:00 AM]
Advertisement
Quote:Original post by someusername
I hope you see what I mean. The actual problem is that there is no problem. How you will deal with it in software, I don't know. Can't you just negate the top level matrix of each frame-hierarchy upon import?


I kind of see what you mean. I don't know why this is so difficult to do, though. I mean, isn't there a transformation in LH that does the SAME transformation as in RH?

What I want then is, the transformations that Maya would give me if it used a LH system. That's all I want. Is it not possible?


Quote:Original post by someusername
In your case, implicit rotations that are hardcoded in matrices are handled through negation of Z, just like the "Flip Z of top-level". Explicit rotations, like "Quaternion(cos(π/4), sin(π/4)*{0,0,1})" need either the axis or the angle to be negated. In any case, you replace all quaternions with their conjugate.
I don't think that this application does anything more than what it says it does.


That site says exactly what I my problem is: 'This works well except for custom programs which import .X files and expect that all coordinates and matrix frames be in LHCS; for the latter case go and enable the "Flip Z of Vectors and Reverse Angle of Quaternions" option.' I need to use my animations on objects that don't know (and shouldn't need to know) about the coordinate system change.

A rotation matrix can be converted to a quaternion and back, so I tried doing exactly that:

// retrieve translation/rotation/scale from transform matrix...// make changestranslation.z *= -1.0;rotation.x *= -1.0;rotation.y *= -1.0;// set my exported matrix using this translation/rotation/scale...


But it doesn't work correctly, the geometry transforms into a weird blob.

Another thing I've considered is just using a RH system in my engine as well. Is it really as simple as changing the view matrix and the DirectX Culling order render state?

Quote:Original post by Dmytry
1:Negate all z coordinates of vertices and normals of model.(!)
2:In all matrices, negate following elements


You posted just when I was about to post this. I tried doing what you said though, and it still didn't work. Look at the screenshot: http://66.253.147.225/images/export_problem.jpg

Thanks :D
404 error on image...
sorry, fixed.
This is strange. I'm writing unit test.
Oh. I get it.

"Handedness" refers to the direction of the z-axis. I thought you where talking about left and right matrix multiplication. =)

Lets invent another operator "^z" which changes the space of a matrix and vector from one handedness to the other.

if R and V are vectors and A is a transformation:
R^z = A^zV^z
then
R = AV
where for any vector V = (V_x, V_y, V_z, V_w), then V^z = (V_x, V_y, -V_z, V_w).

Problem: Find what "^z" does to matrixes.

Does that describe the problem?
my solution surely works. I wrote little test:

#include <iostream>#include <cmath>#include <MersenneTwister.h>#include "../math3/math3.h"using namespace math3;using namespace std;// random number sourceMTRand r;// compute random rotation and translation matrixMatrix4x4f RandomMatrix(){    Quaternionf q;// make random quaternion, normalize it, and convert to matrix    q.a=r()-0.5;    q.b=r()-0.5;    q.c=r()-0.5;    q.d=r()-0.5;    Normalize(q);// append random translation    Matrix4x4f a(QuaternionToMatrix(q));    a.At(0,3)=r()*10.0-5.0;    a.At(1,3)=r()*10.0-5.0;    a.At(2,3)=r()*10.0-5.0;    return a;}// compute random vectorVec3f RandomVector(){    Vec3f result;    result.x=r()*10.0-5.0;    result.y=r()*10.0-5.0;    result.z=r()*10.0-5.0;    return result;}// Mirror hand of matrixvoid MirrorHand(Matrix4x4f &a){    a.At(2,0)=-a.At(2,0);    a.At(2,1)=-a.At(2,1);    a.At(2,3)=-a.At(2,3);    a.At(0,2)=-a.At(0,2);    a.At(1,2)=-a.At(1,2);    a.At(3,2)=-a.At(3,2);}// mirror hand of vectorvoid MirrorHand(Vec3f &v){    v.z=-v.z;};using namespace std;int main(){    Matrix4x4f    a=RandomMatrix(),    b=RandomMatrix(),    c=RandomMatrix(),    d=RandomMatrix();    Vec3f vertex=RandomVector();    cout<<Mulw1(a*b*c*d,vertex)<<endl;// mirror hands of all matrices and vertices    MirrorHand(a);    MirrorHand(b);    MirrorHand(c);    MirrorHand(d);    MirrorHand(vertex);// should have z negated    cout<<Mulw1(a*b*c*d,vertex)<<endl;	//std::cout << "Hello world!" << std::endl;	return 0;}


output:
vector:[3.15286,	7.46052,	-6.50599]vector:[3.15286,	7.46052,	6.50599]


notes: Mulw1 (Matrix4x4 m,Vector3 m)
multiplies 4x4 matrix with vector {v.x,v.y,v.z,1}

if you want i can provide dependencies for compilation
edit: by the way, to convert quaternion, negate i and j components (or real and k, doesn't matter).

[Edited by - Dmytry on April 4, 2006 12:10:24 PM]
NotAYakk: this ^z is my MirrorHand operator (i replied before seeing your message) :-)
My test prints
A*V
and
A^z * V^z
so you can see whever (A*V)^z = A^z * V^z or not.
whoops, missed that
Quote:Original post by someusername
Try negating all the members of the matrix that are either in the third row *or* third column of the matrix. Thus negate the members at positions (3,1), (3,2), (3,3), (3,4), (1,3), (2,3), (4,3)

Almost right, except it's XOR and there shouldn't be (3,3) :)
Quote:

If it doesn't seem to work, can you tell us exactly how the axes are setup in both systems? E.g. the right-handed is: X->right, Y->into the screen, Z->up

Have you tried multiplying the animation matrix with
[ 1  0  0  0 ][ 0  1  0  0 ][ 0  0 -1  0 ][ 0  0  0  1 ]
from both sides?

And this is right, should work too, but only if vertex's z coordinate is also flipped (i.e. if not only all matrices is converted to other handness this way but also all vectors too). It is better idea to just flip signs as described above, it is equivalent but faster. Left multiplication flips signs of third row, and right of third column (so intersection is flipped twice and thus has sign unchanged).

Actually, i was bit uneasy about being unable make simple proof that my method works, but your second thing lets do it elegantly:
we have
M*a*M * M*b*M * M*c*M ... * M*v
(last term is negation of Z in v)
and M*M = identity so it is equal to
M*a*b*c ...*v
and that is exactly what we want. So correctness is proved.
(sorry, Nth post in the row)
as for what OP want, i have no idea, but there's only two conversions that make sense:
a: convert everything (transformation matrices and vectors e.g. vertices, normals, etc) from one handness to other handness so after conversion everything will be just like what'd be if Maya had same handness as you use.(note: you may need to flip vertex winding order too.)
b: put some root transform that flips z when working with things from maya (not really a conversion)
As i understand b is undesired(also it clutters things up), so the only sensible alternative is a. Which is what my example code are doing using MirrorHand() on matrices and vectors, you can try doing that with some custom converter.

This topic is closed to new replies.

Advertisement