source: trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctreeSceneManager.cpp @ 316

Revision 316, 31.9 KB checked in by mattausch, 19 years ago (diff)

queries are realized as templates

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4(Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25/***************************************************************************
26octreescenemanager.cpp  -  description
27-------------------
28begin                : Fri Sep 27 2002
29copyright            : (C) 2002 by Jon Anderson
30email                : janders@users.sf.net
31 
32Enhancements 2003 - 2004 (C) The OGRE Team
33 
34***************************************************************************/
35
36#include <OgreOctreeSceneManager.h>
37#include <OgreOctreeSceneQuery.h>
38#include <OgreOctreeNode.h>
39#include <OgreOctreeCamera.h>
40#include <OgreRenderSystem.h>
41
42
43extern "C"
44{
45    void findNodesInBox( Ogre::SceneManager *sm,
46                         const Ogre::AxisAlignedBox &box,
47                         std::list < Ogre::SceneNode * > &list,
48                         Ogre::SceneNode *exclude )
49    {
50        static_cast<Ogre::OctreeSceneManager*>( sm ) -> findNodesIn( box, list, exclude );
51    }
52    void findNodesInSphere( Ogre::SceneManager *sm,
53                            const Ogre::Sphere &sphere,
54                            std::list < Ogre::SceneNode * > &list,
55                            Ogre::SceneNode *exclude )
56    {
57        static_cast<Ogre::OctreeSceneManager*>( sm ) -> findNodesIn( sphere, list, exclude );
58    }
59}
60
61namespace Ogre
62{
63enum Intersection
64{
65    OUTSIDE=0,
66    INSIDE=1,
67    INTERSECT=2
68};
69int OctreeSceneManager::intersect_call = 0;
70
71Intersection intersect( const Ray &one, const AxisAlignedBox &two )
72{
73    OctreeSceneManager::intersect_call++;
74    // Null box?
75    if (two.isNull()) return OUTSIDE;
76
77    bool inside = true;
78    const Vector3* pCorners = two.getAllCorners();
79    Vector3 origin = one.getOrigin();
80    Vector3 dir = one.getDirection();
81
82    Vector3 maxT(-1, -1, -1);
83
84    int i = 0;
85    for(i=0; i<3; i++ )
86    {
87        if( origin[i] < pCorners[0][i] )
88        {
89            inside = false;
90            if( dir[i] > 0 )
91            {
92                maxT[i] = (pCorners[0][i] - origin[i])/ dir[i];
93            }
94        }
95        else if( origin[i] > pCorners[4][i] )
96        {
97            inside = false;
98            if( dir[i] < 0 )
99            {
100                maxT[i] = (pCorners[4][i] - origin[i]) / dir[i];
101            }
102        }
103    }
104
105    if( inside )
106    {
107        return INTERSECT;
108    }
109    int whichPlane = 0;
110    if( maxT[1] > maxT[whichPlane])
111        whichPlane = 1;
112    if( maxT[2] > maxT[whichPlane])
113        whichPlane = 2;
114
115    if( ((int)maxT[whichPlane]) & 0x80000000 )
116    {
117        return OUTSIDE;
118    }
119    for(i=0; i<3; i++ )
120    {
121        if( i!= whichPlane )
122        {
123            float f = origin[i] + maxT[whichPlane] * dir[i];
124            if ( f < (pCorners[0][i] - 0.00001f) ||
125                    f > (pCorners[4][i] +0.00001f ) )
126            {
127                return OUTSIDE;
128            }
129        }
130    }
131
132    return INTERSECT;
133
134}
135
136
137/** Checks how the second box intersects with the first.
138*/
139Intersection intersect( const PlaneBoundedVolume &one, const AxisAlignedBox &two )
140{
141    OctreeSceneManager::intersect_call++;
142    // Null box?
143    if (two.isNull()) return OUTSIDE;
144
145    // Get corners of the box
146    const Vector3* pCorners = two.getAllCorners();
147
148    // For each plane, see if all points are on the negative side
149    // If so, object is not visible.
150    // If one or more are, it's partial.
151    // If all aren't, full
152    int corners[ 8 ] = {0, 4, 3, 5, 2, 6, 1, 7};
153    bool all_inside = true;
154    PlaneList::const_iterator i, iend;
155    iend = one.planes.end();
156    for (i = one.planes.begin(); i != iend; ++i)
157    {
158        const Plane& plane = *i;
159        bool all_outside = true;
160
161        float distance = 0;
162
163        for ( int corner = 0; corner < 8; ++corner )
164        {
165            distance = plane.getDistance( pCorners[ corners[ corner ] ] );
166            all_outside = all_outside && ( distance < 0 );
167            all_inside = all_inside && ( distance >= 0 );
168
169            if ( !all_outside && !all_inside )
170                break;
171        }
172
173        if ( all_outside )
174            return OUTSIDE;
175    }
176
177    if ( all_inside )
178        return INSIDE;
179    else
180        return INTERSECT;
181
182}
183
184
185/** Checks how the second box intersects with the first.
186*/
187Intersection intersect( const AxisAlignedBox &one, const AxisAlignedBox &two )
188{
189    OctreeSceneManager::intersect_call++;
190    // Null box?
191    if (one.isNull() || two.isNull()) return OUTSIDE;
192
193    const Vector3 * outside = one.getAllCorners();
194    const Vector3 *inside = two.getAllCorners();
195
196    if ( inside[ 4 ].x < outside[ 0 ].x ||
197            inside[ 4 ].y < outside[ 0 ].y ||
198            inside[ 4 ].z < outside[ 0 ].z ||
199            inside[ 0 ].x > outside[ 4 ].x ||
200            inside[ 0 ].y > outside[ 4 ].y ||
201            inside[ 0 ].z > outside[ 4 ].z )
202    {
203        return OUTSIDE;
204    }
205
206    bool full = ( inside[ 0 ].x > outside[ 0 ].x &&
207                  inside[ 0 ].y > outside[ 0 ].y &&
208                  inside[ 0 ].z > outside[ 0 ].z &&
209                  inside[ 4 ].x < outside[ 4 ].x &&
210                  inside[ 4 ].y < outside[ 4 ].y &&
211                  inside[ 4 ].z < outside[ 4 ].z );
212
213    if ( full )
214        return INSIDE;
215    else
216        return INTERSECT;
217
218}
219
220/** Checks how the box intersects with the sphere.
221*/
222Intersection intersect( const Sphere &one, const AxisAlignedBox &two )
223{
224    OctreeSceneManager::intersect_call++;
225    // Null box?
226    if (two.isNull()) return OUTSIDE;
227
228    float sradius = one.getRadius();
229
230    sradius *= sradius;
231
232    Vector3 scenter = one.getCenter();
233
234    const Vector3 *corners = two.getAllCorners();
235
236    float s, d = 0;
237
238    Vector3 mndistance = ( corners[ 0 ] - scenter );
239    Vector3 mxdistance = ( corners[ 4 ] - scenter );
240
241    if ( mndistance.squaredLength() < sradius &&
242            mxdistance.squaredLength() < sradius )
243    {
244        return INSIDE;
245    }
246
247    //find the square of the distance
248    //from the sphere to the box
249    for ( int i = 0 ; i < 3 ; i++ )
250    {
251        if ( scenter[ i ] < corners[ 0 ][ i ] )
252        {
253            s = scenter[ i ] - corners[ 0 ][ i ];
254            d += s * s;
255        }
256
257        else if ( scenter[ i ] > corners[ 4 ][ i ] )
258        {
259            s = scenter[ i ] - corners[ 4 ][ i ];
260            d += s * s;
261        }
262
263    }
264
265    bool partial = ( d <= sradius );
266
267    if ( !partial )
268    {
269        return OUTSIDE;
270    }
271
272    else
273    {
274        return INTERSECT;
275    }
276
277
278}
279
280unsigned long white = 0xFFFFFFFF;
281
282unsigned short OctreeSceneManager::mIndexes[ 24 ] = {0, 1, 1, 2, 2, 3, 3, 0,       //back
283        0, 6, 6, 5, 5, 1,             //left
284        3, 7, 7, 4, 4, 2,             //right
285        6, 7, 5, 4 };          //front
286unsigned long OctreeSceneManager::mColors[ 8 ] = {white, white, white, white, white, white, white, white };
287
288
289OctreeSceneManager::OctreeSceneManager( ) : SceneManager()
290{
291    AxisAlignedBox b( -10000, -10000, -10000, 10000, 10000, 10000 );
292    int depth = 8;
293    mOctree = 0;
294    init( b, depth );
295}
296
297OctreeSceneManager::OctreeSceneManager( AxisAlignedBox &box, int max_depth ) : SceneManager()
298{
299    mOctree = 0;
300    init( box, max_depth );
301}
302
303void OctreeSceneManager::init( AxisAlignedBox &box, int depth )
304{
305    delete mSceneRoot; //get rid of old root.
306
307    // -- Changes by Steve
308    // Don't do it this way, it will add it to the mSceneNodes which we don't want
309    //mSceneRoot = createSceneNode( "SceneRoot" );
310    mSceneRoot = new OctreeNode( this, "SceneRoot" );
311        mSceneRoot->_notifyRootNode();
312    // -- End changes by Steve
313
314    if ( mOctree != 0 )
315        delete mOctree;
316
317    mOctree = new Octree( 0 );
318
319#ifdef GTP_VISIBILITY_MODIFIED_OGRE
320        mNumOctants = 1; // initialise number of octants in tree
321#endif // GTP_VISIBILITY_MODIFIED_OGRE
322
323    mMaxDepth = depth;
324    mBox = box;
325
326    mOctree -> mBox = box;
327
328    Vector3 min = box.getMinimum();
329
330    Vector3 max = box.getMaximum();
331
332    mOctree -> mHalfSize = ( max - min ) / 2;
333
334
335    mShowBoxes = false;
336
337    mCullCamera = false;
338
339    mNumObjects = 0;
340
341    Vector3 v( 1.5, 1.5, 1.5 );
342
343    mScaleFactor.setScale( v );
344
345
346
347    // setDisplaySceneNodes( true );
348    // setShowBoxes( true );
349
350    //
351    //setUseCullCamera( true );
352    //mSceneRoot isn't put into the octree since it has no volume.
353
354}
355
356OctreeSceneManager::~OctreeSceneManager()
357{
358    // -- Changed by Steve
359    // Don't do this here, SceneManager will do it
360    /*
361    if( mSceneRoot )
362    delete mSceneRoot;
363    */
364    // --End Changes by Steve
365
366    if ( mOctree )
367        delete mOctree;
368}
369
370Camera * OctreeSceneManager::createCamera( const String &name )
371{
372    Camera * c = new OctreeCamera( name, this );
373    mCameras.insert( CameraList::value_type( name, c ) );
374    return c;
375}
376
377void OctreeSceneManager::destroySceneNode( const String &name )
378{
379    OctreeNode * on = static_cast < OctreeNode* > ( getSceneNode( name ) );
380
381    if ( on != 0 )
382        _removeOctreeNode( on );
383
384    SceneManager::destroySceneNode( name );
385}
386
387bool OctreeSceneManager::getOptionValues( const String & key, StringVector  &refValueList )
388{
389    return SceneManager::getOptionValues( key, refValueList );
390}
391
392bool OctreeSceneManager::getOptionKeys( StringVector & refKeys )
393{
394    SceneManager::getOptionKeys( refKeys );
395    refKeys.push_back( "CullCamera" );
396    refKeys.push_back( "Size" );
397    refKeys.push_back( "ShowOctree" );
398    refKeys.push_back( "Depth" );
399
400    return true;
401}
402
403
404void OctreeSceneManager::_updateOctreeNode( OctreeNode * onode )
405{
406    AxisAlignedBox box = onode -> _getWorldAABB();
407
408    if ( box.isNull() )
409        return ;
410
411
412    if ( onode -> getOctant() == 0 )
413    {
414        //if outside the octree, force into the root node.
415        if ( ! onode -> _isIn( mOctree -> mBox ) )
416            mOctree->_addNode( onode );
417        else
418            _addOctreeNode( onode, mOctree );
419        return ;
420    }
421
422    if ( ! onode -> _isIn( onode -> getOctant() -> mBox ) )
423    {
424        _removeOctreeNode( onode );
425
426        //if outside the octree, force into the root node.
427        if ( ! onode -> _isIn( mOctree -> mBox ) )
428            mOctree->_addNode( onode );
429        else
430            _addOctreeNode( onode, mOctree );
431    }
432#ifdef GTP_VISIBILITY_MODIFIED_OGRE
433        else // still update because bounding box may be different
434        {
435                onode -> getOctant() -> _updateBounds();
436        }
437#endif // GTP_VISIBILITY_MODIFIED_OGRE
438}
439
440/** Only removes the node from the octree.  It leaves the octree, even if it's empty.
441*/
442void OctreeSceneManager::_removeOctreeNode( OctreeNode * n )
443{
444    Octree * oct = n -> getOctant();
445
446    if ( oct )
447    {
448        oct -> _removeNode( n );
449    }
450
451    n->setOctant(0);
452}
453
454
455void OctreeSceneManager::_addOctreeNode( OctreeNode * n, Octree *octant, int depth )
456{
457
458    AxisAlignedBox bx = n -> _getWorldAABB();
459
460
461    //if the octree is twice as big as the scene node,
462    //we will add it to a child.
463    if ( ( depth < mMaxDepth ) && octant -> _isTwiceSize( bx ) )
464    {
465        int x, y, z;
466        octant -> _getChildIndexes( bx, &x, &y, &z );
467
468        if ( octant -> mChildren[ x ][ y ][ z ] == 0 )
469        {
470            octant -> mChildren[ x ][ y ][ z ] = new Octree( octant );
471#ifdef GTP_VISIBILITY_MODIFIED_OGRE
472                        ++ mNumOctants;
473#endif // GTP_VISIBILITY_MODIFIED_OGRE
474
475            const Vector3 *corners = octant -> mBox.getAllCorners();
476            Vector3 min, max;
477
478            if ( x == 0 )
479            {
480                min.x = corners[ 0 ].x;
481                max.x = ( corners[ 0 ].x + corners[ 4 ].x ) / 2;
482            }
483
484            else
485            {
486                min.x = ( corners[ 0 ].x + corners[ 4 ].x ) / 2;
487                max.x = corners[ 4 ].x;
488            }
489
490            if ( y == 0 )
491            {
492                min.y = corners[ 0 ].y;
493                max.y = ( corners[ 0 ].y + corners[ 4 ].y ) / 2;
494            }
495
496            else
497            {
498                min.y = ( corners[ 0 ].y + corners[ 4 ].y ) / 2;
499                max.y = corners[ 4 ].y;
500            }
501
502            if ( z == 0 )
503            {
504                min.z = corners[ 0 ].z;
505                max.z = ( corners[ 0 ].z + corners[ 4 ].z ) / 2;
506            }
507
508            else
509            {
510                min.z = ( corners[ 0 ].z + corners[ 4 ].z ) / 2;
511                max.z = corners[ 4 ].z;
512            }
513
514            octant -> mChildren[ x ][ y ][ z ] -> mBox.setExtents( min, max );
515            octant -> mChildren[ x ][ y ][ z ] -> mHalfSize = ( max - min ) / 2;
516        }
517
518        _addOctreeNode( n, octant -> mChildren[ x ][ y ][ z ], ++depth );
519
520    }
521
522    else
523    {
524        octant -> _addNode( n );
525    }
526}
527
528
529SceneNode * OctreeSceneManager::createSceneNode( void )
530{
531    OctreeNode * on = new OctreeNode( this );
532    mSceneNodes[ on->getName() ] = on;
533    return on;
534}
535
536SceneNode * OctreeSceneManager::createSceneNode( const String &name )
537{
538    OctreeNode * on = new OctreeNode( this, name );
539    mSceneNodes[ on->getName() ] = on;
540    return on;
541}
542
543void OctreeSceneManager::_updateSceneGraph( Camera * cam )
544{
545    SceneManager::_updateSceneGraph( cam );
546}
547
548void OctreeSceneManager::_alertVisibleObjects( void )
549{
550    NodeList::iterator it = mVisible.begin();
551
552    while ( it != mVisible.end() )
553    {
554        OctreeNode * node = *it;
555
556        ++it;
557    }
558}
559
560void OctreeSceneManager::_findVisibleObjects( Camera * cam, bool onlyShadowCasters )
561{
562
563    getRenderQueue()->clear();
564    mBoxes.clear();
565    mVisible.clear();
566
567    if ( mCullCamera )
568    {
569        Camera * c = getCamera( "CullCamera" );
570
571        if ( c != 0 )
572            cam = getCamera( "CullCamera" );
573    }
574
575    mNumObjects = 0;
576
577    //walk the octree, adding all visible Octreenodes nodes to the render queue.
578    walkOctree( static_cast < OctreeCamera * > ( cam ), getRenderQueue(), mOctree, false, onlyShadowCasters );
579
580
581    // Show the octree boxes & cull camera if required
582    if ( mShowBoxes || mCullCamera )
583    {
584
585
586
587        if ( mShowBoxes )
588        {
589            for ( BoxList::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it )
590            {
591                getRenderQueue()->addRenderable(*it);
592            }
593        }
594
595        if ( mCullCamera )
596        {
597            OctreeCamera * c = static_cast<OctreeCamera*>(getCamera( "CullCamera" ));
598
599            if ( c != 0 )
600            {
601                getRenderQueue()->addRenderable(c);
602            }
603        }
604
605    }
606
607
608
609}
610
611void OctreeSceneManager::walkOctree( OctreeCamera *camera, RenderQueue *queue,
612                                     Octree *octant, bool foundvisible, bool onlyShadowCasters )
613{
614
615    //return immediately if nothing is in the node.
616    if ( octant -> numNodes() == 0 )
617        return ;
618
619    OctreeCamera::Visibility v = OctreeCamera::NONE;
620
621    if ( foundvisible )
622    {
623        v = OctreeCamera::FULL;
624    }
625
626    else if ( octant == mOctree )
627    {
628        v = OctreeCamera::PARTIAL;
629    }
630
631    else
632    {
633        AxisAlignedBox box;
634        octant -> _getCullBounds( &box );
635        v = camera -> getVisibility( box );
636    }
637
638
639    // if the octant is visible, or if it's the root node...
640    if ( v != OctreeCamera::NONE )
641    {
642
643        //Add stuff to be rendered;
644        NodeList::iterator it = octant -> mNodes.begin();
645
646        if ( mShowBoxes )
647        {
648            mBoxes.push_back( octant->getWireBoundingBox() );
649        }
650
651        bool vis = true;
652
653        while ( it != octant -> mNodes.end() )
654        {
655            OctreeNode * sn = *it;
656
657            // if this octree is partially visible, manually cull all
658            // scene nodes attached directly to this level.
659
660            if ( v == OctreeCamera::PARTIAL )
661                vis = camera -> isVisible( sn -> _getWorldAABB() );
662
663            if ( vis )
664            {
665
666                mNumObjects++;
667                sn -> _addToRenderQueue(camera, queue, onlyShadowCasters );
668
669                mVisible.push_back( sn );
670
671                if ( mDisplayNodes )
672                    queue -> addRenderable( sn );
673
674                // check if the scene manager or this node wants the bounding box shown.
675                if (sn->getShowBoundingBox() || mShowBoundingBoxes)
676                    sn->_addBoundingBoxToQueue(queue);
677            }
678
679            ++it;
680        }
681
682        if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
683            walkOctree( camera, queue, octant -> mChildren[ 0 ][ 0 ][ 0 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
684
685        if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
686            walkOctree( camera, queue, octant -> mChildren[ 1 ][ 0 ][ 0 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
687
688        if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
689            walkOctree( camera, queue, octant -> mChildren[ 0 ][ 1 ][ 0 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
690
691        if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
692            walkOctree( camera, queue, octant -> mChildren[ 1 ][ 1 ][ 0 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
693
694        if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
695            walkOctree( camera, queue, octant -> mChildren[ 0 ][ 0 ][ 1 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
696
697        if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
698            walkOctree( camera, queue, octant -> mChildren[ 1 ][ 0 ][ 1 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
699
700        if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
701            walkOctree( camera, queue, octant -> mChildren[ 0 ][ 1 ][ 1 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
702
703        if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
704            walkOctree( camera, queue, octant -> mChildren[ 1 ][ 1 ][ 1 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
705
706    }
707
708}
709
710// --- non template versions
711void _findNodes( const AxisAlignedBox &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
712{
713
714        if ( !full )
715        {
716                AxisAlignedBox obox;
717                octant -> _getCullBounds( &obox );
718
719                Intersection isect = intersect( t, obox );
720
721                if ( isect == OUTSIDE )
722                        return ;
723
724                full = ( isect == INSIDE );
725        }
726
727
728        NodeList::iterator it = octant -> mNodes.begin();
729
730        while ( it != octant -> mNodes.end() )
731        {
732                OctreeNode * on = ( *it );
733
734                if ( on != exclude )
735                {
736                        if ( full )
737                        {
738                                list.push_back( on );
739                        }
740
741                        else
742                        {
743                                Intersection nsect = intersect( t, on -> _getWorldAABB() );
744
745                                if ( nsect != OUTSIDE )
746                                {
747                                        list.push_back( on );
748                                }
749                        }
750
751                }
752
753                ++it;
754        }
755
756
757
758        if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
759                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 0 ] );
760
761        if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
762                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 0 ] );
763
764        if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
765                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 0 ] );
766
767        if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
768                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 0 ] );
769
770        if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
771                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 1 ] );
772
773        if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
774                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 1 ] );
775
776        if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
777                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 1 ] );
778
779        if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
780                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 1 ] );
781
782}
783
784void _findNodes( const Sphere &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
785{
786
787        if ( !full )
788        {
789                AxisAlignedBox obox;
790                octant -> _getCullBounds( &obox );
791
792                Intersection isect = intersect( t, obox );
793
794                if ( isect == OUTSIDE )
795                        return ;
796
797                full = ( isect == INSIDE );
798        }
799
800
801        NodeList::iterator it = octant -> mNodes.begin();
802
803        while ( it != octant -> mNodes.end() )
804        {
805                OctreeNode * on = ( *it );
806
807                if ( on != exclude )
808                {
809                        if ( full )
810                        {
811                                list.push_back( on );
812                        }
813
814                        else
815                        {
816                                Intersection nsect = intersect( t, on -> _getWorldAABB() );
817
818                                if ( nsect != OUTSIDE )
819                                {
820                                        list.push_back( on );
821                                }
822                        }
823
824                }
825
826                ++it;
827        }
828
829
830
831        if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
832                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 0 ] );
833
834        if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
835                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 0 ] );
836
837        if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
838                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 0 ] );
839
840        if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
841                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 0 ] );
842
843        if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
844                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 1 ] );
845
846        if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
847                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 1 ] );
848
849        if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
850                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 1 ] );
851
852        if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
853                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 1 ] );
854
855}
856
857
858void _findNodes( const PlaneBoundedVolume &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
859{
860
861        if ( !full )
862        {
863                AxisAlignedBox obox;
864                octant -> _getCullBounds( &obox );
865
866                Intersection isect = intersect( t, obox );
867
868                if ( isect == OUTSIDE )
869                        return ;
870
871                full = ( isect == INSIDE );
872        }
873
874
875        NodeList::iterator it = octant -> mNodes.begin();
876
877        while ( it != octant -> mNodes.end() )
878        {
879                OctreeNode * on = ( *it );
880
881                if ( on != exclude )
882                {
883                        if ( full )
884                        {
885                                list.push_back( on );
886                        }
887
888                        else
889                        {
890                                Intersection nsect = intersect( t, on -> _getWorldAABB() );
891
892                                if ( nsect != OUTSIDE )
893                                {
894                                        list.push_back( on );
895                                }
896                        }
897
898                }
899
900                ++it;
901        }
902
903
904
905        if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
906                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 0 ] );
907
908        if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
909                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 0 ] );
910
911        if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
912                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 0 ] );
913
914        if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
915                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 0 ] );
916
917        if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
918                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 1 ] );
919
920        if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
921                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 1 ] );
922
923        if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
924                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 1 ] );
925
926        if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
927                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 1 ] );
928
929}
930
931void _findNodes( const Ray &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
932{
933
934        if ( !full )
935        {
936                AxisAlignedBox obox;
937                octant -> _getCullBounds( &obox );
938
939                Intersection isect = intersect( t, obox );
940
941                if ( isect == OUTSIDE )
942                        return ;
943
944                full = ( isect == INSIDE );
945        }
946
947
948        NodeList::iterator it = octant -> mNodes.begin();
949
950        while ( it != octant -> mNodes.end() )
951        {
952                OctreeNode * on = ( *it );
953
954                if ( on != exclude )
955                {
956                        if ( full )
957                        {
958                                list.push_back( on );
959                        }
960
961                        else
962                        {
963                                Intersection nsect = intersect( t, on -> _getWorldAABB() );
964
965                                if ( nsect != OUTSIDE )
966                                {
967                                        list.push_back( on );
968                                }
969                        }
970
971                }
972
973                ++it;
974        }
975
976
977
978        if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
979                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 0 ] );
980
981        if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
982                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 0 ] );
983
984        if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
985                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 0 ] );
986
987        if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
988                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 0 ] );
989
990        if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
991                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 1 ] );
992
993        if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
994                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 1 ] );
995
996        if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
997                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 1 ] );
998
999        if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
1000                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 1 ] );
1001
1002}
1003
1004void OctreeSceneManager::findNodesIn( const AxisAlignedBox &box, std::list < SceneNode * > &list, SceneNode *exclude )
1005{
1006    _findNodes( box, list, exclude, false, mOctree );
1007}
1008
1009void OctreeSceneManager::findNodesIn( const Sphere &sphere, std::list < SceneNode * > &list, SceneNode *exclude )
1010{
1011    _findNodes( sphere, list, exclude, false, mOctree );
1012}
1013
1014void OctreeSceneManager::findNodesIn( const PlaneBoundedVolume &volume, std::list < SceneNode * > &list, SceneNode *exclude )
1015{
1016    _findNodes( volume, list, exclude, false, mOctree );
1017}
1018
1019void OctreeSceneManager::findNodesIn( const Ray &r, std::list < SceneNode * > &list, SceneNode *exclude )
1020{
1021    _findNodes( r, list, exclude, false, mOctree );
1022}
1023
1024void OctreeSceneManager::resize( const AxisAlignedBox &box )
1025{
1026    std::list < SceneNode * > nodes;
1027    std::list < SceneNode * > ::iterator it;
1028
1029    _findNodes( mOctree->mBox, nodes, 0, true, mOctree );
1030
1031    delete mOctree;
1032
1033    mOctree = new Octree( 0 );
1034
1035#ifdef GTP_VISIBILITY_MODIFIED_OGRE
1036        mNumOctreeNodes = 1;
1037#endif // GTP_VISIBILITY_MODIFIED_OGRE
1038
1039    mOctree->mBox = box;
1040
1041    it = nodes.begin();
1042
1043    while ( it != nodes.end() )
1044    {
1045        OctreeNode * on = static_cast < OctreeNode * > ( *it );
1046        on -> setOctant( 0 );
1047        _updateOctreeNode( on );
1048        ++it;
1049    }
1050
1051}
1052
1053bool OctreeSceneManager::setOption( const String & key, const void * val )
1054{
1055    if ( key == "Size" )
1056    {
1057        resize( * static_cast < const AxisAlignedBox * > ( val ) );
1058        return true;
1059    }
1060
1061    else if ( key == "Depth" )
1062    {
1063        mMaxDepth = * static_cast < const int * > ( val );
1064        resize( mOctree->mBox );
1065        return true;
1066    }
1067
1068    else if ( key == "ShowOctree" )
1069    {
1070        mShowBoxes = * static_cast < const bool * > ( val );
1071        return true;
1072    }
1073
1074    else if ( key == "CullCamera" )
1075    {
1076        mCullCamera = * static_cast < const bool * > ( val );
1077        return true;
1078    }
1079
1080    return SceneManager::setOption( key, val );
1081
1082
1083}
1084
1085bool OctreeSceneManager::getOption( const String & key, void *val )
1086{
1087    if ( key == "Size" )
1088    {
1089        AxisAlignedBox * b = static_cast < AxisAlignedBox * > ( val );
1090        b -> setExtents( mOctree->mBox.getMinimum(), mOctree->mBox.getMaximum() );
1091        return true;
1092    }
1093
1094    else if ( key == "Depth" )
1095    {
1096        * static_cast < int * > ( val ) = mMaxDepth;
1097        return true;
1098    }
1099
1100    else if ( key == "ShowOctree" )
1101    {
1102
1103        * static_cast < bool * > ( val ) = mShowBoxes;
1104        return true;
1105    }
1106
1107    else if ( key == "CullCamera" )
1108    {
1109        * static_cast < bool * > ( val ) = mCullCamera;
1110        return true;
1111    }
1112
1113    return SceneManager::getOption( key, val );
1114
1115}
1116
1117void OctreeSceneManager::clearScene(void)
1118{
1119    SceneManager::clearScene();
1120    init(mBox, mMaxDepth);
1121
1122}
1123
1124//---------------------------------------------------------------------
1125AxisAlignedBoxSceneQuery*
1126OctreeSceneManager::createAABBQuery(const AxisAlignedBox& box, unsigned long mask)
1127{
1128    OctreeAxisAlignedBoxSceneQuery* q = new OctreeAxisAlignedBoxSceneQuery(this);
1129    q->setBox(box);
1130    q->setQueryMask(mask);
1131    return q;
1132}
1133//---------------------------------------------------------------------
1134SphereSceneQuery*
1135OctreeSceneManager::createSphereQuery(const Sphere& sphere, unsigned long mask)
1136{
1137    OctreeSphereSceneQuery* q = new OctreeSphereSceneQuery(this);
1138    q->setSphere(sphere);
1139    q->setQueryMask(mask);
1140    return q;
1141}
1142//---------------------------------------------------------------------
1143PlaneBoundedVolumeListSceneQuery*
1144OctreeSceneManager::createPlaneBoundedVolumeQuery(const PlaneBoundedVolumeList& volumes,
1145        unsigned long mask)
1146{
1147    OctreePlaneBoundedVolumeListSceneQuery* q = new OctreePlaneBoundedVolumeListSceneQuery(this);
1148    q->setVolumes(volumes);
1149    q->setQueryMask(mask);
1150    return q;
1151}
1152
1153//---------------------------------------------------------------------
1154RaySceneQuery*
1155OctreeSceneManager::createRayQuery(const Ray& ray, unsigned long mask)
1156{
1157    OctreeRaySceneQuery* q = new OctreeRaySceneQuery(this);
1158    q->setRay(ray);
1159    q->setQueryMask(mask);
1160    return q;
1161}
1162//---------------------------------------------------------------------
1163IntersectionSceneQuery*
1164OctreeSceneManager::createIntersectionQuery(unsigned long mask)
1165{
1166
1167    // Octree implementation performs WORSE for < 500 objects
1168    // TODO: optimise it so it's better in all cases
1169    //OctreeIntersectionSceneQuery* q = new OctreeIntersectionSceneQuery(this);
1170    DefaultIntersectionSceneQuery* q = new DefaultIntersectionSceneQuery(this);
1171    q->setQueryMask(mask);
1172    return q;
1173}
1174#ifdef GTP_VISIBILITY_MODIFIED_OGRE
1175//-----------------------------------------------------------------------       
1176BoxList *OctreeSceneManager::getBoxes()
1177{
1178        return &mBoxes;
1179}
1180//-----------------------------------------------------------------------
1181void OctreeSceneManager::_renderOctant(Camera *cam, Octree *octant, bool onlyShadowCasters,
1182                                                                           const int leavePassesInQueue)
1183{
1184        // delete previously rendered objects from the render queue
1185        _deleteRenderedQueueGroups(leavePassesInQueue);
1186
1187        //Add stuff to be rendered;
1188    NodeList::iterator it = octant->mNodes.begin();
1189         
1190    while(it != octant->mNodes.end())
1191    {
1192                OctreeNode *sn = *it;
1193
1194        ++mNumObjects;
1195
1196                // check bounding box visibility of scene nodes
1197                if (cam->isVisible(sn->_getWorldAABB()))
1198                {
1199                        sn->_addToRenderQueue(cam, getRenderQueue(), onlyShadowCasters);
1200                        mVisible.push_back(sn);
1201
1202                        if (mDisplayNodes)
1203                        {
1204                                getRenderQueue()->addRenderable(sn);
1205                        }
1206
1207                        // check if the scene manager or this node wants the bounding box shown.
1208                        if (sn->getShowBoundingBox() || mShowBoundingBoxes)
1209                        {
1210                                sn->_addBoundingBoxToQueue(getRenderQueue());
1211                        }
1212                }
1213        ++it;
1214        }
1215
1216        if (mShowBoxes)
1217        {
1218                octant->getWireBoundingBox()->setMaterial("BaseWhiteNoLighting");
1219
1220                getRenderQueue()->addRenderable(octant->getWireBoundingBox());
1221                mBoxes.push_back(octant->getWireBoundingBox());
1222        }
1223
1224        //-- the actual rendering
1225        SceneManager::_renderVisibleObjects();
1226}
1227#endif // GTP_VISIBILITY_MODIFIED_OGRE
1228}
Note: See TracBrowser for help on using the repository browser.