天行健 君子当自强而不息

XFile网格的应用(1)

 

三维物体表面的各个剖分三角形构成了一个所谓的网格(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)

posted on 2007-05-18 01:58 lovedday 阅读(1937) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

导航

统计

常用链接

随笔分类(178)

3D游戏编程相关链接

搜索

最新评论