views:

319

answers:

3

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.

+1  A: 

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];
shoosh
this does fix a bug in my code, but it doesn't give me what I want =( I'll edit my code above to reflect this
Tom J Nowell
with your fix in place, if I move the mouse to the top of the window I get a black triangle which is the textured triangles (arranged in a square), with the triangle up against the side of the window and the cursor being the final point with a diagonal line going down to zero, however the triangles point does not follow the cursor and behaves erratically depending on the mouse location
Tom J Nowell
The best thing you can do is debug it and make sure that the matrix you end up with after the transpose is actually the transposed matrix. look at it using the watch window and verify.
shoosh
done and verified, refer to updated question
Tom J Nowell
A: 

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 ?

Bahbar
I tried that and didn't get the expected result at all, I've kinda given up and written an interface with an implementation for directx that wraps around the directx matrix APIs
Tom J Nowell
A: 

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 ...

Goz