第八章:加载Maya2011模型
生活随笔
收集整理的這篇文章主要介紹了
第八章:加载Maya2011模型
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
原文鏈接:
http://www.rastertek.com/gl40tut08.htmlTutorial 8: Loading Maya 2011 Models 第八章:加載Maya2011模型
This tutorial will cover how to import static 3D models from Maya 2011. Note that this tutorial will be focused on Maya but it also applies to pretty much any other 3D modeling software package with some slight changes. 本章將介紹如何導(dǎo)入Maya2011的靜態(tài)模型。通過(guò)稍微修改本章的方法也可以適用于其他3D建模軟件。
In the previous tutorials we have already created our own model format and rendered 3D models using that format. The goal now is to convert Maya 2011 models into our format and render them. I won't go into how to model 3D objects in Maya as there are hundreds of tutorials on the net already dedicated to that, we will instead start at the point where you have a textured and triangulated 3D model ready for export. 在前面的教程里,我們已經(jīng)創(chuàng)建了自己的模型格式用作渲染。現(xiàn)在的目標(biāo)時(shí)將Maya2011的模型轉(zhuǎn)換為自己的模型格式再渲染。本章不會(huì)介紹如何使用Maya進(jìn)行3D建模,這方面已經(jīng)有太多的教程。我們將從導(dǎo)出已經(jīng)包含貼圖的3D模型開(kāi)始。
For the Maya export format we will use the .OBJ format as it is easily readable and good for beginners to start with. 我們將使用Maya導(dǎo)出.OBJ格式文件,此格式結(jié)構(gòu)非常簡(jiǎn)單也很適合初學(xué)者。
To export your model in the .obj format you must first enable the .OBJ exporter in Maya. Click "Window", then "Settings/Preferences", then "Plug-in Manager". Scroll down to objExport.mll and select both "Loaded" and "Auto load". Now to export your model in this format click on "File", then "Export All". Now at the bottom select "Files of type:" and scroll down and select "OBJexport". Give it a file name and hit "Export All" and it will export it to a text file with a .obj extension. To look at the file you can right click and select Open With and choose WordPad to read the file. You will then see something that looks like the following: 要在Maya中導(dǎo)出.obj格式必須先要激活.OBJ導(dǎo)出工具。點(diǎn)擊“Window”,然后“Settings/Preferences”,然后“Plug-in Manager”。找到objExport.mll選擇“Loaded”和“Auto load”。下面開(kāi)始導(dǎo)出,點(diǎn)擊“File”,然后“Export All”。在底部的“Files of type:”選擇“OBJexport”。填寫(xiě)一個(gè)導(dǎo)出的文件名,點(diǎn)擊“Export All”。將導(dǎo)出一個(gè).obj擴(kuò)展名的文本文件。可以用記事本等文本編輯器打開(kāi)文件來(lái)查看文件的內(nèi)容。你講看到類似下面的內(nèi)容:
Cube.obj
# This file uses centimeters as units for non-parametric coordinates.
mtllib cube.mtl g default v -0.500000 -0.500000 0.500000 v 0.500000 -0.500000 0.500000 v -0.500000 0.500000 0.500000 v 0.500000 0.500000 0.500000 v -0.500000 0.500000 -0.500000 v 0.500000 0.500000 -0.500000 v -0.500000 -0.500000 -0.500000 v 0.500000 -0.500000 -0.500000 vt 0.001992 0.001992 vt 0.998008 0.001992 vt 0.001992 0.998008 vt 0.998008 0.998008 vt 0.001992 0.001992 vt 0.998008 0.001992 vt 0.001992 0.998008 vt 0.998008 0.998008 vt 0.001992 0.001992 vt 0.998008 0.001992 vt 0.001992 0.998008 vt 0.998008 0.998008 vt 0.001992 0.001992 vt 0.998008 0.001992 vt 0.001992 0.998008 vt 0.998008 0.998008 vt 0.001992 0.001992 vt 0.998008 0.001992 vt 0.001992 0.998008 vt 0.998008 0.998008 vt 0.998008 0.998008 vt 0.001992 0.998008 vt 0.998008 0.001992 vt 0.001992 0.001992 vn 0.000000 0.000000 1.000000 vn 0.000000 0.000000 1.000000 vn 0.000000 0.000000 1.000000 vn 0.000000 0.000000 1.000000 vn 0.000000 1.000000 0.000000 vn 0.000000 1.000000 0.000000 vn 0.000000 1.000000 0.000000 vn 0.000000 1.000000 0.000000 vn 0.000000 0.000000 -1.000000 vn 0.000000 0.000000 -1.000000 vn 0.000000 0.000000 -1.000000 vn 0.000000 0.000000 -1.000000 vn 0.000000 -1.000000 0.000000 vn 0.000000 -1.000000 0.000000 vn 0.000000 -1.000000 0.000000 vn 0.000000 -1.000000 0.000000 vn 1.000000 0.000000 0.000000 vn 1.000000 0.000000 0.000000 vn 1.000000 0.000000 0.000000 vn 1.000000 0.000000 0.000000 vn -1.000000 0.000000 0.000000 vn -1.000000 0.000000 0.000000 vn -1.000000 0.000000 0.000000 vn -1.000000 0.000000 0.000000 s 1 g pCube1 usemtl file1SG f 1/1/1 2/2/2 3/3/3 f 3/3/3 2/2/2 4/4/4 s 2 f 3/13/5 4/14/6 5/15/7 f 5/15/7 4/14/6 6/16/8 s 3 f 5/21/9 6/22/10 7/23/11 f 7/23/11 6/22/10 8/24/12 s 4 f 7/17/13 8/18/14 1/19/15 f 1/19/15 8/18/14 2/20/16 s 5 f 2/5/17 8/6/18 4/7/19 f 4/7/19 8/6/18 6/8/20 s 6 f 7/9/21 1/10/22 5/11/23 f 5/11/23 1/10/22 3/12/24
This particular .OBJ model file represents a 3D cube. It has 8 vertices, 24 texture coordinates and normal vectors, and 6 sides made up of 12 faces in total. When examining the file you can ignore every line unless it starts with a "V", "VT", "VN", or "F". The extra information in the file will not be needed for converting .obj to our file format. Lets look at what each of the important lines means: 這個(gè).OBJ文件描述了一個(gè)3D盒子。包含8個(gè)頂點(diǎn),24個(gè)紋理坐標(biāo)和法向量,由12個(gè)三角形面組成6個(gè)矩形面。
1. The "V" lines are for the vertices. The cube is made up of 8 vertices for the eight corners of the cube. Each is listed in X, Y, Z float format. 1. “V”開(kāi)頭的行表示頂點(diǎn)。盒子由8個(gè)頂點(diǎn)組成,每個(gè)頂點(diǎn)都包含3個(gè)浮點(diǎn)數(shù)表示x, y, z。
2. The "VT" lines are for the texture coordinates. The cube is has 24 texture coordinates and most of them are duplicated since it records them for every vertex in every triangle in the cube model. They are listed in TU, TV float format. 2. “VT”開(kāi)頭的行表示紋理坐標(biāo)。盒子包含24個(gè)紋理坐標(biāo),對(duì)應(yīng)盒子的每個(gè)三角形的每個(gè)頂點(diǎn)。每個(gè)紋理坐標(biāo)包含2個(gè)浮點(diǎn)數(shù)tu, tv。
3. The "VN" lines are for the normal vectors. The cube is has 24 normal vectors and most of them are duplicated again since it records them for every vertex in every triangle in the cube model. They are listed in NX, NY, NZ float format. 3. “VN”開(kāi)頭的行表示法向量。盒子包含24個(gè)法向量,對(duì)應(yīng)模型的每個(gè)三角形的每個(gè)頂點(diǎn)。每個(gè)法向量包含3個(gè)浮點(diǎn)數(shù)nx, ny, nz。
4. The "F" lines are for each triangle (face) in the cube model. The values listed are indexes into the vertices, texture coordinates, and normal vectors. The format of each face is: 4. “F”開(kāi)頭的行表示盒子模型的三角形面。使用的是頂點(diǎn)的索引,紋理坐標(biāo)的索引,法向量索引。格式如下:
f Vertex1/Texture1/Normal1 Vertex2/Texture2/Normal2 Vertex3/Texture3/Normal3
So a line that says "f 3/13/5 4/14/6 5/15/7" then translates to "Vertex3/Texture13/Normal5 Vertex4/Texture14/Normal6 Vertex5/Texture15/Normal7". "f 3/13/5 4/14/6 5/15/7"意味著“頂點(diǎn)3/紋理坐標(biāo)13/法向量5 頂點(diǎn)4/紋理坐標(biāo)14/法向量6 頂點(diǎn)5/紋理坐標(biāo)15/法向量7”。
The order the data is listed in the .obj file is very important. For example the first vertex in the file corresponds to Vertex1 in the face list. This is the same for texture coordinates and normals as well. obj文件里的數(shù)據(jù)順序非常重要。例如第一個(gè)頂點(diǎn)對(duì)應(yīng)三角形面列表里的頂點(diǎn)1。紋理坐標(biāo)和法向量也是類似的規(guī)則。
Looking at the face lines in the .obj file notice that the three index groups per line make an individual triangle. And in the case of this cube model the 12 total faces make up the 6 sides of the cube that has 2 triangles per side. obj文件里每一個(gè)“f”行定義了一個(gè)三角形面。本章的盒子由12個(gè)三角形面組成。
Right hand to Left hand conversion 左右手坐標(biāo)系轉(zhuǎn)換
By default Maya 2011 is a right handed coordinate system and exports the .obj file data in right hand coordinates. To convert that data into a left handed system which we have setup OpenGL 4.0 as you have to do the following: Maya2011模式使用右手坐標(biāo)系,導(dǎo)出的obj文件也同樣基于右手坐標(biāo)系。要轉(zhuǎn)換obj數(shù)據(jù)到OpenGL 4.0左手坐標(biāo)系我們需要做如下操作:
1. Invert the Z coordinate vertices. In the code you will see it do this: vertices[vertexIndex].z = vertices[vertexIndex].z * -1.0f; 1. 轉(zhuǎn)換頂點(diǎn)Z坐標(biāo)。在代碼里需要這樣做:vertices[vertexIndex].z = vertices[vertexIndex].z * -1.0f;
2. Invert the TV texture coordinate. In the code you will see it do this: texcoords[texcoordIndex].y = 1.0f - texcoords[texcoordIndex].y; 2. 轉(zhuǎn)換紋理TV坐標(biāo)。在代碼里需要這樣做:texcoords[texcoordIndex].y = 1.0f - texcoords[texcoordIndex].y;
3. Invert the NZ normal vertex. In the code you will see it do this: normals[normalIndex].z = normals[normalIndex].z * -1.0f; 3. 轉(zhuǎn)換法向量NZ坐標(biāo)。在代碼里需要這樣做:normals[normalIndex].z = normals[normalIndex].z * -1.0f;
4. Convert the drawing order from counter clockwise to clockwise. In the code I simply read in the indexes in reverse order instead of re-organizing it after the fact: 4. 將繪制順序從逆時(shí)針轉(zhuǎn)換為順時(shí)針。在代碼里我調(diào)整了讀取索引的順序二不是重新構(gòu)造數(shù)據(jù):
fin >> faces[faceIndex].vIndex3 >> input2 >> faces[faceIndex].tIndex3 >> input2 >> faces[faceIndex].nIndex3; fin >> faces[faceIndex].vIndex2 >> input2 >> faces[faceIndex].tIndex2 >> input2 >> faces[faceIndex].nIndex2; fin >> faces[faceIndex].vIndex1 >> input2 >> faces[faceIndex].tIndex1 >> input2 >> faces[faceIndex].nIndex1;
With those four steps complete the model data will be ready for our OpenGL 4.0 setup to render correctly. 經(jīng)過(guò)上面4步,OpenGL 4.0就可以正確處理模型數(shù)據(jù)用于渲染了。
Main.cpp
The program to convert the Maya 2011 .obj files into our OpenGL 4.0 format is fairly simple and is a single program file called main.cpp. It opens a command prompt and asks for the name of the .obj file to convert. Once the user types in the name it will attempt to open the file and read in the data counts and build the structures required to read the data into. After that it reads the data into those structures and converts it to a left hand system. Once that is done it then writes the data out to a model.txt file. That file can then be renamed and used for rendering in OpenGL 4.0 using the 3D model render project from the previous tutorial. 將Maya2011 .obj文件轉(zhuǎn)換為我們自己的OpenGL 4.0格式的程序的文件為main.cpp。它使用命令窗口并要求輸入需要轉(zhuǎn)換的.obj文件名。輸入文件名后,程序試圖打開(kāi)文件并讀取數(shù)據(jù)。在讀完數(shù)據(jù)后將數(shù)據(jù)轉(zhuǎn)換為左手坐標(biāo)系。完成后將轉(zhuǎn)換后的數(shù)據(jù)輸出到model.txt文件。你可以將文件重命名,并使用前面教程的程序加載并渲染。 // Filename: main.cpp// // INCLUDES // // #include <iostream> #include <fstream> using namespace std;// // TYPEDEFS // // typedef struct {float x, y, z; }VertexType;typedef struct {int vIndex1, vIndex2, vIndex3;int tIndex1, tIndex2, tIndex3;int nIndex1, nIndex2, nIndex3; }FaceType;/ // FUNCTION PROTOTYPES // / void GetModelFilename(char*); bool ReadFileCounts(char*, int&, int&, int&, int&); bool LoadDataStructures(char*, int, int, int, int);// // MAIN PROGRAM // // int main() {bool result;char filename[256];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 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 << endl;cout << "Vertices: " << vertexCount << endl;cout << "UVs: " << textureCount << endl;cout << "Normals: " << normalCount << endl;cout << "Faces: " << faceCount << endl;// Now read the data from the file into the data structures and then output it in our model format.result = LoadDataStructures(filename, vertexCount, textureCount, normalCount, faceCount);if(!result){return -1;}// Notify the user the model has been converted.cout << "\nFile has been converted." << endl;cout << "\nDo you wish to exit (y/n)? ";cin >> garbage;return 0; }void GetModelFilename(char* filename) {bool done;ifstream fin;// Loop until we have a file name.done = false;while(!done){// Ask the user for the filename.cout << "Enter model filename: ";// Read in the filename.cin >> 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 the file does not exist or there was an issue opening it then notify the user and repeat the process.fin.clear();cout << endl;cout << "File " << filename << " could not be opened." << endl << endl;}}return; }bool ReadFileCounts(char* filename, int& vertexCount, int& textureCount, int& normalCount, int& faceCount) {ifstream fin;char input;// Initialize the counts.vertexCount = 0;textureCount = 0;normalCount = 0;faceCount = 0;// Open the file.fin.open(filename);// Check if it was successful in opening the file.if(fin.fail() == true){return false;}// Read from the file and continue to read until the end of the file is reached.fin.get(input);while(!fin.eof()){// If the line starts with 'v' then count either the vertex, the texture coordinates, or the normal vector.if(input == 'v'){fin.get(input);if(input == ' ') { vertexCount++; }if(input == 't') { textureCount++; }if(input == 'n') { normalCount++; }}// If the line starts with 'f' then increment the face count.if(input == 'f'){fin.get(input);if(input == ' ') { faceCount++; }}// Otherwise read in the remainder 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();return true; }bool LoadDataStructures(char* filename, int vertexCount, int textureCount, int normalCount, int faceCount) {VertexType *vertices, *texcoords, *normals;FaceType *faces;ifstream fin;int vertexIndex, texcoordIndex, normalIndex, faceIndex, vIndex, tIndex, nIndex;char input, input2;ofstream fout;// Initialize the four data structures.vertices = new VertexType[vertexCount];if(!vertices){return false;}texcoords = new VertexType[textureCount];if(!texcoords){return false;}normals = new VertexType[normalCount];if(!normals){return false;}faces = new FaceType[faceCount];if(!faces){return false;}// Initialize the indexes.vertexIndex = 0;texcoordIndex = 0;normalIndex = 0;faceIndex = 0;// Open the file.fin.open(filename);// Check if it was successful in opening the file.if(fin.fail() == true){return false;}// Read in the vertices, texture coordinates, and normals into the data structures.// Important: Also convert to left hand coordinate system since Maya uses right hand coordinate system.fin.get(input);while(!fin.eof()){if(input == 'v'){fin.get(input);// Read in the vertices.if(input == ' '){fin >> vertices[vertexIndex].x >> vertices[vertexIndex].y >> vertices[vertexIndex].z;// Invert the Z vertex to change to left hand system.vertices[vertexIndex].z = vertices[vertexIndex].z * -1.0f;vertexIndex++;}// Read in the texture uv coordinates.if(input == 't'){fin >> texcoords[texcoordIndex].x >> texcoords[texcoordIndex].y;// Invert the V texture coordinates to left hand system.texcoords[texcoordIndex].y = 1.0f - texcoords[texcoordIndex].y;texcoordIndex++;}// Read in the normals.if(input == 'n'){fin >> normals[normalIndex].x >> normals[normalIndex].y >> normals[normalIndex].z;// Invert the Z normal to change to left hand system.normals[normalIndex].z = normals[normalIndex].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 hand system.fin >> faces[faceIndex].vIndex3 >> input2 >> faces[faceIndex].tIndex3 >> input2 >> faces[faceIndex].nIndex3>> faces[faceIndex].vIndex2 >> input2 >> faces[faceIndex].tIndex2 >> input2 >> faces[faceIndex].nIndex2>> faces[faceIndex].vIndex1 >> input2 >> faces[faceIndex].tIndex1 >> input2 >> faces[faceIndex].nIndex1;faceIndex++;}}// Read in the remainder 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:" << endl;fout << endl;// Now loop through all the faces and output the three vertices for each face.for(int i=0; i<faceIndex; i++){vIndex = faces[i].vIndex1 - 1;tIndex = faces[i].tIndex1 - 1;nIndex = faces[i].nIndex1 - 1;fout << vertices[vIndex].x << ' ' << vertices[vIndex].y << ' ' << vertices[vIndex].z << ' '<< texcoords[tIndex].x << ' ' << texcoords[tIndex].y << ' '<< normals[nIndex].x << ' ' << normals[nIndex].y << ' ' << normals[nIndex].z << endl;vIndex = faces[i].vIndex2 - 1;tIndex = faces[i].tIndex2 - 1;nIndex = faces[i].nIndex2 - 1;fout << vertices[vIndex].x << ' ' << vertices[vIndex].y << ' ' << vertices[vIndex].z << ' '<< texcoords[tIndex].x << ' ' << texcoords[tIndex].y << ' '<< normals[nIndex].x << ' ' << normals[nIndex].y << ' ' << normals[nIndex].z << endl;vIndex = faces[i].vIndex3 - 1;tIndex = faces[i].tIndex3 - 1;nIndex = faces[i].nIndex3 - 1;fout << vertices[vIndex].x << ' ' << vertices[vIndex].y << ' ' << vertices[vIndex].z << ' '<< texcoords[tIndex].x << ' ' << texcoords[tIndex].y << ' '<< normals[nIndex].x << ' ' << normals[nIndex].y << ' ' << normals[nIndex].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; }
Summary 總結(jié)
We can now convert Maya 2011 .obj files into our simple model format. 本章介紹了將Maya 2011 .obj文件轉(zhuǎn)換為我們自己的模型格式的方法。
To Do Exercises 練習(xí)
1. Recompile the program and run it with the supplied .obj model file. 1. 重新編譯并運(yùn)行代碼測(cè)試轉(zhuǎn)換.obj模型文件。
2. Create (or have someone else make for you) a Maya 2011 model and export it in .obj format and run this program to convert it. 2. 創(chuàng)建(或通過(guò)其他途徑獲取)一個(gè)Maya 2011模型并導(dǎo)出為.obj格式文件,然后運(yùn)行本章程序進(jìn)行轉(zhuǎn)換。
3. Convert this code to read in and export a different model format that you might prefer. 3. 修改代碼,使它可以讀取并導(dǎo)出任何你喜歡的模型格式。
Source Code 源代碼
http://www.rastertek.com/gl40src08.zip
總結(jié)
以上是生活随笔為你收集整理的第八章:加载Maya2011模型的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 极致”神话和产品观念
- 下一篇: linux服务器使用WonderShap