source: OGRE/trunk/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctreeSceneManager.cpp @ 657

Revision 657, 31.7 KB checked in by mattausch, 18 years ago (diff)

added ogre dependencies and patched ogre sources

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    // Check name not used
539    if (mSceneNodes.find(name) != mSceneNodes.end())
540    {
541        OGRE_EXCEPT(
542            Exception::ERR_DUPLICATE_ITEM,
543            "A scene node with the name " + name + " already exists",
544            "OctreeSceneManager::createSceneNode" );
545    }
546    OctreeNode * on = new OctreeNode( this, name );
547    mSceneNodes[ on->getName() ] = on;
548    return on;
549}
550
551void OctreeSceneManager::_updateSceneGraph( Camera * cam )
552{
553    SceneManager::_updateSceneGraph( cam );
554}
555
556void OctreeSceneManager::_alertVisibleObjects( void )
557{
558    OGRE_EXCEPT( Exception::UNIMPLEMENTED_FEATURE,
559        "Function doesn't do as advertised",
560        "OctreeSceneManager::_alertVisibleObjects" );
561
562    NodeList::iterator it = mVisible.begin();
563
564    while ( it != mVisible.end() )
565    {
566        OctreeNode * node = *it;
567
568        ++it;
569    }
570}
571
572void OctreeSceneManager::_findVisibleObjects( Camera * cam, bool onlyShadowCasters )
573{
574
575    getRenderQueue()->clear();
576    mBoxes.clear();
577    mVisible.clear();
578
579    if ( mCullCamera )
580    {
581        Camera * c = getCamera( "CullCamera" );
582
583        if ( c != 0 )
584            cam = c;
585    }
586
587    mNumObjects = 0;
588
589    //walk the octree, adding all visible Octreenodes nodes to the render queue.
590    walkOctree( static_cast < OctreeCamera * > ( cam ), getRenderQueue(), mOctree, false, onlyShadowCasters );
591
592
593    // Show the octree boxes & cull camera if required
594    if ( mShowBoxes || mCullCamera )
595    {
596
597
598
599        if ( mShowBoxes )
600        {
601            for ( BoxList::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it )
602            {
603                getRenderQueue()->addRenderable(*it);
604            }
605        }
606
607        if ( mCullCamera )
608        {
609            OctreeCamera * c = static_cast<OctreeCamera*>(getCamera( "CullCamera" ));
610
611            if ( c != 0 )
612            {
613                getRenderQueue()->addRenderable(c);
614            }
615        }
616
617    }
618
619
620
621}
622
623void OctreeSceneManager::walkOctree( OctreeCamera *camera, RenderQueue *queue,
624                                     Octree *octant, bool foundvisible, bool onlyShadowCasters )
625{
626
627    //return immediately if nothing is in the node.
628    if ( octant -> numNodes() == 0 )
629        return ;
630
631    OctreeCamera::Visibility v = OctreeCamera::NONE;
632
633    if ( foundvisible )
634    {
635        v = OctreeCamera::FULL;
636    }
637
638    else if ( octant == mOctree )
639    {
640        v = OctreeCamera::PARTIAL;
641    }
642
643    else
644    {
645        AxisAlignedBox box;
646        octant -> _getCullBounds( &box );
647        v = camera -> getVisibility( box );
648    }
649
650
651    // if the octant is visible, or if it's the root node...
652    if ( v != OctreeCamera::NONE )
653    {
654
655        //Add stuff to be rendered;
656        NodeList::iterator it = octant -> mNodes.begin();
657
658        if ( mShowBoxes )
659        {
660            mBoxes.push_back( octant->getWireBoundingBox() );
661        }
662
663        bool vis = true;
664
665        while ( it != octant -> mNodes.end() )
666        {
667            OctreeNode * sn = *it;
668
669            // if this octree is partially visible, manually cull all
670            // scene nodes attached directly to this level.
671
672            if ( v == OctreeCamera::PARTIAL )
673                vis = camera -> isVisible( sn -> _getWorldAABB() );
674
675            if ( vis )
676            {
677
678                mNumObjects++;
679                sn -> _addToRenderQueue(camera, queue, onlyShadowCasters );
680
681                mVisible.push_back( sn );
682
683                if ( mDisplayNodes )
684                    queue -> addRenderable( sn );
685
686                // check if the scene manager or this node wants the bounding box shown.
687                if (sn->getShowBoundingBox() || mShowBoundingBoxes)
688                    sn->_addBoundingBoxToQueue(queue);
689            }
690
691            ++it;
692        }
693
694        Octree* child;
695        bool childfoundvisible = (v == OctreeCamera::FULL);
696        if ( (child = octant -> mChildren[ 0 ][ 0 ][ 0 ]) != 0 )
697            walkOctree( camera, queue, child, childfoundvisible, onlyShadowCasters );
698
699        if ( (child = octant -> mChildren[ 1 ][ 0 ][ 0 ]) != 0 )
700            walkOctree( camera, queue, child, childfoundvisible, onlyShadowCasters );
701
702        if ( (child = octant -> mChildren[ 0 ][ 1 ][ 0 ]) != 0 )
703            walkOctree( camera, queue, child, childfoundvisible, onlyShadowCasters );
704
705        if ( (child = octant -> mChildren[ 1 ][ 1 ][ 0 ]) != 0 )
706            walkOctree( camera, queue, child, childfoundvisible, onlyShadowCasters );
707
708        if ( (child = octant -> mChildren[ 0 ][ 0 ][ 1 ]) != 0 )
709            walkOctree( camera, queue, child, childfoundvisible, onlyShadowCasters );
710
711        if ( (child = octant -> mChildren[ 1 ][ 0 ][ 1 ]) != 0 )
712            walkOctree( camera, queue, child, childfoundvisible, onlyShadowCasters );
713
714        if ( (child = octant -> mChildren[ 0 ][ 1 ][ 1 ]) != 0 )
715            walkOctree( camera, queue, child, childfoundvisible, onlyShadowCasters );
716
717        if ( (child = octant -> mChildren[ 1 ][ 1 ][ 1 ]) != 0 )
718            walkOctree( camera, queue, child, childfoundvisible, onlyShadowCasters );
719
720    }
721
722}
723
724// --- non template versions
725void _findNodes( const AxisAlignedBox &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
726{
727
728        if ( !full )
729        {
730                AxisAlignedBox obox;
731                octant -> _getCullBounds( &obox );
732
733                Intersection isect = intersect( t, obox );
734
735                if ( isect == OUTSIDE )
736                        return ;
737
738                full = ( isect == INSIDE );
739        }
740
741
742        NodeList::iterator it = octant -> mNodes.begin();
743
744        while ( it != octant -> mNodes.end() )
745        {
746                OctreeNode * on = ( *it );
747
748                if ( on != exclude )
749                {
750                        if ( full )
751                        {
752                                list.push_back( on );
753                        }
754
755                        else
756                        {
757                                Intersection nsect = intersect( t, on -> _getWorldAABB() );
758
759                                if ( nsect != OUTSIDE )
760                                {
761                                        list.push_back( on );
762                                }
763                        }
764
765                }
766
767                ++it;
768        }
769
770        Octree* child;
771
772        if ( (child=octant -> mChildren[ 0 ][ 0 ][ 0 ]) != 0 )
773                _findNodes( t, list, exclude, full, child );
774
775        if ( (child=octant -> mChildren[ 1 ][ 0 ][ 0 ]) != 0 )
776                _findNodes( t, list, exclude, full, child );
777
778        if ( (child=octant -> mChildren[ 0 ][ 1 ][ 0 ]) != 0 )
779                _findNodes( t, list, exclude, full, child );
780
781        if ( (child=octant -> mChildren[ 1 ][ 1 ][ 0 ]) != 0 )
782                _findNodes( t, list, exclude, full, child );
783
784        if ( (child=octant -> mChildren[ 0 ][ 0 ][ 1 ]) != 0 )
785                _findNodes( t, list, exclude, full, child );
786
787        if ( (child=octant -> mChildren[ 1 ][ 0 ][ 1 ]) != 0 )
788                _findNodes( t, list, exclude, full, child );
789
790        if ( (child=octant -> mChildren[ 0 ][ 1 ][ 1 ]) != 0 )
791                _findNodes( t, list, exclude, full, child );
792
793        if ( (child=octant -> mChildren[ 1 ][ 1 ][ 1 ]) != 0 )
794                _findNodes( t, list, exclude, full, child );
795
796}
797
798void _findNodes( const Sphere &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
799{
800
801        if ( !full )
802        {
803                AxisAlignedBox obox;
804                octant -> _getCullBounds( &obox );
805
806                Intersection isect = intersect( t, obox );
807
808                if ( isect == OUTSIDE )
809                        return ;
810
811                full = ( isect == INSIDE );
812        }
813
814
815        NodeList::iterator it = octant -> mNodes.begin();
816
817        while ( it != octant -> mNodes.end() )
818        {
819                OctreeNode * on = ( *it );
820
821                if ( on != exclude )
822                {
823                        if ( full )
824                        {
825                                list.push_back( on );
826                        }
827
828                        else
829                        {
830                                Intersection nsect = intersect( t, on -> _getWorldAABB() );
831
832                                if ( nsect != OUTSIDE )
833                                {
834                                        list.push_back( on );
835                                }
836                        }
837
838                }
839
840                ++it;
841        }
842
843        Octree* child;
844
845        if ( (child=octant -> mChildren[ 0 ][ 0 ][ 0 ]) != 0 )
846                _findNodes( t, list, exclude, full, child );
847
848        if ( (child=octant -> mChildren[ 1 ][ 0 ][ 0 ]) != 0 )
849                _findNodes( t, list, exclude, full, child );
850
851        if ( (child=octant -> mChildren[ 0 ][ 1 ][ 0 ]) != 0 )
852                _findNodes( t, list, exclude, full, child );
853
854        if ( (child=octant -> mChildren[ 1 ][ 1 ][ 0 ]) != 0 )
855                _findNodes( t, list, exclude, full, child );
856
857        if ( (child=octant -> mChildren[ 0 ][ 0 ][ 1 ]) != 0 )
858                _findNodes( t, list, exclude, full, child );
859
860        if ( (child=octant -> mChildren[ 1 ][ 0 ][ 1 ]) != 0 )
861                _findNodes( t, list, exclude, full, child );
862
863        if ( (child=octant -> mChildren[ 0 ][ 1 ][ 1 ]) != 0 )
864                _findNodes( t, list, exclude, full, child );
865
866        if ( (child=octant -> mChildren[ 1 ][ 1 ][ 1 ]) != 0 )
867                _findNodes( t, list, exclude, full, child );
868
869}
870
871
872void _findNodes( const PlaneBoundedVolume &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
873{
874
875        if ( !full )
876        {
877                AxisAlignedBox obox;
878                octant -> _getCullBounds( &obox );
879
880                Intersection isect = intersect( t, obox );
881
882                if ( isect == OUTSIDE )
883                        return ;
884
885                full = ( isect == INSIDE );
886        }
887
888
889        NodeList::iterator it = octant -> mNodes.begin();
890
891        while ( it != octant -> mNodes.end() )
892        {
893                OctreeNode * on = ( *it );
894
895                if ( on != exclude )
896                {
897                        if ( full )
898                        {
899                                list.push_back( on );
900                        }
901
902                        else
903                        {
904                                Intersection nsect = intersect( t, on -> _getWorldAABB() );
905
906                                if ( nsect != OUTSIDE )
907                                {
908                                        list.push_back( on );
909                                }
910                        }
911
912                }
913
914                ++it;
915        }
916
917        Octree* child;
918
919        if ( (child=octant -> mChildren[ 0 ][ 0 ][ 0 ]) != 0 )
920                _findNodes( t, list, exclude, full, child );
921
922        if ( (child=octant -> mChildren[ 1 ][ 0 ][ 0 ]) != 0 )
923                _findNodes( t, list, exclude, full, child );
924
925        if ( (child=octant -> mChildren[ 0 ][ 1 ][ 0 ]) != 0 )
926                _findNodes( t, list, exclude, full, child );
927
928        if ( (child=octant -> mChildren[ 1 ][ 1 ][ 0 ]) != 0 )
929                _findNodes( t, list, exclude, full, child );
930
931        if ( (child=octant -> mChildren[ 0 ][ 0 ][ 1 ]) != 0 )
932                _findNodes( t, list, exclude, full, child );
933
934        if ( (child=octant -> mChildren[ 1 ][ 0 ][ 1 ]) != 0 )
935                _findNodes( t, list, exclude, full, child );
936
937        if ( (child=octant -> mChildren[ 0 ][ 1 ][ 1 ]) != 0 )
938                _findNodes( t, list, exclude, full, child );
939
940        if ( (child=octant -> mChildren[ 1 ][ 1 ][ 1 ]) != 0 )
941                _findNodes( t, list, exclude, full, child );
942
943}
944
945void _findNodes( const Ray &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
946{
947
948        if ( !full )
949        {
950                AxisAlignedBox obox;
951                octant -> _getCullBounds( &obox );
952
953                Intersection isect = intersect( t, obox );
954
955                if ( isect == OUTSIDE )
956                        return ;
957
958                full = ( isect == INSIDE );
959        }
960
961
962        NodeList::iterator it = octant -> mNodes.begin();
963
964        while ( it != octant -> mNodes.end() )
965        {
966                OctreeNode * on = ( *it );
967
968                if ( on != exclude )
969                {
970                        if ( full )
971                        {
972                                list.push_back( on );
973                        }
974
975                        else
976                        {
977                                Intersection nsect = intersect( t, on -> _getWorldAABB() );
978
979                                if ( nsect != OUTSIDE )
980                                {
981                                        list.push_back( on );
982                                }
983                        }
984
985                }
986
987                ++it;
988        }
989
990        Octree* child;
991
992        if ( (child=octant -> mChildren[ 0 ][ 0 ][ 0 ]) != 0 )
993                _findNodes( t, list, exclude, full, child );
994
995        if ( (child=octant -> mChildren[ 1 ][ 0 ][ 0 ]) != 0 )
996                _findNodes( t, list, exclude, full, child );
997
998        if ( (child=octant -> mChildren[ 0 ][ 1 ][ 0 ]) != 0 )
999                _findNodes( t, list, exclude, full, child );
1000
1001        if ( (child=octant -> mChildren[ 1 ][ 1 ][ 0 ]) != 0 )
1002                _findNodes( t, list, exclude, full, child );
1003
1004        if ( (child=octant -> mChildren[ 0 ][ 0 ][ 1 ]) != 0 )
1005                _findNodes( t, list, exclude, full, child );
1006
1007        if ( (child=octant -> mChildren[ 1 ][ 0 ][ 1 ]) != 0 )
1008                _findNodes( t, list, exclude, full, child );
1009
1010        if ( (child=octant -> mChildren[ 0 ][ 1 ][ 1 ]) != 0 )
1011                _findNodes( t, list, exclude, full, child );
1012
1013        if ( (child=octant -> mChildren[ 1 ][ 1 ][ 1 ]) != 0 )
1014                _findNodes( t, list, exclude, full, child );
1015
1016}
1017
1018void OctreeSceneManager::findNodesIn( const AxisAlignedBox &box, std::list < SceneNode * > &list, SceneNode *exclude )
1019{
1020    _findNodes( box, list, exclude, false, mOctree );
1021}
1022
1023void OctreeSceneManager::findNodesIn( const Sphere &sphere, std::list < SceneNode * > &list, SceneNode *exclude )
1024{
1025    _findNodes( sphere, list, exclude, false, mOctree );
1026}
1027
1028void OctreeSceneManager::findNodesIn( const PlaneBoundedVolume &volume, std::list < SceneNode * > &list, SceneNode *exclude )
1029{
1030    _findNodes( volume, list, exclude, false, mOctree );
1031}
1032
1033void OctreeSceneManager::findNodesIn( const Ray &r, std::list < SceneNode * > &list, SceneNode *exclude )
1034{
1035    _findNodes( r, list, exclude, false, mOctree );
1036}
1037
1038void OctreeSceneManager::resize( const AxisAlignedBox &box )
1039{
1040    std::list < SceneNode * > nodes;
1041    std::list < SceneNode * > ::iterator it;
1042
1043    _findNodes( mOctree->mBox, nodes, 0, true, mOctree );
1044
1045    delete mOctree;
1046
1047    mOctree = new Octree( 0 );
1048
1049#ifdef GTP_VISIBILITY_MODIFIED_OGRE
1050        mNumOctants = 1;
1051#endif // GTP_VISIBILITY_MODIFIED_OGRE
1052
1053    mOctree->mBox = box;
1054
1055        const Vector3 min = box.getMinimum();
1056        const Vector3 max = box.getMaximum();
1057        mOctree->mHalfSize = ( max - min ) * 0.5f;
1058
1059    it = nodes.begin();
1060
1061    while ( it != nodes.end() )
1062    {
1063        OctreeNode * on = static_cast < OctreeNode * > ( *it );
1064        on -> setOctant( 0 );
1065        _updateOctreeNode( on );
1066        ++it;
1067    }
1068
1069}
1070
1071bool OctreeSceneManager::setOption( const String & key, const void * val )
1072{
1073    if ( key == "Size" )
1074    {
1075        resize( * static_cast < const AxisAlignedBox * > ( val ) );
1076        return true;
1077    }
1078
1079    else if ( key == "Depth" )
1080    {
1081        mMaxDepth = * static_cast < const int * > ( val );
1082        resize( mOctree->mBox );
1083        return true;
1084    }
1085
1086    else if ( key == "ShowOctree" )
1087    {
1088        mShowBoxes = * static_cast < const bool * > ( val );
1089        return true;
1090    }
1091
1092    else if ( key == "CullCamera" )
1093    {
1094        mCullCamera = * static_cast < const bool * > ( val );
1095        return true;
1096    }
1097
1098    return SceneManager::setOption( key, val );
1099
1100
1101}
1102
1103bool OctreeSceneManager::getOption( const String & key, void *val )
1104{
1105    if ( key == "Size" )
1106    {
1107        AxisAlignedBox * b = static_cast < AxisAlignedBox * > ( val );
1108        b -> setExtents( mOctree->mBox.getMinimum(), mOctree->mBox.getMaximum() );
1109        return true;
1110    }
1111
1112    else if ( key == "Depth" )
1113    {
1114        * static_cast < int * > ( val ) = mMaxDepth;
1115        return true;
1116    }
1117
1118    else if ( key == "ShowOctree" )
1119    {
1120
1121        * static_cast < bool * > ( val ) = mShowBoxes;
1122        return true;
1123    }
1124
1125    else if ( key == "CullCamera" )
1126    {
1127        * static_cast < bool * > ( val ) = mCullCamera;
1128        return true;
1129    }
1130
1131    return SceneManager::getOption( key, val );
1132
1133}
1134
1135void OctreeSceneManager::clearScene(void)
1136{
1137    SceneManager::clearScene();
1138    init(mBox, mMaxDepth);
1139
1140}
1141
1142//---------------------------------------------------------------------
1143AxisAlignedBoxSceneQuery*
1144OctreeSceneManager::createAABBQuery(const AxisAlignedBox& box, unsigned long mask)
1145{
1146    OctreeAxisAlignedBoxSceneQuery* q = new OctreeAxisAlignedBoxSceneQuery(this);
1147    q->setBox(box);
1148    q->setQueryMask(mask);
1149    return q;
1150}
1151//---------------------------------------------------------------------
1152SphereSceneQuery*
1153OctreeSceneManager::createSphereQuery(const Sphere& sphere, unsigned long mask)
1154{
1155    OctreeSphereSceneQuery* q = new OctreeSphereSceneQuery(this);
1156    q->setSphere(sphere);
1157    q->setQueryMask(mask);
1158    return q;
1159}
1160//---------------------------------------------------------------------
1161PlaneBoundedVolumeListSceneQuery*
1162OctreeSceneManager::createPlaneBoundedVolumeQuery(const PlaneBoundedVolumeList& volumes,
1163        unsigned long mask)
1164{
1165    OctreePlaneBoundedVolumeListSceneQuery* q = new OctreePlaneBoundedVolumeListSceneQuery(this);
1166    q->setVolumes(volumes);
1167    q->setQueryMask(mask);
1168    return q;
1169}
1170
1171//---------------------------------------------------------------------
1172RaySceneQuery*
1173OctreeSceneManager::createRayQuery(const Ray& ray, unsigned long mask)
1174{
1175    OctreeRaySceneQuery* q = new OctreeRaySceneQuery(this);
1176    q->setRay(ray);
1177    q->setQueryMask(mask);
1178    return q;
1179}
1180//---------------------------------------------------------------------
1181IntersectionSceneQuery*
1182OctreeSceneManager::createIntersectionQuery(unsigned long mask)
1183{
1184
1185    // Octree implementation performs WORSE for < 500 objects
1186    // TODO: optimise it so it's better in all cases
1187    //OctreeIntersectionSceneQuery* q = new OctreeIntersectionSceneQuery(this);
1188    DefaultIntersectionSceneQuery* q = new DefaultIntersectionSceneQuery(this);
1189    q->setQueryMask(mask);
1190    return q;
1191}
1192#ifdef GTP_VISIBILITY_MODIFIED_OGRE
1193//-----------------------------------------------------------------------       
1194BoxList *OctreeSceneManager::getBoxes()
1195{
1196        return &mBoxes;
1197}
1198//-----------------------------------------------------------------------
1199void OctreeSceneManager::_renderOctant(Camera *cam, Octree *octant, bool onlyShadowCasters,
1200                                                                           const int leavePassesInQueue)
1201{
1202        // delete previously rendered objects from the render queue
1203        _deleteRenderedQueueGroups(leavePassesInQueue);
1204
1205        //Add stuff to be rendered;
1206    NodeList::iterator it = octant->mNodes.begin();
1207         
1208    while(it != octant->mNodes.end())
1209    {
1210                OctreeNode *sn = *it;
1211
1212        ++mNumObjects;
1213
1214                // check bounding box visibility of scene nodes
1215                if (cam->isVisible(sn->_getWorldAABB()))
1216                {
1217                        sn->_addToRenderQueue(cam, getRenderQueue(), onlyShadowCasters);
1218                        mVisible.push_back(sn);
1219
1220                        if (mDisplayNodes)
1221                        {
1222                                getRenderQueue()->addRenderable(sn);
1223                        }
1224
1225                        // check if the scene manager or this node wants the bounding box shown.
1226                        if (sn->getShowBoundingBox() || mShowBoundingBoxes)
1227                        {
1228                                sn->_addBoundingBoxToQueue(getRenderQueue());
1229                        }
1230                }
1231        ++it;
1232        }
1233
1234        if (mShowBoxes)
1235        {
1236                octant->getWireBoundingBox()->setMaterial("BaseWhiteNoLighting");
1237
1238                getRenderQueue()->addRenderable(octant->getWireBoundingBox());
1239                mBoxes.push_back(octant->getWireBoundingBox());
1240        }
1241
1242        //-- the actual rendering
1243        SceneManager::_renderVisibleObjects();
1244}
1245#endif // GTP_VISIBILITY_MODIFIED_OGRE
1246}
Note: See TracBrowser for help on using the repository browser.