source: OGRE/trunk/ogre_changes/Ogre1.2/PlugIns/OctreeSceneManager/src/OgreOctreeSceneManager.cpp @ 921

Revision 921, 33.2 KB checked in by mattausch, 18 years ago (diff)

added updates for visibility

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