vertexBufferRoot.cpp

00001 /*  
00002  *  Copyright (c) 2007, Tobias Wolf <twolf@access.unizh.ch>
00003  *                2009, Stefan Eilemann <eile@equalizergraphics.com>
00004  *
00005  * This library is free software; you can redistribute it and/or modify it under
00006  * the terms of the GNU Lesser General Public License version 2.1 as published
00007  * by the Free Software Foundation.
00008  *  
00009  * This library is distributed in the hope that it will be useful, but WITHOUT
00010  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00011  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00012  * details.
00013  * 
00014  * You should have received a copy of the GNU Lesser General Public License
00015  * along with this library; if not, write to the Free Software Foundation, Inc.,
00016  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00017   
00018     
00019     Implementation of the VertexBufferRoot class.
00020 */
00021 
00022 
00023 #include "vertexBufferRoot.h"
00024 #include "vertexBufferState.h"
00025 #include "vertexData.h"
00026 #include <string>
00027 #include <sstream>
00028 #include <fcntl.h>
00029 #include <sys/types.h>
00030 #include <sys/stat.h>
00031 #ifndef _WIN32
00032 #   include <sys/mman.h>
00033 #endif
00034 
00035 using namespace std;
00036 
00037 namespace mesh
00038 {
00039 
00040 /*  Begin kd-tree setup, go through full range starting with x axis.  */
00041 void VertexBufferRoot::setupTree( VertexData& data )
00042 {
00043     // data is VertexData, _data is VertexBufferData
00044     _data.clear();
00045 
00046     const Axis axis = data.getLongestAxis( 0, data.triangles.size() );
00047 
00048     VertexBufferNode::setupTree( data, 0, data.triangles.size(), 
00049                                  axis, 0, _data );
00050     VertexBufferNode::updateBoundingSphere();
00051     VertexBufferNode::updateRange();
00052 }
00053 
00054 
00055 /*  Set up the common OpenGL state for rendering of all nodes.  */
00056 void VertexBufferRoot::beginRendering( VertexBufferState& state ) const
00057 {
00058     switch( state.getRenderMode() )
00059     {
00060 #ifdef GL_ARB_vertex_buffer_object
00061     case RENDER_MODE_BUFFER_OBJECT:
00062         glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT );
00063         glEnableClientState( GL_VERTEX_ARRAY );
00064         glEnableClientState( GL_NORMAL_ARRAY );
00065         if( state.useColors() )
00066             glEnableClientState( GL_COLOR_ARRAY );
00067 #endif
00068     case RENDER_MODE_DISPLAY_LIST:
00069     case RENDER_MODE_IMMEDIATE:
00070     default:
00071         ;
00072     }
00073 }
00074 
00075 
00076 /*  Delegate rendering to node routine.  */
00077 void VertexBufferRoot::render( VertexBufferState& state ) const
00078 {
00079     VertexBufferNode::render( state );
00080 }
00081 
00082 
00083 /*  Tear down the common OpenGL state for rendering of all nodes.  */
00084 void VertexBufferRoot::endRendering( VertexBufferState& state ) const
00085 {
00086     switch( state.getRenderMode() )
00087     {
00088 #ifdef GL_ARB_vertex_buffer_object
00089     case RENDER_MODE_BUFFER_OBJECT:
00090     {
00091         // deactivate VBO and EBO use
00092 #define glewGetContext state.glewGetContext
00093         glBindBuffer( GL_ARRAY_BUFFER_ARB, 0);
00094         glBindBuffer( GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
00095         glPopClientAttrib();
00096     }
00097 #endif
00098     case RENDER_MODE_DISPLAY_LIST:
00099     case RENDER_MODE_IMMEDIATE:
00100     default:
00101         ;
00102     }
00103 }
00104 
00105 
00106 /*  Determine number of bits used by the current architecture.  */
00107 size_t getArchitectureBits()
00108 {
00109     return ( sizeof( void* ) * 8 );
00110 }
00111 
00112 
00113 /*  Determine whether the current architecture is little endian or not.  */
00114 bool isArchitectureLittleEndian()
00115 {
00116     unsigned char test[2] = { 1, 0 };
00117     short x = *( reinterpret_cast< short* >( test ) );
00118     return ( x == 1 );
00119 }
00120 
00121 
00122 /*  Construct architecture dependent file name.  */
00123 string getArchitectureFilename( const std::string& filename )
00124 {
00125     ostringstream oss;
00126     oss << filename << ( isArchitectureLittleEndian() ? ".le" : ".be" );
00127     oss << getArchitectureBits() << ".bin";
00128     return oss.str();    
00129 }
00130 
00131 
00132 /*  Functions extracted out of readFromFile to enhance readability.  */
00133 bool VertexBufferRoot::_constructFromPly( const std::string& filename )
00134 {
00135     MESHINFO << "Constructing new from PLY file." << endl;
00136     
00137     VertexData data;
00138     if( _invertFaces )
00139         data.useInvertedFaces();
00140     if( !data.readPlyFile( filename ) )
00141     {
00142         MESHERROR << "Unable to load PLY file." << endl;
00143         return false;
00144     }
00145 
00146     data.calculateNormals();
00147     data.scale( 2.0f );
00148     setupTree( data );
00149     if( !writeToFile( filename ))
00150         MESHWARN << "Unable to write binary representation." << endl;
00151     
00152     return true;
00153 }
00154 
00155 bool VertexBufferRoot::_readBinary( const std::string& filename )
00156 {
00157 #ifdef WIN32
00158     // try to open binary file
00159     HANDLE file = CreateFile( filename.c_str(), GENERIC_READ, FILE_SHARE_READ,
00160                               0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
00161     if( file == INVALID_HANDLE_VALUE )
00162         return false;
00163     
00164     MESHINFO << "Reading cached binary representation." << endl;
00165     
00166     // create a file mapping
00167     HANDLE map = CreateFileMapping( file, 0, PAGE_READONLY, 0, 0, 
00168                                     filename.c_str( ));
00169     CloseHandle( file );
00170     if( !map )
00171     {
00172         MESHERROR << "Unable to read binary file, file mapping failed." 
00173                   << endl;
00174         return false;
00175     }
00176     
00177     // get a view of the mapping
00178     char* addr   = static_cast< char* >( MapViewOfFile( map, FILE_MAP_READ, 0, 
00179                                                         0, 0 ) );
00180     bool  result = false;
00181 
00182     if( addr )
00183     {
00184         try
00185         {
00186             fromMemory( addr );
00187             result = true;
00188         }
00189         catch( exception& e )
00190         {
00191             MESHERROR << "Unable to read binary file, an exception occured:  "
00192                       << e.what() << endl;
00193         }
00194         UnmapViewOfFile( addr );
00195     }
00196     else
00197     {
00198         MESHERROR << "Unable to read binary file, memory mapping failed."
00199                   << endl;
00200         return false;
00201     }
00202 
00203     CloseHandle( map );
00204     return result;
00205     
00206 #else
00207     // try to open binary file
00208     int fd = open( filename.c_str(), O_RDONLY );
00209     if( fd < 0 )
00210         return false;
00211     
00212     MESHINFO << "Reading cached binary representation." << endl;
00213     
00214     // retrieving file information
00215     struct stat status;
00216     fstat( fd, &status );
00217     
00218     // create memory mapped file
00219     char* addr   = static_cast< char* >( mmap( 0, status.st_size, PROT_READ, 
00220                                                MAP_SHARED, fd, 0 ) );
00221     bool  result = false;
00222     if( addr != MAP_FAILED )
00223     {
00224         try
00225         {
00226             fromMemory( addr );
00227             result = true;
00228         }
00229         catch( exception& e )
00230         {
00231             MESHERROR << "Unable to read binary file, an exception occured:  "
00232                       << e.what() << endl;
00233         }
00234         munmap( addr, status.st_size );
00235     }
00236     else
00237     {
00238         MESHERROR << "Unable to read binary file, memory mapping failed."
00239                   << endl;
00240     }
00241     
00242     close( fd );
00243     return result;
00244 #endif
00245 }
00246 
00247 
00248 /*  Read binary kd-tree representation, construct from ply if unavailable.  */
00249 bool VertexBufferRoot::readFromFile( const std::string& filename )
00250 {
00251     if( _readBinary( getArchitectureFilename( filename )))
00252     {
00253         _name = filename;
00254         return true;
00255     }
00256     if( _constructFromPly( filename ))
00257     {
00258         _name = filename;
00259         return true;
00260     }
00261     return false;
00262 }
00263 
00264 /*  Write binary representation of the kd-tree to file.  */
00265 bool VertexBufferRoot::writeToFile( const std::string& filename )
00266 {
00267     bool result = false;
00268     
00269     ofstream output( getArchitectureFilename( filename ).c_str(), 
00270                      ios::out | ios::binary );
00271     if( output )
00272     {
00273         // enable exceptions on stream errors
00274         output.exceptions( ofstream::failbit | ofstream::badbit );
00275         try
00276         {
00277             toStream( output );
00278             result = true;
00279         }
00280         catch( exception& e )
00281         {
00282             MESHERROR << "Unable to write binary file, an exception "
00283                       << "occured:  " << e.what() << endl;
00284         }
00285         output.close();
00286     }
00287     else
00288     {
00289         MESHERROR << "Unable to create binary file." << endl;
00290     }
00291     
00292     return result;
00293 }
00294 
00295 
00296 /*  Read root node from memory and continue with other nodes.  */
00297 void VertexBufferRoot::fromMemory( char* start )
00298 {
00299     char** addr = &start;
00300     size_t version;
00301     memRead( reinterpret_cast< char* >( &version ), addr, sizeof( size_t ) );
00302     if( version != FILE_VERSION )
00303         throw MeshException( "Error reading binary file. Version in file "
00304                              "does not match the expected version." );
00305     size_t nodeType;
00306     memRead( reinterpret_cast< char* >( &nodeType ), addr, sizeof( size_t ) );
00307     if( nodeType != ROOT_TYPE )
00308         throw MeshException( "Error reading binary file. Expected the root "
00309                              "node, but found something else instead." );
00310     _data.fromMemory( addr );
00311     VertexBufferNode::fromMemory( addr, _data );
00312     memRead( reinterpret_cast< char* >( &nodeType ), addr, sizeof( size_t ) );
00313     if( nodeType != ROOT_TYPE )
00314         throw MeshException( "Error reading binary file. Expected a custom "
00315                              "EOF marker, but found something else instead." );
00316 }
00317 
00318 
00319 /*  Write root node to output stream and continue with other nodes.  */
00320 void VertexBufferRoot::toStream( std:: ostream& os )
00321 {
00322     size_t version = FILE_VERSION;
00323     os.write( reinterpret_cast< char* >( &version ), sizeof( size_t ) );
00324     size_t nodeType = ROOT_TYPE;
00325     os.write( reinterpret_cast< char* >( &nodeType ), sizeof( size_t ) );
00326     _data.toStream( os );
00327     VertexBufferNode::toStream( os );
00328     os.write( reinterpret_cast< char* >( &nodeType ), sizeof( size_t ) );
00329 }
00330 
00331 }
Generated on Mon Aug 10 18:58:41 2009 for Equalizer 0.9 by  doxygen 1.5.8