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

Revision 135, 31.9 KB checked in by mattausch, 19 years ago (diff)
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                                                                           bool leaveTransparentsInQueue)//, bool useZPassQueue)
1179{
1180        // delete previously rendered objects from the render queue
1181        _deleteRenderedQueueGroups(leaveTransparentsInQueue);
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.