Equalizer 1.0

vertexBufferLeaf.cpp

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 }
Generated on Sun May 8 2011 19:11:07 for Equalizer 1.0 by  doxygen 1.7.3