![]() |
TAPs 0.7.7.3
|
00001 /****************************************************************************** 00002 TAPsReadObj.cpp 00003 00004 Create an OpenGL Model Object from a .obj file. 00005 00006 SUKITTI PUNAK (10/12/2006) 00007 UPDATE (10/15/2006) 00008 ******************************************************************************/ 00009 #include "TAPsReadObj.hpp" 00010 // Using Inclusion Model (i.e. definitions are included in declarations) 00011 // (this name.cpp is included in name.hpp) 00012 // Each friend is defined directly inside its declaration. 00013 00014 //----------------------------------------------------------------------------- 00015 // DEBUG ENABLE 00016 #ifdef TAPs_DEBUG_MODE 00017 #define DEBUG_MESSAGE_TAPs_READ_OBJ_HPP 00018 #endif 00019 00020 BEGIN_NAMESPACE_TAPs 00021 //============================================================================= 00022 template <typename T> FILE * ReadObj<T>::fileIn = NULL; 00023 template <typename T> int ReadObj<T>::faceNo = 0; 00024 template <typename T> int ReadObj<T>::vertexPositionNo = 0; 00025 template <typename T> int ReadObj<T>::vertexTextureCoordNo = 0; 00026 template <typename T> int ReadObj<T>::vertexNormalNo = 0; 00027 template <typename T> MeshData<T> ReadObj<T>::meshData; 00028 //============================================================================= 00029 //----------------------------------------------------------------------------- 00030 // Read an input file 00031 template <typename T> 00032 bool ReadObj<T>::ReadFile ( 00033 const char *fileName, OpenGL::PolygonalModel<T> * const prModel ) 00034 { 00035 if ( !ReadDataFile( fileName, prModel ) ) return false; 00036 //--------------------------------------------------------------- 00037 SetupModel( prModel ); 00038 prModel->GetMaterial()->ApplyMaterial(); 00039 //--------------------------------------------------------------- 00040 meshData.ClearAll(); 00041 return true; 00042 } 00043 //----------------------------------------------------------------------------- 00044 // Read an input file 00045 template <typename T> 00046 bool ReadObj<T>::ReadFile ( 00047 const char *fileName, OpenGL::XPolygonalModel<T> * const prModel ) 00048 { 00049 if ( !ReadDataFile( fileName, prModel ) ) return false; 00050 //--------------------------------------------------------------- 00051 SetupModel( prModel ); 00052 prModel->GetMaterial()->ApplyMaterial(); 00053 //--------------------------------------------------------------- 00054 meshData.ClearAll(); 00055 return true; 00056 } 00057 //----------------------------------------------------------------------------- 00058 // Read an input file 00059 template <typename T> 00060 bool ReadObj<T>::ReadFile ( 00061 const char *fileName, OpenGL::HalfEdgeModel<T> * const prModel ) 00062 { 00063 if ( !ReadDataFile( fileName, prModel ) ) return false; 00064 //--------------------------------------------------------------- 00065 SetupModel( prModel ); 00066 prModel->GetMaterial()->ApplyMaterial(); 00067 //--------------------------------------------------------------- 00068 meshData.ClearAll(); 00069 return true; 00070 } 00071 //----------------------------------------------------------------------------- 00072 //============================================================================= 00073 //----------------------------------------------------------------------------- 00074 // Read an input data file 00075 template <typename T> 00076 bool ReadObj<T>::ReadDataFile ( 00077 const char *fileName, OpenGL::MeshModel<T> * const prModel ) 00078 { 00079 //--------------------------------------------------------------- 00080 // Open the input file 00081 #ifdef DEBUG_MESSAGE_TAPs_READ_OBJ_HPP 00082 std::cout << "Open the input file: " << fileName << std::endl; 00083 #endif 00084 00085 fileIn = fopen( fileName, "r" ); 00086 if ( !fileIn ) { 00087 #ifdef DEBUG_MESSAGE_TAPs_READ_OBJ_HPP 00088 std::perror( fileName ); 00089 #endif 00090 std::cout << fileName << " is Not Found!" << std::endl; 00091 return false; 00092 } 00093 //--------------------------------------------------------------- 00094 #ifdef DEBUG_MESSAGE_TAPs_READ_OBJ_HPP 00095 std::cout << "START READING " << fileName << "\n"; 00096 #endif 00097 //--------------------------------------------------------------- 00098 // Initialization 00099 faceNo = 0; 00100 vertexPositionNo = 0; 00101 vertexTextureCoordNo = 0; 00102 vertexNormalNo = 0; 00103 meshData.ClearAll(); 00104 //--------------------------------------------------------------- 00105 // Read in each line, check what its contents are, 00106 // and pass it out to the relevant decoder function 00107 char line[256]; 00108 fgets( line, 256, fileIn ); 00109 do { 00110 #ifdef DEBUG_MESSAGE_TAPs_READ_OBJ_HPP 00111 //std::cout << "I/P Line: " << line; 00112 #endif 00113 //------------------------------------------------- 00114 // Vertex Normal 00115 if ( !strncmp( line, "vn", strlen( "vn" ) ) ) 00116 ProcessLineVertexNormal_vn( line, prModel ); 00117 //------------------------------------------------- 00118 // Vertex Texture Coordinates 00119 else if ( !strncmp( line, "vt", strlen( "vt" ) ) ) 00120 ProcessLineVertexTextureCoordinates_vt( line, prModel ); 00121 //------------------------------------------------- 00122 // Vertex Position 00123 else if ( !strncmp( line, "v", strlen( "v" ) ) ) 00124 ProcessLineVertexPosition_v( line, prModel ); 00125 //------------------------------------------------- 00126 // Face 00127 else if ( !strncmp( line, "f", strlen( "f" ) ) ) 00128 ProcessLineFace_f( line, prModel ); 00129 //------------------------------------------------- 00130 // Group Name 00131 else if ( !strncmp( line, "g", strlen( "g" ) ) ) 00132 ProcessLineGroupName_g( line, prModel ); 00133 //------------------------------------------------- 00134 // Use Material Name 00135 else if ( !strncmp( line, "usemtl", strlen( "usemtl" ) ) ) 00136 ProcessLineUseMaterialName_usemtl( line, prModel ); 00137 //------------------------------------------------- 00138 // Use Material Name 00139 else if ( !strncmp( line, "mtllib", strlen( "mtllib" ) ) ) 00140 ProcessLineMaterialLibrary_mtllib( line, prModel ); 00141 //------------------------------------------------- 00142 // Object Name 00143 else if ( !strncmp( line, "o", strlen( "o" ) ) ) 00144 ProcessLineObjectName_o( line, prModel ); 00145 //------------------------------------------------- 00146 fgets( line, 256, fileIn ); 00147 } while ( !feof( fileIn ) ); 00148 //--------------------------------------------------------------- 00149 fclose( fileIn ); // close the input file 00150 #ifdef DEBUG_MESSAGE_TAPs_READ_OBJ_HPP 00151 std::cout << "END READING " << fileName << "\n"; 00152 #endif 00153 return true; 00154 } 00155 //----------------------------------------------------------------------------- 00156 // Set Model Properties 00157 template <typename T> 00158 void ReadObj<T>::SetModelProperties ( OpenGL::MeshModel<T> * const prModel ) 00159 { 00160 prModel->SetNumVertices( static_cast<int>( meshData.VertexList.size() ) ); 00161 prModel->SetNumFaces( static_cast<int>( meshData.FaceList.size() ) ); 00162 00163 #ifdef DEBUG_MESSAGE_TAPs_READ_OBJ_HPP 00164 std::cout << "Number of Vertices: " << prModel->GetNumVertices() << "\n"; 00165 std::cout << "Number of Faces: " << prModel->GetNumFaces() << "\n"; 00166 #endif 00167 } 00168 //----------------------------------------------------------------------------- 00169 //============================================================================= 00170 //----------------------------------------------------------------------------- 00171 // Setup Model for PolygonalModel 00172 template <typename T> 00173 void ReadObj<T>::SetupModel ( OpenGL::PolygonalModel<T> * const prModel ) 00174 { 00175 SetModelProperties( prModel ); 00176 prModel->NewVertexListByNoVertices(); 00177 prModel->NewFaceListByNoFaces(); 00178 for ( int i = 0; i < prModel->GetNumVertices(); ++i ) { 00179 prModel->GetVertexList()[i].SetPosition( meshData.VertexList[i]->GetPosition() ); 00180 prModel->GetVertexList()[i].SetNormal( meshData.VertexList[i]->GetNormal() ); 00181 } 00182 for ( int i = 0; i < prModel->GetNumFaces(); ++i ) { 00183 prModel->GetFaceList()[i] = *meshData.FaceList[i]; 00184 } 00185 /* 00186 #ifdef DEBUG_MESSAGE_TAPs_READ_OBJ_HPP 00187 std::cout << "Number of Vertices: " << prModel->GetNumVertices() << "\n"; 00188 for ( int i = 0; i < prModel->GetNumVertices(); ++i ) { 00189 std::cout << "Vertex# " << prModel->GetVertexList()[i] << "\n"; 00190 } 00191 std::cout << "Number of Faces: " << prModel->GetNumFaces() << "\n"; 00192 for ( int i = 0; i < prModel->GetNumFaces(); ++i ) { 00193 std::cout << "Vertex# " << prModel->GetFaceList()[i] << "\n"; 00194 } 00195 #endif 00196 //*/ 00197 } 00198 //----------------------------------------------------------------------------- 00199 // Setup Model for XPolygonalModel 00200 template <typename T> 00201 void ReadObj<T>::SetupModel ( OpenGL::XPolygonalModel<T> * const prModel ) 00202 { 00203 SetModelProperties( prModel ); 00204 prModel->NewVertexListByNoVertices(); 00205 prModel->NewFaceListByNoFaces(); 00206 for ( int i = 0; i < prModel->GetNumVertices(); ++i ) { 00207 prModel->GetVertexList()[i].SetPosition( meshData.VertexList[i]->GetPosition() ); 00208 prModel->GetVertexList()[i].SetNormal( meshData.VertexList[i]->GetNormal() ); 00209 } 00210 for ( int i = 0; i < prModel->GetNumFaces(); ++i ) { 00211 prModel->GetFaceList()[i] = *meshData.FaceList[i]; 00212 } 00213 /* 00214 #ifdef DEBUG_MESSAGE_TAPs_READ_OBJ_HPP 00215 std::cout << "Number of Vertices: " << prModel->GetNumVertices() << "\n"; 00216 for ( int i = 0; i < prModel->GetNumVertices(); ++i ) { 00217 std::cout << "Vertex# " << prModel->GetVertexList()[i] << "\n"; 00218 } 00219 std::cout << "Number of Faces: " << prModel->GetNumFaces() << "\n"; 00220 for ( int i = 0; i < prModel->GetNumFaces(); ++i ) { 00221 std::cout << "Vertex# " << prModel->GetFaceList()[i] << "\n"; 00222 } 00223 #endif 00224 //*/ 00225 } 00226 //----------------------------------------------------------------------------- 00227 // Setup Model for HalfEdgeModel 00228 template <typename T> 00229 void ReadObj<T>::SetupModel ( OpenGL::HalfEdgeModel<T> * const prModel ) 00230 { 00231 SetModelProperties( prModel ); 00232 //--------------------------------------------------------------- 00233 int iNumVertices = prModel->GetNumVertices(); 00234 // Allocate memory for vertices 00235 HelpCreateHalfEdgeModel<T>::vertexList = 00236 new HEVertex<T>*[ iNumVertices ]; 00237 HelpCreateHalfEdgeModel<T>::vertexRingList = 00238 new DS::HashTableBySTLVector<int>( iNumVertices ); 00239 HelpCreateHalfEdgeModel<T>::halfEdgeRingList = 00240 new DS::HashTableBySTLVector< HEHalfEdge<T> * >( iNumVertices ); 00241 //--------------------------------------------------------------- 00242 // For Each Vertex 00243 for ( int i = 0; i < iNumVertices; ++i ) { 00244 // Put created vertex in vertexList for look up later 00245 HelpCreateHalfEdgeModel<T>::vertexList[ i ] = 00246 new HEVertex<T>( 00247 meshData.VertexList[ i ]->GetPosition(), 00248 meshData.VertexList[ i ]->GetNormal() 00249 #ifdef TAPs_USE_DATA_POOL 00250 , prModel->GetArrayOfVertexPositions().GetAddressOfDataNumber( i ) 00251 , prModel->GetArrayOfVertexNormals().GetAddressOfDataNumber( i ) 00252 #endif//TAPs_USE_DATA_POOL 00253 ); 00254 // Put created vertex in vertexList of the model 00255 prModel->GetVertexList()->Append( 00256 HelpCreateHalfEdgeModel<T>::vertexList[ i ] ); 00257 } 00258 //--------------------------------------------------------------- 00259 // For Each Face 00260 for ( int i = 0; i < prModel->GetNumFaces(); ++i ) { 00261 //------------------------------------------------- 00262 HEFace<T> * heFace = new HEFace<T>(); 00263 prModel->GetFaceList()->Append( heFace ); 00264 std::vector< HEHalfEdge<T> * > heHalfEdge; 00265 int v = 0; 00266 //----------------------------------- 00267 // (CCW) Record v0 to v1, v1 to v2, ... in vertexRingList 00268 // put v1 in bucket v0 00269 HelpCreateHalfEdgeModel<T>::vertexRingList->Insert( 00270 meshData.FaceList[i]->GetVertexNo( 1 ), 00271 meshData.FaceList[i]->GetVertexNo( 0 ) ); 00272 //----------------------------------- 00273 // Create and Set half-edge 00274 heHalfEdge.push_back( HelpCreateHalfEdgeModel<T>::CreateHalfEdgeFrom( 00275 HelpCreateHalfEdgeModel<T>::vertexList[ meshData.FaceList[i]->GetVertexNo( 0 ) ], 00276 HelpCreateHalfEdgeModel<T>::vertexList[ meshData.FaceList[i]->GetVertexNo( 1 ) ], 00277 heFace ) ); 00278 //----------------------------------- 00279 // Record half-edges in halfEdgeRingList 00280 HelpCreateHalfEdgeModel<T>::halfEdgeRingList->Insert( 00281 heHalfEdge[0], meshData.FaceList[i]->GetVertexNo( 0 ) ); // put in bucket v0 00282 //----------------------------------- 00283 // Set incident half-edge of this face 00284 heFace->IncidentHalfEdge( heHalfEdge[ 0 ] ); 00285 //----------------------------------- 00286 for ( v = 1; v < meshData.FaceList[i]->GetNumVertices() - 1; ++v ) { 00287 //----------------------------------- 00288 // put v+1 in bucket v 00289 HelpCreateHalfEdgeModel<T>::vertexRingList->Insert( 00290 meshData.FaceList[i]->GetVertexNo( v+1 ), 00291 meshData.FaceList[i]->GetVertexNo( v ) ); 00292 //----------------------------------- 00293 // Create and Set half-edge 00294 heHalfEdge.push_back( HelpCreateHalfEdgeModel<T>::CreateHalfEdgeFrom( 00295 HelpCreateHalfEdgeModel<T>::vertexList[ meshData.FaceList[i]->GetVertexNo( v ) ], 00296 HelpCreateHalfEdgeModel<T>::vertexList[ meshData.FaceList[i]->GetVertexNo( v+1 ) ], 00297 heFace, heHalfEdge[ v-1 ] ) ); // w/ prev ptr 00298 //----------------------------------- 00299 // Record half-edges in halfEdgeRingList 00300 HelpCreateHalfEdgeModel<T>::halfEdgeRingList->Insert( 00301 heHalfEdge[v], meshData.FaceList[i]->GetVertexNo( v ) ); // put in bucket v 00302 } 00303 //----------------------------------- 00304 // put v0 in bucket v 00305 HelpCreateHalfEdgeModel<T>::vertexRingList->Insert( 00306 meshData.FaceList[i]->GetVertexNo( 0 ), 00307 meshData.FaceList[i]->GetVertexNo( v ) ); 00308 //----------------------------------- 00309 // Create and Set half-edge 00310 heHalfEdge.push_back( HelpCreateHalfEdgeModel<T>::CreateHalfEdgeFrom( 00311 HelpCreateHalfEdgeModel<T>::vertexList[ meshData.FaceList[i]->GetVertexNo( v ) ], 00312 HelpCreateHalfEdgeModel<T>::vertexList[ meshData.FaceList[i]->GetVertexNo( 0 ) ], 00313 heFace, heHalfEdge[ v-1 ], heHalfEdge[ 0 ] ) ); // w/ prev and next ptrs 00314 //----------------------------------- 00315 // Record half-edges in halfEdgeRingList 00316 HelpCreateHalfEdgeModel<T>::halfEdgeRingList->Insert( 00317 heHalfEdge[v], meshData.FaceList[i]->GetVertexNo( v ) ); // put in bucket v0 00318 //----------------------------------- 00319 // (CCW) Record v0 to v1, v1 to v2, and v2 to v0 in vertexRingList 00320 // HelpCreateHalfEdgeModel<T>::vertexRingList->Insert( v1, v0 ); // put v1 in bucket v0 00321 // HelpCreateHalfEdgeModel<T>::vertexRingList->Insert( v2, v1 ); // put v2 in bucket v1 00322 // HelpCreateHalfEdgeModel<T>::vertexRingList->Insert( v0, v2 ); // put v0 in bucket v2 00323 //----------------------------------- 00324 // Record half-edges in halfEdgeRingList 00325 // HelpCreateHalfEdgeModel<T>::halfEdgeRingList->Insert( heHalfEdge0, v0 ); // put in bucket v0 00326 // HelpCreateHalfEdgeModel<T>::halfEdgeRingList->Insert( heHalfEdge1, v1 ); // put in bucket v1 00327 // HelpCreateHalfEdgeModel<T>::halfEdgeRingList->Insert( heHalfEdge2, v2 ); // put in bucket v2 00328 } 00329 //--------------------------------------------------------------- 00330 //--------------------------------------------------------------- 00331 HelpCreateHalfEdgeModel<T>::CreateHalfEdgeModel( prModel ); 00332 //*/ 00333 } 00334 //----------------------------------------------------------------------------- 00335 //============================================================================= 00336 //----------------------------------------------------------------------------- 00337 // Process Line Object Name (o) 00338 template <typename T> 00339 void ReadObj<T>::ProcessLineObjectName_o ( 00340 char * line, OpenGL::MeshModel<T> * const prModel ) 00341 { 00342 // ??? 00343 } 00344 //----------------------------------------------------------------------------- 00345 // Process Line Group Name (g) 00346 template <typename T> 00347 void ReadObj<T>::ProcessLineGroupName_g ( 00348 char * line, OpenGL::MeshModel<T> * const prModel ) 00349 { 00350 // ??? 00351 } 00352 //----------------------------------------------------------------------------- 00353 // Process Line Material Library (mtllib) 00354 template <typename T> 00355 void ReadObj<T>::ProcessLineMaterialLibrary_mtllib ( 00356 char * line, OpenGL::MeshModel<T> * const prModel ) 00357 { 00358 // ??? 00359 } 00360 //----------------------------------------------------------------------------- 00361 // Process Line Use Material Name (usemtl) 00362 template <typename T> 00363 void ReadObj<T>::ProcessLineUseMaterialName_usemtl ( 00364 char * line, OpenGL::MeshModel<T> * const prModel ) 00365 { 00366 // ??? 00367 } 00368 //----------------------------------------------------------------------------- 00369 //============================================================================= 00370 // Process Vertex Position (v) 00371 //----------------------------------------------------------------------------- 00372 template <typename T> 00373 void ReadObj<T>::ProcessLineVertexPosition_v ( 00374 char * line, OpenGL::MeshModel<T> * const prModel ) 00375 { 00376 // Example 00377 // v 0.279370 157.247177 -5.951185 00378 float x, y, z; 00379 char acNode[4]; 00380 sscanf( line, "%s %f %f %f", acNode, &x, &y, &z ); 00381 meshData.VertexList.push_back( new Vertex<T>( x, y, z ) ); 00382 //--------------------------------------------------------------- 00383 /* 00384 #ifdef DEBUG_MESSAGE_TAPs_READ_OBJ_HPP 00385 std::cout << "Position# " << vertexPositionNo << ":\t" << x << "\t" << y << "\t" << z << "\n"; 00386 #endif 00387 //*/ 00388 ++vertexPositionNo; 00389 } 00390 //----------------------------------------------------------------------------- 00391 //============================================================================= 00392 // Process Vertex Texture Coordinates (vt) 00393 //----------------------------------------------------------------------------- 00394 template <typename T> 00395 void ReadObj<T>::ProcessLineVertexTextureCoordinates_vt ( 00396 char * line, OpenGL::MeshModel<T> * const prModel ) 00397 { 00398 // Example 00399 // vt 0.2 0.5 00400 float s, t; 00401 char acNode[4]; 00402 sscanf( line, "%vt %f %f", acNode, &s, &t ); 00403 meshData.TextureCoor2DList.push_back( Vector2<T>( s, t ) ); 00404 //--------------------------------------------------------------- 00405 /* 00406 #ifdef DEBUG_MESSAGE_TAPs_READ_OBJ_HPP 00407 std::cout << "TextureCoord# " << vertexTextureCoordNo << ":\t" << s << "\t" << t << "\n"; 00408 #endif 00409 //*/ 00410 ++vertexTextureCoordNo; 00411 } 00412 //----------------------------------------------------------------------------- 00413 //============================================================================= 00414 // Process Vertex Normal (vn) 00415 //----------------------------------------------------------------------------- 00416 template <typename T> 00417 void ReadObj<T>::ProcessLineVertexNormal_vn ( 00418 char * line, OpenGL::MeshModel<T> * const prModel ) 00419 { 00420 // Example 00421 // vn 0.855148 0.250195 -0.454009 00422 float i, j, k; 00423 char acNode[4]; 00424 sscanf( line, "%s %f %f %f", acNode, &i, &j, &k ); 00425 meshData.NormalList.push_back( Vector3<T>( i, j, k ) ); 00426 //--------------------------------------------------------------- 00427 /* 00428 #ifdef DEBUG_MESSAGE_TAPs_READ_OBJ_HPP 00429 std::cout << "Normal# " << vertexNormalNo << ":\t" << i << "\t" << j << "\t" << k << "\n"; 00430 #endif 00431 //*/ 00432 ++vertexNormalNo; 00433 } 00434 //----------------------------------------------------------------------------- 00435 //============================================================================= 00436 // Process Face (f) 00437 //----------------------------------------------------------------------------- 00438 template <typename T> 00439 void ReadObj<T>::ProcessLineFace_f ( 00440 char * line, OpenGL::MeshModel<T> * const prModel ) 00441 { 00442 /* 00443 // DEBUG 00444 char debugLine[256]; 00445 strcpy( debugLine, line ); 00446 //*/ 00447 00448 // Examples 00449 // f 111/49/111 110/129/110 109/102/109 108/30/108 (a quad) 00450 // f 15//15 16//16 8//8 (a triangle without vt) 00451 //--------------------------------------------------------------- 00452 std::vector< int > idxV, idxVT, idxVN; 00453 //--------------------------------------------------------------- 00454 char *delimSpaces = "\t \n"; // tab, space, new line 00455 char *token = NULL; 00456 char *vertexGroup = NULL; 00457 char *firstSlash = NULL; 00458 char *secondSlash = NULL; 00459 int tokenLen = 0; 00460 int len = 0; 00461 char *end; 00462 int numberOfVertices = 0; 00463 //--------------------------------------------------------------- 00464 token = strtok( line, delimSpaces ); // token is now 'f' 00465 token = strtok( '\0', delimSpaces ); // vertex properties (v/vt/vn) 00466 while ( token ) { 00467 tokenLen = static_cast<int>( strlen( token ) ); 00468 //if ( tokenLen <= 0 ) return; 00469 //------------------------------------------------- 00470 // Check format: 00471 // ( v v ... ) 00472 // ( v/vt v/vt ... ) 00473 // ( v//vn v//vn ... ) 00474 // ( v/vt/vn v/vt/vn ... ) 00475 firstSlash = strchr( token, '/' ); 00476 //--------------------------------------- 00477 // Format: v v ... 00478 if ( firstSlash == NULL ) { 00479 idxVT.push_back( -1 ); 00480 idxVN.push_back( -1 ); 00481 idxV.push_back( static_cast<int>( strtol( token, &end, 10 ) ) - 1 ); 00482 } 00483 //--------------------------------------- 00484 // Format: v/vt v/vt ... 00485 else { 00486 secondSlash = strrchr( token, '/' ); 00487 if ( secondSlash == firstSlash ) { 00488 idxVN.push_back( -1 ); 00489 int i = 0; 00490 int n = 0; 00491 char vStr[16]; 00492 //----------------- 00493 // v 00494 for ( ; n < firstSlash - token; ++i, ++n ) { 00495 vStr[n] = token[i]; 00496 } 00497 vStr[n] = '\0'; // null terminated 00498 idxV.push_back( static_cast<int>( strtol( vStr, &end, 10 ) ) - 1 ); 00499 //----------------- 00500 // vt 00501 for ( ++i, n = 0; n < token + tokenLen - firstSlash; ++i, ++n ) { 00502 vStr[n] = token[i]; 00503 } 00504 vStr[n] = '\0'; // null terminated 00505 idxVT.push_back( static_cast<int>( strtol( vStr, &end, 10 ) ) - 1 ); 00506 } 00507 //--------------------------------------- 00508 // Format: v//vn v//vn ... 00509 else { 00510 len = secondSlash - firstSlash; 00511 if ( len == 1 ) { 00512 idxVT.push_back( -1 ); 00513 int i = 0; 00514 int n = 0; 00515 char vStr[16]; 00516 //----------------- 00517 // v 00518 for ( ; n < firstSlash - token; ++i, ++n ) { 00519 vStr[n] = token[i]; 00520 } 00521 vStr[n] = '\0'; // null terminated 00522 idxV.push_back( static_cast<int>( strtol( vStr, &end, 10 ) ) - 1 ); 00523 //----------------- 00524 // vn 00525 for ( i+=2, n = 0; n < token + tokenLen - secondSlash; ++i, ++n ) { 00526 vStr[n] = token[i]; 00527 } 00528 vStr[n] = '\0'; // null terminated 00529 idxVN.push_back( static_cast<int>( strtol( vStr, &end, 10 ) ) - 1 ); 00530 } 00531 //--------------------------------------- 00532 // Format: v/vt/vn v/vt/vn ... 00533 else { 00534 int i = 0; 00535 int n = 0; 00536 char vStr[16]; 00537 //----------------- 00538 // v 00539 for ( ; n < firstSlash - token; ++i, ++n ) { 00540 vStr[n] = token[i]; 00541 } 00542 vStr[n] = '\0'; // null terminated 00543 idxV.push_back( static_cast<int>( strtol( vStr, &end, 10 ) ) - 1 ); 00544 //----------------- 00545 // vt 00546 for ( ++i, n = 0; n < secondSlash - firstSlash - 1; ++i, ++n ) { 00547 vStr[n] = token[i]; 00548 } 00549 vStr[n] = '\0'; // null terminated 00550 idxVT.push_back( static_cast<int>( strtol( vStr, &end, 10 ) ) - 1 ); 00551 //----------------- 00552 // vn 00553 for ( ++i, n = 0; n < token + tokenLen - secondSlash; ++i, ++n ) { 00554 vStr[n] = token[i]; 00555 } 00556 vStr[n] = '\0'; // null terminated 00557 idxVN.push_back( static_cast<int>( strtol( vStr, &end, 10 ) ) - 1 ); 00558 } 00559 } 00560 } 00561 //------------------------------------------------- 00562 ++numberOfVertices; 00563 token = strtok( '\0', delimSpaces ); // vertex properties (v/vt/vn) 00564 //token = strtok( line, delimSpaces ); // vertex properties (v/vt/vn) 00565 } 00566 //--------------------------------------------------------------- 00567 Face<T> * face = new Face<T>(); 00568 //----------------------------------------------------- 00569 // Vertices of Face 00570 /* 00571 #ifdef DEBUG_MESSAGE_TAPs_READ_OBJ_HPP 00572 std::cout << "Face: Number of vertices: " << numberOfVertices << "\n"; 00573 #endif 00574 //*/ 00575 00576 /* 00577 #ifdef DEBUG_MESSAGE_TAPs_READ_OBJ_HPP 00578 char buf[32]; 00579 std::string str = "f"; 00580 for ( int i = 0; i < numberOfVertices; ++i ) { 00581 itoa( idxV[i] + 1, buf, 10 ); 00582 str = str + " " + buf; 00583 if ( idxVT[0] != -1 ) { 00584 itoa( idxVT[i] + 1, buf, 10 ); 00585 str = str + "/" + buf; 00586 if ( idxVN[0] != -1 ) { 00587 itoa( idxVN[i] + 1, buf, 10 ); 00588 str = str + "/" + buf; 00589 } 00590 } 00591 else { 00592 if ( idxVN[0] != -1 ) { 00593 itoa( idxVN[i] + 1, buf, 10 ); 00594 str = str + "//" + buf; 00595 } 00596 } 00597 } 00598 if ( strncmp( debugLine, str.c_str(), strlen( str.c_str() ) ) != 0 ) { 00599 std::cout << "Different!\n"; 00600 std::cout << debugLine; 00601 std::cout << str << "\n"; 00602 std::cout << "Ori Len: " << static_cast<int>( strlen( debugLine ) ) << "\n"; 00603 std::cout << "Str Len: " << static_cast<int>( strlen( str.c_str() ) ) << "\n"; 00604 std::cout << "\n"; 00605 } 00606 #endif 00607 //*/ 00608 00609 face->SetNoVertices( numberOfVertices ); 00610 for ( int i = 0; i < numberOfVertices; ++i ) 00611 face->SetVertexNo( i, idxV[i] ); 00612 //----------------------------------------------------- 00613 // Normals of Vertices of Face 00614 if ( idxVN[ 0 ] != -1 ) { 00615 for ( int i = 0; i < numberOfVertices; ++i ) 00616 meshData.VertexList[ face->GetVertexNo( i ) ]->SetNormal( meshData.NormalList[ idxVN[i] ] ); 00617 } 00618 //----------------------------------------------------- 00619 // Texture Coordinates of Vertices of Face 00620 if ( idxVT[ 0 ] != -1 ) { 00621 face->SetNoTexCoords( numberOfVertices ); 00622 T s, t; 00623 for ( int i = 0; i < numberOfVertices; ++i ) { 00624 meshData.TextureCoor2DList[idxVT[i]].GetXY( s, t ); 00625 face->SetTexCoordNo( i, s, t ); 00626 } 00627 } 00628 //----------------------------------------------------- 00629 meshData.FaceList.push_back( face ); 00630 //--------------------------------------------------------------- 00631 /* 00632 #ifdef DEBUG_MESSAGE_TAPs_READ_OBJ_HPP 00633 std::cout << "Face# " << faceNo << ":\t" << *face << "\n"; 00634 #endif 00635 //*/ 00636 ++faceNo; 00637 } 00638 //----------------------------------------------------------------------------- 00639 //============================================================================= 00640 00641 00642 00643 /* 00644 //----------------------------------------------------------------------------- 00645 //============================================================================= 00646 //----------------------------------------------------------------------------- 00647 // Process VERTEX LIST 00648 template <typename T> 00649 void ReadObj<T>::ProcessVERTEX_LIST ( 00650 FILE * inputFile, OpenGL::PolygonalModel<T> * const prModel ) 00651 { 00652 #ifdef TAPs_DEBUG_MODE 00653 std::cout << "Processing VERTEX LIST\n"; 00654 #endif 00655 //------------------------------------------------------------------ 00656 // Example: x y z values 00657 // 0 0 0 00658 // ... 00659 // 0 0 1 00660 //------------------------------------------------------------------ 00661 char vertexStr[128]; 00662 int vertexNumber = 0; 00663 float x, y, z; // since sscanf does not work for T (template) 00664 //------------------------------------------------------------------ 00665 prModel->NewVertexListByNoVertices(); 00666 do { 00667 do { 00668 fgets( vertexStr, 128, inputFile ); 00669 } while ( strlen( vertexStr ) < 3 || vertexStr[0] == '#' ); 00670 sscanf( vertexStr, "%g %g %g", &x, &y, &z ); 00671 prModel->GetVertexList()[vertexNumber][0] = x; 00672 prModel->GetVertexList()[vertexNumber][1] = y; 00673 prModel->GetVertexList()[vertexNumber][2] = z; 00674 ++vertexNumber; 00675 } while ( vertexNumber < prModel->GetNoVertices() ); 00676 } 00677 //----------------------------------------------------------------------------- 00678 // Process VERTEX LIST 00679 template <typename T> 00680 void ReadObj<T>::ProcessVERTEX_LIST ( 00681 FILE * inputFile, OpenGL::XPolygonalModel<T> * const prModel ) 00682 { 00683 #ifdef TAPs_DEBUG_MODE 00684 std::cout << "Processing VERTEX LIST\n"; 00685 #endif 00686 //------------------------------------------------------------------- 00687 // Example: x y z values 00688 // 0 0 0 00689 // ... 00690 // 0 0 1 00691 //------------------------------------------------------------------- 00692 char vertexStr[128]; 00693 int vertexNumber = 0; 00694 float x, y, z; // since sscanf does not work for T (template) 00695 //------------------------------------------------------------------- 00696 prModel->NewVertexListByNoVertices(); 00697 do { 00698 do { 00699 fgets( vertexStr, 128, inputFile ); 00700 } while ( strlen( vertexStr ) < 3 || vertexStr[0] == '#' ); 00701 sscanf( vertexStr, "%g %g %g", &x, &y, &z ); 00702 prModel->GetVertexList()[vertexNumber][0] = x; 00703 prModel->GetVertexList()[vertexNumber][1] = y; 00704 prModel->GetVertexList()[vertexNumber][2] = z; 00705 ++vertexNumber; 00706 } while ( vertexNumber < prModel->GetNoVertices() ); 00707 } 00708 //----------------------------------------------------------------------------- 00709 // Process VERTEX LIST 00710 template <typename T> 00711 void ReadObj<T>::ProcessVERTEX_LIST ( 00712 FILE * inputFile, OpenGL::HalfEdgeModel<T> * const prModel ) 00713 { 00714 #ifdef TAPs_DEBUG_MODE 00715 std::cout << "Processing VERTEX LIST\n"; 00716 #endif 00717 //------------------------------------------------------------------- 00718 // Example: 00719 // *MESH_VERTEX_LIST { 00720 // *MESH_VERTEX 0 -10.000000 -5.000000 0.000000 00721 // *MESH_VERTEX 1 10.000000 -5.000000 0.000000 00722 // *MESH_VERTEX 2 -10.000000 5.000000 0.000000 00723 // ... 00724 // } 00725 //------------------------------------------------------------------- 00726 char node[128]; 00727 int n; 00728 float x, y, z; 00729 fgets( line, 128, inputFile ); 00730 sscanf( line, "%s %d %g %g %g", node, &n, &x, &y, &z ); 00731 while ( node[0] != '}' ) { 00732 //------------------------------------------------------ 00733 // Put created vertex in vertexList for look up later 00734 HelpCreateHalfEdgeModel<T>::vertexList[vertexNo] = new HEVertex<T>( x, y, z ); 00735 // Put created vertex in vertexList of the model 00736 prModel->GetVertexList()->Append( HelpCreateHalfEdgeModel<T>::vertexList[vertexNo] ); 00737 ++vertexNo; // next vertex# 00738 //std::cout << "Vertex: " << vertexNo << "\n"; 00739 //------------------------------------------------------ 00740 fgets( line, 128, fileIn ); 00741 sscanf( line, "%s %d %g %g %g", node, &n, &x, &y, &z ); 00742 } 00743 } 00744 //----------------------------------------------------------------------------- 00745 //============================================================================= 00746 //----------------------------------------------------------------------------- 00747 // Process FACE LIST 00748 template <typename T> 00749 void ReadObj<T>::ProcessFACE_LIST ( 00750 FILE * inputFile, OpenGL::PolygonalModel<T> * const prModel ) 00751 { 00752 #ifdef TAPs_DEBUG_MODE 00753 std::cout << "Processing FACE LIST\n"; 00754 #endif 00755 //--------------------------------------------------------------- 00756 // Example: number of vertices for this face followed by vertex numbers 00757 // 4 0 1 2 3 00758 // ... 00759 // 3 10 11 12 00760 //--------------------------------------------------------------- 00761 char line[128]; 00762 char *delimiters = "\t "; 00763 char *token = NULL; 00764 char *end; 00765 int numberOfVertices; 00766 int vertexNo; 00767 int faceNo = 0; 00768 //--------------------------------------------------------------- 00769 prModel->NewFaceListByNoFaces(); 00770 do { 00771 do { 00772 fgets( line, 128, inputFile ); 00773 } while ( strlen( line ) < 3 || line[0] == '#' ); 00774 token = strtok( line, delimiters ); // number of vertices 00775 numberOfVertices = static_cast<int>( strtol( token, &end, 10 ) ); 00776 prModel->GetFaceList()[faceNo].SetNoVertices( numberOfVertices ); 00777 for ( int i = 0; i < numberOfVertices; ++i ) { 00778 token = strtok( '\0', delimiters ); // vertex number 00779 vertexNo = static_cast<int>( strtol( token, &end, 10 ) ); 00780 prModel->GetFaceList()[faceNo].SetVertexNo( i, vertexNo ); 00781 } 00782 ++faceNo; 00783 } while ( faceNo < prModel->GetNoFaces() ); 00784 //--------------------------------------------------------------- 00785 } 00786 //----------------------------------------------------------------------------- 00787 // Process FACE LIST 00788 template <typename T> 00789 void ReadObj<T>::ProcessFACE_LIST ( 00790 FILE * inputFile, OpenGL::XPolygonalModel<T> * const prModel ) 00791 { 00792 #ifdef TAPs_DEBUG_MODE 00793 std::cout << "Processing FACE LIST\n"; 00794 #endif 00795 //--------------------------------------------------------------- 00796 // Example: number of vertices for this face followed by vertex numbers 00797 // 4 0 1 2 3 00798 // ... 00799 // 3 10 11 12 00800 //--------------------------------------------------------------- 00801 char line[128]; 00802 char *delimiters = "\t "; 00803 char *token = NULL; 00804 char *end; 00805 int numberOfVertices; 00806 int vertexNo; 00807 int faceNo = 0; 00808 //--------------------------------------------------------------- 00809 prModel->NewFaceListByNoFaces(); 00810 do { 00811 do { 00812 fgets( line, 128, inputFile ); 00813 } while ( strlen( line ) < 3 || line[0] == '#' ); 00814 token = strtok( line, delimiters ); // number of vertices 00815 numberOfVertices = static_cast<int>( strtol( token, &end, 10 ) ); 00816 prModel->GetFaceList()[faceNo].SetNoVertices( numberOfVertices ); 00817 // DEBUG 00818 prModel->GetFaceList()[faceNo].ID = faceNo; 00819 for ( int i = 0; i < numberOfVertices; ++i ) { 00820 token = strtok( '\0', delimiters ); // vertex number 00821 vertexNo = static_cast<int>( strtol( token, &end, 10 ) ); 00822 prModel->GetFaceList()[faceNo].SetVertexNo( i, vertexNo ); 00823 } 00824 ++faceNo; 00825 } while ( faceNo < prModel->GetNoFaces() ); 00826 //--------------------------------------------------------------- 00827 } 00828 //----------------------------------------------------------------------------- 00829 // Process FACE LIST 00830 template <typename T> 00831 void ReadObj<T>::ProcessFACE_LIST ( 00832 FILE * inputFile, OpenGL::HalfEdgeModel<T> * const prModel ) 00833 { 00834 std::cout << "Processing Node MESH_FACE_LIST\n"; 00835 //------------------------------------------------------------------- 00836 // Example: 00837 // *MESH_FACE_LIST { 00838 // *MESH_FACE 0: A: 0 B: 2 C: 3 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 00839 // *MESH_FACE 1: A: 3 B: 1 C: 0 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 2 *MESH_MTLID 1 00840 // *MESH_FACE 2: A: 4 B: 5 C: 7 AB: 1 BC: 1 CA: 0 *MESH_SMOOTHING 3 *MESH_MTLID 0 00841 // ... 00842 // } 00843 //------------------------------------------------------------------- 00844 HEFace<T> *heFace; 00845 char node[128]; 00846 char N[16], A[4], B[4], C[4]; 00847 int v0, v1, v2; 00848 fgets( line, 128, fileIn ); 00849 sscanf( line, "%s %s %s %d %s %d %s %d", node, N, A, &v0, B, &v1, C, &v2 ); 00850 while ( node[0] != '}' ) { 00851 heFace = new HEFace<T>(); 00852 prModel->GetFaceList()->Append( heFace ); 00853 //---------------------------------------------------------------- 00854 // Create and Set all three half-edges 00855 HEHalfEdge<T> *heHalfEdge0 = HelpCreateHalfEdgeModel<T>::CreateHalfEdgeFrom( 00856 HelpCreateHalfEdgeModel<T>::vertexList[v0], 00857 HelpCreateHalfEdgeModel<T>::vertexList[v1], 00858 heFace ); 00859 HEHalfEdge<T> *heHalfEdge1 = HelpCreateHalfEdgeModel<T>::CreateHalfEdgeFrom( 00860 HelpCreateHalfEdgeModel<T>::vertexList[v1], 00861 HelpCreateHalfEdgeModel<T>::vertexList[v2], 00862 heFace, heHalfEdge0 ); 00863 HEHalfEdge<T> *heHalfEdge2 = HelpCreateHalfEdgeModel<T>::CreateHalfEdgeFrom( 00864 HelpCreateHalfEdgeModel<T>::vertexList[v2], 00865 HelpCreateHalfEdgeModel<T>::vertexList[v0], 00866 heFace, heHalfEdge1, heHalfEdge0 ); 00867 halfEdgeCounter += 3; 00868 //---------------------------------------------------------------- 00869 // Set incident half-edge of this face 00870 heFace->IncidentHalfEdge( heHalfEdge0 ); 00871 //---------------------------------------------------------------- 00872 // (CCW) Record v0 to v1, v1 to v2, and v2 to v0 in vertexRingList 00873 HelpCreateHalfEdgeModel<T>::vertexRingList->Insert( v1, v0 ); // put v1 in bucket v0 00874 HelpCreateHalfEdgeModel<T>::vertexRingList->Insert( v2, v1 ); // put v2 in bucket v1 00875 HelpCreateHalfEdgeModel<T>::vertexRingList->Insert( v0, v2 ); // put v0 in bucket v2 00876 //---------------------------------------------------------------- 00877 // Record half-edges in halfEdgeRingList 00878 HelpCreateHalfEdgeModel<T>::halfEdgeRingList->Insert( heHalfEdge0, v0 ); // put in bucket v0 00879 HelpCreateHalfEdgeModel<T>::halfEdgeRingList->Insert( heHalfEdge1, v1 ); // put in bucket v1 00880 HelpCreateHalfEdgeModel<T>::halfEdgeRingList->Insert( heHalfEdge2, v2 ); // put in bucket v2 00881 //---------------------------------------------------------------- 00882 fgets( line, 128, fileIn ); 00883 sscanf( line, "%s %s %s %d %s %d %s %d", node, N, A, &v0, B, &v1, C, &v2 ); 00884 } 00885 } 00886 //*/ 00887 //----------------------------------------------------------------------------- 00888 //============================================================================= 00889 END_NAMESPACE_TAPs 00890 //----------------------------------------------------------------------------- 00891 //34567890123456789012345678901234567890123456789012345678901234567890123456789 00892 //--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----