31 #include "vertexBufferRoot.h"
32 #include "vertexBufferState.h"
33 #include "vertexData.h"
37 #include <sys/types.h>
40 # include <sys/mman.h>
46 typedef vmml::frustum_culler< float > FrustumCuller;
49 size_t getArchitectureBits();
51 bool isArchitectureLittleEndian();
53 std::string getArchitectureFilename(
const std::string& filename );
56 void VertexBufferRoot::setupTree( VertexData& data )
61 const Axis axis = data.getLongestAxis( 0, data.triangles.size() );
63 VertexBufferNode::setupTree( data, 0, data.triangles.size(),
65 VertexBufferNode::updateBoundingSphere();
66 VertexBufferNode::updateRange();
70 Vertex center( _boundingSphere.array );
71 float radius = _boundingSphere.w();
72 float radiusSquared = radius * radius;
73 for(
size_t offset = 0; offset < _data.vertices.size(); ++offset )
75 const Vertex& vertex = _data.vertices[ offset ];
77 const Vertex centerToPoint = vertex - center;
78 const float distanceSquared = centerToPoint.squared_length();
79 LBASSERTINFO( distanceSquared <= radiusSquared,
80 distanceSquared <<
" > " << radiusSquared );
86 void VertexBufferRoot::cullDraw( VertexBufferState& state )
const
88 _beginRendering( state );
91 size_t verticesRendered = 0;
92 size_t verticesOverlap = 0;
95 const Range& range = state.getRange();
97 culler.setup( state.getProjectionModelViewMatrix( ));
100 std::vector< const mesh::VertexBufferBase* > candidates;
101 candidates.push_back(
this );
103 while( !candidates.empty() )
105 if( state.stopRendering( ))
109 candidates.pop_back();
112 if( treeNode->getRange()[0] >= range[1] ||
113 treeNode->getRange()[1] < range[0] )
119 const vmml::Visibility visibility = state.useFrustumCulling() ?
120 culler.test_sphere( treeNode->getBoundingSphere( )) :
121 vmml::VISIBILITY_FULL;
124 case vmml::VISIBILITY_FULL:
126 if( treeNode->getRange()[0] >= range[0] &&
127 treeNode->getRange()[1] < range[1] )
129 treeNode->draw( state );
132 verticesRendered += treeNode->getNumberOfVertices();
138 case vmml::VISIBILITY_PARTIAL:
143 if( !left && !right )
145 if( treeNode->getRange()[0] >= range[0] )
147 treeNode->draw( state );
150 verticesRendered += treeNode->getNumberOfVertices();
151 if( visibility == vmml::VISIBILITY_PARTIAL )
152 verticesOverlap += treeNode->getNumberOfVertices();
160 candidates.push_back( left );
162 candidates.push_back( right );
166 case vmml::VISIBILITY_NONE:
172 _endRendering( state );
175 const size_t verticesTotal = model->getNumberOfVertices();
177 << getName() <<
" rendered " << verticesRendered * 100 / verticesTotal
178 <<
"% of model, overlap <= " << verticesOverlap * 100 / verticesTotal
185 void VertexBufferRoot::_beginRendering( VertexBufferState& state )
const
188 switch( state.getRenderMode() )
190 #ifdef GL_ARB_vertex_buffer_object
191 case RENDER_MODE_BUFFER_OBJECT:
192 glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT );
193 glEnableClientState( GL_VERTEX_ARRAY );
194 glEnableClientState( GL_NORMAL_ARRAY );
195 if( state.useColors() )
196 glEnableClientState( GL_COLOR_ARRAY );
198 case RENDER_MODE_DISPLAY_LIST:
199 case RENDER_MODE_IMMEDIATE:
207 void VertexBufferRoot::draw( VertexBufferState& state )
const
209 VertexBufferNode::draw( state );
214 void VertexBufferRoot::_endRendering( VertexBufferState& state )
const
216 switch( state.getRenderMode() )
218 #ifdef GL_ARB_vertex_buffer_object
219 case RENDER_MODE_BUFFER_OBJECT:
222 #define glewGetContext state.glewGetContext
223 glBindBuffer( GL_ARRAY_BUFFER_ARB, 0);
224 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
228 case RENDER_MODE_DISPLAY_LIST:
229 case RENDER_MODE_IMMEDIATE:
237 size_t getArchitectureBits()
239 return (
sizeof(
void* ) * 8 );
244 bool isArchitectureLittleEndian()
246 unsigned char test[2] = { 1, 0 };
247 short* x =
reinterpret_cast< short*
>( test );
253 std::string getArchitectureFilename(
const std::string& filename )
255 std::ostringstream oss;
256 oss << filename << ( isArchitectureLittleEndian() ?
".le" :
".be" );
257 oss << getArchitectureBits() <<
".bin";
263 bool VertexBufferRoot::_constructFromPly(
const std::string& filename )
265 MESHINFO <<
"Constructing new from PLY file." << std::endl;
269 data.useInvertedFaces();
270 if( !data.readPlyFile( filename ) )
272 MESHERROR <<
"Unable to load PLY file." << std::endl;
276 data.calculateNormals();
279 if( !writeToFile( filename ))
280 MESHWARN <<
"Unable to write binary representation." << std::endl;
285 bool VertexBufferRoot::_readBinary( std::string filename )
290 for(
size_t i=0; i<filename.length(); ++i )
291 if( filename[i] ==
'\\' )
295 HANDLE file = CreateFile( filename.c_str(), GENERIC_READ, FILE_SHARE_READ,
296 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
297 if( file == INVALID_HANDLE_VALUE )
300 MESHINFO <<
"Reading cached binary representation." << std::endl;
303 HANDLE map = CreateFileMapping( file, 0, PAGE_READONLY, 0, 0,
308 MESHERROR <<
"Unable to read binary file, file mapping failed."
314 char* addr =
static_cast< char*
>( MapViewOfFile( map, FILE_MAP_READ, 0,
325 catch(
const std::exception& e )
327 MESHERROR <<
"Unable to read binary file, an exception occured: "
328 << e.what() << std::endl;
330 UnmapViewOfFile( addr );
334 MESHERROR <<
"Unable to read binary file, memory mapping failed."
344 int fd = open( filename.c_str(), O_RDONLY );
350 fstat( fd, &status );
353 char* addr =
static_cast< char*
>( mmap( 0, status.st_size, PROT_READ,
354 MAP_SHARED, fd, 0 ) );
356 if( addr != MAP_FAILED )
363 catch(
const std::exception& e )
365 MESHERROR <<
"Unable to read binary file, an exception occured: "
366 << e.what() << std::endl;
368 munmap( addr, status.st_size );
372 MESHERROR <<
"Unable to read binary file, memory mapping failed."
382 bool VertexBufferRoot::readFromFile(
const std::string& filename )
384 if( _readBinary( getArchitectureFilename( filename )))
389 if( _constructFromPly( filename ))
398 bool VertexBufferRoot::writeToFile(
const std::string& filename )
402 std::ofstream output( getArchitectureFilename( filename ).c_str(),
403 std::ios::out | std::ios::binary );
407 output.exceptions( std::ofstream::failbit | std::ofstream::badbit );
413 catch(
const std::exception& e )
415 MESHERROR <<
"Unable to write binary file, an exception "
416 <<
"occured: " << e.what() << std::endl;
422 MESHERROR <<
"Unable to create binary file." << std::endl;
430 void VertexBufferRoot::fromMemory(
char* start )
432 char** addr = &start;
434 memRead( reinterpret_cast< char* >( &version ), addr,
sizeof(
size_t ) );
435 if( version != FILE_VERSION )
436 throw MeshException(
"Error reading binary file. Version in file "
437 "does not match the expected version." );
439 memRead( reinterpret_cast< char* >( &nodeType ), addr,
sizeof(
size_t ) );
440 if( nodeType != ROOT_TYPE )
441 throw MeshException(
"Error reading binary file. Expected the root "
442 "node, but found something else instead." );
443 _data.fromMemory( addr );
444 VertexBufferNode::fromMemory( addr, _data );
449 void VertexBufferRoot::toStream( std:: ostream& os )
451 size_t version = FILE_VERSION;
452 os.write( reinterpret_cast< char* >( &version ),
sizeof(
size_t ) );
453 size_t nodeType = ROOT_TYPE;
454 os.write( reinterpret_cast< char* >( &nodeType ),
sizeof(
size_t ) );
455 _data.toStream( os );
456 VertexBufferNode::toStream( os );