🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

[Solved] Conversion between righthanded and lefthanded coordinate systems

Started by
9 comments, last by Schrompf 15 years, 3 months ago
Hi there, I'm in the process of rewriting parts of a generic 3d scene loader library. This library offers conversion from (default) righthanded OpenGL like coordinate system to a lefthanded coordinate system like the one Direct3D uses. Up to now I did this by simply mirroring the Z axis of the root node's transformation and inverting all face's orientation. Which was fine, at least in terms of visible result. But the resulting transformation matrix does now contain a inversion at one axis, which means it's not decomposable into quaternions or euler angles anymore. Therefore I'm in search for a different approach to the handiness conversion. Here's what I tried before: a) Dragging the axis inversion into the meshes and subnode's transformations: for every node I only reflected their global position at the global Z axis and mirrored all meshes of this node at the global Z axis. It worked, but required me to duplicate multiple instances of a mesh when the mesh appeared at different nodes. And the process is wholly unapplicable to animations: the transformation chains of animated nodes don't add up to a comparable scene animation. b) Decomposing each node's global transformation into its base vectors, mirroring each of those at the global Z axis, and finally inverting the Z base vector. The resulting matrix is properly decomposable again (what's the correct term for this?) and the process worked fine... but again only for static scenes. If I want to convert node animations using this method, I'd have to calculate the rotation key in *global* space, convert it there, and then transform it back to local parent node space. Which means evaluating the animation tracks for all parent nodes, actually two times for the two transformations to global space and back. This is just nuts... especially for deep hierarchies like for example an skeleton-animated character. I'm out of ideas here. Can someone please leave me a hint on how to approach this problem? I tried to look at the kwXPort plugin which exports Microsoft .x files from 3DSMax. So this plugin probably solved the same problem. But I had a hard time following what the author did there. Apparently it can be done by processing the local node transformation alone, so there *has* to be some way to achieve this :-) Thanks to everyone in advance Bye, Thomas [Edited by - Schrompf on March 10, 2009 2:27:59 PM]
----------
Gonna try that "Indie" stuff I keep hearing about. Let's start with Splatter.
Advertisement
I think you could try swaping the x and y vectors from your transformation matrix:

Original Matrix

[X0 X1 X2]
[Y0 Y1 Y2]
[Z0 Z1 Z2]


Opposite hand system Matrix

[Y0 Y1 Y2]
[X0 X1 X2]
[Z0 Z1 Z2]


which is about the same as multiplying by the following matrix:

[0 1 0]
[1 0 0]
[0 0 1]


I am not 100% this is correct though, you may have to multiply the Z vector by -1 as well (mirror it), its definitely what I'd try, but usually to convert from OpenGL to Direc3D matrices you just have to transpose.

Edit: Ok, Looking at some old code of mine (an XSI exporter), I am pretty sure you want to swap 2 of the vectors (axes), which ones I think depends on which of the axes you originally have and want as pointing "UP", in this case Z is and remains as up.

[Edited by - Kwizatz on February 18, 2009 11:09:35 AM]
Thanks for the hint, but the solution you proposed suffers from the same problem: swapping two axes also results in a matrix that is not decomposable anymore. I'm sorry, I still need a different way.
----------
Gonna try that "Indie" stuff I keep hearing about. Let's start with Splatter.
Quote: Original post by Schrompf
Thanks for the hint, but the solution you proposed suffers from the same problem: swapping two axes also results in a matrix that is not decomposable anymore. I'm sorry, I still need a different way.


Well, I tried [smile], are you sure the problem can't be solved by transposing the matrix? works most of the time for Direct3D-to-OpenGL and vice-versa for me, though that's row mayor vs column mayor.

