D3D中矩阵变换中出现的问题

今天想用D3D实现一个简单的效果:先画一个立方体,然后鼠标左键使之能够沿Y轴旋转,鼠标右键使之能够沿Z轴旋转。第一个功能倒是实现了,但是第二个功能却有些毛病。

代码如下:

LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 函数中:

              ……………

     case WM_LBUTTONDOWN:

         g_iRotateY += 20;

         Render();

         ValidateRect(hWnd, NULL);

         return 0;

     case WM_RBUTTONDOWN:

         g_iRotateZ += 20;

         Render();

         ValidateRect(hWnd, NULL);

                   return 0;

              ……………

VOID SetupMatrices() 函数中:

              ……………

FLOAT angleY = ANGLE_TO_RADIAN(g_iRotateY);

     FLOAT angleZ = ANGLE_TO_RADIAN(g_iRotateZ);

 

     // 定义世界变换矩阵(World Transformation Matrix

     D3DXMATRIX matWorld;

     D3DXMatrixTranslation(&matWorld, 0, 0, 0);// 1

     D3DXMatrixRotationY(&matWorld, angleY);   // 2

     D3DXMatrixRotationZ(&matWorld, angleZ);   // 3

g_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld);

              ……………

注意到蓝色字体部分,为什么执行完这两句后只有一句起作用呢?并且每次都是第二句话起作用(意思是说:当我把第2句话放在第3句话的下面时,就只有绕Y轴旋转,即鼠标左键起作用,右键无效;如果按代码中所示,则只有右键起作用,左键无效)。乍一看,好像没有错误啊,我把矩阵的指针传进去,然后对我的矩阵进行操作,结果由这个矩阵带出来。当我执行第2句时,矩阵发生变化,然后将这个变换后的矩阵再进行第二次操作,即执行第3句话,然后理所当然的应该在刚刚已经变化后的矩阵上进行变换。没有错!!!可恰恰就是错了,请注意:我们在使用这个矩阵matWorld的时候,并没有对其进行初始化,然后就直接用了,如果这个想法成立,那么上面的结果应该就不会错。那么我们可以看一看D3DXMATRIX的构造函数:

#ifdef __cplusplus

typedef struct D3DXMATRIX : public D3DMATRIX

{

public:

    D3DXMATRIX() {};

    D3DXMATRIX( CONST FLOAT * );

    D3DXMATRIX( CONST D3DMATRIX& );

    D3DXMATRIX( CONST D3DXFLOAT16 * );

    D3DXMATRIX( FLOAT _11, FLOAT _12, FLOAT _13, FLOAT _14,

                FLOAT _21, FLOAT _22, FLOAT _23, FLOAT _24,

                FLOAT _31, FLOAT _32, FLOAT _33, FLOAT _34,

                FLOAT _41, FLOAT _42, FLOAT _43, FLOAT _44 );

显然,我们并没有发现默认构造函数将矩阵初始化(矩阵的初始化肯定是单位化)。而我们程序中的结果又是只有最后的一个变换才起到作用,那么我们可以推测,是不是在变换中我们进行了初始化,并进行了变换。推测是成立的,我们三次都是对同一个矩阵进行操作:

1句:将矩阵matWorld进行单位化,然后再对矩阵进行平移操作,操作向量为(0 0 0);

2句:将矩阵matWorld进行单位化,然后再对矩阵进行绕Y轴旋转操作,旋转角度为angleY

3句:将矩阵matWorld进行单位化,然后再对矩阵进行绕Z轴旋转操作,旋转角度为angleZ

由此看出,我们起作用的实际上只有一句,即第3句。

查看函数原型:

D3DXMATRIX * D3DXMatrixTranslation(

  D3DXMATRIX * pOut,

  FLOAT x,

  FLOAT y,

  FLOAT z

);

D3DXMATRIX * D3DXMatrixRotationY(

  D3DXMATRIX * pOut,

  FLOAT Angle

);

             ……………

在这一类矩阵操作函数中都要注意上面说的这个问题,即:先将矩阵单位化,再对这个单位矩阵进行操作。在D3DAPI函数中,把矩阵单位化进行了隐藏。

 

怎么修改:

设置多个矩阵,最后让这些矩阵相乘,然后进行设置。

代码如下:

     D3DXMATRIX matWorld;

     D3DXMATRIX matRotationY;

     D3DXMATRIX matRotationZ;

     D3DXMatrixTranslation(&matWorld, 0, 0, 0);

     D3DXMatrixRotationY(&matRotationY, angleY);

     D3DXMatrixRotationZ(&matRotationZ, angleZ);

     D3DXMatrixMultiply(&matWorld, &matRotationY, &matRotationZ);

g_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld);

你可能感兴趣的:(D3D中矩阵变换中出现的问题)