basic/geometry/vrml_reader/VrmlIndexedFaceSet.cpp

Go to the documentation of this file.
00001 #include <assert.h>
00002 #ifndef NOGL
00003 #include "opengl/glos.h"
00004 #include <gl/gl.h>
00005 #endif
00006 #include <geometry/igs/IGS_Mesh.h>
00007 #include <geometry/igs/IGS_MeshTri.h>
00008 #include <math/Vector4.h>
00009 #include <stdio.h>
00010 #include <string.h>
00011 #include "utility.h"
00012 #include "VrmlCoordinate3.h"
00013 #include "VrmlIndexedFaceSet.h"
00014 #include "VrmlStack.h"
00015 
00016 //=============================================================================
00017 // constructor
00018 //
00019 // Description: constructor
00020 //=============================================================================
00021 VrmlIndexedFaceSet::VrmlIndexedFaceSet()
00022 :
00023         m_Coords( NULL ),
00024         m_TexCoord( NULL ),
00025         m_NormalsComputed( false )
00026 {
00027 }
00028 
00029 //=============================================================================
00030 // Destructor
00031 //
00032 // Description: delete all the nodes
00033 //=============================================================================
00034 VrmlIndexedFaceSet::~VrmlIndexedFaceSet()
00035 {
00036         if( m_Coords != NULL )
00037         {
00038                 m_Coords->Release();
00039                 m_Coords = NULL;
00040         }
00041 
00042         if( m_TexCoord != NULL )
00043         {
00044                 m_TexCoord->Release();
00045                 m_TexCoord = NULL;
00046         }
00047 }
00048 
00049 //=============================================================================
00050 // ComputeNormals
00051 //
00052 // Description: computes the normals for this indexed face set if they weren't 
00053 //                              already specified in the file
00054 //=============================================================================
00055 void VrmlIndexedFaceSet::ComputeNormals( VrmlStack& stack ) const
00056 {
00057         int index = 0;
00058         int size = this->indexes.size();
00059         this->m_Normals.resize( size );
00060         while( index < size )
00061         {
00062                 //compute the normals for this polygon
00063                 int i0 = this->indexes[ index + 0 ];
00064                 int i1 = this->indexes[ index + 1 ];
00065                 int i2 = this->indexes[ index + 2 ];
00066 
00067                 Vector4 v0 = stack.vrmlCoordinate3->GetCoordinate( i0 );
00068                 Vector4 v1 = stack.vrmlCoordinate3->GetCoordinate( i1 );
00069                 Vector4 v2 = stack.vrmlCoordinate3->GetCoordinate( i2 );
00070 
00071                 Vector4 n = ( v1 - v0 ).Cross( v2 - v0 );
00072                 n.Normalize();
00073 
00074                 for( index; this->indexes[ index ] != -1; index++ )
00075                 {
00076                         this->m_Normals[ index ] = n;
00077                 }
00078                 index++;
00079         }
00080         this->m_NormalsComputed = true;
00081 }
00082 
00083 //=============================================================================
00084 // GetNormal
00085 //
00086 // Description: returns the normal that corresponds to a given vertex in a 
00087 //                              specific face
00088 //=============================================================================
00089 Vector4 VrmlIndexedFaceSet::GetNormal( const int index, VrmlStack& stack ) const
00090 {
00091         if( !m_NormalsComputed )
00092         {
00093                 ComputeNormals( stack );
00094         }
00095 
00096         return this->m_Normals[ index ];
00097 }
00098 
00099 //=============================================================================
00100 // GetKeyword
00101 //
00102 // Description: gets the keyword that is valid for an IndexedFaceSet
00103 //=============================================================================
00104 Keyword VrmlIndexedFaceSet::GetKeyword( char*& buffer )
00105 {
00106         char keyword[ 80 ] = "";
00107         VrmlNode::GetKeywordString( buffer, keyword );  
00108 
00109         //compare the keyword with the string values of various keywords
00110         if( strcmp( keyword, VrmlKeywordCcw ) == 0 )
00111         {
00112                 return VRML_Ccw;
00113         }
00114         if( strcmp( keyword, VrmlKeywordCoordIndex ) == 0 )
00115         {
00116                 return VRML_CoordIndex;
00117         }
00118         if( strcmp( keyword, VrmlKeywordMaterialIndex ) == 0 )
00119         {
00120                 return VRML_MaterialIndex;
00121         }
00122         if( strcmp( keyword, VrmlKeywordNormalIndex ) == 0 )
00123         {
00124                 return VRML_NormalIndex;
00125         }
00126         if( strcmp( keyword, VrmlKeywordTextureCoordIndex ) == 0 )
00127         {
00128                 return VRML_TextureCoordIndex;
00129         }
00130 
00131         assert( false );
00132         return VRML_Invalid;
00133 }
00134 
00135 //=============================================================================
00136 // Parse
00137 //
00138 // Description: renders this node to the screen (OpenGL)
00139 //=============================================================================
00140 void VrmlIndexedFaceSet::Parse( char*& buffer )
00141 {
00142         EatWhite( buffer );
00143         while( *buffer != '}' )
00144         {
00145                 EatWhite( buffer );
00146                 Keyword keyword = VrmlNode::GetKeyword( buffer );
00147                 this->ParseSubnode( keyword, buffer );
00148                 EatWhite( buffer );
00149         }
00150 
00151         //advance past the trailing '}'
00152         EatWhite( buffer );
00153         buffer++;
00154 }
00155 
00156 //=============================================================================
00157 // ParseNodeColor
00158 //
00159 // Description: extracts all the color data
00160 //=============================================================================
00161 void VrmlIndexedFaceSet::ParseNodeColor( char*& buffer )
00162 {
00163         EatWhite( buffer );
00164         buffer = strchr( buffer, '}' );
00165         buffer++;
00166 }
00167 
00168 //=============================================================================
00169 // ParseNodeCoord
00170 //
00171 // Description: extracts all the coord data
00172 //=============================================================================
00173 void VrmlIndexedFaceSet::ParseNodeCoord( char*& buffer )
00174 {
00175         Keyword keyword = VrmlNode::GetKeyword( buffer );
00176         EatWhite( buffer );
00177         if( ( keyword != VRML_Define ) && ( keyword != VRML_Use ) )
00178         {
00179                 buffer++;
00180         }
00181         VrmlNode* node = VrmlNode::ParseNode( keyword, buffer );                //IMPROVE: what does it do with the node?
00182         assert( m_Coords == NULL );
00183         this->m_Coords = node;
00184         this->m_Coords->AddRef();
00185 }
00186 
00187 //=============================================================================
00188 // ParseNodeCoordIndex
00189 //
00190 // Description: extracts all the coordIndex data
00191 //=============================================================================
00192 void VrmlIndexedFaceSet::ParseNodeCoordIndex( char*& buffer )
00193 {
00194         EatWhite( buffer );
00195         assert( *buffer == '[' );
00196         buffer++;
00197         EatWhite( buffer );
00198 
00199         while( true )
00200         {
00201                 int value = 0;
00202                 int number = sscanf( buffer, "%d", &value );
00203                 if( number == 1 )
00204                 {
00205                         indexes.push_back( value );
00206                 }
00207 
00208                 int position = strcspn( buffer, ",]" );         //IMPROVE: reuse these characters
00209                 buffer += position;
00210                 if( *buffer == ']' )
00211                 {
00212                         break;
00213                 }
00214                 assert( *buffer == ',' );
00215                 buffer++;
00216         }
00217 
00218         //advance past the trailing ']'
00219         buffer++;
00220 }
00221 
00222 //=============================================================================
00223 // ParseNodeIgnore
00224 //
00225 // Description: parses a subnode but ignores all the data - BAD BAD BAD
00226 //                              IAN IMPROVE: this shoule not even exist
00227 //=============================================================================
00228 void VrmlIndexedFaceSet::ParseNodeIgnore( char*& buffer )
00229 {
00230         EatWhite( buffer );
00231         assert( *buffer == '[' );
00232         buffer = strchr( buffer, ']' );
00233         buffer++;
00234 }
00235 
00236 //=============================================================================
00237 // ParseNodeMaterialIndex
00238 //
00239 // Description: parses a material index
00240 //=============================================================================
00241 void VrmlIndexedFaceSet::ParseNodeMaterialIndex( char*& buffer )
00242 {
00243         EatWhite( buffer );
00244         assert( *buffer == '[' );
00245         buffer++;
00246         EatWhite( buffer );
00247 
00248         while( true )
00249         {
00250                 int value = 0;
00251                 int number = sscanf( buffer, "%d", &value );
00252                 if( number == 1 )
00253                 {
00254                         //indexes.push_back( value );
00255                 }
00256 
00257                 int position = strcspn( buffer, ",]" );         //IMPROVE: reuse these characters
00258                 buffer += position;
00259                 if( *buffer == ']' )
00260                 {
00261                         break;
00262                 }
00263                 assert( *buffer == ',' );
00264                 buffer++;
00265         }
00266 
00267         //advance past the trailing ']'
00268         buffer++;
00269 
00270 }
00271 
00272 //=============================================================================
00273 // ParseNodeNormalIndex
00274 //
00275 // Description: parses a normal index
00276 //=============================================================================
00277 void VrmlIndexedFaceSet::ParseNodeNormalIndex( char*& buffer )
00278 {
00279         EatWhite( buffer );
00280         assert( *buffer == '[' );
00281         buffer++;
00282         EatWhite( buffer );
00283 
00284         while( true )
00285         {
00286                 int value = 0;
00287                 int number = sscanf( buffer, "%d", &value );
00288                 if( number == 1 )
00289                 {
00290                         //indexes.push_back( value );
00291                 }
00292 
00293                 int position = strcspn( buffer, ",]" );         //IMPROVE: reuse these characters
00294                 buffer += position;
00295                 if( *buffer == ']' )
00296                 {
00297                         break;
00298                 }
00299                 assert( *buffer == ',' );
00300                 buffer++;
00301         }
00302         //advance past the trailing ']'
00303         buffer++;
00304 }
00305 
00306 //=============================================================================
00307 // ParseNodeTexCoord
00308 //
00309 // Description: 
00310 //=============================================================================
00311 void VrmlIndexedFaceSet::ParseNodeTexCoord( char*& buffer )
00312 {
00313         EatWhite( buffer );
00314         Keyword keyword = VrmlNode::GetKeyword( buffer );
00315         EatWhite( buffer );
00316         if( ( keyword != VRML_Define ) && ( keyword != VRML_Use ) )
00317         {
00318                 buffer++;
00319         }
00320         VrmlNode* node = VrmlNode::ParseNode( keyword, buffer );                //IMPROVE: what does it do with the node?
00321         this->m_TexCoord = node;
00322         this->m_TexCoord->AddRef();
00323 }
00324 
00325 //=============================================================================
00326 // Parse
00327 //
00328 // Description: parses all the subnodes for this node type
00329 //=============================================================================
00330 void VrmlIndexedFaceSet::ParseSubnode( Keyword keyword, char*& buffer )
00331 {
00332         switch( keyword )
00333         {
00334         case VRML_Ccw:
00335         case VRML_ColorPerVertex:
00336         case VRML_Convex:
00337         case VRML_CreaseAngle:
00338         case VRML_Solid:
00339     case VRML_NormalPerVertex:
00340                 {
00341                         //read until the end of the line
00342                         while( buffer[ 0 ] != '\n' )
00343                         {
00344                                 buffer++;
00345                         }
00346                         break;
00347                 }
00348         case VRML_Coord:
00349                  {
00350                          this->ParseNodeCoord( buffer );
00351                          break;
00352                  }
00353     case VRML_Color:
00354         case VRML_Normal:
00355                  {
00356                          ParseNodeColor( buffer );
00357                          break;
00358                  }
00359         case VRML_CoordIndex:
00360                  {
00361                          this->ParseNodeCoordIndex( buffer );
00362                          break;
00363                  }
00364         case VRML_NormalIndex:
00365                 {
00366                         this->ParseNodeNormalIndex( buffer );
00367                         break;
00368                 }
00369         case VRML_MaterialIndex:
00370                 {
00371                         this->ParseNodeMaterialIndex( buffer );
00372                         break;
00373                 }
00374         case VRML_TexCoord:
00375                 {
00376                         this->ParseNodeTexCoord( buffer );
00377                         break;
00378                 }
00379         case VRML_TextureCoordIndex:
00380         case VRML_TexCoordIndex:
00381     case VRML_Vector:
00382                 {
00383                         this->ParseNodeIgnore( buffer );
00384                         break;
00385                 }
00386         default:
00387                 {
00388                         printf( "WARNING: VrmlIndexedFaceSet::ParseSubnode - Don't know how to parse this keyword\n" );
00389                         IJG_Assert( false );
00390                         break;
00391                 }
00392         }
00393 }
00394 
00395 //=============================================================================
00396 // Render
00397 //
00398 // Description: renders this node to the screen (OpenGL)
00399 //=============================================================================
00400 void VrmlIndexedFaceSet::Render( VrmlStack& stack ) const
00401 {
00402         if( this->m_Coords != NULL )
00403         {
00404                 this->m_Coords->Render( stack );
00405         }
00406 }
00407 
00408 //=============================================================================
00409 // RenderOpenGl
00410 //
00411 // Description: renders this object to an openGl Context
00412 //=============================================================================
00413 void VrmlIndexedFaceSet::RenderOpenGl( VrmlStack& stack ) const
00414 {
00415 #ifndef NOGL
00416         this->Render( stack );
00417 
00418         //IAN IMPROVE: this matrix pushing stuff has not been tested
00419 
00420         ::glPushMatrix();
00421         double matrixValues[ 16 ];
00422         stack.m_Matrix.GetValuesOpenGl( matrixValues );
00423         ::glMultMatrixd( reinterpret_cast< double* >( matrixValues ) );
00424 
00425 
00426         int i = 0;
00427         int size = indexes.size();
00428         while( i < size )
00429         {
00430                 //for every polygon do..
00431                 glBegin( GL_POLYGON );
00432 
00433                 int index = indexes[ i ];
00434                 while( index != -1 )
00435                 {
00436                         //get the normal associated with this vertex
00437                         Vector4 n = this->GetNormal( i, stack );
00438                         ::glNormal3f( n[ 0 ], n[ 1 ], n[ 2 ] );
00439 
00440                         //for every vertex do...
00441                         Vector4 v = stack.vrmlCoordinate3->GetCoordinate( index );
00442                         ::glVertex3f( v[ 0 ], v[ 1 ], v[ 2 ] );
00443                         i++;
00444                         index = indexes[ i ];
00445                 }
00446                 i++;
00447                 glEnd();
00448         }
00449 
00450         ::glPopMatrix();
00451         GLenum errorcode = ::glGetError();
00452         assert( errorcode == GL_NO_ERROR );
00453 
00454 
00455 /*      ::glBegin( GL_POLYGON );                //IAN IMPROVE: is polygons appropriate
00456 
00457         //compute normal to this face for flat shading
00458         int i0 = indexes[ 0 ];
00459         int i1 = indexes[ 1 ];
00460         int i2 = indexes[ 2 ];
00461         Vector4 p0 = stack.vrmlCoordinate3->GetCoordinate( i0 );
00462         Vector4 p1 = stack.vrmlCoordinate3->GetCoordinate( i1 );
00463         Vector4 p2 = stack.vrmlCoordinate3->GetCoordinate( i2 );
00464         Vector4 n = ( p1 - p0 ).Cross( p2 - p0 );
00465         ::glNormal3f( n[ 0 ], n[ 1 ], n[ 2 ] );
00466         int i;
00467         for( i = 0; i < this->indexes.size(); i++ )
00468         {
00469                 int index = indexes[ i ];
00470                 if( index == -1 )
00471                 {
00472                         glEnd();
00473                         glBegin( GL_POLYGON );
00474                         int i0 = indexes[ i + 1 ];
00475                         int i1 = indexes[ i + 2 ];
00476                         int i2 = indexes[ i + 3 ];
00477                         Vector4 p0 = stack.vrmlCoordinate3->GetCoordinate( i0 );
00478                         Vector4 p1 = stack.vrmlCoordinate3->GetCoordinate( i1 );
00479                         Vector4 p2 = stack.vrmlCoordinate3->GetCoordinate( i2 );
00480                         Vector4 n = ( p1 - p0 ).Cross( p2 - p0 );
00481                         ::glNormal3f( n[ 0 ], n[ 1 ], n[ 2 ] );
00482 
00483                 }
00484                 else
00485                 {
00486                         Vector4 vector = stack.vrmlCoordinate3->GetCoordinate( index );
00487                         ::glVertex3f( vector[ 0 ], vector[ 1 ], vector[ 2 ] );
00488                 }
00489         }
00490         ::glEnd();
00491         ::glPopMatrix();
00492 */
00493 #endif
00494 }
00495 
00496 //=============================================================================
00497 // RenderToIGS
00498 //
00499 // Description: creates an IGS object for the mesh
00500 //=============================================================================
00501 IGS_Object* VrmlIndexedFaceSet::RenderToIGS( VrmlStack& stack ) const
00502 {
00503         this->Render( stack );
00504 
00505         //need to build an IGS mesh out of this data
00506         IGS_Mesh* mesh = new IGS_Mesh;
00507         MeshFacet facet;
00508 
00509         int maxIndex = -1;
00510 
00511         int i;
00512         for( i = 0; i < this->indexes.size(); i++ )
00513         {
00514                 int index = indexes[ i ];
00515                 if( index == -1 )
00516                 {
00517                         mesh->AddFacet( facet );
00518                         facet.Clear();
00519                 }
00520                 else
00521                 {
00522                         facet.AddVertexIndex( index );
00523                         if( index > maxIndex )
00524                         {
00525                                 maxIndex = index;
00526                         }
00527                 }
00528         }
00529 
00530         for( i = 0; i < maxIndex + 1; i++ )
00531         {
00532                 assert( stack.vrmlCoordinate3 != NULL );
00533                 Vector4 vector = stack.vrmlCoordinate3->GetCoordinate( i );
00534                 assert( vector.Magnitude() < 1000.0 );
00535                 vector = stack.m_Matrix * vector;
00536                 assert( vector.Magnitude() < 1000.0 );
00537                 mesh->AddVertexCoordinates( vector );
00538         }
00539 
00540         //convert the mesh to a triangulated mesh before we return it
00541         IGS_MeshTri* triangulatedMesh = new IGS_MeshTri( *mesh );
00542         delete mesh;
00543         mesh = NULL;
00544         return triangulatedMesh;
00545 }

Generated on Sat Apr 1 21:30:33 2006 for Motion Planning Kernel by  doxygen 1.4.6-NO