I know at least Quaternions remain the same no matter the handedness (Quaternions don't have handedness), though you extract them differently depending if you're operating on a D3D or OGL matrix (again, because of row/column differences).
AFAIK, Direct3D supports both left-handed and right-handed coordinate systems. Is it a requirement of your loader library to convert from one coordinate system to another?
deathkrushPS3/Xbox360 Graphics Programmer, Mass Media.Completed Projects: Stuntman Ignition (PS3), Saints Row 2 (PS3), Darksiders(PS3, 360)
Thanks for your engagement, guys!

Quote: Original post by deathkrush
AFAIK, Direct3D supports both left-handed and right-handed coordinate systems. Is it a requirement of your loader library to convert from one coordinate system to another?


Yes, it is. It's an open source loader library (http://assimp.sourceforge.net) that loads a wide range of 3D scene formats... some of them being lefthanded, some righthanded. We have quite some users now, some of them using OpenGL, some using DirectX. Conversion in each direction is the same, so I reduced the question to one direction.

Matrix memory layout is an independent topic. OpenGL uses column major layout, DirectX uses row major layout. But that's just a default value, to say so. You are free to use any of the both with any of the graphics APIs. That's why we describe the matrix layout in the documentation and remind DirectX users to transpose if they use the D3DX matrix classes. The problem is: It doesn't solve anything in the lefthanded <-> righthanded issue. I'm sorry, but the topic is still unresolved.

Bye, Thomas
----------
Gonna try that "Indie" stuff I keep hearing about. Let's start with Splatter.
You seem to have contradictory requirements. You want a transformation that will change orientation but that can be expressed as a rotation. Rotations have determinant 1 and anything that changes orientation has negative determinant.

Perhaps you need your code to deal with a larger class of transformations, or perhaps you are looking at your problem wrong, and all you have to do is apply the orientation-flipping transformation once when you load the model or something simple like that.

I explained at the starter post that I'm looking for a general method to transform a whole scene including node animations. I already described what methods I tried and how they performed. Each of the previous methods contained both transformation changes and some sort of processing of the associated meshes. I'm aware of the fact that this job isn't doable with transformations only... I'm sorry if the introductionary post was misworded in this matter.

To rephrase the issue: I'm looking for a way to convert whole scenes between lefthanded and righthanded coordinate spaces. A method which only uses local mesh processing and local scene node transformation processing, no global transformations. Local mesh processing because global mesh processing would require me to duplicate meshes if they're instanced multiple times. Local node transformation processing because nodes can be animated and I need to convert this animation data as well. No inversions or axis swapping because the resulting matrix still has to be decomposable to quaternions. Obviously, if you consider skeleton-based character animations, for example.

I hope the problem is described more clearly, now. I'd appreciate any hint on how to solve this issue under the constraints described above.

Bye, Thomas

----------
Gonna try that "Indie" stuff I keep hearing about. Let's start with Splatter.
Quote: b) Decomposing each node's global transformation into its base vectors, mirroring each of those at the global Z axis, and finally inverting the Z base vector. The resulting matrix is properly decomposable again (what's the correct term for this?) and the process worked fine... but again only for static scenes. If I want to convert node animations using this method, I'd have to calculate the rotation key in *global* space, convert it there, and then transform it back to local parent node space. Which means evaluating the animation tracks for all parent nodes, actually two times for the two transformations to global space and back. This is just nuts... especially for deep hierarchies like for example an skeleton-animated character.


welcome to my world. I have to do the exact same thing to remove scaling from bucket tonnes of animation data (which may be negatively scaled, which causes the handedness to change). The solution you've proposed is the only way to go - even though it's pretty grim. Make sure it's an offline process though ;)

Quote: To rephrase the issue: I'm looking for a way to convert whole scenes between lefthanded and righthanded coordinate spaces. A method which only uses local mesh processing and local scene node transformation processing, no global transformations.


You're looking for something that doesn't exist. b) is the answer you are looking for....
Ah ok, that's an answer, although not the one I hoped for :-)

BTW: the kwXPort plugin I mentioned in my first post appears to do this: it seems to process meshes only locally and it seems to process transformations only locally. And yet it manages to convert a whole animated scene from 3DSMax righthanded space to DirectX lefthanded space. I hoped to find the author here, I was under the impression that he's a regular visitor here. I failed to register at the plugin's forum, it never reacted to my registration attempt.

Maybe... just maybe there's still hope :-)

Good luck on your endeavours, though.
----------
Gonna try that "Indie" stuff I keep hearing about. Let's start with Splatter.

This topic is closed to new replies.

Advertisement