D3D中.X文件的解析

一个完整的.X文件类似这样的结构:
xof 0303txt 0032
//定义模板
template FVFData {
< b6e70a0e-8ef9-4e83-94ad-ecc8b0c04897>
DWORD dwFVF;
DWORD nDWords;
array DWORD data[nDWords];
}

template EffectInstance {
< e331f7e4-0559-4cc2-8e99-1cec1657928f>
STRING EffectFilename;
[...]
}

template EffectParamFloats {
< 3014b9a0-62f5-478c-9b86-e4ac9f4e418b>
STRING ParamName;
DWORD nFloats;
array FLOAT Floats[nFloats];
}

template EffectParamString {
< 1dbc4c88-94c1-46ee-9076-2c28818c9481>
STRING ParamName;
STRING Value;
}

template EffectParamDWord {
< e13963bc-ae51-4c5d-b00f-cfa3a9d97ce5>
STRING ParamName;
DWORD Value;
}

//主框架
Frame BoxFrame{

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,-22.441198,0.000000,-15.434750,1.000000;;
}

//Mesh对象
Mesh {
20;
-28.216623;0.000000;-55.879185;,
28.216623;0.000000;-55.879185;,
-28.216623;0.000000;55.879185;,
28.216623;0.000000;55.879185;,
-28.216623;54.767735;-55.879185;,
28.216623;54.767735;-55.879185;,
-28.216623;54.767735;55.879185;,
28.216623;54.767735;55.879185;,
-28.216623;0.000000;-55.879185;,
28.216623;54.767735;-55.879185;,
28.216623;0.000000;-55.879185;,
-28.216623;54.767735;-55.879185;,
28.216623;0.000000;55.879185;,
28.216623;54.767735;-55.879185;,
28.216623;0.000000;55.879185;,
-28.216623;54.767735;55.879185;,
-28.216623;0.000000;55.879185;,
28.216623;54.767735;55.879185;,
-28.216623;0.000000;55.879185;,
-28.216623;54.767735;-55.879185;;
12;
3;0,3,2;,
3;3,0,1;,
3;4,7,5;,
3;7,4,6;,
3;8,9,10;,
3;9,8,11;,
3;1,7,12;,
3;7,1,13;,
3;14,15,16;,
3;15,14,17;,
3;18,19,0;,
3;19,18,6;;

MeshNormals {
6;
0.000000;-1.000000;0.000000;,
0.000000;1.000000;0.000000;,
0.000000;0.000000;-1.000000;,
1.000000;0.000000;0.000000;,
0.000000;0.000000;1.000000;,
-1.000000;0.000000;0.000000;;
12;
3;0,0,0;,
3;0,0,0;,
3;1,1,1;,
3;1,1,1;,
3;2,2,2;,
3;2,2,2;,
3;3,3,3;,
3;3,3,3;,
3;4,4,4;,
3;4,4,4;,
3;5,5,5;,
3;5,5,5;;
}

MeshMaterialList {
1;
12;
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0;

Material {
0.341176;0.878431;0.560784;1.000000;;
0.000000;
0.341176;0.878431;0.560784;;
0.000000;0.000000;0.000000;;
}
}

MeshTextureCoords {
20;
1.000000;1.000000;,
0.000000;1.000000;,
1.000000;0.000000;,
0.000000;0.000000;,
0.000000;1.000000;,
1.000000;1.000000;,
0.000000;0.000000;,
1.000000;0.000000;,
0.000000;1.000000;,
1.000000;0.000000;,
1.000000;1.000000;,
0.000000;0.000000;,
1.000000;1.000000;,
0.000000;0.000000;,
0.000000;1.000000;,
1.000000;0.000000;,
1.000000;1.000000;,
0.000000;0.000000;,
0.000000;1.000000;,
1.000000;0.000000;;
}

EffectInstance tt{
"fdsfds";
}
}
}
1.其中的xof 0303txt 0032解释为:xof表示这是一个真正的X文件。0303txt表示通知程序使用Directx的X文件,版本为3.3的模版,其中txt表示此文件为文本文件,可读,并非是一个2进制文件。0032表示一个浮点数的位数为32,如果想要用64位的浮点数,可以写成0064。
2.模板的声明有三种类型:
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]以外的数据对象。
3.访问.X文件:
访问任何X文件首先要调用DirectXFileCreate函数创建一个IDirectXFile接口。
IDirectXFile *pDXFile = NULL;
HRESULT Result = DirectXFileCreate(&pDXFile);//用&pDXFile返回指向接口的指针。用SUCCEEDED或者
FAILED宏判断返回值是否有效。
4.注册一个定制或者标准模版:
你可以把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);
5.打开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文件:
strcpy(Filename,"test.x");
IDirectXFileEnumObject *pEnum;
pFile->CreateEnumObject((LPVOID)Filename, DXFILELOAD_FROMFILE, &pEnum);
Filename指向一个有效的文件名,pEnum返回一个枚举对象接口指针。
6.枚举数据对象:
注册完模版,打开X文件并且得到一个枚举对象接口,下面需要从X文件读出数据。枚举对象接口指针指向
文件的第一个数据对象,因为每一个数据对象可能包含内嵌数据对象或者引用的数据对象,所以与第一个
数据对象同在一层级的其它数据对象为同层级数据对象。至于包含的子数据对象的类型,需要对其分别的
行进询问。
可以用 HRESULT IDirectXFileEnumObject::GetNextDataObject(LPDIRECTXFILEDATA*ppDataObj)得到一
个IDirectXFileData接口。它只有一个参数,如下:
IDirectXFileData *pData;
HRESULT hr = pEnum->GetNextDataObject(&pData);
利用此函数,可以不断地访问同一层级的数据对象接口,具体代码如下:
while(SUCCEEDED(pEnum->GetNextDataObject(&pData))) {
// 这里可以对pData数据对象进行操作。
ParseResult = ParseXFileData(m_pDXData); //ParseXFileData为解析函数
pData->Release();//释放接口。
}
当返回值为FAILED,表示已经访问完所有的接口。当访问值为SUCCEEDED,你需要继续判断这个数据对象
7.解析函数:
判断数据对象是否包含子对象。利用接口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数据对象进行操作
ParseXFileData(pSubData);
pSubData->Release();//释放接口。
}

看其是否为引用数据对象:
IDirectXFileDataReference *pRef;
IDirectXFileData *pSubData;
if(SUCCEEDED(pSubObj->QueryInterface( IID_IDirectXFileDataReference, (void**)&pRef))) {
// 如果询问引用的数据对象成功,解析出引用的原型。
pRef->Resolve(&pSubData);
//这里可以对pData数据对象进行操作。
ParseXFileData(pSubData);
pRef->Release();
pSubData->Release();//释放接口。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值