TAPs 0.7.7.3
TAPsReadObj.cpp
Go to the documentation of this file.
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----+----
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines