Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreOctreeSceneManager.cpp

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004 (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://www.ogre3d.org/
00006 
00007 Copyright © 2000-2004 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 /***************************************************************************
00026 octreescenemanager.cpp  -  description
00027 -------------------
00028 begin                : Fri Sep 27 2002
00029 copyright            : (C) 2002 by Jon Anderson
00030 email                : janders@users.sf.net
00031  
00032 Enhancements 2003 - 2004 (C) The OGRE Team
00033  
00034 ***************************************************************************/
00035 
00036 #include <OgreOctreeSceneManager.h>
00037 #include <OgreOctreeSceneQuery.h>
00038 #include <OgreOctreeNode.h>
00039 #include <OgreOctreeCamera.h>
00040 #include <OgreRenderSystem.h>
00041 
00042 
00043 extern "C"
00044 {
00045     void findNodesInBox( Ogre::SceneManager *sm,
00046                          const Ogre::AxisAlignedBox &box,
00047                          std::list < Ogre::SceneNode * > &list,
00048                          Ogre::SceneNode *exclude )
00049     {
00050         static_cast<Ogre::OctreeSceneManager*>( sm ) -> findNodesIn( box, list, exclude );
00051     }
00052     void findNodesInSphere( Ogre::SceneManager *sm,
00053                             const Ogre::Sphere &sphere,
00054                             std::list < Ogre::SceneNode * > &list,
00055                             Ogre::SceneNode *exclude )
00056     {
00057         static_cast<Ogre::OctreeSceneManager*>( sm ) -> findNodesIn( sphere, list, exclude );
00058     }
00059 }
00060 
00061 namespace Ogre
00062 {
00063 enum Intersection
00064 {
00065     OUTSIDE=0,
00066     INSIDE=1,
00067     INTERSECT=2
00068 };
00069 int OctreeSceneManager::intersect_call = 0;
00070 
00071 Intersection intersect( const Ray &one, const AxisAlignedBox &two )
00072 {
00073     OctreeSceneManager::intersect_call++;
00074     // Null box?
00075     if (two.isNull()) return OUTSIDE;
00076 
00077     bool inside = true;
00078     const Vector3* pCorners = two.getAllCorners();
00079     Vector3 origin = one.getOrigin();
00080     Vector3 dir = one.getDirection();
00081 
00082     Vector3 maxT(-1, -1, -1);
00083 
00084     int i = 0;
00085     for(i=0; i<3; i++ )
00086     {
00087         if( origin[i] < pCorners[0][i] )
00088         {
00089             inside = false;
00090             if( dir[i] > 0 )
00091             {
00092                 maxT[i] = (pCorners[0][i] - origin[i])/ dir[i];
00093             }
00094         }
00095         else if( origin[i] > pCorners[4][i] )
00096         {
00097             inside = false;
00098             if( dir[i] < 0 )
00099             {
00100                 maxT[i] = (pCorners[4][i] - origin[i]) / dir[i];
00101             }
00102         }
00103     }
00104 
00105     if( inside )
00106     {
00107         return INTERSECT;
00108     }
00109     int whichPlane = 0;
00110     if( maxT[1] > maxT[whichPlane])
00111         whichPlane = 1;
00112     if( maxT[2] > maxT[whichPlane])
00113         whichPlane = 2;
00114 
00115     if( ((int)maxT[whichPlane]) & 0x80000000 )
00116     {
00117         return OUTSIDE;
00118     }
00119     for(i=0; i<3; i++ )
00120     {
00121         if( i!= whichPlane )
00122         {
00123             float f = origin[i] + maxT[whichPlane] * dir[i];
00124             if ( f < (pCorners[0][i] - 0.00001f) ||
00125                     f > (pCorners[4][i] +0.00001f ) )
00126             {
00127                 return OUTSIDE;
00128             }
00129         }
00130     }
00131 
00132     return INTERSECT;
00133 
00134 }
00135 
00136 
00139 Intersection intersect( const PlaneBoundedVolume &one, const AxisAlignedBox &two )
00140 {
00141     OctreeSceneManager::intersect_call++;
00142     // Null box?
00143     if (two.isNull()) return OUTSIDE;
00144 
00145     // Get corners of the box
00146     const Vector3* pCorners = two.getAllCorners();
00147 
00148     // For each plane, see if all points are on the negative side
00149     // If so, object is not visible.
00150     // If one or more are, it's partial.
00151     // If all aren't, full
00152     int corners[ 8 ] = {0, 4, 3, 5, 2, 6, 1, 7};
00153     bool all_inside = true;
00154     PlaneList::const_iterator i, iend;
00155     iend = one.planes.end();
00156     for (i = one.planes.begin(); i != iend; ++i)
00157     {
00158         const Plane& plane = *i;
00159         bool all_outside = true;
00160 
00161         float distance = 0;
00162 
00163         for ( int corner = 0; corner < 8; ++corner )
00164         {
00165             distance = plane.getDistance( pCorners[ corners[ corner ] ] );
00166             all_outside = all_outside && ( distance < 0 );
00167             all_inside = all_inside && ( distance >= 0 );
00168 
00169             if ( !all_outside && !all_inside )
00170                 break;
00171         }
00172 
00173         if ( all_outside )
00174             return OUTSIDE;
00175     }
00176 
00177     if ( all_inside )
00178         return INSIDE;
00179     else
00180         return INTERSECT;
00181 
00182 }
00183 
00184 
00187 Intersection intersect( const AxisAlignedBox &one, const AxisAlignedBox &two )
00188 {
00189     OctreeSceneManager::intersect_call++;
00190     // Null box?
00191     if (one.isNull() || two.isNull()) return OUTSIDE;
00192 
00193     const Vector3 * outside = one.getAllCorners();
00194     const Vector3 *inside = two.getAllCorners();
00195 
00196     if ( inside[ 4 ].x < outside[ 0 ].x ||
00197             inside[ 4 ].y < outside[ 0 ].y ||
00198             inside[ 4 ].z < outside[ 0 ].z ||
00199             inside[ 0 ].x > outside[ 4 ].x ||
00200             inside[ 0 ].y > outside[ 4 ].y ||
00201             inside[ 0 ].z > outside[ 4 ].z )
00202     {
00203         return OUTSIDE;
00204     }
00205 
00206     bool full = ( inside[ 0 ].x > outside[ 0 ].x &&
00207                   inside[ 0 ].y > outside[ 0 ].y &&
00208                   inside[ 0 ].z > outside[ 0 ].z &&
00209                   inside[ 4 ].x < outside[ 4 ].x &&
00210                   inside[ 4 ].y < outside[ 4 ].y &&
00211                   inside[ 4 ].z < outside[ 4 ].z );
00212 
00213     if ( full )
00214         return INSIDE;
00215     else
00216         return INTERSECT;
00217 
00218 }
00219 
00222 Intersection intersect( const Sphere &one, const AxisAlignedBox &two )
00223 {
00224     OctreeSceneManager::intersect_call++;
00225     // Null box?
00226     if (two.isNull()) return OUTSIDE;
00227 
00228     float sradius = one.getRadius();
00229 
00230     sradius *= sradius;
00231 
00232     Vector3 scenter = one.getCenter();
00233 
00234     const Vector3 *corners = two.getAllCorners();
00235 
00236     float s, d = 0;
00237 
00238     Vector3 mndistance = ( corners[ 0 ] - scenter );
00239     Vector3 mxdistance = ( corners[ 4 ] - scenter );
00240 
00241     if ( mndistance.squaredLength() < sradius &&
00242             mxdistance.squaredLength() < sradius )
00243     {
00244         return INSIDE;
00245     }
00246 
00247     //find the square of the distance
00248     //from the sphere to the box
00249     for ( int i = 0 ; i < 3 ; i++ )
00250     {
00251         if ( scenter[ i ] < corners[ 0 ][ i ] )
00252         {
00253             s = scenter[ i ] - corners[ 0 ][ i ];
00254             d += s * s;
00255         }
00256 
00257         else if ( scenter[ i ] > corners[ 4 ][ i ] )
00258         {
00259             s = scenter[ i ] - corners[ 4 ][ i ];
00260             d += s * s;
00261         }
00262 
00263     }
00264 
00265     bool partial = ( d <= sradius );
00266 
00267     if ( !partial )
00268     {
00269         return OUTSIDE;
00270     }
00271 
00272     else
00273     {
00274         return INTERSECT;
00275     }
00276 
00277 
00278 }
00279 
00280 unsigned long white = 0xFFFFFFFF;
00281 
00282 unsigned short OctreeSceneManager::mIndexes[ 24 ] = {0, 1, 1, 2, 2, 3, 3, 0,       //back
00283         0, 6, 6, 5, 5, 1,             //left
00284         3, 7, 7, 4, 4, 2,             //right
00285         6, 7, 5, 4 };          //front
00286 unsigned long OctreeSceneManager::mColors[ 8 ] = {white, white, white, white, white, white, white, white };
00287 
00288 
00289 OctreeSceneManager::OctreeSceneManager( ) : SceneManager()
00290 {
00291     AxisAlignedBox b( -10000, -10000, -10000, 10000, 10000, 10000 );
00292     int depth = 8; 
00293     mOctree = 0;
00294     init( b, depth );
00295 }
00296 
00297 OctreeSceneManager::OctreeSceneManager( AxisAlignedBox &box, int max_depth ) : SceneManager()
00298 {
00299     mOctree = 0;
00300     init( box, max_depth );
00301 }
00302 
00303 void OctreeSceneManager::init( AxisAlignedBox &box, int depth )
00304 {
00305     delete mSceneRoot; //get rid of old root.
00306 
00307     // -- Changes by Steve
00308     // Don't do it this way, it will add it to the mSceneNodes which we don't want
00309     //mSceneRoot = createSceneNode( "SceneRoot" );
00310     mSceneRoot = new OctreeNode( this, "SceneRoot" );
00311     // -- End changes by Steve
00312 
00313     if ( mOctree != 0 )
00314         delete mOctree;
00315 
00316     mOctree = new Octree( 0 );
00317 
00318     mMaxDepth = depth;
00319     mBox = box;
00320 
00321     mOctree -> mBox = box;
00322 
00323     Vector3 min = box.getMinimum();
00324 
00325     Vector3 max = box.getMaximum();
00326 
00327     mOctree -> mHalfSize = ( max - min ) / 2;
00328 
00329 
00330     mShowBoxes = false;
00331 
00332     mCullCamera = false;
00333 
00334     mNumObjects = 0;
00335 
00336     Vector3 v( 1.5, 1.5, 1.5 );
00337 
00338     mScaleFactor.setScale( v );
00339 
00340 
00341 
00342     // setDisplaySceneNodes( true );
00343     // setShowBoxes( true );
00344 
00345     //
00346     //setUseCullCamera( true );
00347     //mSceneRoot isn't put into the octree since it has no volume.
00348 
00349 }
00350 
00351 OctreeSceneManager::~OctreeSceneManager()
00352 {
00353     // -- Changed by Steve
00354     // Don't do this here, SceneManager will do it
00355     /*
00356     if( mSceneRoot )
00357     delete mSceneRoot;
00358     */ 
00359     // --End Changes by Steve
00360 
00361     if ( mOctree )
00362         delete mOctree;
00363 }
00364 
00365 Camera * OctreeSceneManager::createCamera( const String &name )
00366 {
00367     Camera * c = new OctreeCamera( name, this );
00368     mCameras.insert( CameraList::value_type( name, c ) );
00369     return c;
00370 }
00371 
00372 void OctreeSceneManager::destroySceneNode( const String &name )
00373 {
00374     OctreeNode * on = static_cast < OctreeNode* > ( getSceneNode( name ) );
00375 
00376     if ( on != 0 )
00377         _removeOctreeNode( on );
00378 
00379     SceneManager::destroySceneNode( name );
00380 }
00381 
00382 bool OctreeSceneManager::getOptionValues( const String & key, std::list < SDDataChunk > &refValueList )
00383 {
00384     return SceneManager::getOptionValues( key, refValueList );
00385 }
00386 
00387 bool OctreeSceneManager::getOptionKeys( std::list < String > & refKeys )
00388 {
00389     SceneManager::getOptionKeys( refKeys );
00390     refKeys.push_back( "CullCamera" );
00391     refKeys.push_back( "Size" );
00392     refKeys.push_back( "ShowOctree" );
00393     refKeys.push_back( "Depth" );
00394 
00395     return true;
00396 }
00397 
00398 
00399 void OctreeSceneManager::_updateOctreeNode( OctreeNode * onode )
00400 {
00401     AxisAlignedBox box = onode -> _getWorldAABB();
00402 
00403     if ( box.isNull() )
00404         return ;
00405 
00406 
00407     if ( onode -> getOctant() == 0 )
00408     {
00409         //if outside the octree, force into the root node.
00410         if ( ! onode -> _isIn( mOctree -> mBox ) )
00411             mOctree->_addNode( onode );
00412         else
00413             _addOctreeNode( onode, mOctree );
00414         return ;
00415     }
00416 
00417     if ( ! onode -> _isIn( onode -> getOctant() -> mBox ) )
00418     {
00419         _removeOctreeNode( onode );
00420 
00421         //if outside the octree, force into the root node.
00422         if ( ! onode -> _isIn( mOctree -> mBox ) )
00423             mOctree->_addNode( onode );
00424         else
00425             _addOctreeNode( onode, mOctree );
00426     }
00427 }
00428 
00431 void OctreeSceneManager::_removeOctreeNode( OctreeNode * n )
00432 {
00433     Octree * oct = n -> getOctant();
00434 
00435     if ( oct )
00436     {
00437         oct -> _removeNode( n );
00438     }
00439 
00440     n->setOctant(0);
00441 }
00442 
00443 
00444 void OctreeSceneManager::_addOctreeNode( OctreeNode * n, Octree *octant, int depth )
00445 {
00446 
00447     AxisAlignedBox bx = n -> _getWorldAABB();
00448 
00449 
00450     //if the octree is twice as big as the scene node,
00451     //we will add it to a child.
00452     if ( ( depth < mMaxDepth ) && octant -> _isTwiceSize( bx ) )
00453     {
00454         int x, y, z;
00455         octant -> _getChildIndexes( bx, &x, &y, &z );
00456 
00457         if ( octant -> mChildren[ x ][ y ][ z ] == 0 )
00458         {
00459             octant -> mChildren[ x ][ y ][ z ] = new Octree( octant );
00460 
00461             const Vector3 *corners = octant -> mBox.getAllCorners();
00462             Vector3 min, max;
00463 
00464             if ( x == 0 )
00465             {
00466                 min.x = corners[ 0 ].x;
00467                 max.x = ( corners[ 0 ].x + corners[ 4 ].x ) / 2;
00468             }
00469 
00470             else
00471             {
00472                 min.x = ( corners[ 0 ].x + corners[ 4 ].x ) / 2;
00473                 max.x = corners[ 4 ].x;
00474             }
00475 
00476             if ( y == 0 )
00477             {
00478                 min.y = corners[ 0 ].y;
00479                 max.y = ( corners[ 0 ].y + corners[ 4 ].y ) / 2;
00480             }
00481 
00482             else
00483             {
00484                 min.y = ( corners[ 0 ].y + corners[ 4 ].y ) / 2;
00485                 max.y = corners[ 4 ].y;
00486             }
00487 
00488             if ( z == 0 )
00489             {
00490                 min.z = corners[ 0 ].z;
00491                 max.z = ( corners[ 0 ].z + corners[ 4 ].z ) / 2;
00492             }
00493 
00494             else
00495             {
00496                 min.z = ( corners[ 0 ].z + corners[ 4 ].z ) / 2;
00497                 max.z = corners[ 4 ].z;
00498             }
00499 
00500             octant -> mChildren[ x ][ y ][ z ] -> mBox.setExtents( min, max );
00501             octant -> mChildren[ x ][ y ][ z ] -> mHalfSize = ( max - min ) / 2;
00502         }
00503 
00504         _addOctreeNode( n, octant -> mChildren[ x ][ y ][ z ], ++depth );
00505 
00506     }
00507 
00508     else
00509     {
00510         octant -> _addNode( n );
00511     }
00512 }
00513 
00514 
00515 SceneNode * OctreeSceneManager::createSceneNode( void )
00516 {
00517     OctreeNode * on = new OctreeNode( this );
00518     mSceneNodes[ on->getName() ] = on;
00519     return on;
00520 }
00521 
00522 SceneNode * OctreeSceneManager::createSceneNode( const String &name )
00523 {
00524     OctreeNode * on = new OctreeNode( this, name );
00525     mSceneNodes[ on->getName() ] = on;
00526     return on;
00527 }
00528 
00529 void OctreeSceneManager::_updateSceneGraph( Camera * cam )
00530 {
00531     SceneManager::_updateSceneGraph( cam );
00532 }
00533 
00534 void OctreeSceneManager::_alertVisibleObjects( void )
00535 {
00536     NodeList::iterator it = mVisible.begin();
00537 
00538     while ( it != mVisible.end() )
00539     {
00540         OctreeNode * node = *it;
00541 
00542         ++it;
00543     }
00544 }
00545 
00546 void OctreeSceneManager::_findVisibleObjects( Camera * cam, bool onlyShadowCasters )
00547 {
00548 
00549     getRenderQueue()->clear();
00550     mBoxes.clear();
00551     mVisible.clear();
00552 
00553     if ( mCullCamera )
00554     {
00555         Camera * c = getCamera( "CullCamera" );
00556 
00557         if ( c != 0 )
00558             cam = getCamera( "CullCamera" );
00559     }
00560 
00561     mNumObjects = 0;
00562 
00563     //walk the octree, adding all visible Octreenodes nodes to the render queue.
00564     walkOctree( static_cast < OctreeCamera * > ( cam ), getRenderQueue(), mOctree, false, onlyShadowCasters );
00565 
00566 
00567     // Show the octree boxes & cull camera if required
00568     if ( mShowBoxes || mCullCamera )
00569     {
00570 
00571 
00572 
00573         if ( mShowBoxes )
00574         {
00575             for ( BoxList::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it )
00576             {
00577                 getRenderQueue()->addRenderable(*it);
00578             }
00579         }
00580 
00581         if ( mCullCamera )
00582         {
00583             OctreeCamera * c = static_cast<OctreeCamera*>(getCamera( "CullCamera" ));
00584 
00585             if ( c != 0 )
00586             {
00587                 getRenderQueue()->addRenderable(c);
00588             }
00589         }
00590 
00591     }
00592 
00593 
00594 
00595 }
00596 
00597 void OctreeSceneManager::walkOctree( OctreeCamera *camera, RenderQueue *queue,
00598                                      Octree *octant, bool foundvisible, bool onlyShadowCasters )
00599 {
00600 
00601     //return immediately if nothing is in the node.
00602     if ( octant -> numNodes() == 0 )
00603         return ;
00604 
00605     OctreeCamera::Visibility v = OctreeCamera::NONE;
00606 
00607     if ( foundvisible )
00608     {
00609         v = OctreeCamera::FULL;
00610     }
00611 
00612     else if ( octant == mOctree )
00613     {
00614         v = OctreeCamera::PARTIAL;
00615     }
00616 
00617     else
00618     {
00619         AxisAlignedBox box;
00620         octant -> _getCullBounds( &box );
00621         v = camera -> getVisibility( box );
00622     }
00623 
00624 
00625     // if the octant is visible, or if it's the root node...
00626     if ( v != OctreeCamera::NONE )
00627     {
00628 
00629         //Add stuff to be rendered;
00630         NodeList::iterator it = octant -> mNodes.begin();
00631 
00632         if ( mShowBoxes )
00633         {
00634             mBoxes.push_back( octant->getWireBoundingBox() );
00635         }
00636 
00637         bool vis = true;
00638 
00639         while ( it != octant -> mNodes.end() )
00640         {
00641             OctreeNode * sn = *it;
00642 
00643             // if this octree is partially visible, manually cull all
00644             // scene nodes attached directly to this level.
00645 
00646             if ( v == OctreeCamera::PARTIAL )
00647                 vis = camera -> isVisible( sn -> _getWorldAABB() );
00648 
00649             if ( vis )
00650             {
00651 
00652                 mNumObjects++;
00653                 sn -> _addToRenderQueue(camera, queue, onlyShadowCasters );
00654 
00655                 mVisible.push_back( sn );
00656 
00657                 if ( mDisplayNodes )
00658                     queue -> addRenderable( sn );
00659 
00660                 // check if the scene manager or this node wants the bounding box shown.
00661                 if (sn->getShowBoundingBox() || mShowBoundingBoxes)
00662                     sn->_addBoundingBoxToQueue(queue);
00663             }
00664 
00665             ++it;
00666         }
00667 
00668         if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
00669             walkOctree( camera, queue, octant -> mChildren[ 0 ][ 0 ][ 0 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
00670 
00671         if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
00672             walkOctree( camera, queue, octant -> mChildren[ 1 ][ 0 ][ 0 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
00673 
00674         if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
00675             walkOctree( camera, queue, octant -> mChildren[ 0 ][ 1 ][ 0 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
00676 
00677         if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
00678             walkOctree( camera, queue, octant -> mChildren[ 1 ][ 1 ][ 0 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
00679 
00680         if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
00681             walkOctree( camera, queue, octant -> mChildren[ 0 ][ 0 ][ 1 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
00682 
00683         if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
00684             walkOctree( camera, queue, octant -> mChildren[ 1 ][ 0 ][ 1 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
00685 
00686         if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
00687             walkOctree( camera, queue, octant -> mChildren[ 0 ][ 1 ][ 1 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
00688 
00689         if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
00690             walkOctree( camera, queue, octant -> mChildren[ 1 ][ 1 ][ 1 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
00691 
00692     }
00693 
00694 }
00695 
00696 // --- non template versions
00697 void _findNodes( const AxisAlignedBox &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
00698 {
00699 
00700     if ( !full )
00701     {
00702         AxisAlignedBox obox;
00703         octant -> _getCullBounds( &obox );
00704 
00705         Intersection isect = intersect( t, obox );
00706 
00707         if ( isect == OUTSIDE )
00708             return ;
00709 
00710         full = ( isect == INSIDE );
00711     }
00712 
00713 
00714     NodeList::iterator it = octant -> mNodes.begin();
00715 
00716     while ( it != octant -> mNodes.end() )
00717     {
00718         OctreeNode * on = ( *it );
00719 
00720         if ( on != exclude )
00721         {
00722             if ( full )
00723             {
00724                 list.push_back( on );
00725             }
00726 
00727             else
00728             {
00729                 Intersection nsect = intersect( t, on -> _getWorldAABB() );
00730 
00731                 if ( nsect != OUTSIDE )
00732                 {
00733                     list.push_back( on );
00734                 }
00735             }
00736 
00737         }
00738 
00739         ++it;
00740     }
00741 
00742 
00743 
00744     if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
00745         _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 0 ] );
00746 
00747     if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
00748         _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 0 ] );
00749 
00750     if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
00751         _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 0 ] );
00752 
00753     if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
00754         _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 0 ] );
00755 
00756     if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
00757         _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 1 ] );
00758 
00759     if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
00760         _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 1 ] );
00761 
00762     if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
00763         _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 1 ] );
00764 
00765     if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
00766         _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 1 ] );
00767 
00768 }
00769 
00770 void _findNodes( const Sphere &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
00771 {
00772 
00773     if ( !full )
00774     {
00775         AxisAlignedBox obox;
00776         octant -> _getCullBounds( &obox );
00777 
00778         Intersection isect = intersect( t, obox );
00779 
00780         if ( isect == OUTSIDE )
00781             return ;
00782 
00783         full = ( isect == INSIDE );
00784     }
00785 
00786 
00787     NodeList::iterator it = octant -> mNodes.begin();
00788 
00789     while ( it != octant -> mNodes.end() )
00790     {
00791         OctreeNode * on = ( *it );
00792 
00793         if ( on != exclude )
00794         {
00795             if ( full )
00796             {
00797                 list.push_back( on );
00798             }
00799 
00800             else
00801             {
00802                 Intersection nsect = intersect( t, on -> _getWorldAABB() );
00803 
00804                 if ( nsect != OUTSIDE )
00805                 {
00806                     list.push_back( on );
00807                 }
00808             }
00809 
00810         }
00811 
00812         ++it;
00813     }
00814 
00815 
00816 
00817     if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
00818         _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 0 ] );
00819 
00820     if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
00821         _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 0 ] );
00822 
00823     if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
00824         _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 0 ] );
00825 
00826     if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
00827         _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 0 ] );
00828 
00829     if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
00830         _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 1 ] );
00831 
00832     if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
00833         _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 1 ] );
00834 
00835     if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
00836         _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 1 ] );
00837 
00838     if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
00839         _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 1 ] );
00840 
00841 }
00842 
00843 
00844 void _findNodes( const PlaneBoundedVolume &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
00845 {
00846 
00847     if ( !full )
00848     {
00849         AxisAlignedBox obox;
00850         octant -> _getCullBounds( &obox );
00851 
00852         Intersection isect = intersect( t, obox );
00853 
00854         if ( isect == OUTSIDE )
00855             return ;
00856 
00857         full = ( isect == INSIDE );
00858     }
00859 
00860 
00861     NodeList::iterator it = octant -> mNodes.begin();
00862 
00863     while ( it != octant -> mNodes.end() )
00864     {
00865         OctreeNode * on = ( *it );
00866 
00867         if ( on != exclude )
00868         {
00869             if ( full )
00870             {
00871                 list.push_back( on );
00872             }
00873 
00874             else
00875             {
00876                 Intersection nsect = intersect( t, on -> _getWorldAABB() );
00877 
00878                 if ( nsect != OUTSIDE )
00879                 {
00880                     list.push_back( on );
00881                 }
00882             }
00883 
00884         }
00885 
00886         ++it;
00887     }
00888 
00889 
00890 
00891     if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
00892         _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 0 ] );
00893 
00894     if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
00895         _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 0 ] );
00896 
00897     if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
00898         _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 0 ] );
00899 
00900     if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
00901         _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 0 ] );
00902 
00903     if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
00904         _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 1 ] );
00905 
00906     if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
00907         _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 1 ] );
00908 
00909     if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
00910         _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 1 ] );
00911 
00912     if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
00913         _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 1 ] );
00914 
00915 }
00916 
00917 void _findNodes( const Ray &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
00918 {
00919 
00920     if ( !full )
00921     {
00922         AxisAlignedBox obox;
00923         octant -> _getCullBounds( &obox );
00924 
00925         Intersection isect = intersect( t, obox );
00926 
00927         if ( isect == OUTSIDE )
00928             return ;
00929 
00930         full = ( isect == INSIDE );
00931     }
00932 
00933 
00934     NodeList::iterator it = octant -> mNodes.begin();
00935 
00936     while ( it != octant -> mNodes.end() )
00937     {
00938         OctreeNode * on = ( *it );
00939 
00940         if ( on != exclude )
00941         {
00942             if ( full )
00943             {
00944                 list.push_back( on );
00945             }
00946 
00947             else
00948             {
00949                 Intersection nsect = intersect( t, on -> _getWorldAABB() );
00950 
00951                 if ( nsect != OUTSIDE )
00952                 {
00953                     list.push_back( on );
00954                 }
00955             }
00956 
00957         }
00958 
00959         ++it;
00960     }
00961 
00962 
00963 
00964     if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
00965         _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 0 ] );
00966 
00967     if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
00968         _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 0 ] );
00969 
00970     if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
00971         _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 0 ] );
00972 
00973     if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
00974         _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 0 ] );
00975 
00976     if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
00977         _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 1 ] );
00978 
00979     if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
00980         _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 1 ] );
00981 
00982     if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
00983         _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 1 ] );
00984 
00985     if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
00986         _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 1 ] );
00987 
00988 }
00989 
00990 void OctreeSceneManager::findNodesIn( const AxisAlignedBox &box, std::list < SceneNode * > &list, SceneNode *exclude )
00991 {
00992     _findNodes( box, list, exclude, false, mOctree );
00993 }
00994 
00995 void OctreeSceneManager::findNodesIn( const Sphere &sphere, std::list < SceneNode * > &list, SceneNode *exclude )
00996 {
00997     _findNodes( sphere, list, exclude, false, mOctree );
00998 }
00999 
01000 void OctreeSceneManager::findNodesIn( const PlaneBoundedVolume &volume, std::list < SceneNode * > &list, SceneNode *exclude )
01001 {
01002     _findNodes( volume, list, exclude, false, mOctree );
01003 }
01004 
01005 void OctreeSceneManager::findNodesIn( const Ray &r, std::list < SceneNode * > &list, SceneNode *exclude )
01006 {
01007     _findNodes( r, list, exclude, false, mOctree );
01008 }
01009 
01010 void OctreeSceneManager::resize( const AxisAlignedBox &box )
01011 {
01012     std::list < SceneNode * > nodes;
01013     std::list < SceneNode * > ::iterator it;
01014 
01015     _findNodes( mOctree->mBox, nodes, 0, true, mOctree );
01016 
01017     delete mOctree;
01018 
01019     mOctree = new Octree( 0 );
01020     mOctree->mBox = box;
01021 
01022     it = nodes.begin();
01023 
01024     while ( it != nodes.end() )
01025     {
01026         OctreeNode * on = static_cast < OctreeNode * > ( *it );
01027         on -> setOctant( 0 );
01028         _updateOctreeNode( on );
01029         ++it;
01030     }
01031 
01032 }
01033 
01034 bool OctreeSceneManager::setOption( const String & key, const void * val )
01035 {
01036     if ( key == "Size" )
01037     {
01038         resize( * static_cast < const AxisAlignedBox * > ( val ) );
01039         return true;
01040     }
01041 
01042     else if ( key == "Depth" )
01043     {
01044         mMaxDepth = * static_cast < const int * > ( val );
01045         resize( mOctree->mBox );
01046         return true;
01047     }
01048 
01049     else if ( key == "ShowOctree" )
01050     {
01051         mShowBoxes = * static_cast < const bool * > ( val );
01052         return true;
01053     }
01054 
01055     else if ( key == "CullCamera" )
01056     {
01057         mCullCamera = * static_cast < const bool * > ( val );
01058         return true;
01059     }
01060 
01061     return SceneManager::setOption( key, val );
01062 
01063 
01064 }
01065 
01066 bool OctreeSceneManager::getOption( const String & key, void *val )
01067 {
01068     if ( key == "Size" )
01069     {
01070         AxisAlignedBox * b = static_cast < AxisAlignedBox * > ( val );
01071         b -> setExtents( mOctree->mBox.getMinimum(), mOctree->mBox.getMaximum() );
01072         return true;
01073     }
01074 
01075     else if ( key == "Depth" )
01076     {
01077         * static_cast < int * > ( val ) = mMaxDepth;
01078         return true;
01079     }
01080 
01081     else if ( key == "ShowOctree" )
01082     {
01083 
01084         * static_cast < bool * > ( val ) = mShowBoxes;
01085         return true;
01086     }
01087 
01088     else if ( key == "CullCamera" )
01089     {
01090         * static_cast < bool * > ( val ) = mCullCamera;
01091         return true;
01092     }
01093 
01094     return SceneManager::getOption( key, val );
01095 
01096 }
01097 
01098 void OctreeSceneManager::clearScene(void)
01099 {
01100     SceneManager::clearScene();
01101     init(mBox, mMaxDepth);
01102 
01103 }
01104 
01105 //---------------------------------------------------------------------
01106 AxisAlignedBoxSceneQuery*
01107 OctreeSceneManager::createAABBQuery(const AxisAlignedBox& box, unsigned long mask)
01108 {
01109     OctreeAxisAlignedBoxSceneQuery* q = new OctreeAxisAlignedBoxSceneQuery(this);
01110     q->setBox(box);
01111     q->setQueryMask(mask);
01112     return q;
01113 }
01114 //---------------------------------------------------------------------
01115 SphereSceneQuery*
01116 OctreeSceneManager::createSphereQuery(const Sphere& sphere, unsigned long mask)
01117 {
01118     OctreeSphereSceneQuery* q = new OctreeSphereSceneQuery(this);
01119     q->setSphere(sphere);
01120     q->setQueryMask(mask);
01121     return q;
01122 }
01123 //---------------------------------------------------------------------
01124 PlaneBoundedVolumeListSceneQuery*
01125 OctreeSceneManager::createPlaneBoundedVolumeQuery(const PlaneBoundedVolumeList& volumes,
01126         unsigned long mask)
01127 {
01128     OctreePlaneBoundedVolumeListSceneQuery* q = new OctreePlaneBoundedVolumeListSceneQuery(this);
01129     q->setVolumes(volumes);
01130     q->setQueryMask(mask);
01131     return q;
01132 }
01133 
01134 //---------------------------------------------------------------------
01135 RaySceneQuery*
01136 OctreeSceneManager::createRayQuery(const Ray& ray, unsigned long mask)
01137 {
01138     OctreeRaySceneQuery* q = new OctreeRaySceneQuery(this);
01139     q->setRay(ray);
01140     q->setQueryMask(mask);
01141     return q;
01142 }
01143 //---------------------------------------------------------------------
01144 IntersectionSceneQuery*
01145 OctreeSceneManager::createIntersectionQuery(unsigned long mask)
01146 {
01147 
01148     // Octree implementation performs WORSE for < 500 objects
01149     // TODO: optimise it so it's better in all cases
01150     //OctreeIntersectionSceneQuery* q = new OctreeIntersectionSceneQuery(this);
01151     DefaultIntersectionSceneQuery* q = new DefaultIntersectionSceneQuery(this);
01152     q->setQueryMask(mask);
01153     return q;
01154 }
01155 
01156 
01157 }

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:36 2004