资源描述
第14讲 骨骼动画1、模型动画信息骨骼动画模型中的骨骼是以树状层次结构组织起来的,整个骨骼结构中有一块根骨骼(Root),其他的骨骼都直接或间接连接到根骨骼上,从而形成角色模型的整个骨骼框架,如图所示。不含动画的普通X文件,有一个Mesh单元,保存了各顶点信息、各三角面的索引信息、材质种类及定义等。而动画X文件,则在这个单元中增加了“各骨骼蒙皮信息”、“骨骼层次及结构信息”、“各时刻骨骼矩阵信息”等。(1)在X文件中,骨骼信息是有框架(Frame)组成的,由于Frame模板是开放模板类型,所以在其中可以包含其他的Frame。框架中通过嵌套定义也就形成了父子框架,而并列定义也就形成了兄弟框架,从而形成一个层次结构。同时每块骨骼都包含两个矩阵:初始变换矩阵LocalTransformMatrix和组合变换矩阵CombinedTransformMatrix,其中初始变换矩阵用于表示骨骼的初始位置,而组合变换矩阵用于对骨骼进行各种变换。在Directx中,用一个D3DXFRAME结构或者X文件中的Frame template来表示帧对象。下面看一下Frame template和D3DXFRAME结构的定义:template Frame FrameTransformMatrix frameTransformMatrix; / 骨骼相对于父节点的坐标变换矩阵,就是一个matrix Mesh mesh; / 骨骼的Mesh typedef struct _D3DXFRAMELPSTR Name; / 骨骼名称 D3DXMATRIX TransformationMatrix; / 相对与父节点的坐标变换矩阵 LPD3DXMESHCONTAINER pMeshContainer; / LPD3DXMESHCONTAINER对象, 用来加载MESH,struct _D3DXFRAME*pFrameSibling;/兄弟节点指针 struct _D3DXFRAME *pFrameFirstChild; / 子节点指针 D3DXFRAME, *LPD3DXFRAME;(2)为了使一个X文件产生动画,必须至少提供一个动画集,每个动画集都应具有一个对某个框架的引用。在X文件中,动画集由AnimationSet模板定义,其中由多个开放性模板Animation模板组成。AnimationSet模板及Animation模板的定义如下:template AnimationSet Animation template Animation . AnimationSet模板只存储Animation对象,而Animation通常是由AnimationKey模板进行填充。这个模板用于存储动画关键帧码,这个模板的每一个实例都包含帧码的类型(位置,缩放,转动,矩阵)和帧码数组。数组中的每一个元素包含帧码的值和一个DWORD型的值指出帧的持续时间。AnimationKey模板的定义如下:template AnimationKey /骨骼的各个动画帧时刻的动作数据模板 DWORD keyType; DWORD nKeys; array TimedFloatKeys keysnKeys; template TimedFloatKeys DWORD time; FloatKeys tfkeys; 其中,AnimationKey模板中的keyType表示当前关键帧的类型。若该值为0,则表示旋转键,表示将使用四个分量w、x、y、z存储模型的旋转值。其值为1表示缩放键,它表示分别对应x、y、z轴的模型缩放值。而对于平移键,其值将为2。该值为4,则表示变换矩阵键,此时关键帧的变换数组将使用16个浮点数实现该模型的各种变换。例如:AnimationSet walk Animation AnimationKey 4; /变换矩阵键 2; /2个动作 /第一个动作 0;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000, 0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000;, /第二个动作 4960;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000, 0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000; Scene_Root (3)皮肤属性由XSkinMeshHeader模板定义,其中包含了影响皮肤网格顶点的最大变换数和骨骼数。皮肤权重由SkinWeights模板定义,其中包含了一个具体的骨骼对于相应顶点的影响权重。这两个模板的定义如下:template XSkinMeshHeader WORD nMaxSkinWeightsPerVertex; /一个顶点可以受到骨骼影响的最大骨骼数,可用于计算共同作用时减少遍历次数WORD nMaxSkinWeightsPerFace; /一个三角面可以受到骨骼影响的最大骨骼数。这个数字对硬件顶点混合计算提出了基本要求。 WORD nBones; /当前Mesh的骨骼总数 由于每个骨骼的蒙皮信息都需要用SkinWeights结构去描述,所以有多少块骨骼,在Mesh中就有多少个SkinWeights对象。注意,一般把SkinWeights视作Mesh的一部分。这种Mesh又称Skinned Mesh (蒙皮网格),SkinWeights 结构如下:template SkinWeights STRING transformNodeName; /骨骼名 DWORD nWeights; /权重数组的元素个数,即该骨骼相关的顶点个数array DWORD vertexIndicesnWeights; /受该骨骼控制的顶点索引,实际上定义了该骨骼的蒙皮 array float weightsnWeights; /蒙皮各顶点的受本骨骼影响的权值Matrix4x4 matrixOffset; /骨骼偏移矩阵,用来从初始Mesh坐标,反向计算顶点在子骨骼坐标系中的初始坐标。 在有的书中,把上面的matrixOffset叫骨骼权重矩阵,是不恰当的。我们应该称为骨骼偏移矩阵比较合适。2、加载骨骼动画数据保存从X文件中读取的骨骼动画数据,Direct3D定义了D3DXFRAME和D3DXMESHCONTAINER两个结构。其中,D3DXFRAME结构用于保存X文件中的骨骼信息(框架通常用来描述骨骼,所以也可以将框架看作骨骼),而D3DXMESHCONTAINER结构则用于保存网格蒙皮信息。这两个结构体的定义。 typedef struct _D3DXFRAME /保存框架骨骼信息 LPSTR Name; / 骨骼的名称 D3DXMATRIX TransformationMatrix; / 本骨骼的转换矩阵 LPD3DXMESHCONTAINER pMeshContainer; / 本骨骼所对应Mesh数据 struct _D3DXFRAME *pFrameSibling; / 兄弟骨骼 struct _D3DXFRAME *pFrameFirstChild; / 子骨骼 D3DXFRAME, *LPD3DXFRAME;typedef struct _D3DXMESHCONTAINER /网格容器 保存网格蒙皮信息 LPSTR Name; / Mesh名称 D3DXMESHDATA MeshData; / Mesh数据 LPD3DXMATERIAL pMaterials; / 材质数组 LPD3DXEFFECTINSTANCE pEffects; / 效果 DWORD NumMaterials; / 材质数 DWORD *pAdjacency; / 邻接三角形数组 LPD3DXSKININFO pSkinInfo; / 蒙皮信息 struct _D3DXMESHCONTAINER *pNextMeshContainer; D3DXMESHCONTAINER, *LPD3DXMESHCONTAINER;在实现动画网格模型的绘制前,不仅要得到每个框架的初始变换矩阵,同时还要得到从该框架的所有父节点到本级框架的组合变换矩阵。这是因为任何一个父框架的位置改变都会影响该框架自身位置的变化,所以在此将结构D3DXFRAME 扩展为D3DXFRAME_ DERIVED。例如:struct D3DXFRAME_DERIVED: public D3DXFRAME D3DXMATRIXA16 TransformationMatrix; D3DXMATRIXA16 CombinedTransformationMatrix; /组合转换矩阵; 由于在D3DXMESHCONTAINER结构中并没有记录网格模型的纹理、蒙皮等信息,所以在应用程序中还需要将该结构扩展为D3DXMESHCONTAINER_DERIVED。例如:struct D3DXMESHCONTAINER_DERIVED: public D3DXMESHCONTAINER LPDIRECT3DTEXTURE9* ppTextures; / 纹理数组 LPD3DXMESH pOrigMesh; / 原始网格 LPD3DXATTRIBUTERANGE pAttributeTable; / 网格的属性表 DWORD NumAttributeGroups; / 属性组数量,即子网格数量 DWORD NumInfl; / 每个顶点最多受多少骨骼的影响 LPD3DXBUFFER pBoneCombinationBuf; / 骨骼结合表 D3DXMATRIX* ppBoneMatrixPtrs; / 存放骨骼的组合变换矩阵 D3DXMATRIX* pBoneOffsetMatrices; / 存放骨骼的初始变换矩阵 DWORD NumPaletteEntries; / 骨骼数量上限 bool UseSoftwareVP; / 标志是否使用软件顶点处理; 其中,pBoneCombBuffer指向骨骼结合表,骨骼结合表中的数据按属性组结构体D3DXBONECOMBINATION组织起来。该结构体定义如下:typedef struct D3DXBONECOMBINATION DWORD AttribId; / 属性ID DWORD FaceStart; / 起始的三角面 DWORD FaceCount; / 三角面面数 DWORD VertexStart; / 起始的顶点 DWORD VertexCount; / 顶点数 DWORD * BoneId; / 在每次绘制时所用到的骨骼矩阵 D3DXBONECOMBINATION, *LPD3DXBONECOMBINATION; Direct3D提供了多种骨骼数据的加载方式,然而标准的加载方式是通过调用D3DX库中D3DXLoadMeshHierarchyFromX函数读取Mesh层次信息。该函数的声明如下:HRESULT D3DXLoadMeshHierarchyFromX( /网格层次结构模型 LPCSTR Filename, / X文件名 DWORD MeshOptions, / 加载选项,通常为D3DXMESH_MANAGED LPDIRECT3DDEVICE9 pDevice, LPD3DXALLOCATEHIERARCHY pAlloc, / 自定义数据容器 LPD3DXLOADUSERDATA pUserDataLoader, / 用户数据加载器,通常设为NULL LPD3DXFRAME *ppFrameHierarchy, / 框架层次结构的根框架 LPD3DXANIMATIONCONTROLLER *ppAnimController / 动画控制器); (1)自定义数据容器类:CAllocateHierarchy类自ID3DXAllocateHierarchy接口继承,该类分别重载了ID3DXAllocateHierarchy接口中四个方法,用于实现动画网格模型数据的加载和释放。该类的定义如下:/这里是Directx9.0a的class CAllocateHierarchy: public ID3DXAllocateHierarchypublic:STDMETHOD(CreateFrame)(THIS_ LPCTSTR Name, LPD3DXFRAME *ppNewFrame);#if (D3D_SDK_VERSION & 0xFF)= 31)/这里是Directx9.0b的STDMETHOD(CreateMeshContainer)(THIS_ LPCTSTR Name, LPD3DXMESHDATA pMeshData,LPD3DXMATERIAL pMaterials, LPD3DXEFFECTINSTANCE pEffectInstances, DWORD NumMaterials, DWORD *pAdjacency, LPD3DXSKININFO pSkinInfo, LPD3DXMESHCONTAINER *ppNewMeshContainer);#else/这里是Directx9.0c的STDMETHOD(CreateMeshContainer)(THIS_ LPCSTR Name, CONST D3DXMESHDATA *pMeshData,CONST D3DXMATERIAL *pMaterials, CONST D3DXEFFECTINSTANCE *pEffectInstances, DWORD NumMaterials, CONST DWORD *pAdjacency, LPD3DXSKININFO pSkinInfo, LPD3DXMESHCONTAINER *ppNewMeshContainer);#endifSTDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME pFrameToFree);STDMETHOD(DestroyMeshContainer)(THIS_ LPD3DXMESHCONTAINER pMeshContainerBase);CAllocateHierarchy(CSkinMesh *pSkinMesh) :m_pSkinMesh(pSkinMesh) public:CSkinMesh*m_pSkinMesh;其中,CreateFrame函数仅仅用来创建一个D3DXFRAME对象,并按照指定的参数为该框架命名。HRESULT CAllocateHierarchy:CreateFrame(LPCTSTR Name, LPD3DXFRAME *ppNewFrame) HRESULT hr = S_OK; D3DXFRAME_DERIVED *pFrame; *ppNewFrame = NULL; pFrame = new D3DXFRAME_DERIVED;/为框架指定名称,创建框架结构对象 if (pFrame = NULL) hr = E_OUTOFMEMORY; goto e_Exit; hr = AllocateName(Name, &pFrame-Name); if (FAILED(hr) goto e_Exit;/初始化frame其他成员变量 D3DXMatrixIdentity(&pFrame-TransformationMatrix); D3DXMatrixIdentity(&pFrame-CombinedTransformationMatrix); pFrame-pMeshContainer = NULL; pFrame-pFrameSibling = NULL; pFrame-pFrameFirstChild = NULL; *ppNewFrame = pFrame; pFrame = NULL;e_Exit: delete pFrame; return hr;AllocateName函数用于为一个LPSTR类型字符串分配内存,并用LPCSTR类型的字符串对它进行赋值。HRESULT AllocateName( LPCTSTR Name, LPTSTR *pNewName ) UINT cbLength; if (Name != NULL) cbLength = lstrlen(Name) + 1; *pNewName = new TCHARcbLength; if (*pNewName = NULL) return E_OUTOFMEMORY; memcpy(*pNewName, Name, cbLength*sizeof(TCHAR); else *pNewName = NULL; return S_OK;DestroyFrame函数比较简单,它只有一个LPD3DXFRAME类型参数,并指向准备释放的框架对象。该函数首先通过SAFE_DELETE_ARRAY宏实现框架对象的命名,然后通过SAFE_DELETE宏释放该对象。该函数的实现代码如下HRESULT CAllocateHierarchy:DestroyFrame( LPD3DXFRAME pFrameToFree ) SAFE_DELETE_ARRAY( pFrameToFree-Name ); SAFE_DELETE( pFrameToFree ); return S_OK; 其中:#define SAFE_DELETE(p) if(p) delete (p); (p)=NULL; #define SAFE_DELETE_ARRAY(p) if(p) delete (p); (p)=NULL; #define SAFE_RELEASE(p) if(p) (p)-Release(); (p)=NULL; 从CreateMeshContainer函数的声明中可以看出,传入该函数的参数包括pMeshData、pMaterials、pEffectInstances、NumMaterials、pAjacency和pSkinInfo等。因此,在该函数体内需要将这些数据保存到一个D3DXMESHCONTAINER对象中。并且,其中所有数组所需的空间都需要在全局堆中进行分配。例如:D3DXMESHCONTAINER_DERIVED *pMeshContainer = NULL; pMeshContainer = new D3DXMESHCONTAINER_DERIVED; pMeshContainer-NumMaterials = max( 1, NumMaterials ); pMeshContainer-pMaterials = new D3DXMATERIALpMeshContainer-NumMaterials; pMeshContainer-ppTextures = new LPDIRECT3DTEXTURE9pMeshContainer-NumMaterials; MeshContainer-pAdjacency = new DWORDNumFaces*3; 通过memcpy函数分别将这些对象复制到pMeshContainer对象中。由于在绘制过程中并不需要pEffectInstanes,所以就不需要对它进行保存。如果材质中未包含纹理贴图,那么将使用默认的材质属性。判断pSkinInfo是否包含蒙皮信息,如果pSkinInfo不为NULL,那么就需要通过该信息中的蒙皮信息创建蒙皮网格对象。首先,将原网格对象保存到pMeshContainer对象的pOrigMesh中,然后将保存在pSkinInfo中的各骨骼的偏移矩阵复制到pMeshContainer对象的pBoneOffsetMatrices中。CSkinMesh类中的GenerateSkinnedMesh函数用来生成蒙皮网格数据,其中调用ID3DXSkinInfo接口的ConvertToBlendedMesh或ConvertToIndexedBlendedMesh方法生成已经过顶点混合或索引顶点混合后的蒙皮网格对象。ConvertToBlendedMesh与ConvertToIndexedBlendMesh方法的区别在于,前者将采用无索引的顶点混合生成蒙皮网格对象,而后者则采用含有索引的顶点混合生成蒙皮网格对象。HRESULT ConvertToIBlendedMesh( LPD3DXMESH pMesh, DWORD Options, const DWORD *pAdjacencyIn, LPDWORD pAdjacencyOut, DWORD *pFaceRemap, LPD3DXBUFFER *ppVertexRemap, DWORD *pMaxVertexInfl, DWORD *pNumBoneCombinations, LPD3DXBUFFER *ppBoneCombinationTable, LPD3DXMESH *ppMesh );HRESULT ConvertToIndexedBlendedMesh( LPD3DXMESH pMesh, DWORD Options, DWORD paletteSize, const DWORD *pAdjacencyIn, LPDWORD pAdjacencyOut, DWORD *pFaceRemap, LPD3DXBUFFER *ppVertexRemap, DWORD *pMaxVertexInfl, DWORD *pNumBoneCombinations, LPD3DXBUFFER *ppBoneCombinationTable, LPD3DXMESH *ppMesh );3、顶点混合技术(1)定点混合原理网格模型是由一个个顶点构成的,如果任意一个顶点只受一块骨骼影响,那么网格模型在运动时很容易出现裂缝,特别是在一些结合部位,如肩关节和肘关节等,如图所示。顶点混合就是Direct3D首先会根据骨骼权重和骨骼矩阵对顶点数据(包括顶点位置和顶点法向量)进行混合,然后再对混合后的图形进行渲染。Direct3D最初的图形进行了两次变换。其中,第一次没有对顶点进行变换,它只相当于对顶点数据乘以一个单位矩阵。而第二次对图形进行了简单的旋转变换,它相当于对顶点数据乘以一个旋转矩阵。将两次变换后的顶点数据进行混合,再经过渲染就得到了最终显示的图形,如图所示。Direct3D根据混合矩阵和相应的权重对顶点位置和法线进行线性插值。计算公式如下:因为所有混合权重之和为1.0,所以在顶点数据中只需保存前n-1个混合权重,第n个混合权重为1.0减去前n-1个混合权重之和。在Direct3D引擎中,影响每个顶点的混合矩阵最大数量限定为4,所以在Direct3D中顶点混合就有以下三种情况:(2)索引顶点混合由于Direct3D限定每个顶点最多受到四个混合矩阵的影响,所以每个顶点最多具有四个矩阵索引,并用一个DWORD类型的整数存储和表示,如图所示。在渲染一个三角形时最多可能需要使用12个混合矩阵,因此矩阵调色板中最少需要包含12个混合矩阵,如图所示在渲染图形时,要想启用索引顶点混合,需要将渲染状态D3DRS_INDEXEDVERTEX BLENDENABLE设置为TRUE。另外,还需要在顶点数据中包含矩阵索引的数据,每个顶点的矩阵索引默认为03。例如:g_pd3dDevice-SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, TRUE); g_pd3dDevice-SetRenderState(D3DRS_VERTEXBLEND, ppMeshContainer-NumInfl-1); 4、蒙皮骨骼动画网格模型类介绍5、相关代码:定义SkinMesh.h文件:#pragma once#include #include #include #define SAFE_DELETE(p) if(p) delete (p); (p)=NULL; #define SAFE_DELETE_ARRAY(p) if(p) delete (p); (p)=NULL; #define SAFE_RELEASE(p) if(p) (p)-Release(); (p)=NULL; /-/ Name: struct D3DXFRAME_DERIVED/ Desc: Structure derived from D3DXFRAME so we can add some app-specific/ info that will be stored with each frame/-struct D3DXFRAME_DERIVED: public D3DXFRAME D3DXMATRIXA16 CombinedTransformationMatrix;/-/ Name: struct D3DXMESHCONTAINER_DERIVED/ Desc: Structure derived from D3DXMESHCONTAINER so we can add some app-specific/ info that will be stored with each mesh/-struct D3DXMESHCONTAINER_DERIVED: public D3DXMESHCONTAINER LPDIRECT3DTEXTURE9* ppTextures; / array of textures, entries are NULL if no texture specified / SkinMesh info LPD3DXMESH pOrigMesh; LPD3DXATTRIBUTERANGE pAttributeTable; DWORD NumAttributeGroups; DWORD NumInfl; LPD3DXBUFFER pBoneCombinationBuf; 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;/ enum for various skinning modes possibleenum METHOD D3DNONINDEXED, D3DINDEXED, SOFTWARE, NONE;class CSkinMesh;/-/ Name: class CAllocateHierarchy/ Desc: Custom version of ID3DXAllocateHierarchy with custom methods to create/ frames and meshcontainers./-class CAllocateHierarchy: public ID3DXAllocateHierarchypublic: STDMETHOD(CreateFrame)(THIS_ LPCTSTR Name, LPD3DXFRAME *ppNewFrame);#if (D3D_SDK_VERSION & 0xFF)=31)/这里是Directx9.0b的 STDMETHOD(CreateMeshContainer)(THIS_ LPCTSTR Name, LPD3DXMESHDATA pMeshData, LPD3DXMATERIAL pMaterials, LPD3DXEFFECTINSTANCE pEffectInstances, DWORD NumMaterials, DWORD *pAdjacency, LPD3DXSKININFO pSkinInfo, LPD3DXMESHCONTAINER *ppNewMeshContainer);#else/这里是Directx9.0c的 STDMETHOD(CreateMeshContainer)(THIS_ LPCSTR Name, CONST D3DXMESHDATA *pMeshData, CONST D3DXMATERIAL *pMaterials, CONST D3DXEFFECTINSTANCE *pEffectInstances, DWORD NumMaterials, CONST DWORD *pAdjacency, LPD3DXSKININFO pSkinInfo, LPD3DXMESHCONTAINER *ppNewMeshContainer);#endif STDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME pFrameToFree); STDMETHOD(DestroyMeshContainer)(THIS_ LPD3DXMESHCONTAINER pMeshContainerBase); CAllocateHierarchy(CSkinMesh *pSkinMesh) :m_pSkinMesh(pSkinMesh) public:CSkinMesh*m_pSkinMesh;/蒙皮动画class CSkinMesh public:VOID SetAnim(BOOL bAnim);BOOL CSkinMesh:InterSect( D3DVECTOR *pRayOrig,D3DVECTOR *pRayDir,D3DVECTOR* pVRet);VOID UpdateFrameMatrices( LPD3DXFRAME pFrameBase, LPD3DXMATRIX pParentMatrix );LPD3DXANIMATIONCONTROLLER GetAnimController() return m_pAnimController;BOOL SetAnimationName(char *strAnimName);VOID Render(float fTimeFromLastFrame,D3DXVECTOR3 vPos,float angle,float scale=1.0f);HRESULT LoadFromXFile(char* strFileName);HRESULT GenerateSkinnedMesh(D3DXMESHCONTAINER_DERIVED *pMeshContainer);CSkinMesh(LPDIRECT3DDEVICE9 pD3DDevice);/CSkinMesh(LPDIRECT3DDEVICE9 pD3DDevice,char* strFileName);HRESULT CalculateBondingBox(LPD3DXFRAME pFrameParent, D3DXVECTOR3 *pVmin,D3DXVECTOR3 *pVmax)static LPVOID pV; static LPD3DXMESH pMesh;static LPD3DXMATRIX pMat;static D3DXVECTOR3 vMin,vMax; static D3DXVECTOR3 vTransFormed;if(pFrameParent-pMeshContainer)pMesh=pFrameParent-pMeshContainer-MeshData.pMesh; pMat=&(D3DXFRAME_DERIVED*)pFrameParent)-CombinedTransformationMatrix);pMesh-LockVertexBuffer(0,&pV); D3DXComputeBoundingBox(LPD3DXVECTOR3)pV,pMesh-GetNumVertices(),pMesh-GetNumBytesPerVertex(),&vMin,&vMax); vTransFormed.x=pMat-_11*vMin.x+pMat-_21*vMin.y+pMat-_31*vMin.z+pMat-_41;vTransFormed.y=pMat-_12*vMin.x+pMat-_22*vMin.y+pMat-_32*vMin.z+pMat-_42;vTransFormed.z=pMat-_13*vMin.x+pMat-_23*vMin.y+pMat-_33*vMin.z+pMat-_43;if(vTransFormed.xx) pVmin-x=vTransFormed.x;if(vTransFormed.yy) pVmin-y=vTransFormed.y;if(vTransFormed.zz) pVmin-z=vTransFormed.z;vTransFormed.x=pMat-_11*vMax.x+pMat-_21*vMax.y+pMat-_31*vMax.z+pMat-_41;vTransFormed.y=pMat-_12*vMax.x+pMat-_22*vMax.y+pMat-_32*vMax.z+pMat-_42;vTransFormed.z=pMat-_13*vMax.x+pMat-_23*vMax.y+pMat-_33*vMax.z+pMat-_43;if(vTransFormed.xpVmax-x) pVmax-x=vTransFormed.x;if(vTransFormed.ypVmax-y) pVmax-y=vTransFormed.y;if(vTransFormed.zpVmax-z) pVmax-z=vTransFormed.z;pMesh-UnlockVertexBuffer(); /else return S_OK;if(pFrameParent-pFrameSibling)CalculateBondingBox(pFrameParent-pFrameSibling,pVmin,pVmax);if(pFrameParent-pFrameFirstChild)CalculateBondingBox(pFrameParent-pFrameFirstChild,pVmin,pVmax);return S_OK;virtual CSkinMesh();LPDIRECT3DVERTEXSHADER9 m_pIndexedVertexShader4;D3DXMATRIXA16*m_pBoneMatrices;UINTm_NumBoneMatricesMax;METHODm_SkinningMethod;D3DCAPS9m_d3dCaps;D3DXVECTOR3m_vObjectCenter;/ Center of bounding sphere of objectFLOATm_fObjectRadius;/ Radius of bounding sphere of objectD3DXVECTOR3m_vMin;/ Center of bounding sphere of objectD3DXVECTOR3m_vMax;/ Center of bounding sphere of objectprotected:VOID DrawMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase, LPD3DXFRAME pFrameBase);VOID DrawFrame(LPD3DXFRAME pFrame);HRESULT SetupBoneMatrixPointersOnMesh( LPD3DXMESHCONTAINER pMeshContainerBase );HRESULT SetupBoneMatrixPointers( LPD3DXFRAME pFrame );/FLOATm_fRotateAngle;BOOLm_bMoving;LPDIRECT3DDEVICE9m_pd3dDevice;LPD3DXFRAMEm_pFrameRoot;LPD3DXANIMATIONCONTROLLERm_pAnimController;FLOATm_fElapsedTime; / Time elapsed since last frame;定义SkinMesh.cpp#include SkinMesh.h/-/ Name: AllocateName()/ Desc: Allocates memory for a string to hold the name of a frame or mesh/-HRESULT AllocateName( LPCTSTR Name, LPTSTR *pNewName ) UINT cbLength; if (Name != NULL) cbLength = lstrlen(Name) + 1; *pNewName = new TCHARcbLength; if (*pNewName = NULL) return E_OUTOFMEMORY; memcpy(*pNewName, Name, cbLength*sizeof(TCHAR); else *pNewName = NULL; return S_OK;/-/ Name: CAllocateHierarchy:CreateFrame()/ Desc: /-
展开阅读全文