Tutorial :Matrix classes Directx & OpenGL



Question:

I have the following C++ matrix class:

transform.h transform.cpp

I am using this coupled with a renderer, for which there is an opengl and a directx implementation.

I have a test example where the coordinates of the mouse within the window are used to position a graphic under the cursor. This works as expected under OpenGL.

Because directx is row major and opengl is column major, I reverse the matrix as follows and pass it to directx before rendering:

        if(o->tree){              CObjectTransform* t = o->tree->GetTransform(o->transformID);              D3DMATRIX d;              float* m = (float*)&d;              for (int u=0; u<4; u++){                  for (int v=0; v<4; v++){                      m[u +v*4] = t->worldtransform.matrix[v+u*4];                  }              }              pd3dDevice->SetTransform(D3DTS_WORLD, &d);          }  

The result of this is nothing is shown in the visible area from the graphics, regardless of here I put my cursor.

So:

  1. Is my transform class correctly implemented?
  2. How do I get it working with directx?

edit:

the following code was setup:

            float* m = (float*)&d;              for (int u=0; u<4; u++){                  for (int v=0; v<4; v++){                      m[u +v*4] = t->worldtransform.matrix[v+u*4];                  }              }              float test[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };              memcpy(test,&d,sizeof(d));  

The values of the matrix class:

1,0,0,0
0,1,0,0
0,0,1,0
47,-30,0,1

The values of the swapped matrix:

1,0,0,47
0,1,0,-30
0,0,1,0
0,0,0,1

So the matrix is being swapped around. This rules out the swapping round code as the cause of the problem.


Solution:1

OpenGL and DirectX have opposing matrix representations, but they also have opposite vector * matrix order:

  • OpenGL: M * v. M is column major in memory
  • DirectX: v * M. M is row major in memory

since the multiplication is reversed, you have to transpose your OpenGL matrix to pass to DX. But since DX uses row major, you have to transpose again. Transpose twice is really the identity.

How about you try with no transformation at all ?


Solution:2

I'm assuming you're compiling this as C++.
This:

m[u,v] = t->worldtransform.matrix[v,u];  

Probably doesn't do what you want it to do. in C++, a 2D array is indexed as m[u][v].
What this line actually does is use the , operator which evaluates to its statement, so m[u,v] actually returns the float of the v coordinates.

what you probably want to do is this:

m[u + 4*v] = t->worldtransform.matrix[v + 4*u];  


Solution:3

You appreciate that, of the 2 matrices you show above, the first is a correct DirectX matrix. The second will not work under DX at all ...


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »