实时阴影绘制技术研究

C++博客 首页 新随笔 联系 聚合 管理
  48 Posts :: 20 Stories :: 57 Comments :: 0 Trackbacks
 
今天开始看动画初步,其实主要就是坐标变换。无论对于directX也好,对于openGL也好,坐标变换都是做基本最重要的部分。所以今天一定要好好学习学习。
先看一下D3D的矩阵表示形式:

m._11 m._12 m._13 m._14     ux  uy  uz 0
m._21 m._22 m._23 m._24  = vx  vy  vz 0
m._31 m._32 m._33 m._34    wx wy wz 0
m._41 m._42 m._43 m._44     tx  ty  tz  1

下面看一下D3D需要构造的几个基本矩阵:
1,平移矩阵

1  0   0  0
0  1   0  0
0  0   1  0
tx ty tz  1

平移矩阵可以由函数:VOID D3DMatrixTranslation(D3DMATRIX* m,FLOAT tx,FLOAT ty,FLOAT tz)来构造。
2,旋转矩阵
以绕Y轴旋转为例,矩阵形式如下:

cosR 0 -sinR 0
0    1   0   0
sinR 0  cosR 0
0    0   0   1

以上矩阵可以通过类似VOID D3DMatrixRotationY(D3DMATRIX* m,FLOAT r)来获得。同样可以得到绕X,Z轴旋转的矩阵。
3,缩放矩阵

sx  0  0   0
0   sy 0   0
0   0  sz  0
0   0  0   1

可以通过D3DMATRIX* D3DMatrixScaling(D3DMATRIX *pOut,FLOAT sx,FLOAT sy,FLOAT sz)来获得。
得到上述矩阵以后,可以通过矩阵乘法来累积变换,乘法形式同线性代数中所讲一样,不详述。调用形式如下:D3DMATRIX* D3DMatrixMultiply(D3DMATRIX *pOut,D3DMATRIX *pM1,D3DMATRIX *pM2).其中返回值同pOut值相同。
在C++中由于利用函数重载,还可以写成:pOut = pM1 * pM2的形式,当然也可以连乘:pOut = pM1 * pM2 * pM3.
获得了变换矩阵以后,要对顶点起作用,需要利用m_pDevice->SetTransform(D3DTS_WORLD,&m_matWorld)来设置。当然可以将D3DTS_WORLD换成D3DTS_VIEW,D3DTS_PROJECTION来设置视矩阵和投影矩阵。
下面看一个实际应用的例子:
HRESULT CMyD3DApplication::FrameMove()
{
    // rotates the object about the y-axis
 D3DXMATRIX matRotY;
 D3DXMATRIX matRotZ;
 D3DXMatrixRotationY( &matRotY, m_fTime * 0.5f);
 D3DXMatrixRotationZ( &matRotZ, m_fTime * 1.5f);
 
 D3DXMATRIX matTrans;
 D3DXMatrixTranslation(&matTrans, 0.0f, 0.0f, 0.0f);
 m_pd3dDevice->SetTransform( D3DTS_WORLD, &(matRotY * matRotZ * matTrans));
    return S_OK;
}

我们用FrameMove()函数来制作动画,循环播放。我们只需要调用相应函数获得矩阵,然后乘起来,设置一下就可以了。
再看一小段代码:
// Each viewport fills a quarter of the window
 m_RViewport.Width = MainViewport.Width / 2;
 m_RViewport.Height = MainViewport.Height / 2;
 m_RViewport.Y = m_SRTViewport.Y = 0;
 m_RViewport.X = m_TRViewport.X = 0;
// Set the full Z range for each viewport
 m_RViewport.MinZ = 0.0f;
 m_RViewport.MaxZ = 1.0f;
m_pd3dDevice->SetViewport(&m_RViewport);
m_matWorld = RotationMatrix1;
m_pd3dDevice->SetTransform(D3DTS_WORLD, &m_matWorld);
m_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 
                     0,
                     0, 
                     4,  // number of vertices
                     0, 
                     2); // number of primitives

我们只要把已经做好的矩阵设置成当前世界坐标矩阵,然后依次绘制图元就可以了。
从这个例子我们也可以想象出d3d也存在着类似于openGL那样的一个保存当前状态的自动机。
上边的代码中我们也看到了使用视口的例子,通过设置不同视口的位置和大小,我们可以在屏幕上显示出不同的内容,书中就是使用四个视口分别展示了四种不同的变换。
posted on 2006-01-01 01:46 苦行僧 阅读(869) 评论(0)  编辑 收藏 引用 所属分类: directX

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理