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

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

fixed bug with tight octree boxes
added more flexible renderqueue (can delete per flag)
reordered functions in visibility terrain scene manager

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#ifdef GTP_VISIBILITY_MODIFIED_OGRE
319        mNumOctreeNodes = 1;
320#endif // GTP_VISIBILITY_MODIFIED_OGRE
321    mMaxDepth = depth;
322    mBox = box;
323
324    mOctree -> mBox = box;
325
326    Vector3 min = box.getMinimum();
327
328    Vector3 max = box.getMaximum();
329
330    mOctree -> mHalfSize = ( max - min ) / 2;
331
332
333    mShowBoxes = false;
334
335    mCullCamera = false;
336
337    mNumObjects = 0;
338
339    Vector3 v( 1.5, 1.5, 1.5 );
340
341    mScaleFactor.setScale( v );
342
343
344
345    // setDisplaySceneNodes( true );
346    // setShowBoxes( true );
347
348    //
349    //setUseCullCamera( true );
350    //mSceneRoot isn't put into the octree since it has no volume.
351
352}
353
354OctreeSceneManager::~OctreeSceneManager()
355{
356    // -- Changed by Steve
357    // Don't do this here, SceneManager will do it
358    /*
359    if( mSceneRoot )
360    delete mSceneRoot;
361    */
362    // --End Changes by Steve
363
364    if ( mOctree )
365        delete mOctree;
366}
367
368Camera * OctreeSceneManager::createCamera( const String &name )
369{
370    Camera * c = new OctreeCamera( name, this );
371    mCameras.insert( CameraList::value_type( name, c ) );
372    return c;
373}
374
375void OctreeSceneManager::destroySceneNode( const String &name )
376{
377    OctreeNode * on = static_cast < OctreeNode* > ( getSceneNode( name ) );
378
379    if ( on != 0 )
380        _removeOctreeNode( on );
381
382    SceneManager::destroySceneNode( name );
383}
384
385bool OctreeSceneManager::getOptionValues( const String & key, StringVector  &refValueList )
386{
387    return SceneManager::getOptionValues( key, refValueList );
388}
389
390bool OctreeSceneManager::getOptionKeys( StringVector & refKeys )
391{
392    SceneManager::getOptionKeys( refKeys );
393    refKeys.push_back( "CullCamera" );
394    refKeys.push_back( "Size" );
395    refKeys.push_back( "ShowOctree" );
396    refKeys.push_back( "Depth" );
397
398    return true;
399}
400
401
402void OctreeSceneManager::_updateOctreeNode( OctreeNode * onode )
403{
404    AxisAlignedBox box = onode -> _getWorldAABB();
405
406    if ( box.isNull() )
407        return ;
408
409
410    if ( onode -> getOctant() == 0 )
411    {
412        //if outside the octree, force into the root node.
413        if ( ! onode -> _isIn( mOctree -> mBox ) )
414            mOctree->_addNode( onode );
415        else
416            _addOctreeNode( onode, mOctree );
417        return ;
418    }
419
420    if ( ! onode -> _isIn( onode -> getOctant() -> mBox ) )
421    {
422        _removeOctreeNode( onode );
423
424        //if outside the octree, force into the root node.
425        if ( ! onode -> _isIn( mOctree -> mBox ) )
426            mOctree->_addNode( onode );
427        else
428            _addOctreeNode( onode, mOctree );
429    }
430#ifdef GTP_VISIBILITY_MODIFIED_OGRE
431        else // still update because bounding box may be different
432        {
433                onode -> getOctant() -> _updateBounds();
434        }
435#endif // GTP_VISIBILITY_MODIFIED_OGRE
436}
437
438/** Only removes the node from the octree.  It leaves the octree, even if it's empty.
439*/
440void OctreeSceneManager::_removeOctreeNode( OctreeNode * n )
441{
442    Octree * oct = n -> getOctant();
443
444    if ( oct )
445    {
446        oct -> _removeNode( n );
447    }
448
449    n->setOctant(0);
450}
451
452
453void OctreeSceneManager::_addOctreeNode( OctreeNode * n, Octree *octant, int depth )
454{
455
456    AxisAlignedBox bx = n -> _getWorldAABB();
457
458
459    //if the octree is twice as big as the scene node,
460    //we will add it to a child.
461    if ( ( depth < mMaxDepth ) && octant -> _isTwiceSize( bx ) )
462    {
463        int x, y, z;
464        octant -> _getChildIndexes( bx, &x, &y, &z );
465
466        if ( octant -> mChildren[ x ][ y ][ z ] == 0 )
467        {
468            octant -> mChildren[ x ][ y ][ z ] = new Octree( octant );
469#ifdef GTP_VISIBILITY_MODIFIED_OGRE
470        mNumOctreeNodes ++;
471#endif // GTP_VISIBILITY_MODIFIED_OGRE
472
473            const Vector3 *corners = octant -> mBox.getAllCorners();
474            Vector3 min, max;
475
476            if ( x == 0 )
477            {
478                min.x = corners[ 0 ].x;
479                max.x = ( corners[ 0 ].x + corners[ 4 ].x ) / 2;
480            }
481
482            else
483            {
484                min.x = ( corners[ 0 ].x + corners[ 4 ].x ) / 2;
485                max.x = corners[ 4 ].x;
486            }
487
488            if ( y == 0 )
489            {
490                min.y = corners[ 0 ].y;
491                max.y = ( corners[ 0 ].y + corners[ 4 ].y ) / 2;
492            }
493
494            else
495            {
496                min.y = ( corners[ 0 ].y + corners[ 4 ].y ) / 2;
497                max.y = corners[ 4 ].y;
498            }
499
500            if ( z == 0 )
501            {
502                min.z = corners[ 0 ].z;
503                max.z = ( corners[ 0 ].z + corners[ 4 ].z ) / 2;
504            }
505
506            else
507            {
508                min.z = ( corners[ 0 ].z + corners[ 4 ].z ) / 2;
509                max.z = corners[ 4 ].z;
510            }
511
512            octant -> mChildren[ x ][ y ][ z ] -> mBox.setExtents( min, max );
513            octant -> mChildren[ x ][ y ][ z ] -> mHalfSize = ( max - min ) / 2;
514        }
515
516        _addOctreeNode( n, octant -> mChildren[ x ][ y ][ z ], ++depth );
517
518    }
519
520    else
521    {
522        octant -> _addNode( n );
523    }
524}
525
526
527SceneNode * OctreeSceneManager::createSceneNode( void )
528{
529    OctreeNode * on = new OctreeNode( this );
530    mSceneNodes[ on->getName() ] = on;
531    return on;
532}
533
534SceneNode * OctreeSceneManager::createSceneNode( const String &name )
535{
536    OctreeNode * on = new OctreeNode( this, name );
537    mSceneNodes[ on->getName() ] = on;
538    return on;
539}
540
541void OctreeSceneManager::_updateSceneGraph( Camera * cam )
542{
543    SceneManager::_updateSceneGraph( cam );
544}
545
546void OctreeSceneManager::_alertVisibleObjects( void )
547{
548    NodeList::iterator it = mVisible.begin();
549
550    while ( it != mVisible.end() )
551    {
552        OctreeNode * node = *it;
553
554        ++it;
555    }
556}
557
558void OctreeSceneManager::_findVisibleObjects( Camera * cam, bool onlyShadowCasters )
559{
560
561    getRenderQueue()->clear();
562    mBoxes.clear();
563    mVisible.clear();
564
565    if ( mCullCamera )
566    {
567        Camera * c = getCamera( "CullCamera" );
568
569        if ( c != 0 )
570            cam = getCamera( "CullCamera" );
571    }
572
573    mNumObjects = 0;
574
575    //walk the octree, adding all visible Octreenodes nodes to the render queue.
576    walkOctree( static_cast < OctreeCamera * > ( cam ), getRenderQueue(), mOctree, false, onlyShadowCasters );
577
578
579    // Show the octree boxes & cull camera if required
580    if ( mShowBoxes || mCullCamera )
581    {
582
583
584
585        if ( mShowBoxes )
586        {
587            for ( BoxList::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it )
588            {
589                getRenderQueue()->addRenderable(*it);
590            }
591        }
592
593        if ( mCullCamera )
594        {
595            OctreeCamera * c = static_cast<OctreeCamera*>(getCamera( "CullCamera" ));
596
597            if ( c != 0 )
598            {
599                getRenderQueue()->addRenderable(c);
600            }
601        }
602
603    }
604
605
606
607}
608
609void OctreeSceneManager::walkOctree( OctreeCamera *camera, RenderQueue *queue,
610                                     Octree *octant, bool foundvisible, bool onlyShadowCasters )
611{
612
613    //return immediately if nothing is in the node.
614    if ( octant -> numNodes() == 0 )
615        return ;
616
617    OctreeCamera::Visibility v = OctreeCamera::NONE;
618
619    if ( foundvisible )
620    {
621        v = OctreeCamera::FULL;
622    }
623
624    else if ( octant == mOctree )
625    {
626        v = OctreeCamera::PARTIAL;
627    }
628
629    else
630    {
631        AxisAlignedBox box;
632        octant -> _getCullBounds( &box );
633        v = camera -> getVisibility( box );
634    }
635
636
637    // if the octant is visible, or if it's the root node...
638    if ( v != OctreeCamera::NONE )
639    {
640
641        //Add stuff to be rendered;
642        NodeList::iterator it = octant -> mNodes.begin();
643
644        if ( mShowBoxes )
645        {
646            mBoxes.push_back( octant->getWireBoundingBox() );
647        }
648
649        bool vis = true;
650
651        while ( it != octant -> mNodes.end() )
652        {
653            OctreeNode * sn = *it;
654
655            // if this octree is partially visible, manually cull all
656            // scene nodes attached directly to this level.
657
658            if ( v == OctreeCamera::PARTIAL )
659                vis = camera -> isVisible( sn -> _getWorldAABB() );
660
661            if ( vis )
662            {
663
664                mNumObjects++;
665                sn -> _addToRenderQueue(camera, queue, onlyShadowCasters );
666
667                mVisible.push_back( sn );
668
669                if ( mDisplayNodes )
670                    queue -> addRenderable( sn );
671
672                // check if the scene manager or this node wants the bounding box shown.
673                if (sn->getShowBoundingBox() || mShowBoundingBoxes)
674                    sn->_addBoundingBoxToQueue(queue);
675            }
676
677            ++it;
678        }
679
680        if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
681            walkOctree( camera, queue, octant -> mChildren[ 0 ][ 0 ][ 0 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
682
683        if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
684            walkOctree( camera, queue, octant -> mChildren[ 1 ][ 0 ][ 0 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
685
686        if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
687            walkOctree( camera, queue, octant -> mChildren[ 0 ][ 1 ][ 0 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
688
689        if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
690            walkOctree( camera, queue, octant -> mChildren[ 1 ][ 1 ][ 0 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
691
692        if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
693            walkOctree( camera, queue, octant -> mChildren[ 0 ][ 0 ][ 1 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
694
695        if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
696            walkOctree( camera, queue, octant -> mChildren[ 1 ][ 0 ][ 1 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
697
698        if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
699            walkOctree( camera, queue, octant -> mChildren[ 0 ][ 1 ][ 1 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
700
701        if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
702            walkOctree( camera, queue, octant -> mChildren[ 1 ][ 1 ][ 1 ], ( v == OctreeCamera::FULL ), onlyShadowCasters );
703
704    }
705
706}
707
708// --- non template versions
709void _findNodes( const AxisAlignedBox &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
710{
711
712        if ( !full )
713        {
714                AxisAlignedBox obox;
715                octant -> _getCullBounds( &obox );
716
717                Intersection isect = intersect( t, obox );
718
719                if ( isect == OUTSIDE )
720                        return ;
721
722                full = ( isect == INSIDE );
723        }
724
725
726        NodeList::iterator it = octant -> mNodes.begin();
727
728        while ( it != octant -> mNodes.end() )
729        {
730                OctreeNode * on = ( *it );
731
732                if ( on != exclude )
733                {
734                        if ( full )
735                        {
736                                list.push_back( on );
737                        }
738
739                        else
740                        {
741                                Intersection nsect = intersect( t, on -> _getWorldAABB() );
742
743                                if ( nsect != OUTSIDE )
744                                {
745                                        list.push_back( on );
746                                }
747                        }
748
749                }
750
751                ++it;
752        }
753
754
755
756        if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
757                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 0 ] );
758
759        if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
760                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 0 ] );
761
762        if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
763                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 0 ] );
764
765        if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
766                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 0 ] );
767
768        if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
769                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 1 ] );
770
771        if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
772                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 1 ] );
773
774        if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
775                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 1 ] );
776
777        if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
778                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 1 ] );
779
780}
781
782void _findNodes( const Sphere &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
783{
784
785        if ( !full )
786        {
787                AxisAlignedBox obox;
788                octant -> _getCullBounds( &obox );
789
790                Intersection isect = intersect( t, obox );
791
792                if ( isect == OUTSIDE )
793                        return ;
794
795                full = ( isect == INSIDE );
796        }
797
798
799        NodeList::iterator it = octant -> mNodes.begin();
800
801        while ( it != octant -> mNodes.end() )
802        {
803                OctreeNode * on = ( *it );
804
805                if ( on != exclude )
806                {
807                        if ( full )
808                        {
809                                list.push_back( on );
810                        }
811
812                        else
813                        {
814                                Intersection nsect = intersect( t, on -> _getWorldAABB() );
815
816                                if ( nsect != OUTSIDE )
817                                {
818                                        list.push_back( on );
819                                }
820                        }
821
822                }
823
824                ++it;
825        }
826
827
828
829        if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
830                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 0 ] );
831
832        if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
833                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 0 ] );
834
835        if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
836                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 0 ] );
837
838        if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
839                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 0 ] );
840
841        if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
842                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 1 ] );
843
844        if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
845                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 1 ] );
846
847        if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
848                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 1 ] );
849
850        if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
851                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 1 ] );
852
853}
854
855
856void _findNodes( const PlaneBoundedVolume &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
857{
858
859        if ( !full )
860        {
861                AxisAlignedBox obox;
862                octant -> _getCullBounds( &obox );
863
864                Intersection isect = intersect( t, obox );
865
866                if ( isect == OUTSIDE )
867                        return ;
868
869                full = ( isect == INSIDE );
870        }
871
872
873        NodeList::iterator it = octant -> mNodes.begin();
874
875        while ( it != octant -> mNodes.end() )
876        {
877                OctreeNode * on = ( *it );
878
879                if ( on != exclude )
880                {
881                        if ( full )
882                        {
883                                list.push_back( on );
884                        }
885
886                        else
887                        {
888                                Intersection nsect = intersect( t, on -> _getWorldAABB() );
889
890                                if ( nsect != OUTSIDE )
891                                {
892                                        list.push_back( on );
893                                }
894                        }
895
896                }
897
898                ++it;
899        }
900
901
902
903        if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
904                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 0 ] );
905
906        if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
907                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 0 ] );
908
909        if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
910                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 0 ] );
911
912        if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
913                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 0 ] );
914
915        if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
916                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 1 ] );
917
918        if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
919                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 1 ] );
920
921        if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
922                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 1 ] );
923
924        if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
925                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 1 ] );
926
927}
928
929void _findNodes( const Ray &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
930{
931
932        if ( !full )
933        {
934                AxisAlignedBox obox;
935                octant -> _getCullBounds( &obox );
936
937                Intersection isect = intersect( t, obox );
938
939                if ( isect == OUTSIDE )
940                        return ;
941
942                full = ( isect == INSIDE );
943        }
944
945
946        NodeList::iterator it = octant -> mNodes.begin();
947
948        while ( it != octant -> mNodes.end() )
949        {
950                OctreeNode * on = ( *it );
951
952                if ( on != exclude )
953                {
954                        if ( full )
955                        {
956                                list.push_back( on );
957                        }
958
959                        else
960                        {
961                                Intersection nsect = intersect( t, on -> _getWorldAABB() );
962
963                                if ( nsect != OUTSIDE )
964                                {
965                                        list.push_back( on );
966                                }
967                        }
968
969                }
970
971                ++it;
972        }
973
974
975
976        if ( octant -> mChildren[ 0 ][ 0 ][ 0 ] != 0 )
977                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 0 ] );
978
979        if ( octant -> mChildren[ 1 ][ 0 ][ 0 ] != 0 )
980                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 0 ] );
981
982        if ( octant -> mChildren[ 0 ][ 1 ][ 0 ] != 0 )
983                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 0 ] );
984
985        if ( octant -> mChildren[ 1 ][ 1 ][ 0 ] != 0 )
986                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 0 ] );
987
988        if ( octant -> mChildren[ 0 ][ 0 ][ 1 ] != 0 )
989                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 0 ][ 1 ] );
990
991        if ( octant -> mChildren[ 1 ][ 0 ][ 1 ] != 0 )
992                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 0 ][ 1 ] );
993
994        if ( octant -> mChildren[ 0 ][ 1 ][ 1 ] != 0 )
995                _findNodes( t, list, exclude, full, octant -> mChildren[ 0 ][ 1 ][ 1 ] );
996
997        if ( octant -> mChildren[ 1 ][ 1 ][ 1 ] != 0 )
998                _findNodes( t, list, exclude, full, octant -> mChildren[ 1 ][ 1 ][ 1 ] );
999
1000}
1001
1002void OctreeSceneManager::findNodesIn( const AxisAlignedBox &box, std::list < SceneNode * > &list, SceneNode *exclude )
1003{
1004    _findNodes( box, list, exclude, false, mOctree );
1005}
1006
1007void OctreeSceneManager::findNodesIn( const Sphere &sphere, std::list < SceneNode * > &list, SceneNode *exclude )
1008{
1009    _findNodes( sphere, list, exclude, false, mOctree );
1010}
1011
1012void OctreeSceneManager::findNodesIn( const PlaneBoundedVolume &volume, std::list < SceneNode * > &list, SceneNode *exclude )
1013{
1014    _findNodes( volume, list, exclude, false, mOctree );
1015}
1016
1017void OctreeSceneManager::findNodesIn( const Ray &r, std::list < SceneNode * > &list, SceneNode *exclude )
1018{
1019    _findNodes( r, list, exclude, false, mOctree );
1020}
1021
1022void OctreeSceneManager::resize( const AxisAlignedBox &box )
1023{
1024    std::list < SceneNode * > nodes;
1025    std::list < SceneNode * > ::iterator it;
1026
1027    _findNodes( mOctree->mBox, nodes, 0, true, mOctree );
1028
1029    delete mOctree;
1030
1031    mOctree = new Octree( 0 );
1032#ifdef GTP_VISIBILITY_MODIFIED_OGRE
1033        mNumOctreeNodes = 1;
1034#endif // GTP_VISIBILITY_MODIFIED_OGRE
1035    mOctree->mBox = box;
1036
1037    it = nodes.begin();
1038
1039    while ( it != nodes.end() )
1040    {
1041        OctreeNode * on = static_cast < OctreeNode * > ( *it );
1042        on -> setOctant( 0 );
1043        _updateOctreeNode( on );
1044        ++it;
1045    }
1046
1047}
1048
1049bool OctreeSceneManager::setOption( const String & key, const void * val )
1050{
1051    if ( key == "Size" )
1052    {
1053        resize( * static_cast < const AxisAlignedBox * > ( val ) );
1054        return true;
1055    }
1056
1057    else if ( key == "Depth" )
1058    {
1059        mMaxDepth = * static_cast < const int * > ( val );
1060        resize( mOctree->mBox );
1061        return true;
1062    }
1063
1064    else if ( key == "ShowOctree" )
1065    {
1066        mShowBoxes = * static_cast < const bool * > ( val );
1067        return true;
1068    }
1069
1070    else if ( key == "CullCamera" )
1071    {
1072        mCullCamera = * static_cast < const bool * > ( val );
1073        return true;
1074    }
1075
1076    return SceneManager::setOption( key, val );
1077
1078
1079}
1080
1081bool OctreeSceneManager::getOption( const String & key, void *val )
1082{
1083    if ( key == "Size" )
1084    {
1085        AxisAlignedBox * b = static_cast < AxisAlignedBox * > ( val );
1086        b -> setExtents( mOctree->mBox.getMinimum(), mOctree->mBox.getMaximum() );
1087        return true;
1088    }
1089
1090    else if ( key == "Depth" )
1091    {
1092        * static_cast < int * > ( val ) = mMaxDepth;
1093        return true;
1094    }
1095
1096    else if ( key == "ShowOctree" )
1097    {
1098
1099        * static_cast < bool * > ( val ) = mShowBoxes;
1100        return true;
1101    }
1102
1103    else if ( key == "CullCamera" )
1104    {
1105        * static_cast < bool * > ( val ) = mCullCamera;
1106        return true;
1107    }
1108
1109    return SceneManager::getOption( key, val );
1110
1111}
1112
1113void OctreeSceneManager::clearScene(void)
1114{
1115    SceneManager::clearScene();
1116    init(mBox, mMaxDepth);
1117
1118}
1119
1120//---------------------------------------------------------------------
1121AxisAlignedBoxSceneQuery*
1122OctreeSceneManager::createAABBQuery(const AxisAlignedBox& box, unsigned long mask)
1123{
1124    OctreeAxisAlignedBoxSceneQuery* q = new OctreeAxisAlignedBoxSceneQuery(this);
1125    q->setBox(box);
1126    q->setQueryMask(mask);
1127    return q;
1128}
1129//---------------------------------------------------------------------
1130SphereSceneQuery*
1131OctreeSceneManager::createSphereQuery(const Sphere& sphere, unsigned long mask)
1132{
1133    OctreeSphereSceneQuery* q = new OctreeSphereSceneQuery(this);
1134    q->setSphere(sphere);
1135    q->setQueryMask(mask);
1136    return q;
1137}
1138//---------------------------------------------------------------------
1139PlaneBoundedVolumeListSceneQuery*
1140OctreeSceneManager::createPlaneBoundedVolumeQuery(const PlaneBoundedVolumeList& volumes,
1141        unsigned long mask)
1142{
1143    OctreePlaneBoundedVolumeListSceneQuery* q = new OctreePlaneBoundedVolumeListSceneQuery(this);
1144    q->setVolumes(volumes);
1145    q->setQueryMask(mask);
1146    return q;
1147}
1148
1149//---------------------------------------------------------------------
1150RaySceneQuery*
1151OctreeSceneManager::createRayQuery(const Ray& ray, unsigned long mask)
1152{
1153    OctreeRaySceneQuery* q = new OctreeRaySceneQuery(this);
1154    q->setRay(ray);
1155    q->setQueryMask(mask);
1156    return q;
1157}
1158//---------------------------------------------------------------------
1159IntersectionSceneQuery*
1160OctreeSceneManager::createIntersectionQuery(unsigned long mask)
1161{
1162
1163    // Octree implementation performs WORSE for < 500 objects
1164    // TODO: optimise it so it's better in all cases
1165    //OctreeIntersectionSceneQuery* q = new OctreeIntersectionSceneQuery(this);
1166    DefaultIntersectionSceneQuery* q = new DefaultIntersectionSceneQuery(this);
1167    q->setQueryMask(mask);
1168    return q;
1169}
1170#ifdef GTP_VISIBILITY_MODIFIED_OGRE
1171//-----------------------------------------------------------------------       
1172BoxList *OctreeSceneManager::getBoxes()
1173{
1174        return &mBoxes;
1175}
1176//-----------------------------------------------------------------------
1177void OctreeSceneManager::_renderOctant(Camera *cam, Octree *octant, bool onlyShadowCasters,
1178                                                                           const int leavePassesInQueue)
1179{
1180        // delete previously rendered objects from the render queue
1181        _deleteRenderedQueueGroups(leavePassesInQueue);
1182
1183        //Add stuff to be rendered;
1184    NodeList::iterator it = octant->mNodes.begin();
1185         
1186    while(it != octant->mNodes.end())
1187    {
1188                OctreeNode *sn = *it;
1189
1190        ++mNumObjects;
1191
1192                // check bounding box visibility of scene nodes
1193                if (cam->isVisible(sn->_getWorldAABB()))
1194                {
1195                        sn->_addToRenderQueue(cam, getRenderQueue(), onlyShadowCasters);
1196                        mVisible.push_back(sn);
1197
1198                        if (mDisplayNodes)
1199                        {
1200                                getRenderQueue()->addRenderable(sn);
1201                        }
1202
1203                        // check if the scene manager or this node wants the bounding box shown.
1204                        if (sn->getShowBoundingBox() || mShowBoundingBoxes)
1205                        {
1206                                sn->_addBoundingBoxToQueue(getRenderQueue());
1207                        }
1208                }
1209        ++it;
1210        }
1211
1212        if (mShowBoxes)
1213        {
1214                octant->getWireBoundingBox()->setMaterial("BaseWhiteNoLighting");
1215
1216                getRenderQueue()->addRenderable(octant->getWireBoundingBox());
1217                mBoxes.push_back(octant->getWireBoundingBox());
1218        }
1219
1220        //-- the actual rendering
1221        SceneManager::_renderVisibleObjects();
1222}
1223#endif // GTP_VISIBILITY_MODIFIED_OGRE
1224}
Note: See TracBrowser for help on using the repository browser.