gKitGL
MeshOBJ.h
00001 
00002 #ifndef _MESHOBJ_H
00003 #define _MESHOBJ_H
00004 
00005 #include <string>
00006 
00007 namespace gk {
00008 
00009 class Mesh;
00010 //! renvoie vrai si 'filename' se termine par '.obj'.
00011 bool isMeshOBJ( const std::string& filename );
00012 
00013 int MeshLoadFromOBJ( const std::string& filename, Mesh *mesh );
00014 int MaterialLoadFromMTL( const std::string& filename );
00015 
00016 int MeshWriteToOBJ( Mesh *mesh, const std::string& filename );
00017 int MeshMaterialsMTLLIB( const Mesh *mesh, std::string& mtllib );
00018 int MeshMaterialsWriteToMTL( const Mesh *mesh, const std::string& filename );
00019 
00020 #if 0
00021 //! namespace prive.
00022 /*! namespace prive, pour isoler les classes utilisees pour charger les objets maya .obj et leurs matieres .mtl.
00023     
00024     chargement d'un objet maya obj + construction lineaire d'un maillage triangule.
00025 
00026     cf http://local.wasp.uwa.edu.au/~pbourke/dataformats/obj/
00027     et  http://local.wasp.uwa.edu.au/~pbourke/dataformats/mtl/
00028  */    
00029 namespace OBJ
00030 {
00031 
00032 //! parser pour analyser les fichiers obj et mtl.
00033 class Parser
00034 {
00035     FILE *m_in;
00036     std::string m_token;
00037     
00038     bool is_token( const char c )
00039     {
00040         return ( isalnum( c ) || c == '_' || c == '-' || c == '.' );
00041     }
00042     
00043 public:
00044     Parser( const std::string& filename )
00045             :
00046             m_in( NULL ),
00047             m_token()
00048     {
00049         m_in = fopen( filename.c_str(), "rt" );
00050     }
00051     
00052     ~Parser( )
00053     {
00054         if ( m_in != NULL )
00055             fclose( m_in );
00056     }
00057     
00058     bool isValid( ) const
00059     {
00060         return ( m_in != NULL );
00061     }
00062     
00063     //! lecture sequentielle d'un 'mot' dans le fichier.
00064     //! un mot est un ensemble de caracteres quelconques delimite par des separateurs.
00065     //! renvoie le separateur, si la lecture d'un mot est impossible.
00066     int readToken( )
00067     {
00068         if ( !isValid() )
00069             return EOF;
00070             
00071         // sauter les blancs
00072         char c = fgetc( m_in );
00073         while ( c != EOF && ( c == ' ' || c == '\t' ) )
00074             c = fgetc( m_in );
00075             
00076         if ( c == '\r' )
00077             c = '\n'; // meme gestion des fins de lignes pour linux, mac et windows
00078             
00079         // lire tous les caracteres alphanumeriques
00080         m_token.resize( 0 );
00081         while ( c != EOF && is_token( c ) )
00082         {
00083             m_token.push_back( c );
00084             
00085             c = fgetc( m_in );
00086             if ( c == '\r' )
00087                 c = '\n'; // meme gestion des fins de lignes pour linux, mac et windows
00088         }
00089         
00090         // separateurs
00091         if ( c == '#' )
00092         {
00093             if ( m_token.empty() )
00094                 m_token.push_back( c );
00095             else
00096                 ungetc( c, m_in );
00097         }
00098         else if ( c == '/' ) // ambiguite sur les noms de fichiers ...
00099             m_token.push_back( c );
00100             
00101         // indiquer la fin de la ligne ou du fichier
00102         if ( m_token.empty() )
00103             return c;
00104             
00105         // forcer une fin de ligne avant la fin du fichier
00106         if ( c == EOF )
00107             ungetc( '\n', m_in );
00108             
00109         else if ( c == '\n' )
00110             ungetc( c, m_in );
00111             
00112         return 0;
00113     }
00114     
00115     //! lecture de la fin de la ligne, renvoie la chaine de caracteres.
00116     int readString( )
00117     {
00118         std::string string;
00119         
00120         // concatene tous les tokens jusqu'a la fin de la ligne
00121 #if 0
00122         while ( readToken() != '\n' )
00123             string += m_token;
00124 #else
00125         // ajoute aussi les separateurs dans la chaine ...
00126         int code = readToken();
00127         while ( code != '\n' )
00128         {
00129             string.append( m_token );
00130             if ( code != 0 )
00131                 string.push_back( code );
00132             code = readToken();
00133         }
00134 #endif
00135             
00136         assert( string.length() == strlen( string.c_str() ) );
00137         
00138         m_token.swap( string );
00139         if ( m_token.empty() )
00140             return -1;
00141         else
00142             return 0;
00143     }
00144     
00145     //! renvoie le dernier 'mot' lu par readToken().
00146     const std::string& getToken( ) const
00147     {
00148         return m_token;
00149     }
00150     
00151     //! renvoie le dernier caractere du dernier 'mot' lu.
00152     char getLastChar( ) const
00153     {
00154         const int length = ( int ) m_token.length();
00155         if ( length == 0 )
00156             return 0;
00157             
00158         return m_token[length -1];
00159     }
00160     
00161     //! renvoie un caractere du dernier 'mot' lu.
00162     char getChar( const int i = 0 ) const
00163     {
00164         assert( i >= 0 && i < ( int ) m_token.length() );
00165         return m_token[i];
00166     }
00167     
00168     //! converti le dernier 'mot' lu en reel.
00169     int getFloat( float& v ) const
00170     {
00171         v = 0.f;
00172         if ( sscanf( m_token.c_str(), "%f", &v ) != 1 )
00173             return -1;
00174         else
00175             return 0;
00176     }
00177     
00178     //! converti le dernier 'mot' lu en entier.
00179     int getInt( int& v ) const
00180     {
00181         v = 0;
00182         if ( sscanf( m_token.c_str(), "%d", &v ) != 1 )
00183             return -1;
00184         else
00185             return 0;
00186     }
00187     
00188     //! lit un vecteur 3.
00189     int readVector3( Vector& v )
00190     {
00191         int i;
00192         for ( i = 0; readToken() != '\n'; i++ )
00193             if ( i < 3 && getFloat( v[i] ) < 0 )
00194                 return -1;
00195                 
00196         if ( i < 3 )
00197             return -1;
00198         else
00199             return 0;
00200     }
00201     
00202     //! lit un vecteur 2.
00203     int readVector2( Point2& v )
00204     {
00205         int i;
00206         for ( i = 0; readToken() != '\n'; i++ )
00207             if ( i < 2 && getFloat( v[i] ) < 0 )
00208                 return -1;
00209                 
00210         if ( i < 2 )
00211             return -1;
00212         else
00213             return 0;
00214     }
00215     
00216     //! saute la ligne.
00217     //! lecture de tous les 'mots' jusqu'a la fin de la ligne.
00218     int skipLine( )
00219     {
00220         while ( readToken() != '\n' )
00221         {
00222         #ifdef VERBOSE_DEBUG
00223             printf("skip '%s'\n", getToken().c_str());
00224         #endif
00225         }
00226             
00227         return 0;
00228     }
00229 };
00230 
00231 //! determine l'indice d'un attribut de sommet dans le maillage.
00232 //! renvoie 0 si l'attribut n'existe pas, 1 si l'attribut existe et -1 en cas d'erreur.
00233 inline
00234 int getAttribute( const Parser& parser, int& attr, const int attributes_n )
00235 {
00236     if ( parser.getChar( 0 ) == '/' )
00237         return 0;
00238         
00239     if ( parser.getInt( attr ) < 0 )
00240         return -1;
00241         
00242     if ( attr < 0 )
00243         attr += attributes_n;
00244     else
00245         attr -= 1;
00246         
00247     if ( attr < 0 || attr >= attributes_n )
00248         return -1;
00249     else
00250         return 1;
00251 }
00252 
00253 
00254 //! representation d'un sommet, indice de matiere + triplet d'indices position, normale et texcoord.
00255 struct Vertex
00256 {
00257     int m_indices[4];
00258     
00259     Vertex( ) {}
00260     
00261     Vertex( const int m, const int p, const int n, const int t )
00262     {
00263         m_indices[0] = m;
00264         m_indices[1] = p;
00265         m_indices[2] = n;
00266         m_indices[3] = t;
00267     }
00268     
00269     ~Vertex( ) {}
00270     
00271     //! comparaison de 2 sommets pour l'insertion dans une std::map.
00272     static
00273     bool less( const Vertex& a, const Vertex& b )
00274     {
00275         // definit un ordre lexicographique sur la matiere + les 3 indices : position, normale, texcoord
00276         for ( int i = 0; i < 4; i++ )
00277         {
00278             if ( a.m_indices[i] < b.m_indices[i] )
00279                 // renvoie vrai lorsque a < b
00280                 return true;
00281             else if ( a.m_indices[i] > b.m_indices[i] )
00282                 return false;
00283         }
00284         
00285         return false;
00286     }
00287     
00288     //! renvoie l'indice de la matiere du sommet.
00289     int material( ) const
00290     {
00291         return m_indices[0];
00292     }
00293     
00294     //! renvoie l'indice de la position du sommet.
00295     int position( ) const
00296     {
00297         return m_indices[1];
00298     }
00299     
00300     //! renvoie l'indice de la normale du sommet.
00301     int normal( ) const
00302     {
00303         return m_indices[2];
00304     }
00305     
00306     //! renvoie l'indice de la coordonnee de texture du sommet.
00307     int texcoord( ) const
00308     {
00309         return m_indices[3];
00310     }
00311 };
00312 
00313 //! operateur de comparaison pour l'insertion d'un Vertex dans une std::map.
00314 inline
00315 bool operator<( const Vertex& a, const Vertex& b )
00316 {
00317     return Vertex::less( a, b );
00318 }
00319 
00320 //! representation d'un triangle <abc> pour le maillage.
00321 struct Triangle
00322 {
00323     int m_indices[3];
00324     int m_material_id;  // a stocker a part ... cf. construction de l'index buffer
00325     int m_smooth_id;
00326     
00327     //! contructeur par defaut.
00328     Triangle( )
00329             :
00330             m_material_id( -1 ),
00331             m_smooth_id( -1 )
00332     {}
00333     
00334     //! destructeur.
00335     ~Triangle( ) {}
00336     
00337     //! construit un triangle.
00338     Triangle( const int a, const int b, const int c )
00339     {
00340         m_indices[0] = a;
00341         m_indices[1] = b;
00342         m_indices[2] = c;
00343     }
00344     
00345     //! fixe l'identifiant de la matiere du triangle.
00346     void setMaterial( const int id )
00347     {
00348         m_material_id = id;
00349     }
00350     
00351     //! fixe le smooth group du triangle
00352     void setSmoothGroup( const int group_id )
00353     {
00354         m_smooth_id = group_id;
00355     }
00356     
00357     //! renvoie l'indice du sommet a du triangle.
00358     int a( ) const
00359     {
00360         return m_indices[0];
00361     }
00362     
00363     //! renvoie l'indice du sommet b du triangle.
00364     int b( ) const
00365     {
00366         return m_indices[1];
00367     }
00368     
00369     //! renvoie l'indice du sommet c du triangle.
00370     int c( ) const
00371     {
00372         return m_indices[2];
00373     }
00374     
00375     //! renvoie l'identifiant de la matiere du triangle.
00376     int material( ) const
00377     {
00378         return m_material_id;
00379     }
00380     
00381     //! renvoie l'identifiant du smooth group du triangle.
00382     int smoothGroup( ) const
00383     {
00384         return m_smooth_id;
00385     }
00386     
00387     //! comparaison de 2 sommets pour l'insertion dans une std::map
00388     static
00389     bool material_less( const Triangle& a, const Triangle& b )
00390     {
00391         return ( a.material() < b.material() );
00392     }
00393 };
00394 
00395 } // namespace OBJ
00396 #endif
00397 
00398 }
00399 
00400 #endif
 All Classes Namespaces Functions Variables Typedefs Enumerator Friends