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