Matrix mult order in Direct3D
Asked Answered
B

2

5

I've received two conflicting answers in terms of multiplying matrices in Direct3D to achieve results. Tutorials do state to multiply from left to right and that's fine but it's not how I would visualize it.

Here's an example:

OpenGL (reading from top to bottom):

GLRotatef(90.0f);
GLTranslatef(20.0f,0,0);

So you visualize the world axis rotating 30 degrees. Then you translate 20.0 on the now rotated x-axis so it looks like you are going up on the world y-axis.

In Direct3D, doing:

wm = rotatem * translatem;

is different. It looks like the object was just rotated at the origin and translated on the world's x-axis so it goes to the right and not up. It only works once I reverse the order and read from right to left.

Also for example, in frank luna's book on DX10, he goes into explaining how to do mirror reflections. I get all of that but when he does for example:

reflection_matrix = world_m * reflection_m;

around the xy plane, do I interpret this as first doing a the world positioning then a reflection or the opposite?

Bertina answered 25/5, 2011 at 2:46 Comment(1)
I think this link's top answer give a good discription!Kaneshakang
C
10

The problem is the order you are multiplying the matrices to get the composite transform matrix is reversed from what it should be. You are doing: wm = rotatem * translatem, which follows the order of operations you are doing for OpenGL, but for DirectX the matrix should have been wm = translatem * rotatem

The fundamental difference between OpenGL and DirectX arises from the fact that OpenGL treats matrices in column major order, while DirectX treats matrics in row major order.

To go from column major to row major you need to find the transpose ( swap the rows and the columns ) of the OpenGL matrix.

So, if you write wm = rotatem * translatem in OpenGL, then you want the transpose of that for DirectX, which is:

wmT = (rotatem*translatem)T = translatemT * rotatemT

which explains why the order of the matrix multiply has to be reversed in DirectX.

Charente answered 25/5, 2011 at 3:7 Comment(4)
So in other words, I'm doing it right for all purposes. Do I assume then that the author meant to reflect first and then to apply the world matrix?Bertina
I would need more background to figure out the author's intent. But the difference you mention between the order of transformation between opengl and directx makes perfect sense.Charente
Author's intent was to show how to mirror objects which is just reflection of the cube over an arbitrary xy plane. It makes sense that the reflection would be after the world transformation is performed but that would require that the matrix order should instead be: reflection_matrix * world_matrix if I read from right to left.Bertina
Just played got around to playing around and realized the order doesn't matter for a reflection in this case. Thanks though, you answered my question well.Bertina
H
1

See this answer. In OpenGL, each subsequent operation is a pre-multiplication of all the operations before it, not a post-multiplication. You can see a matrix multiplication of a vector as a function evaluation.

If what you want is to first rotate a vector and then translate your rotated vector, which you in OpenGL would have solved by first calling glRotatef and then calling glTranslatef, you could express that using function calls as

myNewVector = translate(rotate(myOldVector))

The rotate function does this

rotate(anyVector) = rotationMatrix * anyVector

and the translate function does this

translate(anyOtherVector) = translationMatrix * anyOtherVector

so your equivalent expression using matrix multiplications would look like

myNewVector = translationMatrix * rotationMatrix * myOldVector

That is, your combined transformation matrix would look be translationMatrix * rotationMatrix.

Harrold answered 6/2, 2014 at 14:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.