원문: http://www.rastertek.com/dx11tut08.html
이 튜토리얼에서는 마야 2011(Maya 2011)에서 만든 3D 모델을 불러오는 방법을 다룹니다. 여기서는 마야에 초점을 맞추었지만, 조금 변형하여 다른 많은 3D 모델링 패키지 프로그램에도 적용할 수 있습니다.
이전 튜토리얼에서는 우리들만의 포맷을 만들고 이를 이용하여 3D 모델을 그려보았습니다. 이번의 목표는 바로 마야 2011의 모델을 우리 포맷으로 바꾸고 그것을 렌더링하는 것입니다. 마야에서 3D 모델을 만드는 방법은 이미 그에 관해 수백개가 넘는 튜토리얼들이 있기 때문에 따로 다루지 않고 이미 텍스쳐를 붙인 삼각형화된 3D 모델을 만들어서 내보낼 준비가 되었다는
여러 마야 포맷 중에서 초심자에게 좋고 읽기 쉬운 .OBJ 포맷을 사용할 것입니다.
여러분의 모델을 .obj 포맷으로 내보내기 위해서는 반드시 마야의 .obj 익스포터(exporter)을 활성화해야 합니다. 메뉴에서 Window를 선택하고, Settings/Preferences로 간 뒤에 Plug-in Manager로 이동합니다. objExport.mll까지 스크롤 하고 Loaded와 Auto load를 둘 다 선택합니다. 이제 모델을 내보내기 위해서 메뉴의 File을 선택하고 Export All을 선택합니다. 그리고 아랫쪽의 "Files of type: "에서 OBJexport를 스크롤하여 선택합니다. 파일 이름을 입력하고 Export All 버튼을 클릭하면 .obj 확장자를 가진 텍스트 파일로 모델 데이터가 내보내집니다. 파일 내용을 보고 싶다면 파일에 오른쪽 클릭을 한 뒤 "연결 프로그램"에서 워드패드를 골라 열어볼 수 있습니다. 아마 아래 내용과 비슷한 것을 보게 될 겁니다.
//////////////////////////////////////////////////////////////////////////////// // 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; }
'강좌번역 > DirectX 11' 카테고리의 다른 글
DirectX11 Tutorial 10 - 정반사광 (1) | 2013.03.11 |
---|---|
DirectX11 Tutorial 9 - 주변광 (0) | 2013.02.10 |
DirectX11 Tutorial 7 - 3D 모델 렌더링 (1) | 2013.02.02 |
DirectX11 Tutorial 6 - 조명 (1) | 2013.01.22 |
DirectX11 Tutorial 5 - 텍스쳐 (14) | 2013.01.16 |