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