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

Revision 154, 32.0 KB checked in by mattausch, 19 years ago (diff)

added item buffer queries.

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