维爱迪-动画创作家园 >> 动画理论 >> 3D游戏角色动画 |
第三,使用蒙皮网格:
网格可以分为蒙皮网格(Skin Mesh)和普通网格(Mesh)。蒙皮网格就是具有蒙皮信息的普通网格。为了搞清楚蒙皮网格我们需要介绍相关的三个模版:
template Mesh
{
<3D82AB44-62DA-11CF-AB39-0020AF71E433>
DWORD nVertices; //顶点数
array Vector vertices[nVertices]; //顶点坐标数组
DWORD nFaces; //多边形数
array MeshFace faces[nFaces]; //多边形顶点引索
[...]
}
这个模板存储一个表态的网格和网格的材质。在骨骼蒙皮动画中,整个角色只是一个网格,由蒙皮信息确定网格中的每一个部分如何受到骨骼的影响。网格在内部会分成几个子集,每一个子集将受到一些特定骨骼的影响。
template XSkinMeshHeader
{
< 3CF169CE-FF7C-44ab-93C0-F78F62D172E2 >
WORD nMaxSkinWeightsPerVertex; // 网格中受到骨骼影响的顶点数
WORD nMaxSkinWeightsPerFace; // 网格中受到骨骼影响的多边形数
WORD nBones; // 影响网格顶点的骨骼数量
}
这个模版包含于Mesh模版中。包含关于蒙皮信息的属性。
template SkinWeights
{
< 6F0D123B-BAD2-4167-A0D0-80224F25FABB >
STRING transformNodeName; //骨骼的名字
DWORD nWeights; //附属到该骨骼的顶点数
array DWORD vertexIndices[nWeights]; //附属到该骨骼的顶点引索
array float weights[nWeights]; //相应引索的顶点权值
Matrix4x4 matrixOffset; //相对于骨骼位置的偏移矩阵
}
这个模版也包含于Mesh模版中,真正的蒙皮信息就存储在这里。每一个影响到网格的骨骼在模版中都有实例。例如有12个骨骼影响到网格,Mesh模版里将有12个SkinWeights模版的实例。
蒙皮网格和普通网格的唯一不同点就是看XskinMeshHeader和SkinWeights模版是否存在。如果把这两个模版从任何一个蒙皮网格里面移走的话,就可以得到一个普通网格。在X文件中,我们将会发现一个GUID为TID_D3DRMMesh的模版,这表示模版里面存有一个网格。利用D3D的帮助函数D3DXLoadSkinMeshFromXof将会加载蒙皮网格和其它补充性数据。只需要向它传递一个IDirectXFileData指针,然后它将为你做剩下的事情。现在介绍下D3DXLoadSkinMeshFromXof函数:
HRESULT D3DXLoadSkinMeshFromXof(
LPD3DXFILEDATA pxofMesh, //X文件数据接口
DWORD Options, //加载参数
LPDIRECT3DDEVICE9 pD3DDevice, //使用的三维设备
LPD3DXBUFFER * ppAdjacency, //邻接信息缓冲接口
LPD3DXBUFFER * ppMaterials, //材质缓冲接口
LPD3DXBUFFER * ppEffectInstances, //效果实例接口
DWORD * pMatOut, //材质数
LPD3DXSKININFO * ppSkinInfo, //蒙皮信息接口
LPD3DXMESH * ppMesh //加载的网格模型接口
);
需要特别注意是LPD3DXSKININFO * ppSkinInfo接口,储存着蒙皮信息。
当你加载一个网格,并读取了的这些顶点的权值之后,你可以变换这些顶点去匹配骨骼的方向,使用以下步骤:
1)迭代所有的顶点。为每个顶点进行第2步。
2)对当前顶点连接到的每一个骨头,得到骨头的变换矩阵。
3)对于每个骨头的变换矩阵,用顶点的权值乘以这个变换矩阵然后把这个结果应用到顶点的组合变换矩阵。
4)为每个连接的骨头重复第三步,然后为每个顶点通过第四步重复第二步。当你完成以上步骤,把组合变换矩阵应用到具体的被迭代的顶点(从第一步)。
怎样精确的获得顶点的权值?可以利用ID3DXSkinInfo接口的GetBoneVertexInfluence方法得到这些权值。顶点的权值一般储存在Mesh数据对象的末端。执行完以上步骤后,剩下的仅仅是渲染了。结合前面介绍的计时动画技术,可以把关键帧时间和变换矩阵储存在AnimationSet模版中,利用一些变量不断的修改和更新骨骼层级便能创造出各种动画效果。