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