Convert from OpenGL right-hand coordsys to Direct3D left-hand

Hi,

I am porting from OpenGL to Direct3D, but have some trouble going from OpenGL's right-hand coordinate system to Direct3D's left-hand coordinate system.

I have a transformation matrix that I want to apply/load into to the virtual camera (the viewer):

| r00 r01 r02 tx |
| r10 r11 r12 ty |
| r20 r21 r22 tz |
|   0     0    0   1 |

Where the 3x3 r's makes the rotation matrix, and the t's makes the translation vector.

In OpenGL this is what I do to set the position and orientation of my virtual camera:

  1. Transpose the matrix 
  2. glMatrixMode(GL_MODELVIEW);
  3. glLoadMatrixd(myMatrixTransposed)
  4. Draw my 3D graphics

This moves the virtual camera to the position and orientation given my the original transformation matrix. The reason for doing this, is that I have a physical input device that gives position+rotation, and I want to set the pos+rot for the virtual camera to be the same as the physical input device.

My problem is, which steps to I need to make to do the same operations in Direct3D I guess I need to transpose the matrix and set the z-part of the translation to -z, but this seems not to be enough. Do I need to make some operations on the rotation matrix

Thanks,
Torbjorn



Answer this question

Convert from OpenGL right-hand coordsys to Direct3D left-hand

  • Rajat Solanki

    Hi, Have u solved it
  • Arnaud Weil

    This is what happens when I do the transpose:

    original matrix:

    | r00 r01 r02 tx |
    | r10 r11 r12 ty |
    | r20 r21 r22 tz |
    | 0 0 0 1 |

    transposed matrix:

    | r00 r10 r20 0 |
    | r01 r11 r21 0 |
    | r02 r12 r22 0 |
    | tx ty tz 1 |

    As you see, the values are "mirrored". Maybe I should not transpose my rotation matrix, only move the translation vector


  • Tim Wright

    The reason you have to rotate your camera 180 degrees is likely due to using mismatched look-at and projection matrices. A right-handed function like glFrustum will take a frustum on the negative z axis, and map it to a unit cube, while a left-handed version of the same function would map a frustum on the positive z axis to the same unit cube. A right-handed lookAt matrix will map the eye vector onto the negative z axis such that the data is ready for a right-handed projection.

    I hope that all makes sense.

    ESP


  • Canman2

    The only thing I notice is that in direct x the matricis are specified differently: the translation has to be where your zeros are. I was confused about that, using OpenGL before I started with DX as well.

    See "Transforms" in the dx docu for more info.

    Nico

     

    P.S.: Is the transposed matrix the inverse I thought this only works for pure rotation matrices. Or what is the reason for transposing the matrix If you need the inverse matrix you can use the D3DXMatrixInverse(...) function.


  • TELOPHASE

    Yes, I know about transposing, but that is probably not what you need to do. You need the inverse transform of the matrix that places your camera into the world. If it were just a rotation matrix, transposing would inverse it. But think of what a transposition does when there is a translation part: as you noted yourself, the translation moves to the other part of the matrix, that's where the projection lies. So it gets transformed into a projection. That is not the inverse.

    As I said, look on the "Transforms" page in the dx docu. There you find everything you need. Hopefully...

    The rotation matrices there are for left handed coordinate systems, so you are right that you have to do something with the rotation as well. But for a different reason: The translation is in a different place because the rows and colums of the matrix are swapped in DX. 

    Nico

     


  • panjkov

    To my understanding: if you have a rotaion and a translation from your input device that orients the camera in the world, you need to fill a matrix, like you did, but put the tranlations where the zeros are, (this has to do with the way DX transforms vectors by matrices, not with the left handed coordinate system) swap the sign of z and then generate the inverse.

    Nico


  • amitsingh

    Is the transposed matrix the inverse I thought this only works for pure rotation matrices. Or what is the reason for transposing the matrix If you need the inverse matrix you can use the D3DXMatrixInverse(...) function.
  • Nick Burnett

    Hm...I still haven't really figured this out..

    What I do now that seems to work (and it is really strange - I can't explain it) is this:

    Briefly:
    Camera.LoadMatrix(ConvertToLeftHand(RHMatrix).Inverse.Transpose());
    Camera.RotateX(180,absolute);

    Detailed:

    • 1st: change from Right-Hand to Left-Hand as below (is this the right way to do it )


    //Flip sign of 3rd row
    for (int i = 0; i < 4; i++)
    {

    newMatrix[2, i] = -newMatrix[2, i];

    }

    //Flip sign of 3rd column
    for (int i = 0; i < 4; i++)
    {

    newMatrix[i, 2] = -newMatrix[i, 2];

    }


    • 2nd: newMatrixInv = inverse of newMatrix
    • 3rd: newMatrixInvTransposed = newMatrixInv transposed
    • 4th: load newMatrixInvTransposed into the DirectX camera (or actually to Truevision3D.com's TVCamera.SetMatrix, which I think expects the inverse of the DirectX View Matrix - this is a little in a blur to me...) 
    • 5th - and this is the weirdest part: rotate the TVCamera (see point 4) 180 degrees around the X axis of the World coordinate system.

    So...this is not clear to me..could anybody explain to me why this works, and how I perhaps SHOULD do this

    Thanks a lot to all that might have something to contribute with !!


  • altbrot

    Thanks,

    I get the translation-part. But what about the rotation matrix, don't I need to do some kind of conversion there as well

    And why do I need to invert When I speak of transpose, that is not the same as invert, but it "mirrors" the matrix, to move tx,ty and tz to the bottom of the matrix. And the rotation matrix is also "mirrored". But I am not sure if that is what I should do...

    (Sorry for confusing perhaps even more...)


  • BobPSmith

    Couldn't stop thinking about your question! lol ;-)

    I found an old faq with the opengl right handed rotation matrices:

    | 1 0 0 |
    Rx = | 0 cos A -sin A |
    | 0 sin A cos A |


    | cos A 0 sin A |
    Ry = | 0 1 0 |
    | -sin A 0 cos A |

    | cos A -sin A 0 |
    Rz = | sin A cos A 0 |
    | 0 0 1 |

    And this are the left handed dx matrices:

    | 1 0 0 |
    Rx = | 0 cos A sin A |
    | 0 -sin A cos A |


    | cos A 0 -sin A |
    Ry = | 0 1 0 |
    | sin A 0 cos A |

    | cos A sin A 0 |
    Rz = | -sin A cos A 0 |
    | 0 0 1 |

    So if you compare them to their left handed dx versions you see that they only differ in a few signs. So if you don't have the original rotation angles of your input device, it will probably do to just swap the signs of your matrix values in those positions!

    Nico


  • Bernhard_xy

    Well, this is really confusing to me. I just noted, that the matrices I just posted for dx and OGL are identical, just the rows and colums are swapped. ;-) so actually you seem to be right with doing a transpose, because a transpose does nothing else than swapping rows and columns of the matrix! So it should convert an OGL matrix into a dx one. But additionally you should probably change the sign of your z translation, as you noted. And also maybe the sign of the z-rotations angle.

    Maybe somebody else can clarify this!

     


  • Matti Niskasaari

    The best way to convert between left-handed and right-handed renderers is to do no conversion at all! The key is to decide the handedness of the *data* you are using in your application, and create matrices that transform that data in the correct way. To say that OpenGL is right-handed and Direct3D is left-handed is not really true. Both just need you to transform vertices into a unit cube. Luckily for us, this cube has the same z-ordering, so as long as we use exactly the same transformations we will always transform our world's data into the correct location.

    If you started using OpenGL, then your world is likely right-handed because you were using functions like glOrtho, glFrustum and gluPerspective. However, it is actually just these functions that are right-handed rather than the whole of OpenGL. In D3D, just use the equivalent D3DX*MatrixRH functions and you will be good to go. If you started in D3D using the LH functions, don't use OpenGL's glOrtho, glFrustum and gluPerspective. Use your own functions to create these matrices.

    You may need to transpose your matrix depending on row or column major format, but that is a seperate issue from that of left vs right-handed.

    ESP


  • JWK

    Thanks a lot for the help, Nico!!

    I will look into what signs that needs to be flipped in the rotation matrix.

    Cheers,
    Torbjorn


  • __ David Zorin

    Yes, when I transpose the matrix, the translation vector is moved to the bottom of the matrix. Also, the rotation matrix is changed.

    But this does not seem to be enough.


  • Convert from OpenGL right-hand coordsys to Direct3D left-hand