這兩天在做 3D蒙皮動(dòng)畫時(shí)遇到些問(wèn)題,折騰了一天半,嗨!很郁悶啊!我要大叫來(lái)發(fā)泄一下。
本來(lái)打算用D3D設(shè)備直接設(shè)置世界坐標(biāo)矩陣來(lái)實(shí)現(xiàn)動(dòng)畫的,但發(fā)現(xiàn)有一個(gè)問(wèn)題,當(dāng)我不使用D3DXEFFECT來(lái)設(shè)置渲染效果的時(shí)候就可以正常顯示動(dòng)畫;當(dāng)我使用它來(lái)設(shè)置渲染效果的時(shí)候,動(dòng)畫就沒(méi)了。我想可能是用D3DXEFFECT來(lái)設(shè)置渲染效果的時(shí)候把D3D設(shè)備的 SetTransform功能屏蔽掉了(其實(shí)我不理解這個(gè)渲染過(guò)程^_^)。
下面說(shuō)一下加載和渲染蒙皮動(dòng)畫的大概流程吧。
首先繼承2個(gè)結(jié)構(gòu):D3DXFRAME、D3DMESHCONTAINER 和一個(gè)接口:ID3DXAllocateHierarchy。
//------------------------------------------------------------
//說(shuō)明:框架
//------------------------------------------------------------
struct GFrame : public D3DXFRAME
{
D3DXMATRIXA16 CombinedTransformationMatrix; //最終變換矩陣
};
//------------------------------------------------------------
//說(shuō)明:網(wǎng)格容器
//------------------------------------------------------------
struct GMeshContainer : public D3DXMESHCONTAINER
{
LPDIRECT3DTEXTURE9 * _ppTexs; //紋理列表
LPD3DXMESH _pOrigMesh; //原mesh
DWORD _dwNumAttrGroups; //屬性組個(gè)數(shù)
DWORD _dwMaxNumInfl; //一個(gè)面最多受多少骨骼影響
DWORD _dwNumPaletteEntries; //樣色個(gè)數(shù)
LPD3DXBUFFER _pBoneCombBuf; //鄰接矩陣列表
D3DXMATRIX** _ppBoneMatrixPtr; //骨骼矩陣列表
D3DXMATRIX* _pBoneOffsetMatrices; //骨骼矩陣引用
DWORD _iAttrSW; //用戶 GenerateSkinnedMesh
};
//------------------------------------------------------------
//說(shuō)明:封裝網(wǎng)格的創(chuàng)建類
//------------------------------------------------------------
class GAllocateHierarchy : public ID3DXAllocateHierarchy
{
public:
// 下面4個(gè)方法是對(duì)父類的實(shí)現(xiàn)
STDMETHOD(CreateFrame)(THIS_ LPCSTR Name, LPD3DXFRAME *ppNewFrame);
STDMETHOD(CreateMeshContainer)(THIS_
LPCSTR Name,
CONST D3DXMESHDATA *pMeshData,
CONST D3DXMATERIAL *pMaterials,
CONST D3DXEFFECTINSTANCE *pEffectInstances,
DWORD NumMaterials,
CONST DWORD *pAdjacency,
LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER *ppNewMeshContainer);
STDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME pFrameToFree);
STDMETHOD(DestroyMeshContainer)(THIS_ LPD3DXMESHCONTAINER pMeshContainerBase);
};
創(chuàng)建兩個(gè)全局指針:
LPD3DXFRAME g_pFrameRoot = NULL; //根Frame
ID3DXAnimationController* g_pAnimCtl = NULL; //動(dòng)畫控制類
接著在初始化的地方(如果使用DXUT,則可以在OnCreateDevice中)調(diào)用 D3DXLoadMeshHierarchyFromX 來(lái)加載x文件。
GAllocateHierarchy ah;
D3DXLoadMeshHierarchyFromX( strXFileName, D3DXMESH_MANAGED, pDev,
& ah, NULL, & g_pFrameRoot, &g_pAnimCtl );
SetupBoneMatrixPointers( g_pFrameRoot, g_pFrameRoot); //建立矩陣指針
D3DXFrameCalculateBoundingSphere( g_pFrameRoot, & g_vObjCenter, g_fObjRadius ); //獲取模型邊界球
SetupBoneMatrixPointers 實(shí)現(xiàn)如下:
接著在更新信息的地方(如果使用DXUT,則可以在OnFrameMove中添加)添加以下代碼:
UpdateFrameMatrices( g_pFrameRoot, &matWorld); //更新骨骼矩陣(其中 matWorld 可以包含模型的平移、縮放、旋轉(zhuǎn)信息)
if( g_pAnimCtl != NULL)
g_pAnimCtl->AdvanceTime( fElapsedTime, NULL); //更新動(dòng)畫信息就靠它了
UpdateFrameMatrices 的實(shí)現(xiàn)如下:
最后在渲染的地方(如果使用DXUT,則在 OnFrameRender中)調(diào)用:
DrawFrame( pDev, g_pFrameRoot);
DrawFrame 的實(shí)現(xiàn)如下:
到此為止就可以實(shí)現(xiàn)加載和渲染動(dòng)畫了,這個(gè)實(shí)現(xiàn)的過(guò)程也有點(diǎn)復(fù)雜,一不小心搞錯(cuò)了某個(gè)地方,可能折騰半天都找不出原因。