Equalizer 1.0

vertexBufferRoot.cpp

00001 
00002 /* Copyright (c) 2007, Tobias Wolf <twolf@access.unizh.ch>
00003  *               2009-2011, Stefan Eilemann <eile@equalizergraphics.com>
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  * - Redistributions of source code must retain the above copyright notice, this
00009  *   list of conditions and the following disclaimer.
00010  * - Redistributions in binary form must reproduce the above copyright notice,
00011  *   this list of conditions and the following disclaimer in the documentation
00012  *   and/or other materials provided with the distribution.
00013  * - Neither the name of Eyescale Software GmbH nor the names of its
00014  *   contributors may be used to endorse or promote products derived from this
00015  *   software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028   
00029     
00030     Implementation of the VertexBufferRoot class.
00031 */
00032 
00033 
00034 #include "vertexBufferRoot.h"
00035 #include "vertexBufferState.h"
00036 #include "vertexData.h"
00037 #include <string>
00038 #include <sstream>
00039 #include <fcntl.h>
00040 #include <sys/types.h>
00041 #include <sys/stat.h>
00042 #ifndef _WIN32
00043 #   include <sys/mman.h>
00044 #endif
00045 
00046 using namespace std;
00047 
00048 namespace mesh
00049 {
00050 
00051 
00052 /*  Determine number of bits used by the current architecture.  */
00053 size_t getArchitectureBits();
00054 /*  Determine whether the current architecture is little endian or not.  */
00055 bool isArchitectureLittleEndian();
00056 /*  Construct architecture dependent file name.  */
00057 string getArchitectureFilename( const std::string& filename );
00058 
00059 /*  Begin kd-tree setup, go through full range starting with x axis.  */
00060 void VertexBufferRoot::setupTree( VertexData& data )
00061 {
00062     // data is VertexData, _data is VertexBufferData
00063     _data.clear();
00064 
00065     const Axis axis = data.getLongestAxis( 0, data.triangles.size() );
00066 
00067     VertexBufferNode::setupTree( data, 0, data.triangles.size(), 
00068                                  axis, 0, _data );
00069     VertexBufferNode::updateBoundingSphere();
00070     VertexBufferNode::updateRange();
00071 
00072 #if 0
00073     // re-test all points to be in the bounding sphere
00074     Vertex center( _boundingSphere.array );
00075     float  radius        = _boundingSphere.w();
00076     float  radiusSquared =  radius * radius;
00077     for( size_t offset = 0; offset < _data.vertices.size(); ++offset )
00078     {
00079         const Vertex& vertex = _data.vertices[ offset ];
00080         
00081         const Vertex centerToPoint   = vertex - center;
00082         const float  distanceSquared = centerToPoint.squared_length();
00083         EQASSERTINFO( distanceSquared <= radiusSquared,
00084                       distanceSquared << " > " << radiusSquared );
00085     }
00086 #endif
00087 }
00088 
00089 
00090 /*  Set up the common OpenGL state for rendering of all nodes.  */
00091 void VertexBufferRoot::beginRendering( VertexBufferState& state ) const
00092 {
00093     switch( state.getRenderMode() )
00094     {
00095 #ifdef GL_ARB_vertex_buffer_object
00096     case RENDER_MODE_BUFFER_OBJECT:
00097         glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT );
00098         glEnableClientState( GL_VERTEX_ARRAY );
00099         glEnableClientState( GL_NORMAL_ARRAY );
00100         if( state.useColors() )
00101             glEnableClientState( GL_COLOR_ARRAY );
00102 #endif
00103     case RENDER_MODE_DISPLAY_LIST:
00104     case RENDER_MODE_IMMEDIATE:
00105     default:
00106         ;
00107     }
00108 }
00109 
00110 
00111 /*  Delegate rendering to node routine.  */
00112 void VertexBufferRoot::render( VertexBufferState& state ) const
00113 {
00114     VertexBufferNode::render( state );
00115 }
00116 
00117 
00118 /*  Tear down the common OpenGL state for rendering of all nodes.  */
00119 void VertexBufferRoot::endRendering( VertexBufferState& state ) const
00120 {
00121     switch( state.getRenderMode() )
00122     {
00123 #ifdef GL_ARB_vertex_buffer_object
00124     case RENDER_MODE_BUFFER_OBJECT:
00125     {
00126         // deactivate VBO and EBO use
00127 #define glewGetContext state.glewGetContext
00128         glBindBuffer( GL_ARRAY_BUFFER_ARB, 0);
00129         glBindBuffer( GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
00130         glPopClientAttrib();
00131     }
00132 #endif
00133     case RENDER_MODE_DISPLAY_LIST:
00134     case RENDER_MODE_IMMEDIATE:
00135     default:
00136         ;
00137     }
00138 }
00139 
00140 
00141 /*  Determine number of bits used by the current architecture.  */
00142 size_t getArchitectureBits()
00143 {
00144     return ( sizeof( void* ) * 8 );
00145 }
00146 
00147 
00148 /*  Determine whether the current architecture is little endian or not.  */
00149 bool isArchitectureLittleEndian()
00150 {
00151     unsigned char test[2] = { 1, 0 };
00152     short* x = reinterpret_cast< short* >( test );
00153     return ( *x == 1 );
00154 }
00155 
00156 
00157 /*  Construct architecture dependent file name.  */
00158 string getArchitectureFilename( const std::string& filename )
00159 {
00160     ostringstream oss;
00161     oss << filename << ( isArchitectureLittleEndian() ? ".le" : ".be" );
00162     oss << getArchitectureBits() << ".bin";
00163     return oss.str();    
00164 }
00165 
00166 
00167 /*  Functions extracted out of readFromFile to enhance readability.  */
00168 bool VertexBufferRoot::_constructFromPly( const std::string& filename )
00169 {
00170     MESHINFO << "Constructing new from PLY file." << endl;
00171     
00172     VertexData data;
00173     if( _invertFaces )
00174         data.useInvertedFaces();
00175     if( !data.readPlyFile( filename ) )
00176     {
00177         MESHERROR << "Unable to load PLY file." << endl;
00178         return false;
00179     }
00180 
00181     data.calculateNormals();
00182     data.scale( 2.0f );
00183     setupTree( data );
00184     if( !writeToFile( filename ))
00185         MESHWARN << "Unable to write binary representation." << endl;
00186     
00187     return true;
00188 }
00189 
00190 bool VertexBufferRoot::_readBinary( std::string filename )
00191 {
00192 #ifdef WIN32
00193 
00194     // replace dir delimiters since '\' is often used as escape char
00195     for( size_t i=0; i<filename.length(); ++i )
00196         if( filename[i] == '\\' )
00197             filename[i] = '/';
00198 
00199     // try to open binary file
00200     HANDLE file = CreateFile( filename.c_str(), GENERIC_READ, FILE_SHARE_READ,
00201                               0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
00202     if( file == INVALID_HANDLE_VALUE )
00203         return false;
00204     
00205     MESHINFO << "Reading cached binary representation." << endl;
00206     
00207     // create a file mapping
00208     HANDLE map = CreateFileMapping( file, 0, PAGE_READONLY, 0, 0, 
00209                                     filename.c_str( ));
00210     CloseHandle( file );
00211     if( !map )
00212     {
00213         MESHERROR << "Unable to read binary file, file mapping failed." 
00214                   << endl;
00215         return false;
00216     }
00217     
00218     // get a view of the mapping
00219     char* addr   = static_cast< char* >( MapViewOfFile( map, FILE_MAP_READ, 0, 
00220                                                         0, 0 ) );
00221     bool  result = false;
00222 
00223     if( addr )
00224     {
00225         try
00226         {
00227             fromMemory( addr );
00228             result = true;
00229         }
00230         catch( exception& e )
00231         {
00232             MESHERROR << "Unable to read binary file, an exception occured:  "
00233                       << e.what() << endl;
00234         }
00235         UnmapViewOfFile( addr );
00236     }
00237     else
00238     {
00239         MESHERROR << "Unable to read binary file, memory mapping failed."
00240                   << endl;
00241         return false;
00242     }
00243 
00244     CloseHandle( map );
00245     return result;
00246     
00247 #else
00248     // try to open binary file
00249     int fd = open( filename.c_str(), O_RDONLY );
00250     if( fd < 0 )
00251         return false;
00252     
00253     // retrieving file information
00254     struct stat status;
00255     fstat( fd, &status );
00256     
00257     // create memory mapped file
00258     char* addr   = static_cast< char* >( mmap( 0, status.st_size, PROT_READ, 
00259                                                MAP_SHARED, fd, 0 ) );
00260     bool  result = false;
00261     if( addr != MAP_FAILED )
00262     {
00263         try
00264         {
00265             fromMemory( addr );
00266             result = true;
00267         }
00268         catch( exception& e )
00269         {
00270             MESHERROR << "Unable to read binary file, an exception occured:  "
00271                       << e.what() << endl;
00272         }
00273         munmap( addr, status.st_size );
00274     }
00275     else
00276     {
00277         MESHERROR << "Unable to read binary file, memory mapping failed."
00278                   << endl;
00279     }
00280     
00281     close( fd );
00282     return result;
00283 #endif
00284 }
00285 
00286 
00287 /*  Read binary kd-tree representation, construct from ply if unavailable.  */
00288 bool VertexBufferRoot::readFromFile( const std::string& filename )
00289 {
00290     if( _readBinary( getArchitectureFilename( filename )))
00291     {
00292         _name = filename;
00293         return true;
00294     }
00295     if( _constructFromPly( filename ))
00296     {
00297         _name = filename;
00298         return true;
00299     }
00300     return false;
00301 }
00302 
00303 /*  Write binary representation of the kd-tree to file.  */
00304 bool VertexBufferRoot::writeToFile( const std::string& filename )
00305 {
00306     bool result = false;
00307     
00308     ofstream output( getArchitectureFilename( filename ).c_str(), 
00309                      ios::out | ios::binary );
00310     if( output )
00311     {
00312         // enable exceptions on stream errors
00313         output.exceptions( ofstream::failbit | ofstream::badbit );
00314         try
00315         {
00316             toStream( output );
00317             result = true;
00318         }
00319         catch( exception& e )
00320         {
00321             MESHERROR << "Unable to write binary file, an exception "
00322                       << "occured:  " << e.what() << endl;
00323         }
00324         output.close();
00325     }
00326     else
00327     {
00328         MESHERROR << "Unable to create binary file." << endl;
00329     }
00330     
00331     return result;
00332 }
00333 
00334 
00335 /*  Read root node from memory and continue with other nodes.  */
00336 void VertexBufferRoot::fromMemory( char* start )
00337 {
00338     char** addr = &start;
00339     size_t version;
00340     memRead( reinterpret_cast< char* >( &version ), addr, sizeof( size_t ) );
00341     if( version != FILE_VERSION )
00342         throw MeshException( "Error reading binary file. Version in file "
00343                              "does not match the expected version." );
00344     size_t nodeType;
00345     memRead( reinterpret_cast< char* >( &nodeType ), addr, sizeof( size_t ) );
00346     if( nodeType != ROOT_TYPE )
00347         throw MeshException( "Error reading binary file. Expected the root "
00348                              "node, but found something else instead." );
00349     _data.fromMemory( addr );
00350     VertexBufferNode::fromMemory( addr, _data );
00351     memRead( reinterpret_cast< char* >( &nodeType ), addr, sizeof( size_t ) );
00352     if( nodeType != ROOT_TYPE )
00353         throw MeshException( "Error reading binary file. Expected a custom "
00354                              "EOF marker, but found something else instead." );
00355 }
00356 
00357 
00358 /*  Write root node to output stream and continue with other nodes.  */
00359 void VertexBufferRoot::toStream( std:: ostream& os )
00360 {
00361     size_t version = FILE_VERSION;
00362     os.write( reinterpret_cast< char* >( &version ), sizeof( size_t ) );
00363     size_t nodeType = ROOT_TYPE;
00364     os.write( reinterpret_cast< char* >( &nodeType ), sizeof( size_t ) );
00365     _data.toStream( os );
00366     VertexBufferNode::toStream( os );
00367     os.write( reinterpret_cast< char* >( &nodeType ), sizeof( size_t ) );
00368 }
00369 
00370 }
Generated on Sun May 8 2011 19:11:07 for Equalizer 1.0 by  doxygen 1.7.3