维爱迪-动画创作家园 >> 动画理论 >> 3D游戏角色动画 |
第二,内嵌数据对象和模版约束:
首先,我们分别声明了三个不同的模版,请仔细看它们的区别。
template ClosedTemplate {
<4C9D055B-C64D-4bfe-A7D9-981F507E45FF>
DWORD ClosedData;
}
template OpenTemplate {
<4C9D055B-C64D-4bff-A7D9-981F507E45FF>
DWORD OpenData;
[...]
}
template RestrictedTemplate {
<4C9D055B-C64D-4c00-A7D9-981F507E45FF>
DWORD RestrictedData;
[ClosedTemplate]
[OpenTemplate]
}
ClosedTemplate看起来没有什么不同,因为它就是标准的模版声明。在OpenTemplate中包含一个[...],表示这是一个开放模版。开放模版允许在[]中内嵌任何数据对象。例如,你可以实例化OpenTemplate,在里面定义一个OpenData变量和内嵌一个ClosedTemplate的实例。最后的RestrictedTemplate为约束模版。约束模版实例化时只允许包含它列出的数据对象,如,不能在RestrictedTemplate包含[ClosedTemplate],[OpenTemplate]以外的数据对象。
第三,充分利用DirectX .X Standard Templates:
正如上面提到的,X文件广泛用于包含一个mesh信息。一个Standard Templates包含了各种信息。
Table 3: DirectX .X Standard Templates
Template Name Description
Animation: Defines animation data for a single frame.
AnimationKey: Defines a single key frame for the parent animation template.
AnimationOptions: Contains animation playback information.
AnimationSet: Contains a collection of animation templates.
Boolean: Holds a Boolean value.
Boolean2d: Holds two Boolean values.
ColorRGB: Contains red, green, and blue color values.
ColorRGBA: Contains red, green, blue, and alpha color values.
Coords2d: Defines two coordinate values.
FloatKeys: Contains an array of floating-point values.
FrameTransformMatrix: Holds the transformation matrix for a parent Frame template.
Frame: A frame-of-reference template that defines a hierarchy.
Header: The .X file header that contains version numbers.
IndexedColor: Contains an indexed color value.
Material: Contains material color values.
Matrix4x4: Holds a 4x4 homogenous matrix container.
Mesh: Contains a single mesh's data.
MeshFace: Holds a mesh's face data.
MeshFaceWraps: Contains the texture wrapping for mesh faces.
MeshMaterialList: Contains the material for face-mapping values.
MeshNormals: Holds normals used for mesh data.
MeshTextureCoords: Holds texture coordinates used for mesh data.
MeshVertexColors: Holds vertex color information used for mesh vertices.
Patch: Defines a control patch.
PatchMesh: Contains a patch mesh (much like the Mesh template).
Quaternion: Holds a quaternion value.
SkinWeights: Contains an array of weight values mapped to a mesh's vertices. Used in skinned meshes.
TextureFilename: Contains the texture file name to use for a material.
TimedFloatKeys: Contains an array of FloatKeys templates.
Vector: Holds a 3D coordinate value.
VertexDuplicationIndices: Informs you which vertices are duplicates of other vertices.
XSkinMeshHeader: Used by skinned meshes to define the number of bones contained in a mesh.
我们可以在DirectX9SDK的安装目录下搜索到“rmxfguid.h”字样的头文件。在rmxfguid.h中定义了各个模版的宏,例如:
/* {3D82AB44-62DA-11cf-AB39-0020AF71E433} */
DEFINE_GUID(TID_D3DRMMesh,
0x3d82ab44, 0x62da, 0x11cf, 0xab, 0x39, 0x0, 0x20, 0xaf, 0x71, 0xe4, 0x33);
每个模版名加上前缀TID_D3DRM就是宏定义名。既然微软已经帮助我们定义了那么多的模版,我们可以根据需求,充分的去利用这些模版。另外,这些模版往往会有相关的帮助函数,我们使用它们可以事半功倍。
第四,创建X文件接口:
我们已经对X文件的模版概念有所了解,现在将使用它们。当然,要想使用首先得访问X文件。访问任何X文件首先要调用DirectXFileCreate函数创建一个IDirectXFile接口,这个接口就代表了一个X文件。
IDirectXFile *pDXFile = NULL;
HRESULT Result = DirectXFileCreate(&pDXFile);//用&pDXFile返回指向接口的指针。用SUCCEEDED或者FAILED宏判断返回值是否有效。
创建完IDirectXFile接口,我们要注册一个定制模版或者标准模版。定制模版是自己定义的模版,标准模版是微软帮我们定义的模版,其实它们之间没有本质的区别,你现在要做的就是告诉IDirectXFile接口,使用二者之中的哪种。
如何注册定制模版呢?下面举个例子更容易理解。你可以把X文件中的模版移除,直接在代码里定义那些模版。IDirectXFile接口支持这样的特性。需要调用IDirectXFile::RegisterTemplates函数。
HRESULT IDirectXFile::RegisterTemplates(
LPVOID pvData, // 一个定义模版数据的缓存,应该精确无误。
DWORD cbSize); // pvData缓存的字节数。
可以如下定义一个模版数据:
char *Templates = "
"xof 0303txt 0032 \ //标准X文件头。
template CustomTemplate { \
<4c944580-9e9a-11cf-ab43-0120af71e433> \
DWORD Length; \
array DWORD Values[Length]; \
}";
之后在用RegisterTemplates将其注册:
pFile->RegisterTemplates(Templates, strlen(Templates));
如何注册标准模版呢?首先需要在代码中包含rmxfguid.h和rmxftmpl.h。rmxfguid.h定义了各个标准模版的GUDI,rmxftmpl.h以2进制数据形式定义了标准模版数据的缓存和其字节数。然后调用RegisterTemplates将其注册:
pFile->RegisterTemplates(D3DRM_XTEMPLATES, \
D3DRM_XTEMPLATE_BYTES);
第五,打开X文件:
创建完IDirectXFile接口,注册模版之后需要打开X文件,枚举其数据对象。调用IDirectXFile::CreateEnumObject函数。
HRESULT IDirectXfile::CreateEnumObject(LPVOID pvSource, // .X filename
DXFILELOADOPTIONS dwLoadOptions, // Load options
LPDIRECTXFILEENUMOBJECT* ppEnumObj); // Enum interface
当调用CreateEnumObject函数,用pvSource指定一个文件的名字,用ppEnumObj返回一个枚举对象接口指针。用dwLoadOptions指定load操作方式。当指定DXFILELOAD_FROMFILE值,告诉DirectX从磁盘载入一个文件。还有DXFILELOAD_FROMRESOURCE,DXFILELOAD_FROMMEMORY和DXFILELOAD_FROMURL分别表示从一个资源,内存缓冲和Internet上加载X文件。当从Internet加载文件时,需要为其指定完整的网址。
下面代码从磁盘加载X文件:
// Filename = filename to load ("test.x" for example)
IDirectXFileEnumObject *pEnum;
pFile->CreateEnumObject((LPVOID)Filename, \
DXFILELOAD_FROMFILE, &pEnum);
Filename指向一个有效的文件名,pEnum返回一个枚举对象接口指针。