網(wǎng)格模型動畫一般有兩種:一種是漸變動畫;另一種是骨骼動畫,這種動畫包含在網(wǎng)格模型之中,通過網(wǎng)格模型不同部分之間的相對運動來實現(xiàn)動畫。
骨骼動畫基本原理
骨骼動畫是目前最流行也最復雜的角色動畫,它包含以下幾個重要元素:骨骼、動畫。骨骼動畫思想的起源很簡單,自然界中的大多數(shù)動物都擁有一套骨骼,身體的皮毛血肉都依附于骨骼,當骨骼開始運動的時候,依附于對應骨骼的皮毛血肉都隨骨骼一起運動。在三維圖形編程領(lǐng)域,角色的軀體是由網(wǎng)格模型來表示的,網(wǎng)格模型通常由大量三角形圖元組成,而三角形又是由頂點組成的。為了模仿現(xiàn)實世界中角色自身的動作,就需要為角色網(wǎng)格模型添加一套骨骼,同時需要確定哪些頂點依附于哪塊骨骼,這樣當骨骼運動時就能牽引依附骨骼的頂點一起運動,這就是骨骼動畫的基本原理。
骨骼動畫模型的骨骼是以樹狀層次結(jié)構(gòu)組織起來的,整個骨骼結(jié)構(gòu)中有一塊根骨骼,其他的骨骼都直接或間接連接到根骨骼上,形成角色模型的整個骨骼框架。
一般每塊骨骼都帶有兩個矩陣,一個是初始變換矩陣(LocalTransformMatrix),表示骨骼的初始位置;另一個是組合變換矩陣(CombinedTransformMaitrx),用于對骨骼進行各種變換,從而實現(xiàn)角色動畫。在每次渲染角色模型前,需要更新整個骨骼層次結(jié)構(gòu),組合每個連續(xù)的變換,將上層骨骼的運動傳遞到下層骨骼,這個原理可表示為:
(子骨骼的)CombinedTransformMaitrx =
(子骨骼的)LocalTransformMaitrx x (父骨骼的)CombinedTransformMaitrx
骨骼的組合變換矩陣是隨動畫的播放不斷變化的,而它的初始變換矩陣一般是不改變的,正是所有骨骼的這些矩陣相互作用才牽引著頂點的變化,從而實現(xiàn)了骨骼動畫。因為一次變換只能將骨骼變換到一個特定位置,要形成連續(xù)的動畫就需要一幀一幀地連續(xù)改變骨骼的位置,每次改變骨骼的位置都需要一個骨骼變換矩陣,在網(wǎng)格模型中不可能保存任意時刻骨骼的變換矩陣,通常是保存關(guān)鍵時間點骨骼的變換矩陣(即關(guān)鍵楨),然后在播放角色動畫時,根據(jù)播放時間進行插值得到任意時刻骨骼的變換矩陣,從而形成連續(xù)的角色動畫。
骨骼動畫是通過骨骼變換矩陣實現(xiàn)的,在網(wǎng)格模型中保存的也是關(guān)鍵時間點骨骼的變換矩陣,因此插值就是針對這些關(guān)鍵時間點上的骨骼變換矩陣進行的。假設(shè)在s1時刻骨骼變換矩陣是mat1,在s2時刻骨骼變換矩陣是mat2,在s1和s2之間的任意時刻s,其骨骼變換矩陣mat為:
mat = (1-w) * mat1 + w * mat2
其中w是權(quán)值,通過這個權(quán)值來調(diào)節(jié)在s時刻骨骼變換矩陣中mat1和mat2所占的比重,對骨骼變換矩陣進行插值最簡單的方法是線性插值,這時w
= (s-s1) / (s2-s1)
骨骼動畫類的設(shè)計與實現(xiàn)
我們需要將骨骼動畫網(wǎng)格模型的相關(guān)操作封裝到一組類和結(jié)構(gòu)中,這一組類和結(jié)構(gòu)可以看成一套完整的骨骼動畫網(wǎng)格模型接口,它們之間的關(guān)系如下圖所示:

