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

Revision 2554, 34.0 KB checked in by mattausch, 17 years ago (diff)

added functions to accumulate render queue and issue it at one point

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