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