1、DirectX 10 教程 8:加载 Maya 2011 模型原文地址: Tutorial 8: Loading Maya 2011 Models。本教程介绍如何导入 Maya 2011 制作的 3D 模型。虽然本教程讨论的是 Maya,但是要稍加修改也可以处理其他 3D 建模工具导出的 3D 模型。在前面的教程中我们创建了自己的模型格式并进行了绘制。本教程我们要把 Maya 2011 模型格式变换为自己的格式并进行绘制。这里不讨论如何在 Maya 创建 3D 模型,网上有无数的教程,我们直接从一个已经附有纹理的 3D 模型开始。Maya 导出的格式很多,我们使用的是.OBJ,因为它易读,所以
2、适用于初学者。要在 Maya 中将模型导出为.obj 格式,你必须首先打开.OBJ exporter。点击“Window” ,选择“Settings/Preferences” ,然后是“Plug-in Manager”。下拉到 objExport.mll 并选择“Loaded”和“Auto load”。导出时只需点击“File” ,选择“Export All”。在底部选择“Files of type: ”找到“OBJexport” 。指定一个文件名词并点击“Export All”,Maya 就会把模型导出为一个.obj 后缀的文本文件,用任意一个文本编辑器(例如记事本)打开这个文件,内容如下:
3、Cube.obj# This file uses centimeters as units for non-parametric coordinates.mtllib cube.mtlg defaultv -0.500000 -0.500000 0.500000v 0.500000 -0.500000 0.500000v -0.500000 0.500000 0.500000v 0.500000 0.500000 0.500000v -0.500000 0.500000 -0.500000v 0.500000 0.500000 -0.500000v -0.500000 -0.500000 -0
4、.500000v 0.500000 -0.500000 -0.500000vt 0.001992 0.001992vt 0.998008 0.001992vt 0.001992 0.998008vt 0.998008 0.998008vt 0.001992 0.001992vt 0.998008 0.001992vt 0.001992 0.998008vt 0.998008 0.998008vt 0.001992 0.001992vt 0.998008 0.001992vt 0.001992 0.998008vt 0.998008 0.998008vt 0.001992 0.001992vt
5、0.998008 0.001992vt 0.001992 0.998008vt 0.998008 0.998008vt 0.001992 0.001992vt 0.998008 0.001992vt 0.001992 0.998008vt 0.998008 0.998008vt 0.998008 0.998008vt 0.001992 0.998008vt 0.998008 0.001992vt 0.001992 0.001992vn 0.000000 0.000000 1.000000vn 0.000000 0.000000 1.000000vn 0.000000 0.000000 1.00
6、0000vn 0.000000 0.000000 1.000000vn 0.000000 1.000000 0.000000vn 0.000000 1.000000 0.000000vn 0.000000 1.000000 0.000000vn 0.000000 1.000000 0.000000vn 0.000000 0.000000 -1.000000vn 0.000000 0.000000 -1.000000vn 0.000000 0.000000 -1.000000vn 0.000000 0.000000 -1.000000vn 0.000000 -1.000000 0.000000v
7、n 0.000000 -1.000000 0.000000vn 0.000000 -1.000000 0.000000vn 0.000000 -1.000000 0.000000vn 1.000000 0.000000 0.000000vn 1.000000 0.000000 0.000000vn 1.000000 0.000000 0.000000vn 1.000000 0.000000 0.000000vn -1.000000 0.000000 0.000000vn -1.000000 0.000000 0.000000vn -1.000000 0.000000 0.000000vn -1
8、.000000 0.000000 0.000000s 1g pCube1usemtl file1SGf 1/1/1 2/2/2 3/3/3f 3/3/3 2/2/2 4/4/4s 2f 3/13/5 4/14/6 5/15/7f 5/15/7 4/14/6 6/16/8s 3f 5/21/9 6/22/10 7/23/11f 7/23/11 6/22/10 8/24/12s 4f 7/17/13 8/18/14 1/19/15f 1/19/15 8/18/14 2/20/16s 5f 2/5/17 8/6/18 4/7/19f 4/7/19 8/6/18 6/8/20s 6f 7/9/21 1
9、/10/22 5/11/23f 5/11/23 1/10/22 3/12/24这个.OBJ 模型文件表示一个 3D 立方体。它有 6 个顶点,24 个纹理坐标和法线矢量,6 个面共 12 个三角形。注意每行开头的“V ”, “VT”, “VN”“或“F” 。这些额外的信息在转换为我们自定义的格式时是无用的。下面我们讨论一下字母的含义:1 “V”开头的行用于顶点。立方体有 8 个顶点,每个顶点由三个代表 X,Y,Z 的浮点数构成。2 “VT”开头的行用于纹理坐标。立方体有 24 个纹理坐标,大部分坐标是重复的,由两个 TU,TV 浮点数构成。3 “VN”开头的行用于法线矢量。立方体有 24 个法
10、线,大部分是重复的,由三个NX, NY,NZ 浮点数构成。4 “F”开头的行用于每个三角形。由顶点索引,纹理坐标索引和法线索引构成,每个面的格式为:f Vertex1/Texture1/Normal1 Vertex2/Texture2/Normal2 Vertex3/Texture3/Normal3因此“f 3/13/5 4/14/6 5/15/7”表示“Vertex3/Texture13/Normal5 Vertex4/Texture14/Normal6 Vertex5/Texture15/Normal7”。数据的顺序非常重要。例如文件中的第一个顶点对应 face 列表中的 Vertex1,
11、纹理坐标和法线的顺序也是如此。在行 face 中每行的三个索引组代表一个三角形,一个立方体有 12face 组成 6 个面,每个面有 2 个三角形。右手坐标系到左手坐标系的转换Maya 2011 默认使用右手坐标系。要将数据转换为 DirectX 10 使用的左手坐标系,你需要进行以下步骤:1反转顶点的 Z 坐标,代码为:verticesvertexIndex.z = verticesvertexIndex.z * -1.0f;2反转 TV 纹理坐标,代码为:texcoordstexcoordIndex.y = 1.0f - texcoordstexcoordIndex.y;3反转 NZ 法线
12、,代码为:normalsnormalIndex.z = normalsnormalIndex.z * -1.0f;4将绘制顺序由逆时针方向转换为顺时针方向。在代码中只是简单地逆序读取索引组即可实现:fin facesfaceIndex.vIndex3 input2 facesfaceIndex.tIndex3 input2 facesfaceIndex.nIndex3;fin facesfaceIndex.vIndex2 input2 facesfaceIndex.tIndex2 input2 facesfaceIndex.nIndex2;fin facesfaceIndex.vIndex1
13、input2 facesfaceIndex.tIndex1 input2 facesfaceIndex.nIndex1;通过以上四个步骤,模型数据就能把 DirectX 10 正确绘制了。Main.cpp将 Maya 2011 的.obj 文件转换为自定义的 DirectX 10 格式非常简单,只有一个程序文件叫做 main.cpp。这个程序打开一个命令行窗口询问要转换的 .obj 文件名称。用户输入了名称之后,程序就会打开文件并读取到数据结构,然后将它们转换到左手坐标系,完成后就将这些数据写入到 model.txt 文件。这个文件就可以使用上一个教程的代码进行绘制了。/ Filename:
14、main.cpp/ INCLUDES /#include #include using namespace std;/ TYPEDEFS /typedef structfloat x, y, z;VertexType;typedef structint vIndex1, vIndex2, vIndex3;int tIndex1, tIndex2, tIndex3;int nIndex1, nIndex2, nIndex3;FaceType;/ FUNCTION PROTOTYPES /void GetModelFilename(char*);bool ReadFileCounts(char*,
15、 intbool LoadDataStructures(char*, int, int, int, int);/ MAIN PROGRAM /int main()bool result;char filename256;int vertexCount, textureCount, normalCount, faceCount;char garbage;/ Read in the name of the model file.GetModelFilename(filename);/ Read in the number of vertices, tex coords, normals, and
16、faces so that the data structures can be initialized with the exact sizes needed.result = ReadFileCounts(filename, vertexCount, textureCount, normalCount, faceCount);if(!result)return -1;/ Display the counts to the screen for information purposes.cout garbage;return 0;void GetModelFilename(char* fil
17、ename)bool done;ifstream fin;/ Loop until we have a file name.done = false;while(!done)/ Ask the user for the filename.cout filename;/ Attempt to open the file.fin.open(filename);if(fin.good()/ If the file exists and there are no problems then exit since we have the file name.done = true;else/ If th
18、e file does not exist or there was an issue opening it then notify the user and repeat the process.fin.clear();cout verticesvertexIndex.x verticesvertexIndex.y verticesvertexIndex.z;/ Invert the Z vertex to change to left hand system.verticesvertexIndex.z = verticesvertexIndex.z * -1.0f;vertexIndex+
19、; / Read in the texture uv coordinates.if(input = t) fin texcoordstexcoordIndex.x texcoordstexcoordIndex.y;/ Invert the V texture coordinates to left hand system.texcoordstexcoordIndex.y = 1.0f - texcoordstexcoordIndex.y;texcoordIndex+; / Read in the normals.if(input = n) fin normalsnormalIndex.x no
20、rmalsnormalIndex.y normalsnormalIndex.z;/ Invert the Z normal to change to left hand system.normalsnormalIndex.z = normalsnormalIndex.z * -1.0f;normalIndex+; / Read in the faces.if(input = f) fin.get(input);if(input = )/ Read the face data in backwards to convert it to a left hand system from right
21、hand system.fin facesfaceIndex.vIndex3 input2 facesfaceIndex.tIndex3 input2 facesfaceIndex.nIndex3 facesfaceIndex.vIndex2 input2 facesfaceIndex.tIndex2 input2 facesfaceIndex.nIndex2 facesfaceIndex.vIndex1 input2 facesfaceIndex.tIndex1 input2 facesfaceIndex.nIndex1;faceIndex+;/ Read in the remainder
22、of the line.while(input != n)fin.get(input);/ Start reading the beginning of the next line.fin.get(input);/ Close the file.fin.close();/ Open the output file.fout.open(“model.txt“);/ Write out the file header that our model format uses.fout “Vertex Count: “ (faceCount * 3) endl;fout endl;fout “Data:
23、“ endl;fout endl;/ Now loop through all the faces and output the three vertices for each face.for(int i=0; ifaceIndex; i+)vIndex = facesi.vIndex1 - 1;tIndex = facesi.tIndex1 - 1;nIndex = facesi.nIndex1 - 1;fout verticesvIndex.x verticesvIndex.y verticesvIndex.z texcoordstIndex.x texcoordstIndex.y no
24、rmalsnIndex.x normalsnIndex.y normalsnIndex.z endl;vIndex = facesi.vIndex2 - 1;tIndex = facesi.tIndex2 - 1;nIndex = facesi.nIndex2 - 1;fout verticesvIndex.x verticesvIndex.y verticesvIndex.z texcoordstIndex.x texcoordstIndex.y normalsnIndex.x normalsnIndex.y normalsnIndex.z endl;vIndex = facesi.vInd
25、ex3 - 1;tIndex = facesi.tIndex3 - 1;nIndex = facesi.nIndex3 - 1;fout verticesvIndex.x verticesvIndex.y verticesvIndex.z texcoordstIndex.x texcoordstIndex.y normalsnIndex.x normalsnIndex.y normalsnIndex.z endl;/ Close the output file.fout.close();/ Release the four data structures.if(vertices)delete vertices;vertices = 0;if(texcoords)delete texcoords;texcoords = 0;if(normals)delete normals;normals = 0;if(faces)delete faces;faces = 0;return true;总结现在我们就可以将 Maya 2011 导出的.obj 文件转换为自己的简单模型格式了。练习1编译程序处理提供的.obj 模型文件。2创建( 或获得) 一个 Maya 2011 模型,将它导出为.obj 格式,运行程序进行转换。3修改代码读取并导出一个不同的模型格式。