Equalizer  1.4.1
eqPly/vertexBufferLeaf.cpp
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 }
Generated on Mon Nov 26 2012 14:41:50 for Equalizer 1.4.1 by  doxygen 1.7.6.1