Jump to content
主视角中国
  • entries
    44
  • 评论
    24
  • 查看
    145,775

3D游戏角色动画(续一)


3D游戏角色动画

1 介绍微软的X文件

制作3D游戏角色动画需要与之相关的“动画容器”。这个“容器”中储存着动画的数据。微软的X文件正是这样的一种容器。由于微软的影响力,它们公司设计的X文件也广为流传。X文件是一套基于模版定义的文件,理论上它能够容纳任何数据。也就意味着不仅仅是3D模型文件,任何用于游戏引擎加载的外部资源都可以被包含于X文件之中。下面我们详细的介绍下X文件。为了得到一个直观的印象,我们首先浏览下它的全貌。

xof 0302txt 0032

template Header {

<3D82AB43-62DA-11cf-AB39-0020AF71E433>

DWORD major;

DWORD minor;

DWORD flags;

}

template Frame {

<3D82AB46-62DA-11cf-AB39-0020AF71E433>

[FrameTransformMatrix]

[Mesh]

}

Header {

1;

0;

1;

}

Frame Scene_Root {

FrameTransformMatrix {

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;;

}

Frame Pyramid_Frame {

FrameTransformMatrix {

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;;

}

Mesh PyramidMesh {

5;

0.00000;10.00000;0.00000;,

-10.00000;0.00000;10.00000;,

10.00000;0.00000;10.00000;,

-10.00000;0.00000;-10.00000;,

10.00000;0.00000;-10.00000;;

6;

3;0,1,2;,

3;0,2,3;,

3;0,3,4;,

3;0,4,1;,

3;2,1,4;,

3;2,4,3;;

MeshMaterialList {

1;

6;

0,0,0,0,0,0;;

Material Material0 {

1.000000; 1.000000; 1.000000; 1.000000;;

0.000000;

0.050000; 0.050000; 0.050000;;

0.000000; 0.000000; 0.000000;;

}

}

}

}

}

首先看头文件xof 0302txt 0032。xof表示这是一个真正的X文件。0302txt表示通知程序使用Directx的X文件,版本为3.2的模版,其中txt表示此文件为文本文件,可读,并非是一个2进制文件。0032表示一个浮点数的位数为32,如果想要用64位的浮点数,可以写成0064。

下面我们将按照以下七个步骤进行介绍和说明。

第一,声明一个模版:

假设声明 template ContactEntry ,首先需要用guidgen.exe产生一个GUID。产生的GUID如下:

// {4C9D055B-C64D-4bfe-A7D9-981F507E45FF}

DEFINE_GUID(<<name>>,

0x4c9d055b, 0xc64d, 0x4bfe, 0xa7, 0xd9, 0x98, \

0x1f, 0x50, 0x7e, 0x45, 0xff);

之后需要在程序代码中加入:

#include "initguid.h"

// At beginning of source code file - add DEFINE_GUIDs

DEFINE_GUID(ContactEntry, \

0x4c9d055b, 0xc64d, 0x4bfe, 0xa7, 0xd9, 0x98, \

0x1f, 0x50, 0x7e, 0x45, 0xff);

还要在X文件中加入:

template ContactEntry {

<4C9D055B-C64D-4bfe-A7D9-981F507E45FF>}

这里介绍下声明模版用到的数据类型:

关键字 描述

WORD 16-bit value (short)

DWORD 32-bit value (32-bit int or long)

FLOAT IEEE float value (float)

DOUBLE 64-bit floating-point value (double)

CHAR 8-bit signed value (signed char)

UCHAR 8-bit unsigned value (unsigned char)

BYTE 8-bit unsigned value (unsigned char)

STRING A NULL-terminated string (char[]))

array Signifies an array of following data type to follow ([])

使用数据类型的举例:

DWORD Value;

array STRING Text[20];//定义一个名为Text的数组,类型为STRING,大小为20。

DWORD ArraySize; array STRING Names[ArraySize]; //可以将大小设置为变量。

现在,我们声明一个ContactEntry模版:

template ContactEntry {

<4C9D055B-C64D-4bfe-A7D9-981F507E45FF>

STRING Name; // The contact's name

STRING PhoneNumber; // The contact's phone number

DWORD Age; // The contact's age

}

实例化一个模版对象:

ContactEntry JimsEntry {

"Jim Adams";

"(800) 555-1212";

30;

}

{JimsEntry} 可以用这样的形式引用一个数据对象。例如,在一个animation sequence template中引用一个Frame data object做为其内嵌数据对象。也可以利用引用表示一个数据对象的副本,没有必要重复书写这个数据对象。

第二,内嵌数据对象和模版约束:

首先,我们分别声明了三个不同的模版,请仔细看它们的区别。

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);

0 评论


Recommended Comments

没有要显示的评论。

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

登录

Already have an account? Sign in here.

现在登录
×
×
  • 创建新的...