呼,趁热打铁,继续复习>_<真的好想玩玩啊,虽然不知道有什么好玩的,出去压马路太无聊了,恩,谁要是有什么比较不错的动漫,推荐下。

恩,立方体我们绘制出来了。接下来该把它放置到世界空间去了吧。

还记得第十章我在进行D3D基础名词解释时提到过的本地空间和世界空间,视图空间么。我们现在的所有模型绘制都是在一个本地空间中进行的,所以不存在任何的与其他物体的遮挡的情况出现,而且,恩,还不能旋转移动缩放等,现在我们就为这个立方体加上这些要素,有时间话争取今天给它帖上纹理,那就好看了,灯光材质嘛还要等明天。

恩,首先我们还要先讲些概念的东西。

我们可以回忆一下高中几何,我们确定一个面,可以依靠几种手段?三个点可以确定一个面,一条直线和直线外的一个点可以确定一个面,两条相交或平行的直线可以确定一个面。似乎就这样了吧.

呃,再补充个概念,假如我们有一个向量垂直于我们的平面,我们就称这条向量为平面的法线。

我们在D3D中确定平面可以这么写:

  1. 已知道了平面的法线向量n和平面上任意一点p,则获得一个确定的平面
D3DXPlaneFromPointNormal(
D3DXPLANE* pOut,   //构造出的平面指针
const D3DXVECTOR3* pPoint, //点p
const D3DXVECTOR3* pNormal //法线n
);
  1. 当我们知道了平面上三个点,我们可以获得两个向量,再通过这两个向量的叉乘来获得垂直于他们的向量(为什么会获得?去看看我前面的日志),当一个向量同时垂直于两个相交的向量,那么这个向量则垂直于相交两条向量所在的面,这是我们高中已知的概念。等我们获得了平面法线向量后,又有其他的点,我们可以确定这个平面。
D3DXPlaneFromPoints(
D3DXPLANE* pOut,   //构造出的平面
CONST D3DXVECTOR3* pV1,  //点1
CONST D3DXVECTOR3* pV2,  //点2
CONST D3DXVECTOR3* pV3,  //点3
);
  1. 我们通过上两个公式获得的pOut是一个平面,它是由一个由四个数组成的数组。

D3DXPLANE x(a, b, c, d);

其中,a,b,c表示平面的法线向量,d是一个常量,它表示点(a,b,c)到平面的最小距离。

当我们获得平面后,我们需要将其标准化,对于平移变换矩阵,我们则需要得到它的逆转置矩阵。(这里真烦,我本想尽量避免来说明相关立体几何和线代的东西,看来还是逃不掉,下个章节就专门讲这东西了,现在大家就先死记一下吧,抱歉抱歉)

呃,获得逆转置矩阵和标准化平面的方法不需要我们自己手动写算法,D3D提供了一些函数,当然记住这些函数也可以做出一款游戏来,但是终究需要了解其原理的好,下一篇日志我将这些部分更加详细的讲解。现在大家先看下D3D提供的函数

D3DXPlaneNormalize(
D3DXPLANE* pOut,   //标准化后的平面
CONST D3DXPLANE*  pP  //原平面
);

通过这个函数我们获得标准化平面,

D3DXPlaneTransform(
D3DXPLANE* pOut,      //平移后的平面
CONST D3DXPLANE*  pP,        //原平面的标准化平面
CONST D3DXMATRIX* pM      //平移矩阵的逆转置矩阵
);

通过这个函数我们可以获得一个矩阵的逆转置矩阵,这样我们就无需管矩阵中到底是什么样子的数据,仅用地址调用就可以了

  1. 当我们获得了变换矩阵后,我们对D3D设备使用我们的变换矩阵,函数为

g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);

这是通知我们的D3D设备,进行世界空间的变换,第一个参数为空间变换类型,第二个参数是我们的变换矩阵。

  1. 平移变换矩阵
 D3DXMATRIX *D3DXMatrixTranslation(
  D3DXMATRIX *pOut, //输出矩阵
  FLOAT x,  //x轴上的平移量   
  FLOAT y,  // y轴上的平移量   
  FLOAT z   // z轴上的平移量
  );
  1. 缩放变换矩阵
 D3DXMATRIX *D3DXMatrixScaling(         
  D3DXMATRIX *pOut, //输出矩阵
  FLOAT sx,  //x轴上的缩放量   
  FLOAT sy,  // y轴上的缩放量   
  FLOAT sz  // z轴上的缩放量
  );

