4.2.7 向量的矩阵转换
根据转换矩阵转换单个向量为齐次向量, w = 1
pV * pM = pOut = (x, y, z, 1)
D3DXVECTOR4 * D3DXVec3Transform(D3DXVECTOR4 * pOut,
CONST D3DXVECTOR3 * pV,
CONST D3DXMATRIX * pM);
根据转换矩阵转换含N个向量的数组为N个向量的齐次向量数组, Wn = 1
pV[n] * pM = pOut = (Xn, Yn, Zn, 1),
OutStride = sizeof(D3DXVECTOR4), VStride = sizeof(D3DXVECTOR3),
n = count of pV array
D3DXVECTOR4 * D3DXVec3TransformArray(D3DXVECTOR4 * pOut,
UINT OutStride,
CONST D3DXVECTOR3* pV,
UINT VStride,
CONST D3DXMATRIX* pM,
UINT n);
根据转换矩阵转换单个向量, w = 1
pV * pM = (x, y, z, 1), pOut = (x, y, z)
D3DXVECTOR3 * D3DXVec3TransformCoord(D3DXVECTOR3 * pOut,
CONST D3DXVECTOR3 * pV,
CONST D3DXMATRIX * pM);
根据转换矩阵转换含N个向量的数组, Wn = 1
pV[n] * pM = (Xn, Yn, Zn, 1), pOut = (Xn, Yn, Zn)
OutStride = sizeof(D3DXVECTOR3), VStride = sizeof(D3DXVECTOR3),
n = count of pV array
D3DXVECTOR3 * D3DXVec3TransformCoordArray(D3DXVECTOR3* pOut,
UINT OutStride,
CONST D3DXVECTOR3* pV,
UINT VStride,
CONST D3DXMATRIX* pM,
UINT n);
根据转换矩阵转换单个法向量, w = 0
pV * pM = (x, y, z, 0), pOut = (x, y, z)
D3DXVECTOR3 * D3DXVec3TransformNormal(D3DXVECTOR3 * pOut,
CONST D3DXVECTOR3 * pV,
CONST D3DXMATRIX * pM);
根据转换矩阵转换含N个法向量的数组, Wn = 0
pV[n] * pM = (Xn, Yn, Zn, 0), pOut = (Xn, Yn, Zn)
OutStride = sizeof(D3DXVECTOR3), VStride = sizeof(D3DXVECTOR3),
n = count of pV array
D3DXVECTOR3 * D3DXVec3TransformNormalArray(D3DXVECTOR3* pOut,
UINT OutStride,
CONST D3DXVECTOR3* pV,
UINT VStride,
CONST D3DXMATRIX* pM,
UINT n);
4.3 平面
平面可以用平面内的任意向量P和平面的法向量N表示, P DOT N = 0, 平面内的任意向量P可用平面中的两点表示, 其中选一特殊点P0和任意点P, 就有(P
–
P0) DOT N = 0,
N
* P + d = 0(d = - N * P0), 所以平面也可以由平面法向量和一数值来确定.
确定一个点X和平面的关系, 只需将点的坐标代入上面的公式就能知道,
(1)
N
* X + d = 0, 点在面内
(2)
N
* X + d > 0, 点在面正半侧
(3)
N
* X + d < 0, 点在面负半侧
使用下面的函数来判断,
FLOAT D3DXPlaneDotCoord(CONST D3DXPLANE * pP,
CONST D3DXVECTOR3 * pV);
平面用的比较少, 在视域内可设置特殊的裁截面.
DirectX Graphics中,
平面
以D3DXPLANE结构表示.
4.4 模型旋转的例子
4.4.1 代码更新
这一集的例子和上集的差不多, 上集中的例子所有的模型使用同样的模型转换矩阵, 这集的例子我们对每个模型使用不同的模型转换矩阵.
默认例子中使用的投影转换都是透视投影, 可以改成正射投影看看不同之出.
我们来看看game3的主要更新的代码(下载game3 project)
---------------------------------------------------------------
// direct9.cpp
中我们设置了些特殊的位移和缩放矩阵
HRESULT CD9Game::InitObject()
{
D3DXMatrixTranslation(&g_mMR20, 20.0, 0.0, 0.0);
D3DXMatrixTranslation(&g_mML20, -20.0, 0.0, 0.0);
D3DXMatrixTranslation(&g_mMU10, 0.0, 10.0, 0.0);
D3DXMatrixTranslation(&g_mMD10, 0.0, -10.0, 0.0);
D3DXMatrixTranslation(&g_mMR8, 8.0, 0.0, 0.0);
D3DXMatrixTranslation(&g_mML8, -8.0, 0.0, 0.0);
D3DXMatrixScaling(&g_mScaleUp, 2.0, 2.0, 2.0);
m_paObject[0] = new CD9Object(m_pD3DDev);
if ( m_paObject[0] == NULL )
{
return E_FAIL;
}
m_paObject[0]->SetPos(-20.0, 0.0, 0.0, 8.0, 8.0, 8.0);
m_paObject[1] = new CD9Object(m_pD3DDev);
if ( m_paObject[1] == NULL )
{
return E_FAIL;
}
m_paObject[1]->SetPos(-8.0, 0.0, 0.0, 8.0, 8.0, 8.0);
m_paObject[2] = new CD9Object(m_pD3DDev);
if ( m_paObject[2] == NULL )
{
return E_FAIL;
}
m_paObject[2]->SetPos(0.0, 10.0, 0.0, 8.0, 8.0, 8.0);
m_paObject[3] = new CD9Object(m_pD3DDev);
if ( m_paObject[3] == NULL )
{
return E_FAIL;
}
m_paObject[3]->SetPos(8.0, 0.0, 0.0, 8.0, 8.0, 8.0);
m_paObject[4] = new CD9Object(m_pD3DDev);
if ( m_paObject[4] == NULL )
{
return E_FAIL;
}
m_paObject[4]->SetPos(20.0, 0.0, 0.0, 8.0, 8.0, 8.0);
return S_OK;
}
//
我们为每个模型设置了不同的转换, 具体解释在后面的说明中
VOID CD9Game::Render()
{
D3DXMATRIX mWorld, mWorldX, mWorldY, mWorldZ;
D3DXMATRIX mWorld2, mWorld3, mWorld4, mWorld5;
if (m_nRot > MAXROT)
{
m_nRot = 0;
}
m_nRot++;
FLOAT rat = m_nRot * ROT;
D3DXMatrixRotationX(&mWorldX, rat);
D3DXMatrixRotationY(&mWorldY, rat);
D3DXMatrixRotationZ(&mWorldZ, rat);
D3DXMatrixRotationAxis(&mWorld, &D3DXVECTOR3(1.0, 1.0, 0.0), rat);
D3DXMatrixMultiply(&mWorld2, &g_mMR8, &mWorldY);
D3DXMatrixMultiply(&mWorld2, &mWorld2, &g_mML8);
D3DXMatrixMultiply(&mWorld3, &g_mMD10, &mWorldY);
D3DXMatrixMultiply(&mWorld3, &mWorld3, &mWorldX);
D3DXMatrixMultiply(&mWorld3, &mWorld3, &mWorldZ);
D3DXMatrixMultiply(&mWorld3, &mWorld3, &g_mMU10);
D3DXMatrixMultiply(&mWorld3, &mWorld3, &g_mScaleUp);
D3DXMatrixMultiply(&mWorld4, &g_mML8, &mWorldZ);
D3DXMatrixMultiply(&mWorld4, &mWorld4, &g_mMR8);
D3DXMatrixMultiply(&mWorld5, &g_mML20, &mWorld);
D3DXMatrixMultiply(&mWorld5, &mWorld5, &g_mMR20);
m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
m_pD3DDev->BeginScene();
m_pD3DDev->SetTransform(D3DTS_WORLD, &mWorldX);
m_paObject[0]->Render();
m_pD3DDev->SetTransform(D3DTS_WORLD, &mWorld2);
m_paObject[1]->Render();
m_pD3DDev->SetTransform(D3DTS_WORLD, &mWorld3);
m_paObject[2]->Render();
m_pD3DDev->SetTransform(D3DTS_WORLD, &mWorld4);
m_paObject[3]->Render();
m_pD3DDev->SetTransform(D3DTS_WORLD, &mWorld5);
m_paObject[4]->Render();
m_pD3DDev->EndScene();
m_pD3DDev->Present(NULL, NULL, NULL, NULL);
}
//
设置摄影机坐标系
VOID CD9Game::SetCamera()
{
D3DXMATRIX mView;
D3DXMatrixLookAtLH(&mView, &D3DXVECTOR3(m_fx, m_fy,-64.0f),
&D3DXVECTOR3(0.0f, 0.0f, 0.0f),
&D3DXVECTOR3(0.0f, 1.0f, 0.0f));
m_pD3DDev->SetTransform(D3DTS_VIEW, &mView);
}
//
设置投影模式
VOID CD9Game::SetPerspective()
{
D3DXMATRIX mProj;
D3DXMatrixPerspectiveFovLH(&mProj, D3DX_PI/4, 1.0f, 1.0f, 512.0f);
//D3DXMatrixOrthoLH(&mProj, 64.0f, 64.0f, 1.0f, 512.0f);
m_pD3DDev->SetTransform(D3DTS_PROJECTION, &mProj);
}
---------------------------------------------------------------
4.4.2
说明
其实, 设置摄影机和投影在game1中就使用到了. 例子中5个模型绕不同的轴自转, 第一个绕X轴自转, 第二个绕Y轴自转, 第三个先X轴再Y轴最后Z轴自转, 同时把物体放大了一倍, 第四个绕Z轴自转, 最后的绕自定义的轴自转.
因为模型的坐标是参考世界坐标系建立的(这集的前面提到过), 而且模型是自转的, 所以我们必须作相映的坐标变换使模型能正确自转. 如果不这么做模型会变成绕轴旋转而不是自转了, 如图4.7.
图4.7
在转换中, 转换的矩阵的先后顺序很重要, 因为矩阵的乘法不可交换, 所以不同的先后顺序产生的效果是不同的, 一定要注意 -- 顺序.
第四集 小结
这一集我们学习了要进行DirectX Graphics 3D编程中的高等代数知识部分, 向量, 矩阵等, 例子是使用不同的模型转换矩阵来变换不同的模型.