Equalizer 1.0
|
00001 /* Copyright (c) 2007, Tobias Wolf <twolf@access.unizh.ch> 00002 * Copyright (c) 2008-2009, Stefan Eilemann <eile@equalizergraphics.com> 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions are met: 00006 * 00007 * - Redistributions of source code must retain the above copyright notice, this 00008 * list of conditions and the following disclaimer. 00009 * - Redistributions in binary form must reproduce the above copyright notice, 00010 * this list of conditions and the following disclaimer in the documentation 00011 * and/or other materials provided with the distribution. 00012 * - Neither the name of Eyescale Software GmbH nor the names of its 00013 * contributors may be used to endorse or promote products derived from this 00014 * software without specific prior written permission. 00015 * 00016 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00017 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00018 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00019 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00020 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00021 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00022 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00023 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00024 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00025 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00026 * POSSIBILITY OF SUCH DAMAGE. 00027 00028 00029 Implementation of the VertexBufferLeaf class. 00030 */ 00031 00032 00033 #include "vertexBufferLeaf.h" 00034 #include "vertexBufferData.h" 00035 #include "vertexBufferState.h" 00036 #include "vertexData.h" 00037 #include <map> 00038 00039 using namespace std; 00040 00041 namespace mesh 00042 { 00043 00044 /* Finish partial setup - sort, reindex and merge into global data. */ 00045 void VertexBufferLeaf::setupTree( VertexData& data, const Index start, 00046 const Index length, const Axis axis, 00047 const size_t depth, 00048 VertexBufferData& globalData ) 00049 { 00050 data.sort( start, length, axis ); 00051 _vertexStart = globalData.vertices.size(); 00052 _vertexLength = 0; 00053 _indexStart = globalData.indices.size(); 00054 _indexLength = 0; 00055 00056 const bool hasColors = ( data.colors.size() > 0 ); 00057 00058 // stores the new indices (relative to _start) 00059 map< Index, ShortIndex > newIndex; 00060 00061 for( Index t = 0; t < length; ++t ) 00062 { 00063 for( Index v = 0; v < 3; ++v ) 00064 { 00065 Index i = data.triangles[start + t][v]; 00066 if( newIndex.find( i ) == newIndex.end() ) 00067 { 00068 newIndex[i] = _vertexLength++; 00069 // assert number of vertices does not exceed SmallIndex range 00070 MESHASSERT( _vertexLength ); 00071 globalData.vertices.push_back( data.vertices[i] ); 00072 if( hasColors ) 00073 globalData.colors.push_back( data.colors[i] ); 00074 globalData.normals.push_back( data.normals[i] ); 00075 } 00076 globalData.indices.push_back( newIndex[i] ); 00077 ++_indexLength; 00078 } 00079 } 00080 00081 #ifndef NDEBUG 00082 MESHINFO << "VertexBufferLeaf::setupTree" 00083 << "( " << _indexStart << ", " << _indexLength << "; start " 00084 << _vertexStart << ", " << _vertexLength << " vertices)." << endl; 00085 #endif 00086 } 00087 00088 00089 /* Compute the bounding sphere of the leaf's indexed vertices. */ 00090 const BoundingSphere& VertexBufferLeaf::updateBoundingSphere() 00091 { 00092 // We determine a bounding sphere by: 00093 // 1) Using the inner sphere of the dominant axis of the bounding box as an 00094 // estimate 00095 // 2) Test all points to be in that sphere 00096 // 3) Expand the sphere to contain all points outside. 00097 00098 00099 // 1a) initialize and compute a bounding box 00100 BoundingBox boundingBox; 00101 boundingBox[0] = 00102 _globalData.vertices[ _vertexStart + _globalData.indices[_indexStart] ]; 00103 boundingBox[1] = 00104 _globalData.vertices[ _vertexStart + _globalData.indices[_indexStart] ]; 00105 00106 for( Index offset = 1; offset < _indexLength; ++offset ) 00107 { 00108 const Vertex& vertex = 00109 _globalData.vertices[ _vertexStart + 00110 _globalData.indices[_indexStart + offset] ]; 00111 00112 boundingBox[0][0] = min( boundingBox[0][0], vertex[0] ); 00113 boundingBox[1][0] = max( boundingBox[1][0], vertex[0] ); 00114 boundingBox[0][1] = min( boundingBox[0][1], vertex[1] ); 00115 boundingBox[1][1] = max( boundingBox[1][1], vertex[1] ); 00116 boundingBox[0][2] = min( boundingBox[0][2], vertex[2] ); 00117 boundingBox[1][2] = max( boundingBox[1][2], vertex[2] ); 00118 } 00119 00120 // 1b) get inner sphere of bounding box as an initial estimate 00121 _boundingSphere.x() = ( boundingBox[0].x() + boundingBox[1].x() ) * 0.5f; 00122 _boundingSphere.y() = ( boundingBox[0].y() + boundingBox[1].y() ) * 0.5f; 00123 _boundingSphere.z() = ( boundingBox[0].z() + boundingBox[1].z() ) * 0.5f; 00124 00125 _boundingSphere.w() = EQ_MAX( boundingBox[1].x() - boundingBox[0].x(), 00126 boundingBox[1].y() - boundingBox[0].y() ); 00127 _boundingSphere.w() = EQ_MAX( boundingBox[1].z() - boundingBox[0].z(), 00128 _boundingSphere.w() ); 00129 _boundingSphere.w() *= .5f; 00130 00131 float radius = _boundingSphere.w(); 00132 float radiusSquared = radius * radius; 00133 Vertex center( _boundingSphere.array ); 00134 00135 // 2) test all points to be in the estimated bounding sphere 00136 for( Index offset = 0; offset < _indexLength; ++offset ) 00137 { 00138 const Vertex& vertex = 00139 _globalData.vertices[ _vertexStart + 00140 _globalData.indices[_indexStart + offset] ]; 00141 00142 const Vertex centerToPoint = vertex - center; 00143 const float distanceSquared = centerToPoint.squared_length(); 00144 if( distanceSquared <= radiusSquared ) // point is inside existing BS 00145 continue; 00146 00147 // 3) expand sphere to contain 'outside' points 00148 const float distance = sqrtf( distanceSquared ); 00149 const float delta = distance - radius; 00150 00151 radius = ( radius + distance ) * .5f; 00152 radiusSquared = radius * radius; 00153 const Vertex normdelta = normalize( centerToPoint ) * ( 0.5f * delta ); 00154 00155 center += normdelta; 00156 00157 EQASSERTINFO( Vertex( vertex-center ).squared_length() <= 00158 ( radiusSquared + 2.f* numeric_limits<float>::epsilon( )), 00159 vertex << " c " << center << " r " << radius << " (" 00160 << Vertex( vertex-center ).length() << ")" ); 00161 } 00162 00163 #ifndef NDEBUG 00164 // 2a) re-test all points to be in the estimated bounding sphere 00165 for( Index offset = 0; offset < _indexLength; ++offset ) 00166 { 00167 const Vertex& vertex = 00168 _globalData.vertices[ _vertexStart + 00169 _globalData.indices[_indexStart + offset] ]; 00170 00171 const Vertex centerToPoint = vertex - center; 00172 const float distanceSquared = centerToPoint.squared_length(); 00173 EQASSERTINFO( distanceSquared <= 00174 ( radiusSquared + 2.f* numeric_limits<float>::epsilon( )), 00175 vertex << " c " << center << " r " << radius << " (" 00176 << Vertex( vertex-center ).length() << ")" ); 00177 } 00178 #endif 00179 00180 // store optimal bounding sphere 00181 _boundingSphere.x() = center.x(); 00182 _boundingSphere.y() = center.y(); 00183 _boundingSphere.z() = center.z(); 00184 _boundingSphere.w() = radius; 00185 00186 #ifndef NDEBUG 00187 MESHINFO << "updateBoundingSphere" << "( " << _boundingSphere << " )." 00188 << endl; 00189 #endif 00190 00191 return _boundingSphere; 00192 } 00193 00194 00195 /* Compute the range of this child. */ 00196 void VertexBufferLeaf::updateRange() 00197 { 00198 _range[0] = 1.0f * _indexStart / _globalData.indices.size(); 00199 _range[1] = _range[0] + 1.0f * _indexLength / _globalData.indices.size(); 00200 00201 #ifndef NDEBUG 00202 MESHINFO << "updateRange" << "( " << _range[0] << ", " << _range[1] 00203 << " )." << endl; 00204 #endif 00205 } 00206 00207 #define glewGetContext state.glewGetContext 00208 00209 /* Set up rendering of the leaf nodes. */ 00210 void VertexBufferLeaf::setupRendering( VertexBufferState& state, 00211 GLuint* data ) const 00212 { 00213 switch( state.getRenderMode() ) 00214 { 00215 case RENDER_MODE_IMMEDIATE: 00216 break; 00217 00218 case RENDER_MODE_BUFFER_OBJECT: 00219 { 00220 const char* charThis = reinterpret_cast< const char* >( this ); 00221 00222 if( data[VERTEX_OBJECT] == state.INVALID ) 00223 data[VERTEX_OBJECT] = state.newBufferObject( charThis + 0 ); 00224 glBindBuffer( GL_ARRAY_BUFFER, data[VERTEX_OBJECT] ); 00225 glBufferData( GL_ARRAY_BUFFER, _vertexLength * sizeof( Vertex ), 00226 &_globalData.vertices[_vertexStart], GL_STATIC_DRAW ); 00227 00228 if( data[NORMAL_OBJECT] == state.INVALID ) 00229 data[NORMAL_OBJECT] = state.newBufferObject( charThis + 1 ); 00230 glBindBuffer( GL_ARRAY_BUFFER, data[NORMAL_OBJECT] ); 00231 glBufferData( GL_ARRAY_BUFFER, _vertexLength * sizeof( Normal ), 00232 &_globalData.normals[_vertexStart], GL_STATIC_DRAW ); 00233 00234 if( data[COLOR_OBJECT] == state.INVALID ) 00235 data[COLOR_OBJECT] = state.newBufferObject( charThis + 2 ); 00236 if( state.useColors() ) 00237 { 00238 glBindBuffer( GL_ARRAY_BUFFER, data[COLOR_OBJECT] ); 00239 glBufferData( GL_ARRAY_BUFFER, _vertexLength * sizeof( Color ), 00240 &_globalData.colors[_vertexStart], GL_STATIC_DRAW ); 00241 } 00242 00243 if( data[INDEX_OBJECT] == state.INVALID ) 00244 data[INDEX_OBJECT] = state.newBufferObject( charThis + 3 ); 00245 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, data[INDEX_OBJECT] ); 00246 glBufferData( GL_ELEMENT_ARRAY_BUFFER, 00247 _indexLength * sizeof( ShortIndex ), 00248 &_globalData.indices[_indexStart], GL_STATIC_DRAW ); 00249 00250 break; 00251 } 00252 case RENDER_MODE_DISPLAY_LIST: 00253 default: 00254 { 00255 if( data[0] == state.INVALID ) 00256 { 00257 char* key = (char*)( this ); 00258 if( state.useColors( )) 00259 ++key; 00260 data[0] = state.newDisplayList( key ); 00261 } 00262 glNewList( data[0], GL_COMPILE ); 00263 renderImmediate( state ); 00264 glEndList(); 00265 break; 00266 } 00267 } 00268 } 00269 00270 00271 /* Render the leaf. */ 00272 void VertexBufferLeaf::render( VertexBufferState& state ) const 00273 { 00274 if ( state.stopRendering( )) 00275 return; 00276 00277 switch( state.getRenderMode() ) 00278 { 00279 case RENDER_MODE_IMMEDIATE: 00280 renderImmediate( state ); 00281 return; 00282 case RENDER_MODE_BUFFER_OBJECT: 00283 renderBufferObject( state ); 00284 return; 00285 case RENDER_MODE_DISPLAY_LIST: 00286 default: 00287 renderDisplayList( state ); 00288 return; 00289 } 00290 } 00291 00292 00293 /* Render the leaf with buffer objects. */ 00294 void VertexBufferLeaf::renderBufferObject( VertexBufferState& state ) const 00295 { 00296 GLuint buffers[4]; 00297 for( int i = 0; i < 4; ++i ) 00298 buffers[i] = 00299 state.getBufferObject( reinterpret_cast< const char* >(this) + i ); 00300 if( buffers[VERTEX_OBJECT] == state.INVALID || 00301 buffers[NORMAL_OBJECT] == state.INVALID || 00302 buffers[COLOR_OBJECT] == state.INVALID || 00303 buffers[INDEX_OBJECT] == state.INVALID ) 00304 00305 setupRendering( state, buffers ); 00306 00307 if( state.useColors() ) 00308 { 00309 glBindBuffer( GL_ARRAY_BUFFER, buffers[COLOR_OBJECT] ); 00310 glColorPointer( 4, GL_UNSIGNED_BYTE, 0, 0 ); 00311 } 00312 glBindBuffer( GL_ARRAY_BUFFER, buffers[NORMAL_OBJECT] ); 00313 glNormalPointer( GL_FLOAT, 0, 0 ); 00314 glBindBuffer( GL_ARRAY_BUFFER, buffers[VERTEX_OBJECT] ); 00315 glVertexPointer( 3, GL_FLOAT, 0, 0 ); 00316 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, buffers[INDEX_OBJECT] ); 00317 glDrawElements( GL_TRIANGLES, GLsizei( _indexLength ), GL_UNSIGNED_SHORT, 0 ); 00318 } 00319 00320 00321 /* Render the leaf with a display list. */ 00322 inline 00323 void VertexBufferLeaf::renderDisplayList( VertexBufferState& state ) const 00324 { 00325 char* key = (char*)( this ); 00326 if( state.useColors( )) 00327 ++key; 00328 00329 GLuint displayList = state.getDisplayList( key ); 00330 00331 if( displayList == state.INVALID ) 00332 setupRendering( state, &displayList ); 00333 00334 glCallList( displayList ); 00335 } 00336 00337 00338 /* Render the leaf with immediate mode primitives or vertex arrays. */ 00339 inline 00340 void VertexBufferLeaf::renderImmediate( VertexBufferState& state ) const 00341 { 00342 glBegin( GL_TRIANGLES ); 00343 for( Index offset = 0; offset < _indexLength; ++offset ) 00344 { 00345 const Index i =_vertexStart + _globalData.indices[_indexStart + offset]; 00346 if( state.useColors() ) 00347 glColor4ubv( &_globalData.colors[i][0] ); 00348 glNormal3fv( &_globalData.normals[i][0] ); 00349 glVertex3fv( &_globalData.vertices[i][0] ); 00350 } 00351 glEnd(); 00352 00353 // if( state.useColors() ) 00354 // glColorPointer( 4, GL_UNSIGNED_BYTE, 0, 00355 // &_globalData.colors[_vertexStart] ); 00356 // glNormalPointer( GL_FLOAT, 0, &_globalData.normals[_vertexStart] ); 00357 // glVertexPointer( 3, GL_FLOAT, 0, &_globalData.vertices[_vertexStart] ); 00358 // glDrawElements( GL_TRIANGLES, _indexLength, GL_UNSIGNED_SHORT, 00359 // &_globalData.indices[_indexStart] ); 00360 } 00361 00362 00363 /* Read leaf node from memory. */ 00364 void VertexBufferLeaf::fromMemory( char** addr, VertexBufferData& globalData ) 00365 { 00366 size_t nodeType; 00367 memRead( reinterpret_cast< char* >( &nodeType ), addr, sizeof( size_t ) ); 00368 if( nodeType != LEAF_TYPE ) 00369 throw MeshException( "Error reading binary file. Expected a leaf " 00370 "node, but found something else instead." ); 00371 VertexBufferBase::fromMemory( addr, globalData ); 00372 memRead( reinterpret_cast< char* >( &_vertexStart ), addr, 00373 sizeof( Index ) ); 00374 memRead( reinterpret_cast< char* >( &_vertexLength ), addr, 00375 sizeof( ShortIndex ) ); 00376 memRead( reinterpret_cast< char* >( &_indexStart ), addr, 00377 sizeof( Index ) ); 00378 memRead( reinterpret_cast< char* >( &_indexLength ), addr, 00379 sizeof( Index ) ); 00380 } 00381 00382 00383 /* Write leaf node to output stream. */ 00384 void VertexBufferLeaf::toStream( std::ostream& os ) 00385 { 00386 size_t nodeType = LEAF_TYPE; 00387 os.write( reinterpret_cast< char* >( &nodeType ), sizeof( size_t ) ); 00388 VertexBufferBase::toStream( os ); 00389 os.write( reinterpret_cast< char* >( &_vertexStart ), sizeof( Index ) ); 00390 os.write( reinterpret_cast< char* >( &_vertexLength ),sizeof( ShortIndex )); 00391 os.write( reinterpret_cast< char* >( &_indexStart ), sizeof( Index ) ); 00392 os.write( reinterpret_cast< char* >( &_indexLength ), sizeof( Index ) ); 00393 } 00394 00395 }