这里介绍的是Direct里提供的骨骼动画Api。
D3DXFRAME和D3DXMESHCONTAINER是Direct3D提供的两个结构,D3DXFRAME用于保存模型的骨骼框架,D3DXMESHCONTAINER结构用于保存模型的网格数据。
在使用时我们要继承这两个结构,添加一些新的成员。
struct D3DXFRAME_EX: public D3DXFRAME //扩展D3D框架类
{
D3DXMATRIXA16 CombinedTransformationMatrix; //组合后的变换矩阵
};
扩展的CombinedTransformationMatrix是为了复合世界矩阵后保存的结果,Frame中的矩阵保存的是骨骼动画本地的矩阵,而我们真正用到的应该是和世界矩阵复合后的矩阵,所以扩展此变量来保存复合后的结果。
struct D3DXMESHCONTAINER_EX: public D3DXMESHCONTAINER //扩展D3D网格容器类
{
LPDIRECT3DTEXTURE9 *ppTextures; // 纹理数组
// 蒙皮网格信息
LPD3DXMESH pOrigMesh; //骨骼动画最原始的Mesh
LPD3DXATTRIBUTERANGE pAttributeTable;
DWORD NumAttributeGroups; //ConvertToBlendedMesh中生成
DWORD NumInfl; //ConvertToBlendedMesh中生成
LPD3DXBUFFER pBoneCombinationBuf; //ConvertToBlendedMesh中生成
D3DXMATRIX** ppBoneMatrixPtrs;
D3DXMATRIX* pBoneOffsetMatrices;
DWORD NumPaletteEntries;
bool UseSoftwareVP;
DWORD iAttributeSW; // used to denote the split between SW and HW if necessary for non-indexed skinning
};
主要是pBoneCombinationBuf和pBoneOffsetMatrices两个参数pBoneOffsetMatrices表示骨骼相对本地空间变化的矩阵,而ppBoneMatrixPtrs记录的是矩阵的地址的数组,记录的是其对应的Frame的CombinedTransformationMatrix地址(此地址复合过世界矩阵),所以pBoneCombinationBuf和pBoneOffsetMatrices中相同骨骼复合后的矩阵就为世界空间中世界矩阵。
介绍完这两个必用的结构体后我们来封装骨骼动画的类,他继承于CXPhyOBJ类。
class CAnimMesh:public CXPhyOBJ
{
public:
CAnimMesh(void);
public:
~CAnimMesh(void);
HRESULT LoadAnmMeshFromFile(char* sFile,char* sText ); //加载.x文件
int Render(float fPass);
OBJSTATE SetState(OBJSTATE OS,bool IsBackSpeed=false) ; //设置动画的状态和运动的方向,根据动画状态决定播放哪个动画
HRESULT Attack();
D3DXMATRIX GetWorldByBone(char* sBoneName,bool ForTrans=false); //通过骨骼名称得到骨骼的世界矩阵
BOOL GetFrameMatrix(LPD3DXFRAME pFrameBase, char *strFrameName,D3DXMATRIX *pMat);
D3DXMATRIX* GetFrameMatrix(char *sFrameName); //通过骨骼名称得到骨骼的世界矩阵
private:
LPD3DXFRAME mFrameRoot; //Frame根节点
LPD3DXANIMATIONCONTROLLER mAnimController; //动画控制器
VOID DrawMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase, LPD3DXFRAME pFrameBase); //根据LPD3DXMESHCONTAINER和LPD3DXFRAME绘制动画的Mesh
VOID DrawFrame(LPD3DXFRAME pFrame); //从根节点遍历的绘制
HRESULT SetupBoneMatrixPointers(LPD3DXFRAME pFrame) ; //从frameRoot遍历调用各个Frame的SetupBoneMatrixPointersOnMesh
HRESULT SetupBoneMatrixPointersOnMesh(LPD3DXMESHCONTAINER pMeshContainerBase) ; //使MeshContaniner转换成D3DXMESHCONTAINER_EX类型使其中的ppBoneMatrixPtrs与相应的Frame的CombinedTransforCombinedTransformationMatrix绑定
LPDIRECT3DTEXTURE9 mFace; //纹理
VOID UpdateFrameMatrices(LPD3DXFRAME pFrameBase,LPD3DXMATRIX pParentMatrix); //从pFrameBase遍历,使本身的矩阵与pParent的矩阵复合,pParent常为世界矩阵
LPD3DXANIMATIONSET mAnimSet; //动作集根据不同的动作集设置不同的动画
DWORD mOldAnimSetFrame,mCurAnimSetFrame; //动画播放的时间,用来判断是否动画播放完毕
bool mIsOneSetPlayDone;
BONEINFO mBones[128]; //自建的骨骼信息
int mNowBoneInfoCount; //当前的骨骼数量
HRESULT CheckMouseHit(LPD3DXMESH Mesh,int iAttr); //鼠标的点选
BONEINFO *GetBoneInfo(char *sBoneName); //通过骨骼名称得到骨骼信息
int AddBoneInfo(int Index,char *sBoneName,D3DXMATRIX* pMat); //添加骨骼到mBones中
CHeaderInfo mHeader;
CAmmo *mAmmo;
};
Direct骨骼动画的调用过程:主要的核心函数为D3DXLoadMeshHierarchyFromX(sFile, D3DXMESH_MANAGED, mDVC->GetDVC(), &Alloc, NULL, &mFrameRoot, &mAnimController);
第四个参数为继承于ID3DXAllocateHierarchy的类,此类必须实现父类的CreateFrame,CreateMeshContainer,DestroyFrame,DestroyMeshContainer方法。mFrameRoot为.x文件中Frame的跟节点,最后一个为动画控制器。
Frame中的TransformationMatrix为Mesh自身相对自身空间的变换矩阵,结合基类的世界矩阵后复合成CombinedTransformationMatrix(此矩阵的地址对应ppBoneMatrixPtrs,此处的使用展现了指针的灵活性),而pBoneOffsetMatrices为骨骼相对于自身空间的变化矩阵,所以每个骨骼使用相应的pBoneOffsetMatrices和ppBoneMatrixPtrs复合后的矩阵,随着动画控制器中传入的时间参数不断的变化,矩阵也随着变化,结果就产生了动画。
浙公网安备 33010602011771号