有很多朋友也许想更加了解X文件,正好,本文将全面的介绍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)
DWORD32-bit value (32-bit int or long)
FLOATIEEE float value (float)
DOUBLE 64-bit floating-point value (double)
CHAR 8-bit signed value (signed char)
UCHAR8-bit unsigned value (unsigned char)
BYTE 8-bit unsigned value (unsigned char)
STRING A NULL-terminated string (char[]))
arraySignifies 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.2: 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.
在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文件首先要调用DirectXFileCreate函数创建一个IDirectXFile接口。
IDirectXFile *pDXFile = NULL;
HRESULT Result = DirectXFileCreate(&pDXFile);//用&pDXFile返回指向接口的指针。用SUCCEEDED或者
FAILED宏判断返回值是否有效。
注册一个定制ro标准模版:\\\\\\\\\\\\\你可以把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返回一个枚举对象接口指针。
枚举数据对象:\\\\\\\\\\\\\\\注册完模版,打开X文件并且得到一个枚举对象接口,下面需要从X文件读出数据。枚举对象接口指针指向
文件的第一个数据对象,因为每一个数据对象可能包含内嵌数据对象或者引用的数据对象,所以与第一个
数据对象同在一层级的其它数据对象为同层级数据对象。至于包含的子数据对象的类型,需要对其分别的
行进询问。
可以用 HRESULT IDirectXFileEnumObject::GetNextDataObject(LPDIRECTXFILEDATA*ppDataObj)得到一
个IDirectXFileData接口。它只有一个参数,如下:
IDirectXFileData *pData;
HRESULT hr = pEnum->GetNextDataObject(&pData);
利用此函数,可以不断地访问同一层级的数据对象接口,具体代码如下:
while(SUCCEEDED(pEnum->GetNextDataObject(&pData))) {
// 这里可以对pData数据对象进行操作。
pData->Release();//释放接口。
}
当返回值为FAILED,表示已经访问完所有的接口。当访问值为SUCCEEDED,你需要继续判断这个数据对象
是否包含子对象。利用接口IDirectXFileObject,和HRESULT IDirectXFileData::GetNextObject(
LPDIRECTXFILEOBJECT* ppChildObj)函数,代码如下:
IDirectXFileObject *pObject;
while(SUCCEEDED(pData->GetNextObject(&pObject)))
{
// 如果一个子对象存在,需要继续询问它,判断出它的类型为内嵌数据对象或者引用的数据对象。
pObject->Release();// 释放接口。
}
接下来询问接口,看其是否为内嵌数据对象:
IDirectXFileData *pSubData;
if(SUCCEEDED(pObject->QueryInterface( IID_IDirectXFileData, (void**)&pSubData))) {
// 如果询问内嵌数据对象成功,可以对pSubData数据对象进行操作
pSubData->Release();//释放接口。
}
看其是否为引用数据对象:
IDirectXFileDataReference *pRef;
IDirectXFileData *pSubData;
if(SUCCEEDED(pSubObj->QueryInterface( IID_IDirectXFileDataReference, (void**)&pRef))) {
// 如果询问引用的数据对象成功,解析出引用的原型。
pRef->Resolve(&pSubData);
//这里可以对pData数据对象进行操作。
pRef->Release();
pSubData->Release();//释放接口。
}
现在整理下思路:大体的思路其实很简单,首先枚举最顶层的数据对象,然后判断其是否有子对象,这个
子对象可能是内嵌对象或者引用对象二者之一,分别询问其接口,就可以判断出具体的类型。
下面是完整的Parse模版的函数:
BOOL Parse(char *Filename)
{
IDirectXFile *pFile = NULL;
IDirectXFileEnumObject *pEnum = NULL;
IDirectXFileData *pData = NULL;
if(FAILED(DirectXFileCreate(&pFile)))
return FALSE;
//注册标准模版。
if(FAILED(pFile->RegisterTemplates( (LPVOID)D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES)))
return FALSE;
//创建一个枚举对象接口。
if(FAILED(pDXFile->CreateEnumObject((LPVOID)Filename, DXFILELOAD_FROMFILE, &pEnum))) {
pFile->Release();
return FALSE;
}
// 遍历所有的顶层数据对象。
while(SUCCEEDED(pEnum->GetNextDataObject(&pData))) {
// 用ParseObject解析其子数据对象。
ParseObject(pData);
pData->Release();
}
pEnum->Release();
pFile->Release();
return TRUE;
}
这个函数的主要部分在ParseObject(pData),它负责解析子数据对象:
void ParseObject(IDirectXFileData *pData)
{
IDirectXFileObject *pObject = NULL;
IDirectXFileData *pSubData = NULL;
IDirectXFileDataReference *pRef = NULL;
while(SUCCEEDED(pData->GetNextObject(&pObject))) {
if(SUCCEEDED(pObject->QueryInterface( IID_IDirectXFileDataReference, (void**)&pRef))) {
pRef->Resolve(&pSubData);
ParseObject(pSubData);
pSubData->Release();
pRef->Release();
}
if(SUCCEEDED(pObject->QueryInterface( IID_IDirectXFileData, (void**)&pSubData))) {
ParseObject(pSubData);
pSubData->Release();
}
pObject->Release();
}
}
这是个第归函数,调用函数自身。判断子对象的类别,对其继续解析,直到返回值为FAILED,表示已没有
子对象。从上面可以看出,这个函数除了枚举所有的对象,并没有做任何事情,下面就要从这些数据对象
检索数据。
从数据对象检索数据://///////////////
当你用IDirectXFileData接口指针指向一个有效的数据对象,可以调用IDirectXFileData::GetName函数得到该数据对象的名字。函数原型为:
HRESULT IDirectXFileData::GetName(
LPSTR pstrNameBuf, // 名字缓冲
LPDWORD pdwBufLen); // 名字缓冲的大小
可以这样使用这个函数:
DWORD Size;
pData->GetName(NULL, &Size);
char *Name = new char[Size];
pData->GetName(Name, &Size);
首先声明一个DWORD Size变量,调用GetName函数时将第一个参数设为NULL,在Size返回名字缓冲的大小。之后利用这个Size值创建存放名字的缓冲,再调用GetName在Name中返回数据对象的名字。
得到了数据对象的名字,你需要得到这个数据对象的模版GUID,去判断这个数据对象是否为你想使用的那个模版的数据对象。利用IDirectXFileData::GetType函数,其原型为:
HRESULT IDirectXFileData::GetType(const GUID ** ppguid);
可以这样使用这个函数:
const GUID *TemplateGUID = NULL;
pData->GetType(&TemplateGUID);//在TemplateGUID中返回该数据对象对应模版的GUID。
现在去匹配这个GUID,看它是否为你想使用的模版的数据对象。
if(*TemplateGUID == TID_D3DRMMeshNormals) {
// 如果匹配成功,这里可以继续处理这个模版的数据对象。
}
最后将介绍GetData函数,用它真正的得到了数据对象的数据。其原型为:
HRESULT IDirectXFileData::GetData(
LPCSTR szMember, // 设置为NULL
DWORD *pcbSize, // 数据的大小
void **ppvData); // 数据指针
下面介绍用GetData得到数据对象结构的大小和数据对象的数据。
假设有这样一个颜色的模版:
template ColorRGBA {
<35FF44E0-6C7C-11cf-8F52-0040333594A3>
FLOAT red;
FLOAT green;
FLOAT blue;
FLOAT alpha;
}
你想访问基于此模版的数据对象的数据你可以这样做:
DWORD DataSize;
float *DataPtr;
pData->GetData(NULL, &DataSize, (void**)&DataPtr);
float red = *DataPtr++;
float green = *DataPtr++;
float blue = *DataPtr++;
float alpha = *DataPtr++;
得到指向数据对象的数据的指针后,就像访问一般的结构一样简单。当然,你可以做得更直接:
typedef struct {
float red, green, blue, alpha;
} sColorRGBA;//定一个结构方便访问数据对象的数据。
sColorRGBA *Color;
DWORD DataSize;
pData->GetData(NULL, &DataSize,(void**)&Color);
这样访问数据时更直接:
float red = Color->red;
float blue = Color->blue;
float green = Color->green;
float alpha = Color->alpha;
访问单个变量是很简单的,下面继续介绍访问数组或字符串。
访问数组:
DWORD DataSize;
DWORD *DataPtr;
pData->GetData(NULL, &DataSize, (void**)&DataPtr);
DWORD NumKeys = *DataPtr++;
for(DWORD i=0;i<NumKeys;i++) {
float fvalue = *(FLOAT*)DataPtr++;
访问字符串:
DWORD DataSize;
DWORD *DataPtr;
pData->GetData(NULL, &DataSize, (void**)&DataPtr);
char *StringPtr = (char*)DataPtr;
MessageBox(NULL, StringPtr, "Texture Filename", MB_OK);
为了访问数组或字符串,其本质就是把指针转化成匹配的类型,方便指针的定位操作。
我以后还会写关于3D模型文件格式和骨骼动画,地形渲染方面的文章,请关注 ;)
分享到:
相关推荐
使用X-文件锁进行文件加密是实施数据安全策略的一部分。除了加密,还应结合其他安全措施,如访问控制、身份验证和审计日志等,以构建全面的安全防护体系。 6. 应用场景: X-文件锁适用于企业内部文件分享、外部...
本文将深入探讨3ds Max中用于导出.X文件的插件及其使用方法。 首先,我们需要理解.X文件格式的重要性。这种格式由微软开发,主要用于游戏开发,因为它可以高效地存储3D几何数据、纹理坐标、骨骼和动画信息。由于其...
在使用微软X文件读写程序时,开发者需要注意以下几点: 1. 文件格式理解:理解X文件的结构和数据布局是必不可少的,包括头部信息、模型数据、材质信息和动画关键帧等。 2. 数据解析:正确解析X文件中的每个元素,如...
### X-Modem 文件传输协议详解 #### 一、引言 X-Modem 文件传输协议是由 Larry Jordan 提出的一种用于通过电话系统在计算机之间进行文件传输的技术方案。该协议旨在解决数据传输过程中可能遇到的问题,如电气噪声...
4. **模型加载**:使用D3DXLoadMeshFromX函数可以从.x文件中加载模型。这个函数会返回一个ID3DXMesh对象,它代表了一个3D模型的实例,包含了模型的所有顶点和面信息。 5. **顶点缓冲区和索引缓冲区**:为了在GPU上...
3. **打开并读取.X文件**: 使用`IDirect3DXFile::Load`方法打开指定的`.X`文件,获取文件内容。此过程可能涉及到错误检查,确保文件存在并且可以成功读取。 4. **解析文件结构**: `.X`文件的结构是基于节点的,每个...
"X文件查看器"是一款专为DirectX设计的工具,主要用于查看和理解使用DirectX技术创建的特定类型文件,即扩展名为“.X”的文件。DirectX是由微软开发的一系列应用程序接口(APIs),广泛应用于游戏开发、图形渲染、...
总结来说,要进行"CXD转MAT文件"的操作,你需要利用MATLAB的文件I/O函数,特别是bfopen,理解CXD文件格式,然后将读取的数据转换为MATLAB可以处理的格式,最终使用save函数保存为MAT文件。如果"bfmatlab"提供了相关...
《.x文件查看器Dxviewer.ext与DirectX深度解析》 在计算机图形学领域,DirectX是一款由微软公司开发的API(应用程序接口),主要用于Windows操作系统中的多媒体和游戏开发,尤其是3D图形处理。它为开发者提供了一...
总之,"hex6x文件转换"是一个在嵌入式系统开发中常见的步骤,通过将DSP的.out文件转换为16进制(hex)格式,可以提高程序的移植性和易用性。了解这两种文件格式的特点,以及如何使用工具进行转换,对于任何涉及嵌入式...
在3D建模领域,3DS(Autodesk 3ds Max)是一种广泛使用的建模软件,而.x文件格式是DirectX支持的一种3D模型文件格式,主要用于在游戏中存储和加载3D模型。 3DS导出成.x文件的工具是DirectX SDK的一部分,它允许...
FileX是ThreadX的一个文件系统模块,支持多种文件格式,并适用于深度嵌入式实时IoT应用,它是一个符合工业级标准的嵌入式文件系统。 AzureRTOSFileX是ThreadX RTOS中的FileX文件系统的概述,它支持Microsoft FAT...
在处理这类问题时,确保许可证文件的完整性和正确性至关重要,否则可能导致激活失败或软件功能受限。 总的来说,Dash 4.x 激活文件是让用户能够充分利用这款文档查询利器的关键。正确导入和激活这个文件,可以享受...
提供一个教学使用的.x文件,方便大家学习使用
**DSP2833X_v142库文件**是针对TI公司生产的TMS320F28335数字信号处理器(DSP)的一套完整的开发库,用于支持外设驱动和应用例程的开发。这个库包含了必要的函数、头文件和其他资源,帮助开发者在v142版本的软件环境...
在提供的压缩包中,"把X文件转换为xpl的工具"就是这样一个工具。这个工具可能包含了读取`.x`文件并将其重新打包成`.xpl`格式的功能。使用步骤通常如下: 1. **安装转换工具**:首先,你需要解压缩提供的文件,然后...
3d .x文件 模型 DirectX 装了DirectX 9.0或以上的才可以双击打开x文件 要把 max文件 转为 x文件 建议用Deep Exploration 来 File->Batch Operations->Convert 3D Files 要用Deep Exploration 打开max 文件 请看...
本主题涉及的"签名文件.rar"压缩包包含了三个关键文件:`signapk.jar`,`platform.x509.pem`以及`platform.pk8`,这些都是用于Android应用程序签名的重要组成部分。 `signapk.jar`是一个Java可执行文件,它是Google...
Adobe Acrobat X Pro是一款由Adobe公司推出的专业的PDF文档处理软件,其汉化补丁是为了让中国用户能够更加方便地使用这款工具。在不熟悉英文界面的情况下,汉化补丁显得尤为重要,它将软件的原始英文界面翻译成中文...
Parasolid X_T格式文件参考 Parasolid X_T 格式文件是三维模型数据文件的结构参考,广泛应用于 ug、SolidWorks 等 CAD 软件中。下面是对 Parasolid X_T 格式文件的详细介绍: Parasolid X_T 格式文件的结构 ...