其中,D3DXFRAME和D3DXMESHCONTAINER是Direct3D提供的兩個結(jié)構(gòu),D3DXMESHCONTAINER結(jié)構(gòu)用于保存模型的網(wǎng)格數(shù)據(jù),D3DXFRAME用于保存模型的骨骼框架。結(jié)構(gòu)D3DXMESHCONTAINER_DERIVED繼承自Direct3D提供的結(jié)構(gòu)D3DXMESHCONTAINER,結(jié)構(gòu)D3DXFRAME_DERIVED繼承自Direct3D提供的結(jié)構(gòu)D3DXFRAME,分別進行了相應的擴充,使其能夠保存所需要的其他數(shù)據(jù)。
cAllocateHierarchy類負責從動畫網(wǎng)格模型文件加載各種數(shù)據(jù),該類繼承自Direct3D中的ID3DXAllocateHierarchy接口。
cAnimMesh類是唯一對外開放的類,它通過cAllocateHierarchy類的對象從模型文件中加載所需的數(shù)據(jù),并負責處理骨骼動畫信息以及網(wǎng)格模型的渲染。
繼承并擴展結(jié)構(gòu)體D3DXFRAME
為了在渲染網(wǎng)格模型的同時播放包含在網(wǎng)格模型的動畫,需要處理兩個單獨的實體:骨骼結(jié)構(gòu)(即框架結(jié)構(gòu))和網(wǎng)格模型。框架結(jié)構(gòu)和網(wǎng)格模型的相關(guān)數(shù)據(jù)分別使用D3DXFRAME_DERIVED和D3DXMESHCONTAINER_DERIVED結(jié)構(gòu)保存。需要指出的是.x文件中的一個網(wǎng)格模型可以由多個框架和多個網(wǎng)格組成,但具體到某一個框架時,它一般只有一個網(wǎng)格,當然它也可以有多個網(wǎng)格。
為了方便加載骨骼動畫網(wǎng)格模型,Direct3D提供了兩個重要的結(jié)構(gòu)體:D3DXFRAME和D3DXMESHCONTAINER,其中D3DXFRAME用來加載框架,其定義如下:
Encapsulates a transform frame in a transformation
frame hierarchy.
typedef struct D3DXFRAME {
LPSTR Name;
D3DXMATRIX TransformationMatrix;
LPD3DXMESHCONTAINER pMeshContainer;
D3DXFRAME * pFrameSibling;
D3DXFRAME * pFrameFirstChild;
} D3DXFRAME, *LPD3DXFRAME;
Members
- Name
- Name of the frame.
- TransformationMatrix
- Transformation matrix.
- pMeshContainer
- Pointer to the mesh container.
- pFrameSibling
- Pointer to a sibling frame.
- pFrameFirstChild
- Pointer to a child frame.
Remarks
An application can derive from this structure to add
other data.
顯然在實現(xiàn)動畫網(wǎng)格模型的繪制前,不僅要得到每個框架的初始變換矩陣,同時還要得到從該框架的所有父節(jié)點到本級框架的組合變換矩陣,這是因為任何一個父框架的位置改變都會影響該框架自身位置的變化,所以在此將結(jié)構(gòu)D3DXFRAME擴展為D3DXFRAME_DERIVED,在D3DXFRAME_DERIVED中添加一個成員變量CombinedTransformMaitrx,用TransformationMatrix記錄在任何動畫數(shù)據(jù)未加載前框架的初始變換矩陣,也就是該框架的初始位置,用CombinedTransformMaitrx來記錄從所有的父框架到該框架自身所積累起來的組合變換矩陣,這樣就將整個網(wǎng)格模型很方便地組織起來了。
結(jié)構(gòu)D3DXFRAME_DERIVED的定義如下:
struct D3DXFRAME_DERIVED : public D3DXFRAME
{
D3DXMATRIX CombinedTransformMatrix;
};
繼承并擴展結(jié)構(gòu)體D3DXMESHCONTAINER
結(jié)構(gòu)體D3DXMESHCONTAINER用來加載每個具體網(wǎng)格模型的數(shù)據(jù),其定義如下:
Encapsulates a mesh object in a transformation frame
hierarchy.
typedef struct D3DXMESHCONTAINER {
LPSTR Name;
D3DXMESHDATA MeshData;
LPD3DXMATERIAL pMaterials;
LPD3DXEFFECTINSTANCE pEffects;
DWORD NumMaterials;
DWORD * pAdjacency;
LPD3DXSKININFO pSkinInfo;
D3DXMESHCONTAINER * pNextMeshContainer;
} D3DXMESHCONTAINER, *LPD3DXMESHCONTAINER;
Members
- Name
- Mesh name.
- MeshData
- Type of data in the mesh.
- pMaterials
- Array of mesh materials.
- pEffects
- Pointer to a set of default effect parameters.
- NumMaterials
- Number of materials in the mesh.
- pAdjacency
- Pointer to an array of three DWORDs per triangle
of the mesh that contains adjacency information.
- pSkinInfo
- Pointer to the skin information interface.
- pNextMeshContainer
- Pointer to the next mesh container.
結(jié)構(gòu)體D3DXMESHCONTAINER中沒有記錄網(wǎng)格模型的紋理信息,所以將該結(jié)構(gòu)體擴展為D3DXMESHCONTAINER_DERIVED,定義如下:
struct D3DXMESHCONTAINER_DERIVED : public D3DXMESHCONTAINER
{
IDirect3DTexture9** ppTextures;
};
其中ppTextures用來存儲網(wǎng)格模型的紋理對象。