三維物體表面的各個(gè)剖分三角形構(gòu)成了一個(gè)所謂的網(wǎng)格(Mesh),使用3D建模軟件繪制三維圖象,可取得網(wǎng)格的頂點(diǎn)坐標(biāo),頂點(diǎn)紋理坐標(biāo)以及三角形面的材質(zhì)等數(shù)據(jù),并可將這些數(shù)據(jù)保存到相應(yīng)的三維圖象文件中。此時(shí)調(diào)用DirectX提供的網(wǎng)格接口函數(shù),讀取三維圖象文件的頂點(diǎn)數(shù)據(jù),就可對(duì)三維物體表面進(jìn)行渲染處理。
.X文件的基本格式
使用 DirectX SDK安裝目錄下的MView.exe可以打開(kāi).X文件,比如我的電腦上的可執(zhí)行文件路徑是E:\Microsoft
DirectX 9.0 SDK (April 2005)\Utilities\Bin\x86\MView.exe。 (注: 最新版的DirectX
SDK已經(jīng)不包含該文件了,所以你可能需要下載安裝舊版的DirectX SDK來(lái)得到這個(gè)文件。)
下面是使用MeshView打開(kāi)一個(gè).X文件的截圖:
我們來(lái)看看下面這個(gè).X文件的具體信息描述,該文件描述與上面那個(gè)截圖無(wú)關(guān)。
xof 0302txt 0064
template Header {
<3D82AB43-62DA-11cf-AB39-0020AF71E433>
WORD major;
WORD minor;
DWORD flags;
}
template Vector {
<3D82AB5E-62DA-11cf-AB39-0020AF71E433>
FLOAT x;
FLOAT y;
FLOAT z;
}
template Coords2d {
<F6F23F44-7686-11cf-8F52-0040333594A3>
FLOAT u;
FLOAT v;
}
template Matrix4x4 {
<F6F23F45-7686-11cf-8F52-0040333594A3>
array FLOAT matrix[16];
}
template ColorRGBA {
<35FF44E0-6C7C-11cf-8F52-0040333594A3>
FLOAT red;
FLOAT green;
FLOAT blue;
FLOAT alpha;
}
template ColorRGB {
<D3E16E81-7835-11cf-8F52-0040333594A3>
FLOAT red;
FLOAT green;
FLOAT blue;
}
template IndexedColor {
<1630B820-7842-11cf-8F52-0040333594A3>
DWORD index;
ColorRGBA indexColor;
}
template Boolean {
<4885AE61-78E8-11cf-8F52-0040333594A3>
WORD truefalse;
}
template Boolean2d {
<4885AE63-78E8-11cf-8F52-0040333594A3>
Boolean u;
Boolean v;
}
template MaterialWrap {
<4885AE60-78E8-11cf-8F52-0040333594A3>
Boolean u;
Boolean v;
}
template TextureFilename {
<A42790E1-7810-11cf-8F52-0040333594A3>
STRING filename;
}
template Material {
<3D82AB4D-62DA-11cf-AB39-0020AF71E433>
ColorRGBA faceColor;
FLOAT power;
ColorRGB specularColor;
ColorRGB emissiveColor;
[...]
}
template MeshFace {
<3D82AB5F-62DA-11cf-AB39-0020AF71E433>
DWORD nFaceVertexIndices;
array DWORD faceVertexIndices[nFaceVertexIndices];
}
template MeshFaceWraps {
<4885AE62-78E8-11cf-8F52-0040333594A3>
DWORD nFaceWrapValues;
Boolean2d faceWrapValues;
}
template MeshTextureCoords {
<F6F23F40-7686-11cf-8F52-0040333594A3>
DWORD nTextureCoords;
array Coords2d textureCoords[nTextureCoords];
}
template MeshMaterialList {
<F6F23F42-7686-11cf-8F52-0040333594A3>
DWORD nMaterials;
DWORD nFaceIndexes;
array DWORD faceIndexes[nFaceIndexes];
[Material <3D82AB4D-62DA-11cf-AB39-0020AF71E433>]
}
template MeshNormals {
<F6F23F43-7686-11cf-8F52-0040333594A3>
DWORD nNormals;
array Vector normals[nNormals];
DWORD nFaceNormals;
array MeshFace faceNormals[nFaceNormals];
}
template MeshVertexColors {
<1630B821-7842-11cf-8F52-0040333594A3>
DWORD nVertexColors;
array IndexedColor vertexColors[nVertexColors];
}
template Mesh {
<3D82AB44-62DA-11cf-AB39-0020AF71E433>
DWORD nVertices;
array Vector vertices[nVertices];
DWORD nFaces;
array MeshFace faces[nFaces];
[...]
}
template FrameTransformMatrix {
<F6F23F41-7686-11cf-8F52-0040333594A3>
Matrix4x4 frameMatrix;
}
template Frame {
<3D82AB46-62DA-11cf-AB39-0020AF71E433>
[...]
}
Frame Scene_Root { // 場(chǎng)景主框架
FrameTransformMatrix { // 主框架的變換矩陣
0.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 Quad { // 主框架下的Quad框架
Mesh { // 網(wǎng)格數(shù)據(jù)
4; // 頂點(diǎn)數(shù)
-0.500000; -0.500000; 0.000000;, // 頂點(diǎn)1坐標(biāo)
0.500000; -0.500000; 0.000000;, // 頂點(diǎn)2坐標(biāo)
-0.500000; 0.500000; 0.000000;, // 頂點(diǎn)3坐標(biāo)
0.500000; 0.500000; 0.000000;; // 頂點(diǎn)4坐標(biāo)
2; // 三角形面數(shù)
3; 0,1,2;, // 第一個(gè)三角形面的頂點(diǎn)索引數(shù)和三個(gè)頂點(diǎn)索引值
3; 0,2,1;; // 第二個(gè)三角形面的頂點(diǎn)索引數(shù)和三個(gè)頂點(diǎn)索引值
MeshNormals {
4; // 頂點(diǎn)法向量的個(gè)數(shù)
0.000000; 0.000000; 1.000000;, // 頂點(diǎn)1的法向量坐標(biāo)
0.000000; 0.000000; 1.000000;, // 頂點(diǎn)2的法向量坐標(biāo)
0.000000; 0.000000; 1.000000;, // 頂點(diǎn)3的法向量坐標(biāo)
0.000000; 0.000000; 1.000000;; // 頂點(diǎn)4的法向量坐標(biāo)
2; // 三角形面的法向量個(gè)數(shù)
3; 0, 1, 2;, // 法向量的索引數(shù)和3個(gè)法向量的索引值(計(jì)算面的法向量)
3; 3, 2, 1;; // 法向量的索引數(shù)和3個(gè)法向量的索引值(計(jì)算面的法向量)
}
MeshTextureCoords { // 紋理坐標(biāo)模版
4; // 紋理坐標(biāo)個(gè)數(shù)
0.000000; 1.000000;, // 紋理坐標(biāo)1
1.000000; 1.000000;, // 紋理坐標(biāo)2
0.000000; 0.000000;, // 紋理坐標(biāo)3
1.000000; 0.000000;; // 紋理坐標(biāo)4
}
MeshMaterialList { // 材質(zhì)列表模版
1; // 材質(zhì)個(gè)數(shù)
2; // 三角形面的材質(zhì)索引數(shù)(實(shí)際是三角形面的個(gè)數(shù))
0, // 第一個(gè)三角形使用0號(hào)材質(zhì)索引
0, // 第二個(gè)三角形使用0號(hào)材質(zhì)索引
Material{ // 材質(zhì)模版
1.000000; 1.000000; 1.000000; 1.000000;; // 三角形面的顏色
0.000000; // 鏡面光的高光強(qiáng)度
1.000000; 1.000000; 1.000000;; // 鏡面光顏色
0.000000; 0.000000; 0.000000;; // 自發(fā)射光顏色
TextureFilename { // 紋理貼圖文件
"bb.jpg";
};
}
}
}
}
}
第一行的“
xof 0302txt 0064”表明這個(gè)文件是一個(gè).X
文件(由"xof"子串解析),文件的版本為3.2(由“0302”子串解析),數(shù)據(jù)以文本格式進(jìn)行存放(由"txt"子串解析),所使用的浮點(diǎn)數(shù)是64
位的浮點(diǎn)數(shù)據(jù)(由"0064"子串進(jìn)行解析)。如果第一行的內(nèi)容為“xof 0303bin
0032”,則表示該.X文件是一個(gè)二進(jìn)制文件,此時(shí)將不能直接查看文件數(shù)據(jù)的含義。
接下來(lái)是 Scene_Root對(duì)象的定義,該對(duì)象為一個(gè)Frame模版數(shù)據(jù),用Frame
Scene_Root引出,在隨后的配對(duì)大括號(hào)"{"和"}"內(nèi),定義Scene_Root對(duì)象的具體數(shù)據(jù)。這里,作為數(shù)據(jù)類型的Frame模版同樣提供了數(shù)據(jù)正確性的檢測(cè)方法和它的對(duì)象數(shù)據(jù)的說(shuō)明方法。
Frame模版用來(lái)定義游戲場(chǎng)景的各個(gè)框架部分,通過(guò)在框架中定義子框架,就可形成具有層次關(guān)系的一系列框架。Frame模版在DirectX中定義如下:
template Frame {
<3D82AB46-62DA-11cf-AB39-0020AF71E433>
[...]
}
關(guān)鍵字"template"表明下面是一個(gè)模版的定義,F(xiàn)rame為該模版的名字,每個(gè)模版都有一個(gè)唯一的全局標(biāo)志符,隨后的
[...]說(shuō)明Frame模版是一個(gè)開(kāi)放模版(Open Template),開(kāi)放模版的對(duì)象可以定義其他模版類型的數(shù)據(jù)。
在Scene_Root對(duì)象中,定義了一個(gè)省略了對(duì)象名的FrameTransformMatrix模版對(duì)象如下:
FrameTransformMatrix { // 主框架的變換矩陣
0.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;;
}
FrameTransformMatrix模版用來(lái)指定框架的變換矩陣,它的定義如下所示:
template FrameTransformMatrix {
<F6F23F41-7686-11cf-8F52-0040333594A3>
Matrix4x4 frameMatrix;
}
template Matrix4x4 {
<F6F23F45-7686-11cf-8F52-0040333594A3>
array FLOAT matrix[16];
}
在Scene_Root框架對(duì)象內(nèi)定義了另一個(gè)Quad框架對(duì)象如下:
Mesh {
// 網(wǎng)格數(shù)據(jù)
4; // 頂點(diǎn)數(shù)
-0.500000; -0.500000; 0.000000;, // 頂點(diǎn)1坐標(biāo)
0.500000; -0.500000; 0.000000;, // 頂點(diǎn)2坐標(biāo)
-0.500000; 0.500000; 0.000000;, // 頂點(diǎn)3坐標(biāo)
0.500000; 0.500000; 0.000000;; // 頂點(diǎn)4坐標(biāo)
2; // 三角形面數(shù)
3; 0,1,2;, // 第一個(gè)三角形面的頂點(diǎn)索引數(shù)和三個(gè)頂點(diǎn)索引值
3; 0,2,1;; // 第二個(gè)三角形面的頂點(diǎn)索引數(shù)和三個(gè)頂點(diǎn)索引值
MeshNormals {
4; // 頂點(diǎn)法向量的個(gè)數(shù)
0.000000; 0.000000; 1.000000;, // 頂點(diǎn)1的法向量坐標(biāo)
0.000000; 0.000000; 1.000000;, // 頂點(diǎn)2的法向量坐標(biāo)
0.000000; 0.000000; 1.000000;, // 頂點(diǎn)3的法向量坐標(biāo)
0.000000; 0.000000; 1.000000;; // 頂點(diǎn)4的法向量坐標(biāo)
2; // 三角形面的法向量個(gè)數(shù)
3; 0, 1, 2;, // 法向量的索引數(shù)和3個(gè)法向量的索引值(計(jì)算面的法向量)
3; 3, 2, 1;; // 法向量的索引數(shù)和3個(gè)法向量的索引值(計(jì)算面的法向量)
}
MeshTextureCoords { // 紋理坐標(biāo)模版
4; // 紋理坐標(biāo)個(gè)數(shù)
0.000000; 1.000000;, // 紋理坐標(biāo)1
1.000000; 1.000000;, // 紋理坐標(biāo)2
0.000000; 0.000000;, // 紋理坐標(biāo)3
1.000000; 0.000000;; // 紋理坐標(biāo)4
}
MeshMaterialList { // 材質(zhì)列表模版
1; // 材質(zhì)個(gè)數(shù)
2; // 三角形面的材質(zhì)索引數(shù)(實(shí)際是三角形面的個(gè)數(shù))
0, // 第一個(gè)三角形使用0號(hào)材質(zhì)索引
0, // 第二個(gè)三角形使用0號(hào)材質(zhì)索引
Material{ // 材質(zhì)模版
1.000000; 1.000000; 1.000000; 1.000000;; // 三角形面的顏色
0.000000; // 鏡面光的高光強(qiáng)度
1.000000; 1.000000; 1.000000;; // 鏡面光顏色
0.000000; 0.000000; 0.000000;; // 自發(fā)射光顏色
TextureFilename { // 紋理貼圖文件
"bb.jpg";
};
}
}
}
該對(duì)象提供了正方形網(wǎng)格(Mesh)的數(shù)據(jù)說(shuō)明,如下所示:
template Mesh { // 網(wǎng)格模版定義
<3D82AB44-62DA-11cf-AB39-0020AF71E433>
DWORD nVertices; // 頂點(diǎn)數(shù)
array Vector vertices [nVertices]; // 頂點(diǎn)數(shù)組
DWORD nFaces; // 三角形面數(shù)
array MeshFace faces[nFaces]; // 三角形面數(shù)組
[...] // 開(kāi)放模版定義
}
template MeshFace {
<3D82AB5F-62DA-11cf-AB39-0020AF71E433>
DWORD nFaceVertexIndices; //
三角形面的頂點(diǎn)索引數(shù),一般為3。
array DWORD faceVertexIndices[nFaceVertexIndices]; // 三角形面內(nèi)各個(gè)頂點(diǎn)的索引值
}
而在Mesh數(shù)據(jù)里又定義了一個(gè)模板數(shù)據(jù)MeshNormals如下:
MeshNormals {
4; // 頂點(diǎn)法向量的個(gè)數(shù)
0.000000; 0.000000; 1.000000;, // 頂點(diǎn)1的法向量坐標(biāo)
0.000000; 0.000000; 1.000000;, // 頂點(diǎn)2的法向量坐標(biāo)
0.000000; 0.000000; 1.000000;, // 頂點(diǎn)3的法向量坐標(biāo)
0.000000; 0.000000; 1.000000;; // 頂點(diǎn)4的法向量坐標(biāo)
2; // 三角形面的法向量個(gè)數(shù)
3; 0, 1, 2;, // 法向量的索引數(shù)和3個(gè)法向量的索引值(計(jì)算面的法向量)
3; 3, 2, 1;; // 法向量的索引數(shù)和3個(gè)法向量的索引值(計(jì)算面的法向量)
}
來(lái)看看MeshNormals對(duì)象的模版數(shù)據(jù)說(shuō)明,定義了頂點(diǎn)和三角形面的法向量,如下所示:
template MeshNormals {
<F6F23F43-7686-11cf-8F52-0040333594A3>
DWORD nNormals; // 頂點(diǎn)法向量個(gè)數(shù)
array Vector normals [nNormals]; // 頂點(diǎn)法向量數(shù)組
DWORD nFaceNormals; // 三角形面法向量個(gè)數(shù)
array MeshFace faceNormals[nFaceNormals]; // 三角形面法向量數(shù)組
}
template Vector {
<3D82AB5E-62DA-11cf-AB39-0020AF71E433>
FLOAT x;
FLOAT y;
FLOAT z;
}
template MeshFace {
<3D82AB5F-62DA-11cf-AB39-0020AF71E433>
DWORD nFaceVertexIndices;
array DWORD faceVertexIndices[nFaceVertexIndices];
}
在Mesh數(shù)據(jù)里又定義了一個(gè)正方形的紋理貼圖模板數(shù)據(jù)MeshTextureCoords以指定紋理坐標(biāo)如下:
MeshTextureCoords { // 紋理坐標(biāo)模版
4; // 紋理坐標(biāo)個(gè)數(shù)
0.000000; 1.000000;, // 紋理坐標(biāo)1
1.000000; 1.000000;, // 紋理坐標(biāo)2
0.000000; 0.000000;, // 紋理坐標(biāo)3
1.000000; 0.000000;; // 紋理坐標(biāo)4
}
來(lái)看看MeshTextureCoords模版的定義:
template MeshTextureCoords {
<F6F23F40-7686-11cf-8F52-0040333594A3>
DWORD nTextureCoords; // 紋理坐標(biāo)數(shù)
array Coords2d textureCoords [nTextureCoords]; // 紋理坐標(biāo)數(shù)組
}
template Coords2d {
<F6F23F44-7686-11cf-8F52-0040333594A3>
FLOAT u; // 紋理U坐標(biāo)
FLOAT v; // 紋理V坐標(biāo)
}
在Mesh數(shù)據(jù)里還定義了一個(gè)模板數(shù)據(jù)MeshMaterialList以指示材質(zhì)信息:
MeshMaterialList { // 材質(zhì)列表模版
1; // 材質(zhì)個(gè)數(shù)
2; // 三角形面的材質(zhì)索引數(shù)(實(shí)際是三角形面的個(gè)數(shù))
0, // 第一個(gè)三角形使用0號(hào)材質(zhì)索引
0, // 第二個(gè)三角形使用0號(hào)材質(zhì)索引
Material{ // 材質(zhì)模版
1.000000; 1.000000; 1.000000; 1.000000;; // 三角形面的顏色
0.000000; // 鏡面光的高光強(qiáng)度
1.000000; 1.000000; 1.000000;; // 鏡面光顏色
0.000000; 0.000000; 0.000000;; // 自發(fā)射光顏色
TextureFilename { // 紋理貼圖文件
"bb.jpg";
};
}
}
MeshMaterialList模版說(shuō)明該Mesh網(wǎng)格所使用的材質(zhì)數(shù)目,每個(gè)三角形面對(duì)應(yīng)的材質(zhì)索引和Material材質(zhì)對(duì)象。在MeshMaterialList模版中,用[Material
<3D82AB4D-62DA-11cf-AB39-0020AF71E433>]來(lái)指明MeshMaterialList模版的對(duì)象可包含全局標(biāo)志符為"3D82AB4D-62DA-11cf-AB39-0020AF71E433"的Material模版對(duì)象(可以不止一個(gè)對(duì)象)。
template MeshMaterialList { // 材質(zhì)列表模版
<F6F23F42-7686-11cf-8F52-0040333594A3>
DWORD nMaterials; // 材質(zhì)個(gè)數(shù)
DWORD nFaceIndexes; // 三角形面的材質(zhì)索引數(shù)(實(shí)際是三角形面的個(gè)數(shù))
array DWORD faceIndexes[nFaceIndexes]; //
三角形面的材質(zhì)索引值
[Material <3D82AB4D-62DA-11cf-AB39-0020AF71E433>]
// 材質(zhì)
}
template Material { // 材質(zhì)模版
<3D82AB4D-62DA-11cf-AB39-0020AF71E433>
ColorRGBA faceColor; // 三角形面的顏色
FLOAT power; // 鏡面光的高光強(qiáng)度
ColorRGB specularColor; // 鏡面光的顏色
ColorRGB emissiveColor; // 自發(fā)射光的顏色
[...]
}
template ColorRGBA {
<35FF44E0-6C7C-11cf-8F52-0040333594A3>
FLOAT red;
FLOAT green;
FLOAT blue;
FLOAT alpha;
}
template ColorRGB {
<D3E16E81-7835-11cf-8F52-0040333594A3>
FLOAT red;
FLOAT green;
FLOAT blue;
}
模版中通過(guò)"[模版]"的形式引入其他模版的對(duì)象,這種模版稱為嚴(yán)格模版(Restricted
Template)。MeshMaterialList模版就是一個(gè)嚴(yán)格模版。
通常在Material模版對(duì)象中加入紋理貼圖文件的說(shuō)明,此時(shí)需要使用TextureFilename模版對(duì)象來(lái)指定文件名。
template TextureFilename {
<A42790E1-7810-11cf-8F52-0040333594A3>
STRING filename; // 紋理貼圖的文件名
}
最后,對(duì)模版的定義和使用進(jìn)行簡(jiǎn)單的歸納。如下所示是模版的一般定義格式:
template <template-name> { // 模版定義
<GUID> // 全局標(biāo)志符
<mmeber 1> // 成員1
....
<mmeber 2> // 成員2
[restrictions] // 其他模版對(duì)象
}
其中,各個(gè)成員對(duì)象的類型可取為WORD, DWORD, FLOAT, DOUBLE, CHAR, UCHAR, BYTE,
STRING等。此外,還可以使用如下的數(shù)組形式來(lái)說(shuō)明模版中的數(shù)據(jù)對(duì)象。
array <data-type>
<name>[<dimension-size>];
array為數(shù)組的關(guān)鍵字,data-type為數(shù)組元素的類型,name為數(shù)組的名字,dimension-size為數(shù)組的維數(shù)。
模版的全局標(biāo)志符可利用VS提供的guidgen.exe程序自動(dòng)生成,該工具位于“$ vs_setup_dir\Common7\Tools”下,如下所示:
如果一個(gè)模版,如ColorRGB模版,不包含其他模版的數(shù)據(jù),那么該模版稱為封閉模版(Closed Template),是最簡(jiǎn)單的一種說(shuō)明數(shù)據(jù)格式的模版。
在模版對(duì)象中,用來(lái)分隔數(shù)據(jù)的逗號(hào)和分號(hào)的用法需要補(bǔ)充說(shuō)明一下。例如下面的變換矩陣的定義,中間全部用逗號(hào)分隔,最后用兩個(gè)分號(hào)結(jié)束。
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;;
}
在上面的矩陣數(shù)據(jù)中,中間的逗號(hào)是數(shù)組元素的分隔,最后的第一個(gè)分號(hào)來(lái)自于數(shù)組定義的結(jié)束,第二個(gè)分號(hào)來(lái)自于矩陣數(shù)據(jù)定義的結(jié)束。觀察如下的模版定義,可以清楚的看出。
template FrameTransformMatrix {
<F6F23F41-7686-11cf-8F52-0040333594A3>
Matrix4x4 frameMatrix; // 產(chǎn)生第2個(gè)分號(hào)
}
template Matrix4x4 {
<F6F23F45-7686-11cf-8F52-0040333594A3>
array FLOAT matrix[16]; // 產(chǎn)生第1個(gè)分號(hào),數(shù)組元素之間規(guī)定用逗號(hào)分隔
}
由此可見(jiàn),定義模版對(duì)象數(shù)據(jù)時(shí),應(yīng)采用代入的觀點(diǎn)進(jìn)行數(shù)據(jù)的構(gòu)造,即保持模版定義中的逗號(hào)和分號(hào)不變,只是將具體的數(shù)值代入相應(yīng)的變量處,就可簡(jiǎn)單地構(gòu)造出合法的模版對(duì)象數(shù)據(jù)。
閱讀下篇:
XFile網(wǎng)格的應(yīng)用(2)