Coverage Report

Created: 2026-02-26 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ogre/PlugIns/OctreeSceneManager/src/OgreOctreeSceneManager.cpp
Line
Count
Source
1
/*
2
-----------------------------------------------------------------------------
3
This source file is part of OGRE
4
(Object-oriented Graphics Rendering Engine)
5
For the latest info, see http://www.ogre3d.org/
6
7
Copyright (c) 2000-2014 Torus Knot Software Ltd
8
9
Permission is hereby granted, free of charge, to any person obtaining a copy
10
of this software and associated documentation files (the "Software"), to deal
11
in the Software without restriction, including without limitation the rights
12
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
copies of the Software, and to permit persons to whom the Software is
14
furnished to do so, subject to the following conditions:
15
16
The above copyright notice and this permission notice shall be included in
17
all copies or substantial portions of the Software.
18
19
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
THE SOFTWARE.
26
-----------------------------------------------------------------------------
27
*/
28
/***************************************************************************
29
octreescenemanager.cpp  -  description
30
-------------------
31
begin                : Fri Sep 27 2002
32
copyright            : (C) 2002 by Jon Anderson
33
email                : janders@users.sf.net
34
  
35
***************************************************************************/
36
37
#include "OgreOctreeSceneManager.h"
38
#include "OgreOctreeSceneQuery.h"
39
#include "OgreOctreeNode.h"
40
#include "OgreOctreeCamera.h"
41
#include "OgreWireBoundingBox.h"
42
43
namespace Ogre
44
{
45
enum Intersection
46
{
47
    OUTSIDE=0,
48
    INSIDE=1,
49
    INTERSECT=2
50
};
51
int OctreeSceneManager::intersect_call = 0;
52
53
static Intersection intersect( const Ray &one, const AxisAlignedBox &two )
54
0
{
55
0
    OctreeSceneManager::intersect_call++;
56
    // Null box?
57
0
    if (two.isNull()) return OUTSIDE;
58
    // Infinite box?
59
0
    if (two.isInfinite()) return INTERSECT;
60
61
0
    bool inside = true;
62
0
    const Vector3& twoMin = two.getMinimum();
63
0
    const Vector3& twoMax = two.getMaximum();
64
0
    Vector3 origin = one.getOrigin();
65
0
    Vector3 dir = one.getDirection();
66
67
0
    Vector3 maxT(-1, -1, -1);
68
69
0
    int i = 0;
70
0
    for(i=0; i<3; i++ )
71
0
    {
72
0
        if( origin[i] < twoMin[i] )
73
0
        {
74
0
            inside = false;
75
0
            if( dir[i] > 0 )
76
0
            {
77
0
                maxT[i] = (twoMin[i] - origin[i])/ dir[i];
78
0
            }
79
0
        }
80
0
        else if( origin[i] > twoMax[i] )
81
0
        {
82
0
            inside = false;
83
0
            if( dir[i] < 0 )
84
0
            {
85
0
                maxT[i] = (twoMax[i] - origin[i]) / dir[i];
86
0
            }
87
0
        }
88
0
    }
89
90
0
    if( inside )
91
0
    {
92
0
        return INTERSECT;
93
0
    }
94
0
    int whichPlane = 0;
95
0
    if( maxT[1] > maxT[whichPlane])
96
0
        whichPlane = 1;
97
0
    if( maxT[2] > maxT[whichPlane])
98
0
        whichPlane = 2;
99
100
0
    if( ((int)maxT[whichPlane]) & 0x80000000 )
101
0
    {
102
0
        return OUTSIDE;
103
0
    }
104
0
    for(i=0; i<3; i++ )
105
0
    {
106
0
        if( i!= whichPlane )
107
0
        {
108
0
            float f = origin[i] + maxT[whichPlane] * dir[i];
109
0
            if ( f < (twoMin[i] - 0.00001f) ||
110
0
                    f > (twoMax[i] +0.00001f ) )
111
0
            {
112
0
                return OUTSIDE;
113
0
            }
114
0
        }
115
0
    }
116
117
0
    return INTERSECT;
118
119
0
}
120
121
122
/** Checks how the second box intersects with the first.
123
*/
124
static Intersection intersect( const PlaneBoundedVolume &one, const AxisAlignedBox &two )
125
0
{
126
0
    OctreeSceneManager::intersect_call++;
127
    // Null box?
128
0
    if (two.isNull()) return OUTSIDE;
129
    // Infinite box?
130
0
    if (two.isInfinite()) return INTERSECT;
131
132
    // Get centre of the box
133
0
    Vector3 centre = two.getCenter();
134
    // Get the half-size of the box
135
0
    Vector3 halfSize = two.getHalfSize();
136
137
    // For each plane, see if all points are on the negative side
138
    // If so, object is not visible.
139
    // If one or more are, it's partial.
140
    // If all aren't, full
141
0
    bool all_inside = true;
142
0
    PlaneList::const_iterator i, iend;
143
0
    iend = one.planes.end();
144
0
    for (i = one.planes.begin(); i != iend; ++i)
145
0
    {
146
0
        const Plane& plane = *i;
147
148
0
        Plane::Side side = plane.getSide(centre, halfSize);
149
0
        if(side == one.outside)
150
0
                return OUTSIDE;
151
0
        if(side == Plane::BOTH_SIDE)
152
0
                all_inside = false; 
153
0
    }
154
155
0
    if ( all_inside )
156
0
        return INSIDE;
157
0
    else
158
0
        return INTERSECT;
159
160
0
}
161
162
163
/** Checks how the second box intersects with the first.
164
*/
165
static Intersection intersect( const AxisAlignedBox &one, const AxisAlignedBox &two )
166
0
{
167
0
    OctreeSceneManager::intersect_call++;
168
    // Null box?
169
0
    if (one.isNull() || two.isNull()) return OUTSIDE;
170
0
    if (one.isInfinite()) return INSIDE;
171
0
    if (two.isInfinite()) return INTERSECT;
172
173
174
0
    const Vector3& insideMin = two.getMinimum();
175
0
    const Vector3& insideMax = two.getMaximum();
176
177
0
    const Vector3& outsideMin = one.getMinimum();
178
0
    const Vector3& outsideMax = one.getMaximum();
179
180
0
    if (    insideMax.x < outsideMin.x ||
181
0
            insideMax.y < outsideMin.y ||
182
0
            insideMax.z < outsideMin.z ||
183
0
            insideMin.x > outsideMax.x ||
184
0
            insideMin.y > outsideMax.y ||
185
0
            insideMin.z > outsideMax.z )
186
0
    {
187
0
        return OUTSIDE;
188
0
    }
189
190
0
    bool full = ( insideMin.x > outsideMin.x &&
191
0
                  insideMin.y > outsideMin.y &&
192
0
                  insideMin.z > outsideMin.z &&
193
0
                  insideMax.x < outsideMax.x &&
194
0
                  insideMax.y < outsideMax.y &&
195
0
                  insideMax.z < outsideMax.z );
196
197
0
    if ( full )
198
0
        return INSIDE;
199
0
    else
200
0
        return INTERSECT;
201
202
0
}
203
204
/** Checks how the box intersects with the sphere.
205
*/
206
static Intersection intersect( const Sphere &one, const AxisAlignedBox &two )
207
0
{
208
0
    OctreeSceneManager::intersect_call++;
209
    // Null box?
210
0
    if (two.isNull()) return OUTSIDE;
211
0
    if (two.isInfinite()) return INTERSECT;
212
213
0
    float sradius = one.getRadius();
214
215
0
    sradius *= sradius;
216
217
0
    Vector3 scenter = one.getCenter();
218
219
0
    const Vector3& twoMin = two.getMinimum();
220
0
    const Vector3& twoMax = two.getMaximum();
221
222
0
    float s, d = 0;
223
224
0
    Vector3 mndistance = ( twoMin - scenter );
225
0
    Vector3 mxdistance = ( twoMax - scenter );
226
227
0
    if ( mndistance.squaredLength() < sradius &&
228
0
            mxdistance.squaredLength() < sradius )
229
0
    {
230
0
        return INSIDE;
231
0
    }
232
233
    //find the square of the distance
234
    //from the sphere to the box
235
0
    for ( int i = 0 ; i < 3 ; i++ )
236
0
    {
237
0
        if ( scenter[ i ] < twoMin[ i ] )
238
0
        {
239
0
            s = scenter[ i ] - twoMin[ i ];
240
0
            d += s * s;
241
0
        }
242
243
0
        else if ( scenter[ i ] > twoMax[ i ] )
244
0
        {
245
0
            s = scenter[ i ] - twoMax[ i ];
246
0
            d += s * s;
247
0
        }
248
249
0
    }
250
251
0
    bool partial = ( d <= sradius );
252
253
0
    if ( !partial )
254
0
    {
255
0
        return OUTSIDE;
256
0
    }
257
258
0
    else
259
0
    {
260
0
        return INTERSECT;
261
0
    }
262
263
264
0
}
265
266
unsigned long white = 0xFFFFFFFF;
267
268
unsigned short OctreeSceneManager::mIndexes[ 24 ] = {0, 1, 1, 2, 2, 3, 3, 0,       //back
269
        0, 6, 6, 5, 5, 1,             //left
270
        3, 7, 7, 4, 4, 2,             //right
271
        6, 7, 5, 4 };          //front
272
unsigned long OctreeSceneManager::mColors[ 8 ] = {white, white, white, white, white, white, white, white };
273
274
275
0
OctreeSceneManager::OctreeSceneManager(const String& name) : SceneManager(name)
276
0
{
277
0
    AxisAlignedBox b( -10000, -10000, -10000, 10000, 10000, 10000 );
278
0
    int depth = 8; 
279
0
    mOctree = 0;
280
0
    init( b, depth );
281
0
}
282
283
OctreeSceneManager::OctreeSceneManager(const String& name, AxisAlignedBox &box, int max_depth ) 
284
0
: SceneManager(name)
285
0
{
286
0
    mOctree = 0;
287
0
    init( box, max_depth );
288
0
}
289
290
const String& OctreeSceneManager::getTypeName(void) const
291
0
{
292
0
    return OctreeSceneManagerFactory::FACTORY_TYPE_NAME;
293
0
}
294
295
void OctreeSceneManager::init( AxisAlignedBox &box, int depth )
296
0
{
297
298
0
    if ( mOctree != 0 )
299
0
        OGRE_DELETE mOctree;
300
301
0
    mOctree = OGRE_NEW Octree( 0 );
302
303
0
    mMaxDepth = depth;
304
0
    mBox = box;
305
306
0
    mOctree -> mBox = box;
307
308
0
    Vector3 min = box.getMinimum();
309
310
0
    Vector3 max = box.getMaximum();
311
312
0
    mOctree -> mHalfSize = ( max - min ) / 2;
313
314
315
0
    mShowBoxes = false;
316
317
0
    mNumObjects = 0;
318
319
0
    Vector3 v( 1.5, 1.5, 1.5 );
320
321
0
    mScaleFactor.setScale( v );
322
323
324
325
    // setDisplaySceneNodes( true );
326
    // setShowBoxes( true );
327
328
    //
329
    //mSceneRoot isn't put into the octree since it has no volume.
330
331
0
}
332
333
OctreeSceneManager::~OctreeSceneManager()
334
0
{
335
336
0
    if ( mOctree )
337
0
    {
338
0
        OGRE_DELETE mOctree;
339
0
        mOctree = 0;
340
0
    }
341
0
}
342
343
Camera * OctreeSceneManager::createCamera( const String &name )
344
0
{
345
    // Check name not used
346
0
    if (mCameras.find(name) != mCameras.end())
347
0
    {
348
0
        OGRE_EXCEPT(
349
0
            Exception::ERR_DUPLICATE_ITEM,
350
0
            "A camera with the name " + name + " already exists",
351
0
            "OctreeSceneManager::createCamera" );
352
0
    }
353
354
0
    Camera * c = OGRE_NEW OctreeCamera( name, this );
355
0
    mCameras.emplace(name, c);
356
357
    // create visible bounds aab map entry
358
0
    mCamVisibleObjectsMap[c] = VisibleObjectsBoundsInfo();
359
    
360
0
    return c;
361
0
}
362
363
void OctreeSceneManager::destroySceneNode( SceneNode* sn )
364
0
{
365
0
    OctreeNode * on = static_cast < OctreeNode* > ( sn );
366
367
0
    if ( on != 0 )
368
0
        _removeOctreeNode( on );
369
370
0
    SceneManager::destroySceneNode( sn );
371
0
}
372
373
bool OctreeSceneManager::getOptionValues( const String & key, StringVector  &refValueList )
374
0
{
375
0
    return SceneManager::getOptionValues( key, refValueList );
376
0
}
377
378
bool OctreeSceneManager::getOptionKeys( StringVector & refKeys )
379
0
{
380
0
    SceneManager::getOptionKeys( refKeys );
381
0
    refKeys.push_back( "Size" );
382
0
    refKeys.push_back( "ShowOctree" );
383
0
    refKeys.push_back( "Depth" );
384
385
0
    return true;
386
0
}
387
388
389
void OctreeSceneManager::_updateOctreeNode( OctreeNode * onode )
390
0
{
391
0
    const AxisAlignedBox& box = onode -> _getWorldAABB();
392
393
0
    if ( box.isNull() )
394
0
        return ;
395
396
    // Skip if octree has been destroyed (shutdown conditions)
397
0
    if (!mOctree)
398
0
        return;
399
400
0
    if ( onode -> getOctant() == 0 )
401
0
    {
402
        //if outside the octree, force into the root node.
403
0
        if ( ! onode -> _isIn( mOctree -> mBox ) )
404
0
            mOctree->_addNode( onode );
405
0
        else
406
0
            _addOctreeNode( onode, mOctree );
407
0
        return ;
408
0
    }
409
410
0
    if ( ! onode -> _isIn( onode -> getOctant() -> mBox ) )
411
0
    {
412
0
        _removeOctreeNode( onode );
413
414
        //if outside the octree, force into the root node.
415
0
        if ( ! onode -> _isIn( mOctree -> mBox ) )
416
0
            mOctree->_addNode( onode );
417
0
        else
418
0
            _addOctreeNode( onode, mOctree );
419
0
    }
420
0
}
421
422
/** Only removes the node from the octree.  It leaves the octree, even if it's empty.
423
*/
424
void OctreeSceneManager::_removeOctreeNode( OctreeNode * n )
425
0
{
426
    // Skip if octree has been destroyed (shutdown conditions)
427
0
    if (!mOctree)
428
0
        return;
429
430
0
    Octree * oct = n -> getOctant();
431
432
0
    if ( oct )
433
0
    {
434
0
        oct -> _removeNode( n );
435
0
    }
436
437
0
    n->setOctant(0);
438
0
}
439
440
441
void OctreeSceneManager::_addOctreeNode( OctreeNode * n, Octree *octant, int depth )
442
0
{
443
444
    // Skip if octree has been destroyed (shutdown conditions)
445
0
    if (!mOctree)
446
0
        return;
447
448
0
    const AxisAlignedBox& bx = n -> _getWorldAABB();
449
450
451
    //if the octree is twice as big as the scene node,
452
    //we will add it to a child.
453
0
    if ( ( depth < mMaxDepth ) && octant -> _isTwiceSize( bx ) )
454
0
    {
455
0
        int x, y, z;
456
0
        octant -> _getChildIndexes( bx, &x, &y, &z );
457
458
0
        if ( octant -> mChildren[ x ][ y ][ z ] == 0 )
459
0
        {
460
0
            octant -> mChildren[ x ][ y ][ z ] = OGRE_NEW Octree( octant );
461
0
            const Vector3& octantMin = octant -> mBox.getMinimum();
462
0
            const Vector3& octantMax = octant -> mBox.getMaximum();
463
0
            Vector3 min, max;
464
465
0
            if ( x == 0 )
466
0
            {
467
0
                min.x = octantMin.x;
468
0
                max.x = ( octantMin.x + octantMax.x ) / 2;
469
0
            }
470
471
0
            else
472
0
            {
473
0
                min.x = ( octantMin.x + octantMax.x ) / 2;
474
0
                max.x = octantMax.x;
475
0
            }
476
477
0
            if ( y == 0 )
478
0
            {
479
0
                min.y = octantMin.y;
480
0
                max.y = ( octantMin.y + octantMax.y ) / 2;
481
0
            }
482
483
0
            else
484
0
            {
485
0
                min.y = ( octantMin.y + octantMax.y ) / 2;
486
0
                max.y = octantMax.y;
487
0
            }
488
489
0
            if ( z == 0 )
490
0
            {
491
0
                min.z = octantMin.z;
492
0
                max.z = ( octantMin.z + octantMax.z ) / 2;
493
0
            }
494
495
0
            else
496
0
            {
497
0
                min.z = ( octantMin.z + octantMax.z ) / 2;
498
0
                max.z = octantMax.z;
499
0
            }
500
501
0
            octant -> mChildren[ x ][ y ][ z ] -> mBox.setExtents( min, max );
502
0
            octant -> mChildren[ x ][ y ][ z ] -> mHalfSize = ( max - min ) / 2;
503
0
        }
504
505
0
        _addOctreeNode( n, octant -> mChildren[ x ][ y ][ z ], ++depth );
506
507
0
    }
508
509
0
    else
510
0
    {
511
0
        octant -> _addNode( n );
512
0
    }
513
0
}
514
515
516
SceneNode * OctreeSceneManager::createSceneNodeImpl( void )
517
0
{
518
0
    return OGRE_NEW OctreeNode( this );
519
0
}
520
521
SceneNode * OctreeSceneManager::createSceneNodeImpl( const String &name )
522
0
{
523
0
    return OGRE_NEW OctreeNode( this, name );
524
0
}
525
526
void OctreeSceneManager::_updateSceneGraph( Camera * cam )
527
0
{
528
0
    SceneManager::_updateSceneGraph( cam );
529
0
}
530
531
void OctreeSceneManager::_findVisibleObjects(Camera * cam, 
532
    VisibleObjectsBoundsInfo* visibleBounds, bool onlyShadowCasters )
533
0
{
534
535
0
    getRenderQueue()->clear();
536
0
    mBoxes.clear();
537
0
    mVisible.clear();
538
539
0
    mNumObjects = 0;
540
541
    //walk the octree, adding all visible Octreenodes nodes to the render queue.
542
0
    walkOctree( static_cast < OctreeCamera * > ( cam ), getRenderQueue(), mOctree, 
543
0
                visibleBounds, false, onlyShadowCasters );
544
545
    // Show the octree boxes & cull camera if required
546
0
    if ( mShowBoxes )
547
0
    {
548
0
        for ( BoxList::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it )
549
0
        {
550
0
            getRenderQueue()->addRenderable(*it);
551
0
        }
552
0
    }
553
0
}
554
555
void OctreeSceneManager::walkOctree( OctreeCamera *camera, RenderQueue *queue, 
556
    Octree *octant, VisibleObjectsBoundsInfo* visibleBounds, 
557
    bool foundvisible, bool onlyShadowCasters )
558
0
{
559
560
    //return immediately if nothing is in the node.
561
0
    if ( octant -> numNodes() == 0 )
562
0
        return ;
563
564
0
    OctreeCamera::Visibility v = OctreeCamera::NONE;
565
566
0
    if ( foundvisible )
567
0
    {
568
0
        v = OctreeCamera::FULL;
569
0
    }
570
571
0
    else if ( octant == mOctree )
572
0
    {
573
0
        v = OctreeCamera::PARTIAL;
574
0
    }
575
576
0
    else
577
0
    {
578
0
        AxisAlignedBox box;
579
0
        octant -> _getCullBounds( &box );
580
0
        v = camera -> getVisibility( box );
581
0
    }
582
583
584
    // if the octant is visible, or if it's the root node...
585
0
    if ( v != OctreeCamera::NONE )
586
0
    {
587
588
        //Add stuff to be rendered;
589
0
        Octree::NodeList::iterator it = octant -> mNodes.begin();
590
591
0
        if ( mShowBoxes )
592
0
        {
593
0
            mBoxes.push_back( octant->getWireBoundingBox() );
594
0
        }
595
596
0
        bool vis = true;
597
598
0
        while ( it != octant -> mNodes.end() )
599
0
        {
600
0
            OctreeNode * sn = *it;
601
602
            // if this octree is partially visible, manually cull all
603
            // scene nodes attached directly to this level.
604
605
0
            if ( v == OctreeCamera::PARTIAL )
606
0
                vis = camera -> isVisible( sn -> _getWorldAABB() );
607
608
0
            if ( vis )
609
0
            {
610
611
0
                mNumObjects++;
612
0
                sn -> _addToRenderQueue(camera, queue, onlyShadowCasters, visibleBounds );
613
614
0
                mVisible.push_back( sn );
615
616
0
                if (getDebugDrawer())
617
0
                    getDebugDrawer()->drawSceneNode(sn);
618
0
            }
619
620
0
            ++it;
621
0
        }
622
623
0
        Octree* child;
624
0
        bool childfoundvisible = (v == OctreeCamera::FULL);
625
0
        if ( (child = octant -> mChildren[ 0 ][ 0 ][ 0 ]) != 0 )
626
0
            walkOctree( camera, queue, child, visibleBounds, childfoundvisible, onlyShadowCasters );
627
628
0
        if ( (child = octant -> mChildren[ 1 ][ 0 ][ 0 ]) != 0 )
629
0
            walkOctree( camera, queue, child, visibleBounds, childfoundvisible, onlyShadowCasters );
630
631
0
        if ( (child = octant -> mChildren[ 0 ][ 1 ][ 0 ]) != 0 )
632
0
            walkOctree( camera, queue, child, visibleBounds, childfoundvisible, onlyShadowCasters );
633
634
0
        if ( (child = octant -> mChildren[ 1 ][ 1 ][ 0 ]) != 0 )
635
0
            walkOctree( camera, queue, child, visibleBounds, childfoundvisible, onlyShadowCasters );
636
637
0
        if ( (child = octant -> mChildren[ 0 ][ 0 ][ 1 ]) != 0 )
638
0
            walkOctree( camera, queue, child, visibleBounds, childfoundvisible, onlyShadowCasters );
639
640
0
        if ( (child = octant -> mChildren[ 1 ][ 0 ][ 1 ]) != 0 )
641
0
            walkOctree( camera, queue, child, visibleBounds, childfoundvisible, onlyShadowCasters );
642
643
0
        if ( (child = octant -> mChildren[ 0 ][ 1 ][ 1 ]) != 0 )
644
0
            walkOctree( camera, queue, child, visibleBounds, childfoundvisible, onlyShadowCasters );
645
646
0
        if ( (child = octant -> mChildren[ 1 ][ 1 ][ 1 ]) != 0 )
647
0
            walkOctree( camera, queue, child, visibleBounds, childfoundvisible, onlyShadowCasters );
648
649
0
    }
650
651
0
}
652
653
// --- non template versions
654
static void _findNodes( const AxisAlignedBox &t, std::list< SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
655
0
{
656
657
0
    if ( !full )
658
0
    {
659
0
        AxisAlignedBox obox;
660
0
        octant -> _getCullBounds( &obox );
661
662
0
        Intersection isect = intersect( t, obox );
663
664
0
        if ( isect == OUTSIDE )
665
0
            return ;
666
667
0
        full = ( isect == INSIDE );
668
0
    }
669
670
671
0
    Octree::NodeList::iterator it = octant -> mNodes.begin();
672
673
0
    while ( it != octant -> mNodes.end() )
674
0
    {
675
0
        OctreeNode * on = ( *it );
676
677
0
        if ( on != exclude )
678
0
        {
679
0
            if ( full )
680
0
            {
681
0
                list.push_back( on );
682
0
            }
683
684
0
            else
685
0
            {
686
0
                Intersection nsect = intersect( t, on -> _getWorldAABB() );
687
688
0
                if ( nsect != OUTSIDE )
689
0
                {
690
0
                    list.push_back( on );
691
0
                }
692
0
            }
693
694
0
        }
695
696
0
        ++it;
697
0
    }
698
699
0
    Octree* child;
700
701
0
    if ( (child=octant -> mChildren[ 0 ][ 0 ][ 0 ]) != 0 )
702
0
        _findNodes( t, list, exclude, full, child );
703
704
0
    if ( (child=octant -> mChildren[ 1 ][ 0 ][ 0 ]) != 0 )
705
0
        _findNodes( t, list, exclude, full, child );
706
707
0
    if ( (child=octant -> mChildren[ 0 ][ 1 ][ 0 ]) != 0 )
708
0
        _findNodes( t, list, exclude, full, child );
709
710
0
    if ( (child=octant -> mChildren[ 1 ][ 1 ][ 0 ]) != 0 )
711
0
        _findNodes( t, list, exclude, full, child );
712
713
0
    if ( (child=octant -> mChildren[ 0 ][ 0 ][ 1 ]) != 0 )
714
0
        _findNodes( t, list, exclude, full, child );
715
716
0
    if ( (child=octant -> mChildren[ 1 ][ 0 ][ 1 ]) != 0 )
717
0
        _findNodes( t, list, exclude, full, child );
718
719
0
    if ( (child=octant -> mChildren[ 0 ][ 1 ][ 1 ]) != 0 )
720
0
        _findNodes( t, list, exclude, full, child );
721
722
0
    if ( (child=octant -> mChildren[ 1 ][ 1 ][ 1 ]) != 0 )
723
0
        _findNodes( t, list, exclude, full, child );
724
725
0
}
726
727
static void _findNodes( const Sphere &t, std::list< SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
728
0
{
729
730
0
    if ( !full )
731
0
    {
732
0
        AxisAlignedBox obox;
733
0
        octant -> _getCullBounds( &obox );
734
735
0
        Intersection isect = intersect( t, obox );
736
737
0
        if ( isect == OUTSIDE )
738
0
            return ;
739
740
0
        full = ( isect == INSIDE );
741
0
    }
742
743
744
0
    Octree::NodeList::iterator it = octant -> mNodes.begin();
745
746
0
    while ( it != octant -> mNodes.end() )
747
0
    {
748
0
        OctreeNode * on = ( *it );
749
750
0
        if ( on != exclude )
751
0
        {
752
0
            if ( full )
753
0
            {
754
0
                list.push_back( on );
755
0
            }
756
757
0
            else
758
0
            {
759
0
                Intersection nsect = intersect( t, on -> _getWorldAABB() );
760
761
0
                if ( nsect != OUTSIDE )
762
0
                {
763
0
                    list.push_back( on );
764
0
                }
765
0
            }
766
767
0
        }
768
769
0
        ++it;
770
0
    }
771
772
0
    Octree* child;
773
774
0
    if ( (child=octant -> mChildren[ 0 ][ 0 ][ 0 ]) != 0 )
775
0
        _findNodes( t, list, exclude, full, child );
776
777
0
    if ( (child=octant -> mChildren[ 1 ][ 0 ][ 0 ]) != 0 )
778
0
        _findNodes( t, list, exclude, full, child );
779
780
0
    if ( (child=octant -> mChildren[ 0 ][ 1 ][ 0 ]) != 0 )
781
0
        _findNodes( t, list, exclude, full, child );
782
783
0
    if ( (child=octant -> mChildren[ 1 ][ 1 ][ 0 ]) != 0 )
784
0
        _findNodes( t, list, exclude, full, child );
785
786
0
    if ( (child=octant -> mChildren[ 0 ][ 0 ][ 1 ]) != 0 )
787
0
        _findNodes( t, list, exclude, full, child );
788
789
0
    if ( (child=octant -> mChildren[ 1 ][ 0 ][ 1 ]) != 0 )
790
0
        _findNodes( t, list, exclude, full, child );
791
792
0
    if ( (child=octant -> mChildren[ 0 ][ 1 ][ 1 ]) != 0 )
793
0
        _findNodes( t, list, exclude, full, child );
794
795
0
    if ( (child=octant -> mChildren[ 1 ][ 1 ][ 1 ]) != 0 )
796
0
        _findNodes( t, list, exclude, full, child );
797
798
0
}
799
800
801
static void _findNodes( const PlaneBoundedVolume &t, std::list< SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
802
0
{
803
804
0
    if ( !full )
805
0
    {
806
0
        AxisAlignedBox obox;
807
0
        octant -> _getCullBounds( &obox );
808
809
0
        Intersection isect = intersect( t, obox );
810
811
0
        if ( isect == OUTSIDE )
812
0
            return ;
813
814
0
        full = ( isect == INSIDE );
815
0
    }
816
817
818
0
    Octree::NodeList::iterator it = octant -> mNodes.begin();
819
820
0
    while ( it != octant -> mNodes.end() )
821
0
    {
822
0
        OctreeNode * on = ( *it );
823
824
0
        if ( on != exclude )
825
0
        {
826
0
            if ( full )
827
0
            {
828
0
                list.push_back( on );
829
0
            }
830
831
0
            else
832
0
            {
833
0
                Intersection nsect = intersect( t, on -> _getWorldAABB() );
834
835
0
                if ( nsect != OUTSIDE )
836
0
                {
837
0
                    list.push_back( on );
838
0
                }
839
0
            }
840
841
0
        }
842
843
0
        ++it;
844
0
    }
845
846
0
    Octree* child;
847
848
0
    if ( (child=octant -> mChildren[ 0 ][ 0 ][ 0 ]) != 0 )
849
0
        _findNodes( t, list, exclude, full, child );
850
851
0
    if ( (child=octant -> mChildren[ 1 ][ 0 ][ 0 ]) != 0 )
852
0
        _findNodes( t, list, exclude, full, child );
853
854
0
    if ( (child=octant -> mChildren[ 0 ][ 1 ][ 0 ]) != 0 )
855
0
        _findNodes( t, list, exclude, full, child );
856
857
0
    if ( (child=octant -> mChildren[ 1 ][ 1 ][ 0 ]) != 0 )
858
0
        _findNodes( t, list, exclude, full, child );
859
860
0
    if ( (child=octant -> mChildren[ 0 ][ 0 ][ 1 ]) != 0 )
861
0
        _findNodes( t, list, exclude, full, child );
862
863
0
    if ( (child=octant -> mChildren[ 1 ][ 0 ][ 1 ]) != 0 )
864
0
        _findNodes( t, list, exclude, full, child );
865
866
0
    if ( (child=octant -> mChildren[ 0 ][ 1 ][ 1 ]) != 0 )
867
0
        _findNodes( t, list, exclude, full, child );
868
869
0
    if ( (child=octant -> mChildren[ 1 ][ 1 ][ 1 ]) != 0 )
870
0
        _findNodes( t, list, exclude, full, child );
871
872
0
}
873
874
static void _findNodes( const Ray &t, std::list< SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
875
0
{
876
877
0
    if ( !full )
878
0
    {
879
0
        AxisAlignedBox obox;
880
0
        octant -> _getCullBounds( &obox );
881
882
0
        Intersection isect = intersect( t, obox );
883
884
0
        if ( isect == OUTSIDE )
885
0
            return ;
886
887
0
        full = ( isect == INSIDE );
888
0
    }
889
890
891
0
    Octree::NodeList::iterator it = octant -> mNodes.begin();
892
893
0
    while ( it != octant -> mNodes.end() )
894
0
    {
895
0
        OctreeNode * on = ( *it );
896
897
0
        if ( on != exclude )
898
0
        {
899
0
            if ( full )
900
0
            {
901
0
                list.push_back( on );
902
0
            }
903
904
0
            else
905
0
            {
906
0
                Intersection nsect = intersect( t, on -> _getWorldAABB() );
907
908
0
                if ( nsect != OUTSIDE )
909
0
                {
910
0
                    list.push_back( on );
911
0
                }
912
0
            }
913
914
0
        }
915
916
0
        ++it;
917
0
    }
918
919
0
    Octree* child;
920
921
0
    if ( (child=octant -> mChildren[ 0 ][ 0 ][ 0 ]) != 0 )
922
0
        _findNodes( t, list, exclude, full, child );
923
924
0
    if ( (child=octant -> mChildren[ 1 ][ 0 ][ 0 ]) != 0 )
925
0
        _findNodes( t, list, exclude, full, child );
926
927
0
    if ( (child=octant -> mChildren[ 0 ][ 1 ][ 0 ]) != 0 )
928
0
        _findNodes( t, list, exclude, full, child );
929
930
0
    if ( (child=octant -> mChildren[ 1 ][ 1 ][ 0 ]) != 0 )
931
0
        _findNodes( t, list, exclude, full, child );
932
933
0
    if ( (child=octant -> mChildren[ 0 ][ 0 ][ 1 ]) != 0 )
934
0
        _findNodes( t, list, exclude, full, child );
935
936
0
    if ( (child=octant -> mChildren[ 1 ][ 0 ][ 1 ]) != 0 )
937
0
        _findNodes( t, list, exclude, full, child );
938
939
0
    if ( (child=octant -> mChildren[ 0 ][ 1 ][ 1 ]) != 0 )
940
0
        _findNodes( t, list, exclude, full, child );
941
942
0
    if ( (child=octant -> mChildren[ 1 ][ 1 ][ 1 ]) != 0 )
943
0
        _findNodes( t, list, exclude, full, child );
944
945
0
}
946
947
void OctreeSceneManager::findNodesIn( const AxisAlignedBox &box, std::list< SceneNode * > &list, SceneNode *exclude )
948
0
{
949
0
    _findNodes( box, list, exclude, false, mOctree );
950
0
}
951
952
void OctreeSceneManager::findNodesIn( const Sphere &sphere, std::list< SceneNode * > &list, SceneNode *exclude )
953
0
{
954
0
    _findNodes( sphere, list, exclude, false, mOctree );
955
0
}
956
957
void OctreeSceneManager::findNodesIn( const PlaneBoundedVolume &volume, std::list< SceneNode * > &list, SceneNode *exclude )
958
0
{
959
0
    _findNodes( volume, list, exclude, false, mOctree );
960
0
}
961
962
void OctreeSceneManager::findNodesIn( const Ray &r, std::list< SceneNode * > &list, SceneNode *exclude )
963
0
{
964
0
    _findNodes( r, list, exclude, false, mOctree );
965
0
}
966
967
void OctreeSceneManager::resize( const AxisAlignedBox &box )
968
0
{
969
0
    std::list< SceneNode * > nodes;
970
0
    std::list< SceneNode * > ::iterator it;
971
972
0
    _findNodes( mOctree->mBox, nodes, 0, true, mOctree );
973
974
0
    OGRE_DELETE mOctree;
975
976
0
    mOctree = OGRE_NEW Octree( 0 );
977
0
    mOctree->mBox = box;
978
979
0
    const Vector3 &min = box.getMinimum();
980
0
    const Vector3 &max = box.getMaximum();
981
0
    mOctree->mHalfSize = ( max - min ) * 0.5f;
982
983
0
    it = nodes.begin();
984
985
0
    while ( it != nodes.end() )
986
0
    {
987
0
        OctreeNode * on = static_cast < OctreeNode * > ( *it );
988
0
        on -> setOctant( 0 );
989
0
        _updateOctreeNode( on );
990
0
        ++it;
991
0
    }
992
993
0
}
994
995
bool OctreeSceneManager::setOption( const String & key, const void * val )
996
0
{
997
0
    if ( key == "Size" )
998
0
    {
999
0
        resize( * static_cast < const AxisAlignedBox * > ( val ) );
1000
0
        return true;
1001
0
    }
1002
1003
0
    else if ( key == "Depth" )
1004
0
    {
1005
0
        mMaxDepth = * static_cast < const int * > ( val );
1006
        // copy the box since resize will delete mOctree and reference won't work
1007
0
        AxisAlignedBox box = mOctree->mBox;
1008
0
        resize(box);
1009
0
        return true;
1010
0
    }
1011
1012
0
    else if ( key == "ShowOctree" )
1013
0
    {
1014
0
        mShowBoxes = * static_cast < const bool * > ( val );
1015
0
        return true;
1016
0
    }
1017
1018
1019
0
    return SceneManager::setOption( key, val );
1020
1021
1022
0
}
1023
1024
bool OctreeSceneManager::getOption( const String & key, void *val )
1025
0
{
1026
0
    if ( key == "Size" )
1027
0
    {
1028
0
        AxisAlignedBox * b = static_cast < AxisAlignedBox * > ( val );
1029
0
        b -> setExtents( mOctree->mBox.getMinimum(), mOctree->mBox.getMaximum() );
1030
0
        return true;
1031
0
    }
1032
1033
0
    else if ( key == "Depth" )
1034
0
    {
1035
0
        * static_cast < int * > ( val ) = mMaxDepth;
1036
0
        return true;
1037
0
    }
1038
1039
0
    else if ( key == "ShowOctree" )
1040
0
    {
1041
1042
0
        * static_cast < bool * > ( val ) = mShowBoxes;
1043
0
        return true;
1044
0
    }
1045
1046
1047
0
    return SceneManager::getOption( key, val );
1048
1049
0
}
1050
1051
void OctreeSceneManager::clearScene(void)
1052
0
{
1053
0
    SceneManager::clearScene();
1054
0
    init(mBox, mMaxDepth);
1055
1056
0
}
1057
1058
//---------------------------------------------------------------------
1059
AxisAlignedBoxSceneQuery*
1060
OctreeSceneManager::createAABBQuery(const AxisAlignedBox& box, uint32 mask)
1061
0
{
1062
0
    OctreeAxisAlignedBoxSceneQuery* q = OGRE_NEW OctreeAxisAlignedBoxSceneQuery(this);
1063
0
    q->setBox(box);
1064
0
    q->setQueryMask(mask);
1065
0
    return q;
1066
0
}
1067
//---------------------------------------------------------------------
1068
SphereSceneQuery*
1069
OctreeSceneManager::createSphereQuery(const Sphere& sphere, uint32 mask)
1070
0
{
1071
0
    OctreeSphereSceneQuery* q = OGRE_NEW OctreeSphereSceneQuery(this);
1072
0
    q->setSphere(sphere);
1073
0
    q->setQueryMask(mask);
1074
0
    return q;
1075
0
}
1076
//---------------------------------------------------------------------
1077
PlaneBoundedVolumeListSceneQuery*
1078
OctreeSceneManager::createPlaneBoundedVolumeQuery(const PlaneBoundedVolumeList& volumes,
1079
        uint32 mask)
1080
0
{
1081
0
    OctreePlaneBoundedVolumeListSceneQuery* q = OGRE_NEW OctreePlaneBoundedVolumeListSceneQuery(this);
1082
0
    q->setVolumes(volumes);
1083
0
    q->setQueryMask(mask);
1084
0
    return q;
1085
0
}
1086
1087
//---------------------------------------------------------------------
1088
RaySceneQuery*
1089
OctreeSceneManager::createRayQuery(const Ray& ray, uint32 mask)
1090
0
{
1091
0
    OctreeRaySceneQuery* q = OGRE_NEW OctreeRaySceneQuery(this);
1092
0
    q->setRay(ray);
1093
0
    q->setQueryMask(mask);
1094
0
    return q;
1095
0
}
1096
//---------------------------------------------------------------------
1097
IntersectionSceneQuery*
1098
OctreeSceneManager::createIntersectionQuery(uint32 mask)
1099
0
{
1100
1101
    // Octree implementation performs WORSE for < 500 objects
1102
    // TODO: optimise it so it's better in all cases
1103
    //OctreeIntersectionSceneQuery* q = OGRE_NEW OctreeIntersectionSceneQuery(this);
1104
0
    DefaultIntersectionSceneQuery* q = OGRE_NEW DefaultIntersectionSceneQuery(this);
1105
0
    q->setQueryMask(mask);
1106
0
    return q;
1107
0
}
1108
//-----------------------------------------------------------------------
1109
const String OctreeSceneManagerFactory::FACTORY_TYPE_NAME = "OctreeSceneManager";
1110
//-----------------------------------------------------------------------
1111
SceneManager* OctreeSceneManagerFactory::createInstance(
1112
    const String& instanceName)
1113
0
{
1114
0
    return OGRE_NEW OctreeSceneManager(instanceName);
1115
0
}
1116
1117
}