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