vertexBufferNode.cpp

00001 /*  
00002     vertexBufferNode.cpp
00003     Copyright (c) 2007, Tobias Wolf <twolf@access.unizh.ch>
00004     Copyright (c) 2008, Stefan Eilemann <eile@equalizergraphics.com>
00005  *
00006  * This library is free software; you can redistribute it and/or modify it under
00007  * the terms of the GNU Lesser General Public License version 2.1 as published
00008  * by the Free Software Foundation.
00009  *  
00010  * This library is distributed in the hope that it will be useful, but WITHOUT
00011  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00012  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00013  * details.
00014  * 
00015  * You should have received a copy of the GNU Lesser General Public License
00016  * along with this library; if not, write to the Free Software Foundation, Inc.,
00017  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00018   
00019     
00020     Implementation of the VertexBufferNode class.
00021 */
00022 
00023 
00024 #include "vertexBufferNode.h"
00025 #include "vertexBufferLeaf.h"
00026 #include "vertexBufferState.h"
00027 #include "vertexData.h"
00028 #include <set>
00029 
00030 
00031 using namespace std;
00032 
00033 namespace mesh
00034 {
00035 
00036 inline static bool _subdivide( const Index length, const size_t depth )
00037 {
00038     return ( length / 2 > LEAF_SIZE ) || ( depth < 3 && length > 1 );
00039 }
00040 
00041 /*  Continue kd-tree setup, create intermediary or leaf nodes as required.  */
00042 void VertexBufferNode::setupTree( VertexData& data, const Index start,
00043                                   const Index length, const Axis axis,
00044                                   const size_t depth,
00045                                   VertexBufferData& globalData )
00046 {
00047     #ifndef NDEBUG
00048     MESHINFO << "Entering VertexBufferNode::setupTree"
00049              << "( " << start << ", " << length << ", " << axis << ", " 
00050              << depth << " )." << endl;
00051     #endif
00052 
00053     data.sort( start, length, axis );
00054     const Index median = start + ( length / 2 );
00055 
00056     // left child will include elements smaller than the median
00057     const Index leftLength    = length / 2;
00058     const bool  subdivideLeft = _subdivide( leftLength, depth );
00059 
00060     if( subdivideLeft )
00061         _left = new VertexBufferNode;
00062     else
00063         _left = new VertexBufferLeaf( globalData );
00064     
00065     // right child will include elements equal to or greater than the median
00066     const Index rightLength    = ( length + 1 ) / 2;
00067     const bool  subdivideRight = _subdivide( rightLength, depth );
00068 
00069     if( subdivideRight )
00070         _right = new VertexBufferNode;
00071     else
00072         _right = new VertexBufferLeaf( globalData );
00073     
00074     // move to next axis and continue contruction in the child nodes
00075     const Axis newAxisLeft  = subdivideLeft ? 
00076                         data.getLongestAxis( start , leftLength  ) : AXIS_X;
00077 
00078     const Axis newAxisRight = subdivideRight ? 
00079                         data.getLongestAxis( median, rightLength ) : AXIS_X;
00080 
00081     static_cast< VertexBufferNode* >
00082             ( _left )->setupTree( data, start, leftLength, newAxisLeft, depth+1, 
00083                                   globalData );
00084     static_cast< VertexBufferNode* >
00085         ( _right )->setupTree( data, median, rightLength, newAxisRight, depth+1,
00086                                globalData );
00087 
00088 }
00089 
00090 
00091 /*  Compute the bounding sphere from the children's bounding spheres.  */
00092 const BoundingSphere& VertexBufferNode::updateBoundingSphere()
00093 {
00094     // take the bounding spheres returned by the children
00095     const BoundingSphere& sphere1 = _left->updateBoundingSphere();
00096     const BoundingSphere& sphere2 = _right->updateBoundingSphere();
00097     
00098     // compute enclosing sphere
00099     const Vertex center1( sphere1.array );
00100     const Vertex center2( sphere2.array );
00101     Vertex c1ToC2     = center2 - center1;
00102     c1ToC2.normalize();
00103     
00104     const Vertex outer1 = center1 - c1ToC2 * sphere1.w();
00105     const Vertex outer2 = center2 + c1ToC2 * sphere2.w();
00106 
00107     Vertex vertexBoundingSphere = Vertex( outer1 + outer2 ) * 0.5f; 
00108     _boundingSphere.x() = vertexBoundingSphere.x();
00109     _boundingSphere.y() = vertexBoundingSphere.y();
00110     _boundingSphere.z() = vertexBoundingSphere.z();
00111     _boundingSphere.w() = Vertex( outer1 - outer2 ).length() * 0.5f;
00112     
00113 #ifndef NDEBUG
00114     MESHINFO << "Exiting VertexBufferNode::updateBoundingSphere" 
00115              << "( " << _boundingSphere << " )." 
00116              << endl;
00117 #endif
00118     
00119     return _boundingSphere;
00120 }
00121 
00122 
00123 /*  Compute the range from the children's ranges.  */
00124 void VertexBufferNode::updateRange()
00125 {
00126     // update the children's ranges
00127     static_cast< VertexBufferNode* >( _left )->updateRange();
00128     static_cast< VertexBufferNode* >( _right )->updateRange();
00129     
00130     // set node range to min/max of the children's ranges
00131     _range[0] = min( _left->getRange()[0], _right->getRange()[0] );
00132     _range[1] = max( _left->getRange()[1], _right->getRange()[1] );
00133     
00134     #ifndef NDEBUG
00135     MESHINFO << "Exiting VertexBufferNode::updateRange" 
00136              << "( " << _range[0] << ", " << _range[1] << " )." << endl;
00137     #endif
00138 }
00139 
00140 
00141 /*  Render the node by rendering the children.  */
00142 void VertexBufferNode::render( VertexBufferState& state ) const
00143 {
00144     _left->render( state );
00145     _right->render( state );
00146 }
00147 
00148 
00149 /*  Read node from memory and continue with remaining nodes.  */
00150 void VertexBufferNode::fromMemory( char** addr, VertexBufferData& globalData )
00151 {
00152     // read node itself   
00153     size_t nodeType;
00154     memRead( reinterpret_cast< char* >( &nodeType ), addr, sizeof( size_t ) );
00155     if( nodeType != NODE_TYPE )
00156         throw MeshException( "Error reading binary file. Expected a regular "
00157                              "node, but found something else instead." );
00158     VertexBufferBase::fromMemory( addr, globalData );
00159     
00160     // read left child (peek ahead)
00161     memRead( reinterpret_cast< char* >( &nodeType ), addr, sizeof( size_t ) );
00162     if( nodeType != NODE_TYPE && nodeType != LEAF_TYPE )
00163         throw MeshException( "Error reading binary file. Expected either a "
00164                              "regular or a leaf node, but found neither." );
00165     *addr -= sizeof( size_t );
00166     if( nodeType == NODE_TYPE )
00167         _left = new VertexBufferNode;
00168     else
00169         _left = new VertexBufferLeaf( globalData );
00170     static_cast< VertexBufferNode* >( _left )->fromMemory( addr, globalData );
00171     
00172     // read right child (peek ahead)
00173     memRead( reinterpret_cast< char* >( &nodeType ), addr, sizeof( size_t ) );
00174     if( nodeType != NODE_TYPE && nodeType != LEAF_TYPE )
00175         throw MeshException( "Error reading binary file. Expected either a "
00176                              "regular or a leaf node, but found neither." );
00177     *addr -= sizeof( size_t );
00178     if( nodeType == NODE_TYPE )
00179         _right = new VertexBufferNode;
00180     else
00181         _right = new VertexBufferLeaf( globalData );
00182     static_cast< VertexBufferNode* >( _right )->fromMemory( addr, globalData );
00183 }
00184 
00185 
00186 /*  Write node to output stream and continue with remaining nodes.  */
00187 void VertexBufferNode::toStream( std::ostream& os )
00188 {
00189     size_t nodeType = NODE_TYPE;
00190     os.write( reinterpret_cast< char* >( &nodeType ), sizeof( size_t ) );
00191     VertexBufferBase::toStream( os );
00192     static_cast< VertexBufferNode* >( _left )->toStream( os );
00193     static_cast< VertexBufferNode* >( _right )->toStream( os );
00194 }
00195 
00196 
00197 /*  Destructor, clears up children as well.  */
00198 VertexBufferNode::~VertexBufferNode()
00199 {
00200     delete static_cast< VertexBufferNode* >( _left );
00201     delete static_cast< VertexBufferNode* >( _right );
00202 }
00203 }
Generated on Mon Aug 10 18:58:41 2009 for Equalizer 0.9 by  doxygen 1.5.8