当我们各方向上缩放量相等时,图象将进行一个均匀的变换,当我们各个方向上缩放量不同时,我们的图象将会呈现出一种拉伸或者挤压的现象。

pOut就是我们实现该功能的所需要的变换矩阵指针,我们将它传入相应的函数中,就能实现相应的图象变换。

  1. 旋转变换矩阵

(1):绕X轴旋转:D3DXMatrixRotationX( D3DXMATRIX* pOut, FLOAT Angle);

(2):绕Y轴旋转:D3DXMatrixRotationY(参数同上)第一个参数为输出此变换矩阵的指针,第二个参数为旋转的角度

(3):绕Z轴旋转:D3DXMatrixRotationZ(参数同上)

(4):自定义旋转轴的旋转:D3DXMatrixRotationAxis( D3DXMATRIX* pOut,CONST D3DXVECTOR3* pV,FLOAT Angle);

其中第一个参数还是输出矩阵地址,第二参数是旋转轴的向量表示,第三个参数是旋转角度。

  1. 组合变换

若我们不仅需要旋转,还需要平移和缩放的话,我们可以使用矩阵的乘法来获得最终组合好的变换矩阵。

矩阵乘法函数为:

 D3DXMatrixMultiply( D3DXMATRIX* pOut, //输出的组合变换矩阵
    D3DXMATRIX* p1, //第一种变换矩阵
    D3DXMATRIX* p2  //第二种变换矩阵
   );

我们拿上次的立方体代码来说,我们需将下列代码替换其中的SetupRotation(),SetupCamera()两个方法就可以实现一个立方体的变换了。

SetupCamera()的改变是为了调整好我们的视角,避免图形变换出了我们的视野。

//设置旋转、移动和缩放,即设置世界变换
void SetupRotation() 
{
     D3DXMATRIX matWorld, matWorldX, matWorldY, matWorldZ;
     D3DXMATRIX matScaling;
     D3DXMATRIX matTranslation;
     DWORD time = timeGetTime();
     static int nScaling;
     static bool bEnlarge;
     // 分别绕X,Y,Z轴旋转。
     D3DXMatrixRotationX(&matWorldX, time/400.0f);
     D3DXMatrixRotationY(&matWorldY,time/400.0f); 
     D3DXMatrixRotationZ(&matWorldZ, time/400.0f); 
     float fK = 1.0f + nScaling/ 60.0f;
     if (bEnlarge) {
      nScaling++;
      if (nScaling >= 60) bEnlarge = false;
     } else {
      nScaling--;
      if (nScaling <= 0) bEnlarge = true;
     }
     // 进行缩放。
     D3DXMatrixScaling(&matScaling, fK, fK, fK);
     // 在X,Y方向平移。
     D3DXMatrixTranslation(&matTranslation, nScaling/(FLOAT)3.5, -nScaling/(FLOAT)3.5, 0.0f);
     // 把各种变化组合起来。
     D3DXMatrixMultiply(&matWorld, &matWorldX, &matWorldY);
     D3DXMatrixMultiply(&matWorld, &matWorld, &matWorldZ);
     D3DXMatrixMultiply(&matWorld, &matWorld, &matScaling);
     D3DXMatrixMultiply(&matWorld, &matWorld, &matTranslation);//进行平移
     g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);
}

// 设置摄像机
void SetupCamera()
{
 
    D3DXMATRIX matView;
    D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(30.0f, 30.0f,30.0f),  //摄像机的位置
                                 &D3DXVECTOR3(0.0f, 0.0f, 0.0f),  //摄像机的朝向
                                 &D3DXVECTOR3(0.0f, -1.0f, 0.0f));  //摄像机的顶方向
    g_pD3DDevice->SetTransform(D3DTS_VIEW, &matView);
}