Equalizer
1.4.1
|
00001 00002 /* Copyright (c) 2007, Tobias Wolf <twolf@access.unizh.ch> 00003 * 2008-2012, 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 00031 #include "vertexBufferLeaf.h" 00032 #include "vertexBufferData.h" 00033 #include "vertexBufferState.h" 00034 #include "vertexData.h" 00035 #include <map> 00036 00037 namespace mesh 00038 { 00039 00040 /* Finish partial setup - sort, reindex and merge into global data. */ 00041 void VertexBufferLeaf::setupTree( VertexData& data, const Index start, 00042 const Index length, const Axis axis, 00043 const size_t depth, 00044 VertexBufferData& globalData ) 00045 { 00046 data.sort( start, length, axis ); 00047 _vertexStart = globalData.vertices.size(); 00048 _vertexLength = 0; 00049 _indexStart = globalData.indices.size(); 00050 _indexLength = 0; 00051 00052 const bool hasColors = ( data.colors.size() > 0 ); 00053 00054 // stores the new indices (relative to _start) 00055 std::map< Index, ShortIndex > newIndex; 00056 00057 for( Index t = 0; t < length; ++t ) 00058 { 00059 for( Index v = 0; v < 3; ++v ) 00060 { 00061 Index i = data.triangles[start + t][v]; 00062 if( newIndex.find( i ) == newIndex.end() ) 00063 { 00064 newIndex[i] = _vertexLength++; 00065 // assert number of vertices does not exceed SmallIndex range 00066 MESHASSERT( _vertexLength ); 00067 globalData.vertices.push_back( data.vertices[i] ); 00068 if( hasColors ) 00069 globalData.colors.push_back( data.colors[i] ); 00070 globalData.normals.push_back( data.normals[i] ); 00071 } 00072 globalData.indices.push_back( newIndex[i] ); 00073 ++_indexLength; 00074 } 00075 } 00076 00077 #ifndef NDEBUG 00078 MESHINFO << "setupTree" << "( " << _indexStart << ", " << _indexLength 00079 << "; start " << _vertexStart << ", " << _vertexLength 00080 << " vertices)." << std::endl; 00081 #endif 00082 } 00083 00084 00085 /* Compute the bounding sphere of the leaf's indexed vertices. */ 00086 const BoundingSphere& VertexBufferLeaf::updateBoundingSphere() 00087 { 00088 // We determine a bounding sphere by: 00089 // 1) Using the inner sphere of the dominant axis of the bounding box as an 00090 // estimate 00091 // 2) Test all points to be in that sphere 00092 // 3) Expand the sphere to contain all points outside. 00093 00094 00095 // 1a) initialize and compute a bounding box 00096 _boundingBox[0] = _globalData.vertices[ _vertexStart + 00097 _globalData.indices[_indexStart] ]; 00098 _boundingBox[1] = _globalData.vertices[ _vertexStart + 00099 _globalData.indices[_indexStart] ]; 00100 00101 for( Index i = 1 + _indexStart; i < _indexStart + _indexLength; ++i ) 00102 { 00103 const Vertex& vertex = _globalData.vertices[ _vertexStart + 00104 _globalData.indices[ i ] ]; 00105 _boundingBox[0][0] = std::min( _boundingBox[0][0], vertex[0] ); 00106 _boundingBox[1][0] = std::max( _boundingBox[1][0], vertex[0] ); 00107 _boundingBox[0][1] = std::min( _boundingBox[0][1], vertex[1] ); 00108 _boundingBox[1][1] = std::max( _boundingBox[1][1], vertex[1] ); 00109 _boundingBox[0][2] = std::min( _boundingBox[0][2], vertex[2] ); 00110 _boundingBox[1][2] = std::max( _boundingBox[1][2], vertex[2] ); 00111 } 00112 00113 // 1b) get inner sphere of bounding box as an initial estimate 00114 _boundingSphere.x() = ( _boundingBox[0].x() + _boundingBox[1].x() ) * 0.5f; 00115 _boundingSphere.y() = ( _boundingBox[0].y() + _boundingBox[1].y() ) * 0.5f; 00116 _boundingSphere.z() = ( _boundingBox[0].z() + _boundingBox[1].z() ) * 0.5f; 00117 00118 _boundingSphere.w() = LB_MAX( _boundingBox[1].x() - _boundingBox[0].x(), 00119 _boundingBox[1].y() - _boundingBox[0].y() ); 00120 _boundingSphere.w() = LB_MAX( _boundingBox[1].z() - _boundingBox[0].z(), 00121 _boundingSphere.w() ); 00122 _boundingSphere.w() *= .5f; 00123 00124 float radius = _boundingSphere.w(); 00125 float radiusSquared = radius * radius; 00126 Vertex center( _boundingSphere.array ); 00127 00128 // 2) test all points to be in the estimated bounding sphere 00129 for( Index offset = 0; offset < _indexLength; ++offset ) 00130 { 00131 const Vertex& vertex = 00132 _globalData.vertices[ _vertexStart + 00133 _globalData.indices[_indexStart + offset] ]; 00134 00135 const Vertex centerToPoint = vertex - center; 00136 const float distanceSquared = centerToPoint.squared_length(); 00137 if( distanceSquared <= radiusSquared ) // point is inside existing BS 00138 continue; 00139 00140 // 3) expand sphere to contain 'outside' points 00141 const float distance = sqrtf( distanceSquared ); 00142 const float delta = distance - radius; 00143 00144 radius = ( radius + distance ) * .5f; 00145 radiusSquared = radius * radius; 00146 const Vertex normdelta = normalize( centerToPoint ) * ( 0.5f * delta ); 00147 00148 center += normdelta; 00149 00150 LBASSERTINFO( Vertex( vertex-center ).squared_length() <= 00151 ( radiusSquared + 2.f * std::numeric_limits<float>::epsilon( )), 00152 vertex << " c " << center << " r " << radius << " (" 00153 << Vertex( vertex-center ).length() << ")" ); 00154 } 00155 00156 #ifndef NDEBUG 00157 // 2a) re-test all points to be in the estimated bounding sphere 00158 for( Index offset = 0; offset < _indexLength; ++offset ) 00159 { 00160 const Vertex& vertex = 00161 _globalData.vertices[ _vertexStart + 00162 _globalData.indices[_indexStart + offset] ]; 00163 00164 const Vertex centerToPoint = vertex - center; 00165 const float distanceSquared = centerToPoint.squared_length(); 00166 LBASSERTINFO( distanceSquared <= 00167 ( radiusSquared + 2.f * std::numeric_limits<float>::epsilon( )), 00168 vertex << " c " << center << " r " << radius << " (" 00169 << Vertex( vertex-center ).length() << ")" ); 00170 } 00171 #endif 00172 00173 // store optimal bounding sphere 00174 _boundingSphere.x() = center.x(); 00175 _boundingSphere.y() = center.y(); 00176 _boundingSphere.z() = center.z(); 00177 _boundingSphere.w() = radius; 00178 00179 #ifndef NDEBUG 00180 MESHINFO << "updateBoundingSphere" << "( " << _boundingSphere << " )." 00181 << std::endl; 00182 #endif 00183 00184 return _boundingSphere; 00185 } 00186 00187 00188 /* Compute the range of this child. */ 00189 void VertexBufferLeaf::updateRange() 00190 { 00191 _range[0] = 1.0f * _indexStart / _globalData.indices.size(); 00192 _range[1] = _range[0] + 1.0f * _indexLength / _globalData.indices.size(); 00193 00194 #ifndef NDEBUG 00195 MESHINFO << "updateRange" << "( " << _range[0] << ", " << _range[1] 00196 << " )." << std::endl; 00197 #endif 00198 } 00199 00200 #define glewGetContext state.glewGetContext 00201 00202 /* Set up rendering of the leaf nodes. */ 00203 void VertexBufferLeaf::setupRendering( VertexBufferState& state, 00204 GLuint* data ) const 00205 { 00206 switch( state.getRenderMode() ) 00207 { 00208 case RENDER_MODE_IMMEDIATE: 00209 break; 00210 00211 case RENDER_MODE_BUFFER_OBJECT: 00212 { 00213 const char* charThis = reinterpret_cast< const char* >( this ); 00214 00215 if( data[VERTEX_OBJECT] == state.INVALID ) 00216 data[VERTEX_OBJECT] = state.newBufferObject( charThis + 0 ); 00217 glBindBuffer( GL_ARRAY_BUFFER, data[VERTEX_OBJECT] ); 00218 glBufferData( GL_ARRAY_BUFFER, _vertexLength * sizeof( Vertex ), 00219 &_globalData.vertices[_vertexStart], GL_STATIC_DRAW ); 00220 00221 if( data[NORMAL_OBJECT] == state.INVALID ) 00222 data[NORMAL_OBJECT] = state.newBufferObject( charThis + 1 ); 00223 glBindBuffer( GL_ARRAY_BUFFER, data[NORMAL_OBJECT] ); 00224 glBufferData( GL_ARRAY_BUFFER, _vertexLength * sizeof( Normal ), 00225 &_globalData.normals[_vertexStart], GL_STATIC_DRAW ); 00226 00227 if( data[COLOR_OBJECT] == state.INVALID ) 00228 data[COLOR_OBJECT] = state.newBufferObject( charThis + 2 ); 00229 if( state.useColors() ) 00230 { 00231 glBindBuffer( GL_ARRAY_BUFFER, data[COLOR_OBJECT] ); 00232 glBufferData( GL_ARRAY_BUFFER, _vertexLength * sizeof( Color ), 00233 &_globalData.colors[_vertexStart], GL_STATIC_DRAW ); 00234 } 00235 00236 if( data[INDEX_OBJECT] == state.INVALID ) 00237 data[INDEX_OBJECT] = state.newBufferObject( charThis + 3 ); 00238 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, data[INDEX_OBJECT] ); 00239 glBufferData( GL_ELEMENT_ARRAY_BUFFER, 00240 _indexLength * sizeof( ShortIndex ), 00241 &_globalData.indices[_indexStart], GL_STATIC_DRAW ); 00242 00243 break; 00244 } 00245 case RENDER_MODE_DISPLAY_LIST: 00246 default: 00247 { 00248 if( data[0] == state.INVALID ) 00249 { 00250 char* key = (char*)( this ); 00251 if( state.useColors( )) 00252 ++key; 00253 data[0] = state.newDisplayList( key ); 00254 } 00255 glNewList( data[0], GL_COMPILE ); 00256 renderImmediate( state ); 00257 glEndList(); 00258 break; 00259 } 00260 } 00261 } 00262 00263 /* Draw the leaf. */ 00264 void VertexBufferLeaf::draw( VertexBufferState& state ) const 00265 { 00266 if( state.stopRendering( )) 00267 return; 00268 00269 state.updateRegion( _boundingBox ); 00270 switch( state.getRenderMode() ) 00271 { 00272 case RENDER_MODE_IMMEDIATE: 00273 renderImmediate( state ); 00274 return; 00275 case RENDER_MODE_BUFFER_OBJECT: 00276 renderBufferObject( state ); 00277 return; 00278 case RENDER_MODE_DISPLAY_LIST: 00279 default: 00280 renderDisplayList( state ); 00281 return; 00282 } 00283 } 00284 00285 /* Render the leaf with buffer objects. */ 00286 void VertexBufferLeaf::renderBufferObject( VertexBufferState& state ) const 00287 { 00288 GLuint buffers[4]; 00289 for( int i = 0; i < 4; ++i ) 00290 buffers[i] = 00291 state.getBufferObject( reinterpret_cast< const char* >(this) + i ); 00292 if( buffers[VERTEX_OBJECT] == state.INVALID || 00293 buffers[NORMAL_OBJECT] == state.INVALID || 00294 buffers[COLOR_OBJECT] == state.INVALID || 00295 buffers[INDEX_OBJECT] == state.INVALID ) 00296 00297 setupRendering( state, buffers ); 00298 00299 if( state.useColors() ) 00300 { 00301 glBindBuffer( GL_ARRAY_BUFFER, buffers[COLOR_OBJECT] ); 00302 glColorPointer( 4, GL_UNSIGNED_BYTE, 0, 0 ); 00303 } 00304 glBindBuffer( GL_ARRAY_BUFFER, buffers[NORMAL_OBJECT] ); 00305 glNormalPointer( GL_FLOAT, 0, 0 ); 00306 glBindBuffer( GL_ARRAY_BUFFER, buffers[VERTEX_OBJECT] ); 00307 glVertexPointer( 3, GL_FLOAT, 0, 0 ); 00308 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, buffers[INDEX_OBJECT] ); 00309 glDrawElements( GL_TRIANGLES, GLsizei( _indexLength ), GL_UNSIGNED_SHORT, 0 ); 00310 } 00311 00312 00313 /* Render the leaf with a display list. */ 00314 inline 00315 void VertexBufferLeaf::renderDisplayList( VertexBufferState& state ) const 00316 { 00317 char* key = (char*)( this ); 00318 if( state.useColors( )) 00319 ++key; 00320 00321 GLuint displayList = state.getDisplayList( key ); 00322 00323 if( displayList == state.INVALID ) 00324 setupRendering( state, &displayList ); 00325 00326 glCallList( displayList ); 00327 } 00328 00329 00330 /* Render the leaf with immediate mode primitives or vertex arrays. */ 00331 inline 00332 void VertexBufferLeaf::renderImmediate( VertexBufferState& state ) const 00333 { 00334 glBegin( GL_TRIANGLES ); 00335 for( Index offset = 0; offset < _indexLength; ++offset ) 00336 { 00337 const Index i =_vertexStart + _globalData.indices[_indexStart + offset]; 00338 if( state.useColors() ) 00339 glColor4ubv( &_globalData.colors[i][0] ); 00340 glNormal3fv( &_globalData.normals[i][0] ); 00341 glVertex3fv( &_globalData.vertices[i][0] ); 00342 } 00343 glEnd(); 00344 00345 // if( state.useColors() ) 00346 // glColorPointer( 4, GL_UNSIGNED_BYTE, 0, 00347 // &_globalData.colors[_vertexStart] ); 00348 // glNormalPointer( GL_FLOAT, 0, &_globalData.normals[_vertexStart] ); 00349 // glVertexPointer( 3, GL_FLOAT, 0, &_globalData.vertices[_vertexStart] ); 00350 // glDrawElements( GL_TRIANGLES, _indexLength, GL_UNSIGNED_SHORT, 00351 // &_globalData.indices[_indexStart] ); 00352 } 00353 00354 00355 /* Read leaf node from memory. */ 00356 void VertexBufferLeaf::fromMemory( char** addr, VertexBufferData& globalData ) 00357 { 00358 size_t nodeType; 00359 memRead( reinterpret_cast< char* >( &nodeType ), addr, sizeof( size_t ) ); 00360 if( nodeType != LEAF_TYPE ) 00361 throw MeshException( "Error reading binary file. Expected a leaf " 00362 "node, but found something else instead." ); 00363 VertexBufferBase::fromMemory( addr, globalData ); 00364 memRead( reinterpret_cast< char* >( &_boundingBox ), addr, 00365 sizeof( BoundingBox ) ); 00366 memRead( reinterpret_cast< char* >( &_vertexStart ), addr, 00367 sizeof( Index ) ); 00368 memRead( reinterpret_cast< char* >( &_vertexLength ), addr, 00369 sizeof( ShortIndex ) ); 00370 memRead( reinterpret_cast< char* >( &_indexStart ), addr, 00371 sizeof( Index ) ); 00372 memRead( reinterpret_cast< char* >( &_indexLength ), addr, 00373 sizeof( Index ) ); 00374 } 00375 00376 00377 /* Write leaf node to output stream. */ 00378 void VertexBufferLeaf::toStream( std::ostream& os ) 00379 { 00380 size_t nodeType = LEAF_TYPE; 00381 os.write( reinterpret_cast< char* >( &nodeType ), sizeof( size_t )); 00382 VertexBufferBase::toStream( os ); 00383 os.write( reinterpret_cast< char* >( &_boundingBox ), sizeof( BoundingBox)); 00384 os.write( reinterpret_cast< char* >( &_vertexStart ), sizeof( Index )); 00385 os.write( reinterpret_cast< char* >( &_vertexLength ),sizeof( ShortIndex )); 00386 os.write( reinterpret_cast< char* >( &_indexStart ), sizeof( Index )); 00387 os.write( reinterpret_cast< char* >( &_indexLength ), sizeof( Index )); 00388 } 00389 00390 }