Equalizer 1.0

vertexBufferNode.cpp

00001 
00002 /* Copyright (c) 2007, Tobias Wolf <twolf@access.unizh.ch>
00003  * Copyright (c) 2008, 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     Implementation of the VertexBufferNode class.
00031 */
00032 
00033 
00034 #include "vertexBufferNode.h"
00035 #include "vertexBufferLeaf.h"
00036 #include "vertexBufferState.h"
00037 #include "vertexData.h"
00038 #include <set>
00039 
00040 
00041 using namespace std;
00042 
00043 namespace mesh
00044 {
00045 
00046 inline static bool _subdivide( const Index length, const size_t depth )
00047 {
00048     return ( length / 2 > LEAF_SIZE ) || ( depth < 3 && length > 1 );
00049 }
00050 
00051 /*  Continue kd-tree setup, create intermediary or leaf nodes as required.  */
00052 void VertexBufferNode::setupTree( VertexData& data, const Index start,
00053                                   const Index length, const Axis axis,
00054                                   const size_t depth,
00055                                   VertexBufferData& globalData )
00056 {
00057 #ifndef NDEBUG
00058     MESHINFO << "setupTree"
00059              << "( " << start << ", " << length << ", " << axis << ", " 
00060              << depth << " )." << endl;
00061 #endif
00062 
00063     data.sort( start, length, axis );
00064     const Index median = start + ( length / 2 );
00065 
00066     // left child will include elements smaller than the median
00067     const Index leftLength    = length / 2;
00068     const bool  subdivideLeft = _subdivide( leftLength, depth );
00069 
00070     if( subdivideLeft )
00071         _left = new VertexBufferNode;
00072     else
00073         _left = new VertexBufferLeaf( globalData );
00074     
00075     // right child will include elements equal to or greater than the median
00076     const Index rightLength    = ( length + 1 ) / 2;
00077     const bool  subdivideRight = _subdivide( rightLength, depth );
00078 
00079     if( subdivideRight )
00080         _right = new VertexBufferNode;
00081     else
00082         _right = new VertexBufferLeaf( globalData );
00083     
00084     // move to next axis and continue contruction in the child nodes
00085     const Axis newAxisLeft  = subdivideLeft ? 
00086                         data.getLongestAxis( start , leftLength  ) : AXIS_X;
00087 
00088     const Axis newAxisRight = subdivideRight ? 
00089                         data.getLongestAxis( median, rightLength ) : AXIS_X;
00090 
00091     static_cast< VertexBufferNode* >
00092             ( _left )->setupTree( data, start, leftLength, newAxisLeft, depth+1,
00093                                   globalData );
00094     static_cast< VertexBufferNode* >
00095         ( _right )->setupTree( data, median, rightLength, newAxisRight, depth+1,
00096                                globalData );
00097 
00098 }
00099 
00100 
00101 /*  Compute the bounding sphere from the children's bounding spheres.  */
00102 const BoundingSphere& VertexBufferNode::updateBoundingSphere()
00103 {
00104     // take the bounding spheres returned by the children
00105     const BoundingSphere& sphere1 = _left->updateBoundingSphere();
00106     const BoundingSphere& sphere2 = _right->updateBoundingSphere();
00107     
00108     // compute enclosing sphere
00109     const Vertex center1( sphere1.array );
00110     const Vertex center2( sphere2.array );
00111     Vertex c1ToC2     = center2 - center1;
00112     c1ToC2.normalize();
00113     
00114     const Vertex outer1 = center1 - c1ToC2 * sphere1.w();
00115     const Vertex outer2 = center2 + c1ToC2 * sphere2.w();
00116 
00117     Vertex vertexBoundingSphere = Vertex( outer1 + outer2 ) * 0.5f; 
00118     _boundingSphere.x() = vertexBoundingSphere.x();
00119     _boundingSphere.y() = vertexBoundingSphere.y();
00120     _boundingSphere.z() = vertexBoundingSphere.z();
00121     _boundingSphere.w() = Vertex( outer1 - outer2 ).length() * 0.5f;
00122     
00123 #ifndef NDEBUG
00124     MESHINFO << "updateBoundingSphere" << "( " << _boundingSphere << " )." 
00125              << endl;
00126 #endif
00127     
00128     return _boundingSphere;
00129 }
00130 
00131 
00132 /*  Compute the range from the children's ranges.  */
00133 void VertexBufferNode::updateRange()
00134 {
00135     // update the children's ranges
00136     static_cast< VertexBufferNode* >( _left )->updateRange();
00137     static_cast< VertexBufferNode* >( _right )->updateRange();
00138     
00139     // set node range to min/max of the children's ranges
00140     _range[0] = min( _left->getRange()[0], _right->getRange()[0] );
00141     _range[1] = max( _left->getRange()[1], _right->getRange()[1] );
00142     
00143     #ifndef NDEBUG
00144     MESHINFO << "updateRange" << "( " << _range[0] << ", " << _range[1]
00145              << " )." << endl;
00146     #endif
00147 }
00148 
00149 
00150 /*  Render the node by rendering the children.  */
00151 void VertexBufferNode::render( VertexBufferState& state ) const
00152 {
00153     if ( state.stopRendering( ))
00154         return;
00155 
00156     _left->render( state );
00157     _right->render( state );
00158 }
00159 
00160 
00161 /*  Read node from memory and continue with remaining nodes.  */
00162 void VertexBufferNode::fromMemory( char** addr, VertexBufferData& globalData )
00163 {
00164     // read node itself   
00165     size_t nodeType;
00166     memRead( reinterpret_cast< char* >( &nodeType ), addr, sizeof( size_t ) );
00167     if( nodeType != NODE_TYPE )
00168         throw MeshException( "Error reading binary file. Expected a regular "
00169                              "node, but found something else instead." );
00170     VertexBufferBase::fromMemory( addr, globalData );
00171     
00172     // read left 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         _left = new VertexBufferNode;
00180     else
00181         _left = new VertexBufferLeaf( globalData );
00182     static_cast< VertexBufferNode* >( _left )->fromMemory( addr, globalData );
00183     
00184     // read right child (peek ahead)
00185     memRead( reinterpret_cast< char* >( &nodeType ), addr, sizeof( size_t ) );
00186     if( nodeType != NODE_TYPE && nodeType != LEAF_TYPE )
00187         throw MeshException( "Error reading binary file. Expected either a "
00188                              "regular or a leaf node, but found neither." );
00189     *addr -= sizeof( size_t );
00190     if( nodeType == NODE_TYPE )
00191         _right = new VertexBufferNode;
00192     else
00193         _right = new VertexBufferLeaf( globalData );
00194     static_cast< VertexBufferNode* >( _right )->fromMemory( addr, globalData );
00195 }
00196 
00197 
00198 /*  Write node to output stream and continue with remaining nodes.  */
00199 void VertexBufferNode::toStream( std::ostream& os )
00200 {
00201     size_t nodeType = NODE_TYPE;
00202     os.write( reinterpret_cast< char* >( &nodeType ), sizeof( size_t ) );
00203     VertexBufferBase::toStream( os );
00204     static_cast< VertexBufferNode* >( _left )->toStream( os );
00205     static_cast< VertexBufferNode* >( _right )->toStream( os );
00206 }
00207 
00208 
00209 /*  Destructor, clears up children as well.  */
00210 VertexBufferNode::~VertexBufferNode()
00211 {
00212     delete static_cast< VertexBufferNode* >( _left );
00213     delete static_cast< VertexBufferNode* >( _right );
00214 }
00215 }
Generated on Sun May 8 2011 19:11:07 for Equalizer 1.0 by  doxygen 1.7.3