博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

骨骼动画

Posted on 2011-06-29 01:42  +石头+  阅读(590)  评论(0)    收藏  举报

这里介绍的是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复合后的矩阵,随着动画控制器中传入的时间参数不断的变化,矩阵也随着变化,结果就产生了动画。