source: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdTreeSceneManager.cpp @ 1296

Revision 1296, 39.9 KB checked in by szydlowski, 18 years ago (diff)

Implemented PVS support in kdtree scene manager - not complete, defunct
modified BoundingBoxConverter? to work with KdTreeSceneManager?

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of the GameTools Project
4http://www.gametools.org
5
6Author: Martin Szydlowski
7-----------------------------------------------------------------------------
8*/
9
10#include <OgreCamera.h>
11#include <OgreSubEntity.h>
12#include <OgreMaterialManager.h>
13#include <OgreLogManager.h>
14#include <OgreStringConverter.h>
15
16#include "OgreKdTreeSceneManager.h"
17#include "OgreKdTreeSceneNode.h"
18#include "OgreKdTree.h"
19
20#include <OgreMeshInstance.h>
21#include <OgreBoundingBoxConverter.h>
22#include <OgreTypeConverter.h>
23#include <VisibilityEnvironment.h>
24#include "OgreVisibilityOptionsManager.h"
25
26namespace Ogre
27{
28
29KdTreeSceneManager::KdTreeSceneManager(const String& name, GtpVisibility::VisibilityManager *vm):
30SceneManager(name),
31mVisibilityManager(vm),
32mKdTree(0),
33mMaxDepth(KDTREE_MAX_DEPTH),
34mShowBoxes(false),
35mHiLiteLevel(0),
36mShowAllBoxes(false),
37mEnhancedVisiblity(true),
38mBuildMethod(KdTree::KDBM_PRIORITYQUEUE),
39mRenderMethod(KdTree::KDRM_INTERNAL),
40mShowVisualization(false),
41mRenderNodesForViz(false),
42mRenderNodesContentForViz(false),
43mVisualizeCulledNodes(false),
44mLeavePassesInQueue(0),
45mDelayRenderTransparents(true),
46mUseDepthPass(true),
47mIsDepthPassPhase(false),
48mUseItemBuffer(false),
49mIsItemBufferPhase(false),
50mCurrentEntityId(1),
51mEnableDepthWrite(true),
52mSkipTransparents(false),
53mRenderTransparentsForItemBuffer(true),
54mExecuteVertexProgramForAllPasses(false),
55mIsHierarchicalCulling(false),
56mDeleteQueueAfterRendering(true),
57mViewCellsLoaded(false),
58mUseViewCells(false),
59mUseVisibilityFilter(false),
60mViewCellsManager(0),
61mElementaryViewCell(0),
62mCurrentViewCell(0)
63{
64        // Replace root node with my node
65        OGRE_DELETE(mSceneRoot);
66        mSceneRoot = new KdTreeSceneNode(this, "root node");
67        mSceneRoot->_notifyRootNode();
68
69        // init heirarchy interface
70        mHierarchyInterface = new KdTreeHierarchyInterface(this, mDestRenderSystem);
71}
72
73KdTreeSceneManager::~KdTreeSceneManager(void)
74{
75        delete mHierarchyInterface;
76        delete mKdTree;
77}
78
79void KdTreeSceneManager::clearScene()
80{
81        // DEBUG
82        //if (mKdTree)
83        //      mKdTree->dump();
84
85        // must happen before actual scene is cleared
86        OGRE_DELETE(mKdTree);
87
88        SceneManager::clearScene();
89}
90
91
92const String& KdTreeSceneManager::getTypeName(void) const
93{
94        return KdTreeSceneManagerFactory::FACTORY_TYPE_NAME;
95}
96
97void KdTreeSceneManager::setShowBoxes(bool showboxes)
98{
99        mShowBoxes = showboxes;
100}
101
102bool KdTreeSceneManager::getShowBoxes(void) const
103{
104        return mShowBoxes;
105}
106
107bool KdTreeSceneManager::setOption(const String& strKey, const void* pValue)
108{
109        // change max depth of the kdtree
110        // rebuild the tree if already exists
111        if (strKey == "KdTreeMaxDepth")
112        {
113                int maxdepth = *static_cast<const int *>(pValue);
114
115                // no negative depth, plz!
116                if (maxdepth < 0)
117                {
118                        return false;
119                }
120                else
121                {
122                        mMaxDepth = maxdepth;
123                        if (mHiLiteLevel > mMaxDepth)
124                                mHiLiteLevel = mMaxDepth;
125                        return true;
126                }
127                return true;
128        }
129        else if (strKey == "KT")
130        {
131                Real kt = *static_cast<const Real *>(pValue);
132                if (kt > 0)
133                {
134                        PlaneEvent::KT = kt;
135                        return true;
136                }
137                else
138                {
139                        return false;
140                }
141        }
142        else if (strKey == "KI")
143        {
144                Real ki = *static_cast<const Real *>(pValue);
145                if (ki > 0)
146                {
147                        PlaneEvent::KI = ki;
148                        return true;
149                }
150                else
151                {
152                        return false;
153                }
154        }
155        else if (strKey == "RebuildKdTree")
156        {
157                OGRE_DELETE(mKdTree);
158                mKdTree = new KdTree(mMaxDepth, mBuildMethod, mHiLiteLevel, mShowAllBoxes, mShowNodes);
159                mKdTree->build(static_cast<KdTreeSceneNode *>(mSceneRoot));
160                mKdTree->setEnhancedVis(mEnhancedVisiblity);
161                return true;
162        }
163        else if (strKey == "EnhancedVisibility")
164        {
165                bool enh = *static_cast<const bool *>(pValue);
166                mEnhancedVisiblity = enh;
167                if (mKdTree)
168                        mKdTree->setEnhancedVis(mEnhancedVisiblity);
169                //setEnhancedVis(enh);
170                return true;
171        }
172        else if (strKey == "BuildMethod")
173        {
174                KdTree::BuildMethod bm = *static_cast<const KdTree::BuildMethod *>(pValue);
175                if (bm == KdTree::KDBM_RECURSIVE || bm == KdTree::KDBM_PRIORITYQUEUE)
176                {
177                        mBuildMethod = bm;
178                        return true;
179                }
180                else
181                {
182                        return false;
183                }
184        }
185        else if (strKey == "RenderMethod")
186        {
187                KdTree::RenderMethod rm = *static_cast<const KdTree::RenderMethod *>(pValue);
188                if (rm == KdTree::KDRM_INTERNAL)
189                {
190                        mRenderMethod = rm;
191                        return true;
192                }
193                else if (rm == KdTree::KDRM_GTP_VFC)
194                {
195                        mRenderMethod = rm;
196                        int cmt = GtpVisibility::VisibilityEnvironment::FRUSTUM_CULLING;
197                        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface)
198                                .setOption("Algorithm", &cmt);
199                }
200                else if (rm == KdTree::KDRM_GTP_SWC)
201                {
202                        mRenderMethod = rm;
203                        int cmt = GtpVisibility::VisibilityEnvironment::STOP_AND_WAIT_CULLING;
204                        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface)
205                                .setOption("Algorithm", &cmt);
206                }
207                else if (rm == KdTree::KDRM_GTP_CHC)
208                {
209                        mRenderMethod = rm;
210                        int cmt = GtpVisibility::VisibilityEnvironment::COHERENT_HIERARCHICAL_CULLING;
211                        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface)
212                                .setOption("Algorithm", &cmt);
213                }
214                else
215                {
216                        return false;
217                }
218        }
219        // little hack in case someone uses "Algorithm" option from VisOptMan directly
220        else if (strKey == "Algorithm")
221        {
222                bool success = VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface)
223                        .setOption(strKey, pValue);
224                // change setting only if change in VisOptMan was successful
225                if (success)
226                {
227                        int val = *static_cast<const int *>(pValue);
228                        if (val == GtpVisibility::VisibilityEnvironment::FRUSTUM_CULLING)
229                                mRenderMethod = KdTree::KDRM_GTP_VFC;
230                        else if (val == GtpVisibility::VisibilityEnvironment::STOP_AND_WAIT_CULLING)
231                                mRenderMethod = KdTree::KDRM_GTP_SWC;
232                        else if (val == GtpVisibility::VisibilityEnvironment::COHERENT_HIERARCHICAL_CULLING)
233                                mRenderMethod = KdTree::KDRM_GTP_CHC;
234                        // default, should never happen
235                        else
236                                mRenderMethod = KdTree::KDRM_INTERNAL;
237                }
238                else
239                {
240                        mRenderMethod = KdTree::KDRM_INTERNAL;
241                }
242                return success;
243        }
244        else if (strKey == "ShowKdTree")
245        {
246                bool sk = *static_cast<const bool *>(pValue);
247                mShowBoxes = sk;
248                return true;
249        }
250        else if (strKey == "HiLiteLevel")
251        {
252                int hl = *static_cast<const int *>(pValue);
253                if (hl >= 0 && hl <= mMaxDepth)
254                {
255                        mHiLiteLevel = hl;
256                        if (mKdTree)
257                                mKdTree->setHiLiteLevel(mHiLiteLevel);
258                        return true;
259                }
260                else
261                {
262                        return false;
263                }
264        }
265        else if (strKey == "ShowAllBoxes")
266        {
267                bool sa = *static_cast<const bool *>(pValue);
268                mShowAllBoxes = sa;
269                if (mKdTree)
270                        mKdTree->setShowAllBoxes(mShowAllBoxes);
271                return true;
272        }
273        else if (strKey == "ShowNodes")
274        {
275                bool sn = *static_cast<const bool *>(pValue);
276                mShowNodes = sn;
277                if (mKdTree)
278                        mKdTree->setShowNodes(mShowNodes);
279                return true;
280        }
281        // options for CHC
282        else if (strKey == "UseDepthPass")
283        {
284                mUseDepthPass = (*static_cast<const bool *>(pValue));
285                return true;
286        }
287        else if (strKey == "PrepareVisualization")
288        {
289                mShowVisualization = (*static_cast<const bool *>(pValue));
290                return true;
291        }
292        else if (strKey == "RenderNodesForViz")
293        {
294                mRenderNodesForViz = (*static_cast<const bool *>(pValue));
295                return true;
296        }
297        else if (strKey == "RenderNodesContentForViz")
298        {
299                mRenderNodesContentForViz = (*static_cast<const bool *>(pValue));
300                return true;
301        }
302        else if (strKey == "SkyBoxEnabled")
303        {
304                mSkyBoxEnabled = (*static_cast<const bool *>(pValue));
305                return true;
306        }
307        else if (strKey == "SkyPlaneEnabled")
308        {
309                mSkyPlaneEnabled = (*static_cast<const bool *>(pValue));
310                return true;
311        }
312        else if (strKey == "SkyDomeEnabled")
313        {
314                mSkyDomeEnabled = (*static_cast<const bool *>(pValue));
315                return true;
316        }
317        else if (strKey == "VisualizeCulledNodes")
318        {
319                mVisualizeCulledNodes = (*static_cast<const bool *>(pValue));
320                return true;
321        }
322        else if (strKey == "DelayRenderTransparents")
323        {
324                mDelayRenderTransparents = (*static_cast<const bool *>(pValue));
325                return true;
326        }
327
328        else if (strKey == "DepthWrite")
329        {
330                mEnableDepthWrite = (*static_cast<const bool *>(pValue));
331                return true;
332        }
333        else if (strKey == "UseItemBuffer")
334        {
335                mUseItemBuffer = (*static_cast<const bool *>(pValue));
336                return true;
337        }
338        else if (strKey == "ExecuteVertexProgramForAllPasses")
339        {
340                mExecuteVertexProgramForAllPasses  = (*static_cast<const bool *>(pValue));
341                return true;
342        }
343        else if (strKey == "RenderTransparentsForItemBuffer")
344        {
345                mRenderTransparentsForItemBuffer  = (*static_cast<const bool *>(pValue));
346                return true;
347        }
348        else if (strKey == "DeleteRenderQueue")
349        {
350                mDeleteQueueAfterRendering = (*static_cast<const bool *>(pValue));
351                return true;
352        }
353        // options for viewcells
354        else if (strKey == "LoadViewCells")
355        {
356                if (!mViewCellsLoaded)
357                {
358                        String filename(static_cast<const char *>(pValue));
359                        mViewCellsLoaded = LoadViewCells(filename);     
360                }
361
362                return mViewCellsLoaded;
363        }
364        else if (strKey == "UseViewCells")
365        {
366                if (mViewCellsLoaded)
367                {
368                        mUseViewCells = *static_cast<const bool *>(pValue);
369
370                        // reset view cell
371                        OGRE_DELETE(mCurrentViewCell);
372
373                        if (mUseViewCells)
374                                mCurrentViewCell = mViewCellsManager->GenerateViewCell();
375
376                        mElementaryViewCell = NULL;
377
378                        // if using view cells, all objects are set to false initially
379                        SetObjectsVisible(!mUseViewCells);
380
381                        return true;
382                }
383                else
384                {
385                        return false;
386                }
387
388        }
389        else if (strKey == "UseVisibilityFilter")
390        {
391                if (mViewCellsLoaded)
392                {
393                        mUseVisibilityFilter = *static_cast<const bool *>(pValue);
394                        // set null =>recomputation of the pvs
395                        mElementaryViewCell = NULL;
396                        return true;
397                }
398                else
399                {
400                        return false;
401                }
402        }
403
404        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface)
405                .setOption(strKey, pValue) || SceneManager::setOption(strKey, pValue);
406}
407
408bool KdTreeSceneManager::getOption(const String& strKey, void* pDestValue)
409{
410        if (strKey == "KdTreeMaxDepth")
411        {
412                *static_cast<int *>(pDestValue) = mMaxDepth;
413                return true;
414        }
415        else if (strKey == "KT")
416        {
417                *static_cast<Real *>(pDestValue) = PlaneEvent::KT;
418                return true;
419        }
420        else if (strKey == "KI")
421        {
422                *static_cast<Real *>(pDestValue) = PlaneEvent::KI;
423                return true;
424        }
425        else if (strKey == "EnhancedVisibility")
426        {
427                if (mKdTree)
428                        *static_cast<bool *>(pDestValue) = mKdTree->getEnhancedVis();
429                else
430                        *static_cast<bool *>(pDestValue) = mEnhancedVisiblity;
431                return true;
432        }
433        else if (strKey == "BuildMethod")
434        {
435                *static_cast<KdTree::BuildMethod *>(pDestValue) = mBuildMethod;
436                return true;
437        }
438        else if (strKey == "RenderMethod")
439        {
440                *static_cast<KdTree::RenderMethod *>(pDestValue) = mRenderMethod;
441                return true;
442        }
443        else if (strKey == "ShowKdTree")
444        {
445                *static_cast<bool *>(pDestValue) = mShowBoxes;
446                return true;
447        }       
448        else if (strKey == "HiLiteLevel")
449        {
450                *static_cast<int *>(pDestValue) = mHiLiteLevel;
451                return true;
452        }
453        else if (strKey == "ShowAllBoxes")
454        {
455                *static_cast<bool *>(pDestValue) = mShowAllBoxes;
456                return true;
457        }
458        else if (strKey == "ShowNodes")
459        {
460                *static_cast<bool *>(pDestValue) = mShowNodes;
461                return true;
462        }
463        // vis options
464        else if (strKey == "NumHierarchyNodes")
465        {
466                unsigned int numnodes = 0;
467                if (mKdTree)
468                        numnodes = mKdTree->getStats().mNumNodes;
469
470                * static_cast<unsigned int *>(pDestValue) = (unsigned int)numnodes;
471                return true;
472        }
473        else if (strKey == "VisibilityManager")
474        {
475                * static_cast<GtpVisibility::VisibilityManager **>(pDestValue) =
476                        (GtpVisibility::VisibilityManager *)mVisibilityManager;
477                return true;
478        }
479        else if (strKey == "HierarchInterface")
480        {
481                * static_cast<GtpVisibility::HierarchyInterface **>(pDestValue) =
482                        (GtpVisibility::HierarchyInterface *)mHierarchyInterface;
483                return true;
484        }
485        // view cell options
486
487        else if (strKey == "UseViewCells")
488        {
489                *static_cast<bool *>(pDestValue) = mUseViewCells;
490                return mViewCellsLoaded;
491        }
492        else if (strKey == "UseVisibilityFilter")
493        {
494                *static_cast<bool *>(pDestValue) = mUseVisibilityFilter;
495                return mViewCellsLoaded;
496        }
497
498        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface)
499                .getOption(strKey, pDestValue) || SceneManager::getOption(strKey, pDestValue);
500}
501
502bool KdTreeSceneManager::getOptionKeys(StringVector &refKeys)
503{
504        refKeys.push_back("Algorithm");
505        refKeys.push_back("BuildMethod");
506        refKeys.push_back("DelayRenderTransparents");
507        refKeys.push_back("DeleteRenderQueue");
508        refKeys.push_back("DepthWrite");
509        refKeys.push_back("EnhancedVisibility");
510        refKeys.push_back("ExecuteVertexProgramForAllPasses");
511        refKeys.push_back("HiLiteLevel");
512        refKeys.push_back("HierarchInterface");
513        refKeys.push_back("KI");
514        refKeys.push_back("KT");
515        refKeys.push_back("KdTreeMaxDepth");
516        refKeys.push_back("LoadViewCells");
517        refKeys.push_back("NumHierarchyNodes");
518        refKeys.push_back("PrepareVisualization");
519        refKeys.push_back("RebuildKdTree");
520        refKeys.push_back("RenderMethod");
521        refKeys.push_back("RenderNodesContentForViz");
522        refKeys.push_back("RenderNodesForViz");
523        refKeys.push_back("RenderTransparentsForItemBuffer");
524        refKeys.push_back("ShowAllBoxes");
525        refKeys.push_back("ShowKdTree");
526        refKeys.push_back("ShowNodes");
527        refKeys.push_back("SkyBoxEnabled");
528        refKeys.push_back("SkyDomeEnabled");
529        refKeys.push_back("SkyPlaneEnabled");
530        refKeys.push_back("UseDepthPass");
531        refKeys.push_back("UseItemBuffer");
532        refKeys.push_back("UseViewCells");
533        refKeys.push_back("UseVisibilityFilter");
534        refKeys.push_back("VisibilityManager");
535        refKeys.push_back("VisualizeCulledNodes");
536        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface)
537                .getOptionKeys(refKeys);
538}
539
540bool KdTreeSceneManager::getOptionValues(const String & key, StringVector &refValueList)
541{
542        return SceneManager::getOptionValues(key, refValueList);
543}
544
545void KdTreeSceneManager::setVisibilityManager(GtpVisibility::VisibilityManager *visManager)
546{
547        mVisibilityManager = visManager;
548}
549
550GtpVisibility::VisibilityManager * KdTreeSceneManager::getVisibilityManager()
551{
552        return mVisibilityManager;
553}
554
555GtpVisibility::VisibilityManager * KdTreeSceneManager::GetVisibilityManager()
556{
557        return mVisibilityManager;
558}
559
560KdTreeHierarchyInterface * KdTreeSceneManager::GetHierarchyInterface()
561{
562        return mHierarchyInterface;
563}
564
565Camera* KdTreeSceneManager::createCamera(const String& name)
566{
567        // Check name not used
568        if (mCameras.find(name) != mCameras.end())
569        {
570                OGRE_EXCEPT(
571                        Exception::ERR_DUPLICATE_ITEM,
572                        "A camera with the name " + name + " already exists",
573                        "SceneManager::createCamera" );
574        }
575
576        Camera *c = new KdTreeCamera(name, this);
577        mCameras.insert(CameraList::value_type(name, c));
578
579        return c;
580}
581
582SceneNode* KdTreeSceneManager::createSceneNode(void)
583{
584        SceneNode* sn = new KdTreeSceneNode(this);
585        assert(mSceneNodes.find(sn->getName()) == mSceneNodes.end());
586        mSceneNodes[sn->getName()] = sn;
587        return sn;
588}
589
590SceneNode* KdTreeSceneManager::createSceneNode(const String& name)
591{
592        // Check name not used
593        if (mSceneNodes.find(name) != mSceneNodes.end())
594        {
595                OGRE_EXCEPT(
596                        Exception::ERR_DUPLICATE_ITEM,
597                        "A scene node with the name " + name + " already exists",
598                        "KdTreeSceneManager::createSceneNode" );
599        }
600
601        SceneNode* sn = new KdTreeSceneNode(this, name);
602        mSceneNodes[sn->getName()] = sn;
603        return sn;
604}
605
606Entity * KdTreeSceneManager::createEntity(const String& entityName, const String& meshName)
607{
608        Entity *ent = SceneManager::createEntity(entityName, meshName);
609#ifdef GTP_VISIBILITY_MODIFIED_OGRE
610        for (int i = 0; i < (int)ent->getNumSubEntities(); ++i)
611        {
612                ent->getSubEntity(i)->setId(mCurrentEntityId);
613        }
614
615        // increase counter of entity id values
616        ++ mCurrentEntityId;
617#endif
618        return ent;
619}
620
621// make sure it's called only for non-empty nodes .. avoids one uneccessary funciton call
622void KdTreeSceneManager::_updateNode(KdTreeSceneNode *node)
623{
624        //LogManager::getSingleton().logMessage("### _updateNode called for " + node->getName());
625
626        /* Rebuild kdtree when it was wiped out
627                * Usually this happens only before the first frame
628                * The initial AABB shall enclose all objects present
629                * in the scene at the time of construction
630                * TODO: find a more appropriate place for it,
631                * e.g., before the first render call
632                * teh stupid thing is I can't find any other place so far ...
633                */
634        if (!mKdTree)
635        {
636                mKdTree = new KdTree(mMaxDepth, mBuildMethod);
637                mKdTree->build(static_cast<KdTreeSceneNode *>(mSceneRoot));
638                mKdTree->setEnhancedVis(mEnhancedVisiblity);
639        }
640
641        // if the node is in the tree and _updateNode was called, then the node was moved/rotated/resized/wahtever
642        if (node->isAttached())
643        {
644                // TEST: perfomance when adding & removing for every frame
645                //mKdTree->remove(node);
646                //mKdTree->insert(node);
647        }
648        // there's a new node in town ...
649        else
650        {                       
651                // inserting single nodes yields sub-optimal results
652                // rebuilding tree takes too long
653                // "What now?", spoke Zeus ...
654
655                //mKdTree->insert(node);
656               
657                //delete mKdTree;
658                //mKdTree = new KdTree(mMaxDepth);
659                //mKdTree->build(static_cast<KdTreeSceneNode *>(mSceneRoot));
660        }
661
662}
663
664void KdTreeSceneManager::_updateSceneGraph(Camera* cam)
665{
666        mVisibilityManager->GetCullingManager()->SetHierarchyInterface(mHierarchyInterface);
667        mHierarchyInterface->SetRenderSystem(mDestRenderSystem);
668
669        SceneManager::_updateSceneGraph(cam);
670}
671
672void KdTreeSceneManager::_findVisibleObjects(Camera *cam, bool onlyShadowCasters)
673{
674        if (mRenderMethod == KdTree::KDRM_INTERNAL)
675        {
676                getRenderQueue()->clear();
677                if (mShowVisualization)
678                {
679                        PrepareVisualization(cam);
680                }
681                else
682                {
683                        mVisibleNodes.clear();
684                        if (mKdTree)
685                                mKdTree->queueVisibleObjects(KDCAMPTR_CAST(cam), getRenderQueue(), onlyShadowCasters, mShowBoxes, mVisibleNodes);
686                }
687        }
688        else
689        {
690                //-- show visible scene nodes and octree bounding boxes from last frame
691                if (mShowVisualization)
692                {
693                        PrepareVisualization(cam);
694                }
695                else
696                {       
697                        // for hierarchical culling, we interleave identification
698                        // and rendering of objects in _renderVisibibleObjects
699
700                        // for the shadow pass we use only standard rendering
701                        // because of low occlusion
702                        if (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE &&
703                                mIlluminationStage == IRS_RENDER_TO_TEXTURE)
704                        {
705                                getRenderQueue()->clear();
706                                if (mKdTree)
707                                        mKdTree->queueVisibleObjects(KDCAMPTR_CAST(cam), getRenderQueue(), onlyShadowCasters, mShowBoxes, mVisibleNodes);
708                        }
709
710                        // only shadow casters will be rendered in shadow texture pass
711                        if (0) mHierarchyInterface->SetOnlyShadowCasters(onlyShadowCasters);
712
713
714                        //-- apply view cell pvs -
715                        updatePvs(cam);
716                }
717                mVisibleNodes.clear(); 
718        }
719}
720
721void KdTreeSceneManager::_renderVisibleObjects()
722{
723        if (mRenderMethod == KdTree::KDRM_INTERNAL)
724        {
725                SceneManager::_renderVisibleObjects();
726        }
727        else
728        {
729                InitDepthPass();          // create material for depth pass
730                InitItemBufferPass(); // create material for item buffer pass
731
732                // save ambient light to reset later
733                ColourValue savedAmbient = mAmbientLight;
734
735                //-- apply standard rendering for some modes (e.g., visualization, shadow pass)
736
737                if (mShowVisualization ||
738                        (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE &&
739                        mIlluminationStage == IRS_RENDER_TO_TEXTURE))
740                {       
741                        IlluminationRenderStage savedStage = mIlluminationStage;
742
743                        if (mShowVisualization)
744                        {
745                                // disable illumination stage to prevent rendering shadows
746                                mIlluminationStage = IRS_NONE;
747                        }
748
749                        // standard rendering for shadow maps because of performance
750                        SceneManager::_renderVisibleObjects();
751
752                        mIlluminationStage = savedStage;
753                }
754                else //-- the hierarchical culling algorithm
755                {
756                        // this is also called in TerrainSceneManager: really necessary?
757                        //mDestRenderSystem -> setLightingEnabled(false);
758
759                        // don't render backgrounds for item buffer
760                        if (mUseItemBuffer)
761                        {
762                                clearSpecialCaseRenderQueues();
763                                getRenderQueue()->clear();
764                        }
765
766                        //-- hierarchical culling
767
768                        // the objects of different layers (e.g., background, scene,
769                        // overlay) must be identified and rendered one after another
770
771                        //-- render all early skies
772                        clearSpecialCaseRenderQueues();
773                        addSpecialCaseRenderQueue(RENDER_QUEUE_BACKGROUND);
774                        addSpecialCaseRenderQueue(RENDER_QUEUE_SKIES_EARLY);
775                        setSpecialCaseRenderQueueMode(SceneManager::SCRQM_INCLUDE);
776
777                        SceneManager::_renderVisibleObjects();
778
779#ifdef GTP_VISIBILITY_MODIFIED_OGRE
780                        // delete previously rendered content
781                        _deleteRenderedQueueGroups();
782#endif
783
784                        //-- prepare queue for visible objects (i.e., all but overlay and skies late)
785                        clearSpecialCaseRenderQueues();
786                        addSpecialCaseRenderQueue(RENDER_QUEUE_SKIES_LATE);
787                        addSpecialCaseRenderQueue(RENDER_QUEUE_OVERLAY);
788
789                        // exclude this queues from hierarchical rendering
790                        setSpecialCaseRenderQueueMode(SceneManager::SCRQM_EXCLUDE);
791
792
793                        // set all necessary parameters for
794                        // hierarchical visibility culling and rendering
795                        InitVisibilityCulling(mCameraInProgress);
796
797
798                        /**
799                        * the hierarchical culling algorithm
800                        * for depth pass: we just find objects and update depth buffer
801                        * for "delayed" rendering: we render some passes afterwards
802                        * e.g., transparents, because they need front-to-back sorting
803                        **/
804
805                        mVisibilityManager->ApplyVisibilityCulling();
806
807                        // delete remaining renderables from queue:
808                        // all which are not in mLeavePassesInQueue
809#ifdef GTP_VISIBILITY_MODIFIED_OGRE
810                        _deleteRenderedQueueGroups(mLeavePassesInQueue);
811#endif
812
813                        //-- reset parameters
814                        mIsDepthPassPhase = false;
815                        mIsItemBufferPhase = false;
816                        mSkipTransparents = false;
817                        mIsHierarchicalCulling = false;
818
819                        mLeavePassesInQueue = 0;
820
821                        // add visible nodes found by the visibility culling algorithm
822                        if (mUseDepthPass)
823                        {
824                                KdTree::NodeList::const_iterator it, end = mVisibleNodes.end();
825                                for (it = mVisibleNodes.begin(); it != end; it++)
826                                {
827                                        (*it)->queueVisibleObjects(mHierarchyInterface->GetFrameId(), mCameraInProgress,
828                                                getRenderQueue(), false, mShowBoxes);
829                                }
830                        }
831
832                        //-- now we can render all remaining queue objects
833                        //-- used for depth pass, transparents, overlay
834                        clearSpecialCaseRenderQueues();
835
836                        SceneManager::_renderVisibleObjects();
837                } // hierarchical culling
838
839
840                // reset ambient light
841                setAmbientLight(savedAmbient);
842
843                if (!mDeleteQueueAfterRendering)
844                        getRenderQueue()->clear(); // finally clear render queue
845                else
846                        OGRE_DELETE(mRenderQueue); // HACK: should rather only be cleared ...
847
848                if (0) WriteLog(); // write out stats
849        }
850}
851
852
853void KdTreeSceneManager::_renderNode(KdTree::NodePtr node, Camera * cam,
854                                                                         bool onlyShadowCasters, int leavePassesInQueue)
855{
856        RenderQueueGroup *currentGroup =
857                getRenderQueue()->getQueueGroup(getRenderQueue()->getDefaultQueueGroup());
858        currentGroup->clear(leavePassesInQueue);
859
860        node->queueVisibleObjects(mHierarchyInterface->GetFrameId(), cam, getRenderQueue(),
861                onlyShadowCasters, mShowBoxes);
862        mVisibleNodes.push_back(node);
863
864        _renderQueueGroupObjects(currentGroup, QueuedRenderableCollection::OM_PASS_GROUP);
865}
866
867//-----------------------------------------------------------------------
868const Pass *KdTreeSceneManager::_setPass(const Pass* pass, bool evenIfSuppressed)
869{
870        if (mRenderMethod == KdTree::KDRM_INTERNAL)
871        {
872                return SceneManager::_setPass(pass);
873        }
874
875        // TODO: setting vertex program is not efficient
876        //Pass *usedPass = ((mIsDepthPassPhase && !pass->hasVertexProgram()) ? mDepthPass : pass);
877
878        // set depth fill pass if we currently do not make an aabb occlusion query
879        const bool useDepthPass =
880                (mIsDepthPassPhase && !mHierarchyInterface->IsBoundingBoxQuery());
881
882        const IlluminationRenderStage savedStage = mIlluminationStage;
883
884        // set illumination stage to NONE so no shadow material is used
885        // for depth pass or for occlusion query
886        if (mIsDepthPassPhase || mHierarchyInterface->IsBoundingBoxQuery())
887        {
888                mIlluminationStage = IRS_NONE;
889        }
890
891        // --- set vertex program of current pass in order to set correct depth
892        if (mExecuteVertexProgramForAllPasses &&
893                mIsDepthPassPhase &&
894                pass->hasVertexProgram())
895        {
896                // add vertex program of current pass to depth pass
897                mDepthPass->setVertexProgram(pass->getVertexProgramName());
898
899                if (mDepthPass->hasVertexProgram())
900                {
901                        const GpuProgramPtr& prg = mDepthPass->getVertexProgram();
902                        // Load this program if not done already
903                        if (!prg->isLoaded())
904                                prg->load();
905                        // Copy params
906                        mDepthPass->setVertexProgramParameters(pass->getVertexProgramParameters());
907                }
908        }
909        else if (mDepthPass->hasVertexProgram()) // reset vertex program
910        {
911                mDepthPass->setVertexProgram("");
912        }
913
914        const Pass *usedPass = useDepthPass ? mDepthPass : pass;
915
916        // save old depth write: needed for item buffer
917        const bool IsDepthWrite = usedPass->getDepthWriteEnabled();
918
919        // global option which enables / disables depth writes
920        if (!mEnableDepthWrite)
921        {
922                //      usedPass->setDepthWriteEnabled(false);
923        }
924        //else if (mIsItemBufferPass) {usedPass = mItemBufferPass;}
925
926
927        //-- set actual pass here
928        const Pass *result = SceneManager::_setPass(usedPass);
929
930
931        // reset depth write
932        if (!mEnableDepthWrite)
933        {
934                //      usedPass->setDepthWriteEnabled(IsDepthWrite);
935        }
936
937        // reset illumination stage
938        mIlluminationStage = savedStage;
939
940        return result;
941}
942//-----------------------------------------------------------------------
943void KdTreeSceneManager::renderBasicQueueGroupObjects(RenderQueueGroup* pGroup,
944                                                                                                          QueuedRenderableCollection::OrganisationMode om)
945{
946        // Basic render loop
947        // Iterate through priorities
948        RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
949
950        while (groupIt.hasMoreElements())
951        {
952                RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
953
954                // Sort the queue first
955                pPriorityGrp->sort(mCameraInProgress);
956
957                // Do solids
958                renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
959
960                // for correct rendering, transparents must be rendered after hierarchical culling
961                // => do nothing
962
963                // Do transparents (always descending)
964                if (mRenderMethod == KdTree::KDRM_INTERNAL || !mSkipTransparents)
965                {
966                        renderObjects(pPriorityGrp->getTransparents(),
967                                QueuedRenderableCollection::OM_SORT_DESCENDING, true);
968                }
969
970
971        }// for each priority
972}
973//-----------------------------------------------------------------------
974bool KdTreeSceneManager::validatePassForRendering(Pass* pass)
975{
976        if (mRenderMethod == KdTree::KDRM_INTERNAL)
977        {
978                return SceneManager::validatePassForRendering(pass);
979        }
980
981        // skip all but first pass if we are doing the depth pass
982        if ((mIsDepthPassPhase || mIsItemBufferPhase) && (pass->getIndex() > 0))
983        {
984                return false;
985        }
986        // all but first pass
987        /*else if ((!mIsDepthPassPhase || mIsItemBufferPhase) && (pass->getIndex() != 0))
988        {
989        return false;
990        }*/
991
992        return SceneManager::validatePassForRendering(pass);
993}
994//-----------------------------------------------------------------------
995void KdTreeSceneManager::_renderQueueGroupObjects(RenderQueueGroup* pGroup,
996                                                                                                  QueuedRenderableCollection::OrganisationMode om)
997{
998        if (mRenderMethod == KdTree::KDRM_INTERNAL || !mIsItemBufferPhase)
999        {
1000                SceneManager::_renderQueueGroupObjects(pGroup, om);
1001                return;
1002        }
1003#ifdef  ITEM_BUFFER
1004        //-- item buffer
1005        //-- item buffer: render objects using false colors
1006
1007        // Iterate through priorities
1008        RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1009
1010        while (groupIt.hasMoreElements())
1011        {
1012                RenderItemBuffer(groupIt.getNext());
1013        }
1014#endif // ITEM_BUFFER
1015}
1016//-----------------------------------------------------------------------
1017void KdTreeSceneManager::renderAdditiveStencilShadowedQueueGroupObjects(
1018        RenderQueueGroup* pGroup, QueuedRenderableCollection::OrganisationMode om)
1019{
1020        // only render solid passes during hierarchical culling
1021        if (mIsHierarchicalCulling)
1022        {
1023                RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1024                LightList lightList;
1025
1026                while (groupIt.hasMoreElements())
1027                {
1028                        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1029
1030                        // Sort the queue first
1031                        pPriorityGrp->sort(mCameraInProgress);
1032
1033                        // Clear light list
1034                        lightList.clear();
1035
1036                        // Render all the ambient passes first, no light iteration, no lights
1037                        /*** msz: no more IRS_AMBIENT, see OgreSceneManager.h ***/
1038                        // mIlluminationStage = IRS_AMBIENT;
1039
1040                        SceneManager::renderObjects(pPriorityGrp->getSolidsBasic(), om, false, &lightList);
1041                        // Also render any objects which have receive shadows disabled
1042                        SceneManager::renderObjects(pPriorityGrp->getSolidsNoShadowReceive(), om, true);
1043                }
1044        }
1045        else // render the rest of the passes
1046        {
1047                SceneManager::renderAdditiveStencilShadowedQueueGroupObjects(pGroup, om);
1048        }
1049}
1050//-----------------------------------------------------------------------
1051void KdTreeSceneManager::renderModulativeStencilShadowedQueueGroupObjects(
1052        RenderQueueGroup* pGroup, QueuedRenderableCollection::OrganisationMode om)
1053{
1054        if (mIsHierarchicalCulling)
1055        {
1056                // Iterate through priorities
1057                RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1058
1059                while (groupIt.hasMoreElements())
1060                {
1061                        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1062
1063                        // Sort the queue first
1064                        pPriorityGrp->sort(mCameraInProgress);
1065
1066                        // Do (shadowable) solids
1067                        SceneManager::renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
1068                }
1069        }
1070        else
1071        {
1072                SceneManager::renderModulativeStencilShadowedQueueGroupObjects(pGroup, om);
1073        }
1074}
1075//-----------------------------------------------------------------------
1076void KdTreeSceneManager::InitDepthPass()
1077{
1078        MaterialPtr depthMat = MaterialManager::getSingleton().getByName("Visibility/DepthPass");
1079
1080        if (depthMat.isNull())
1081        {
1082                depthMat = MaterialManager::getSingleton().create(
1083                        "Visibility/DepthPass",
1084                        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
1085
1086                mDepthPass = depthMat->getTechnique(0)->getPass(0);
1087                mDepthPass->setColourWriteEnabled(false);
1088                mDepthPass->setDepthWriteEnabled(true);
1089                mDepthPass->setLightingEnabled(false);
1090        }
1091        else
1092        {
1093                mDepthPass = depthMat->getTechnique(0)->getPass(0);
1094        }
1095}
1096//-----------------------------------------------------------------------
1097void KdTreeSceneManager::InitItemBufferPass()
1098{
1099        MaterialPtr itemBufferMat = MaterialManager::getSingleton().
1100                getByName("Visibility/ItemBufferPass");
1101
1102        if (itemBufferMat.isNull())
1103        {
1104                // Init
1105                itemBufferMat = MaterialManager::getSingleton().create("Visibility/ItemBufferPass",
1106                        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
1107
1108                mItemBufferPass = itemBufferMat->getTechnique(0)->getPass(0);
1109                mItemBufferPass->setColourWriteEnabled(true);
1110                mItemBufferPass->setDepthWriteEnabled(true);
1111                mItemBufferPass->setLightingEnabled(true);
1112                //mItemBufferPass->setLightingEnabled(false);
1113        }
1114        else
1115        {
1116                mItemBufferPass = itemBufferMat->getTechnique(0)->getPass(0);
1117        }
1118        //mItemBufferPass->setAmbient(1, 1, 0);
1119}
1120//-----------------------------------------------------------------------
1121void KdTreeSceneManager::PrepareVisualization(Camera *cam)
1122{
1123        // add player camera for visualization purpose
1124        try
1125        {
1126                Camera *c;
1127                if ((c = getCamera("PlayerCam")) != NULL)
1128                {
1129                        getRenderQueue()->addRenderable(c);
1130                }   
1131        }
1132        catch (...)
1133        {
1134                // ignore
1135        }
1136
1137        if (mRenderNodesForViz || mRenderNodesContentForViz)
1138        {
1139                RenderQueue * queue = getRenderQueue();
1140                unsigned long frameid = 0;
1141
1142                if (mRenderMethod == KdTree::KDRM_INTERNAL)
1143                        frameid = Root::getSingleton().getCurrentFrameNumber();
1144                else
1145                        frameid = mHierarchyInterface->GetFrameId();
1146
1147                for (KdTree::NodeList::iterator it = mVisibleNodes.begin(); it != mVisibleNodes.end(); ++it)
1148                {
1149                        if (mRenderNodesForViz && (*it)->isLeaf())
1150                        {
1151                                WireBoundingBox * wirebox = (*it)->getWireBoundingBox();
1152                                wirebox->setMaterial("KdTree/BoxViz");
1153                                getRenderQueue()->addRenderable(wirebox);
1154                        }
1155                        // add renderables itself
1156                        if (mRenderNodesContentForViz)
1157                        {
1158                                (*it)->queueVisibleObjects(frameid, cam, queue, false, false);
1159                        }
1160                }
1161        }       
1162}
1163//-----------------------------------------------------------------------
1164void KdTreeSceneManager::InitVisibilityCulling(Camera *cam)
1165{
1166        // reset culling manager stats
1167        mVisibilityManager->GetCullingManager()->InitFrame(mVisualizeCulledNodes);
1168
1169        // set depth pass flag before rendering
1170        mIsDepthPassPhase = mUseDepthPass;
1171
1172        mIsHierarchicalCulling = true; // during hierarchical culling
1173
1174        // item buffer needs full ambient lighting to use item colors as unique id
1175        if (mUseItemBuffer)
1176        {
1177                mIsItemBufferPhase = true;
1178                setAmbientLight(ColourValue(1,1,1,1));
1179        }
1180
1181
1182        // set passes which are stored in render queue
1183        // for rendering AFTER hierarchical culling, i.e., passes which need
1184        // a special rendering order
1185
1186        mLeavePassesInQueue = 0;
1187
1188        // if we have the depth pass or use an item buffer, no passes are left in the queue
1189        if (1 && !mUseDepthPass && !mUseItemBuffer)
1190        {
1191                if (mShadowTechnique == SHADOWTYPE_STENCIL_ADDITIVE)
1192                {
1193                        // TODO: remove this pass because it should be processed during hierarchical culling
1194                        //mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_NOSHADOW;
1195
1196                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_DECAL;
1197                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_DIFFUSE_SPECULAR;
1198                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
1199
1200                        // just render ambient passes
1201                        /*** msz: no more IRS_AMBIENT, see OgreSceneManager.h ***/
1202                        // mIlluminationStage = IRS_AMBIENT;
1203                        //getRenderQueue()->setSplitPassesByLightingType(true);
1204                }
1205
1206                if (mShadowTechnique == SHADOWTYPE_STENCIL_MODULATIVE)
1207                {
1208                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_NOSHADOW;
1209                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
1210                }
1211
1212                // transparents should be rendered after hierarchical culling to
1213                // provide front-to-back ordering
1214                if (mDelayRenderTransparents)
1215                {
1216                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
1217                }
1218        }
1219
1220        // skip rendering transparents during the hierarchical culling
1221        // (because they will be rendered afterwards)
1222        mSkipTransparents =
1223                (mIsDepthPassPhase || (mLeavePassesInQueue & RenderPriorityGroup::TRANSPARENT_PASSES));
1224
1225        // -- initialise interface for rendering traversal of the hierarchy
1226        mHierarchyInterface->SetHierarchyRoot(mKdTree->getRoot());
1227
1228        // possible two cameras (one for culling, one for rendering)
1229        mHierarchyInterface->InitTraversal(mCameraInProgress,
1230                /*mCullCamera ? getCamera("CullCamera") : */NULL,
1231                mLeavePassesInQueue);
1232
1233}
1234
1235//-------------------------------------------------------------------------
1236void KdTreeSceneManager::SetObjectsVisible(const bool visible)
1237{
1238        GtpVisibilityPreprocessor::ObjectContainer::iterator it, it_end = mObjects.end();
1239
1240        for (it = mObjects.begin(); it != it_end; ++ it)
1241        {
1242                OgreMeshInstance *omi = static_cast<OgreMeshInstance *>(*it);
1243                Entity *ent = omi->GetMesh();
1244
1245                ent->setVisible(visible);
1246        }
1247}
1248//-----------------------------------------------------------------------
1249bool KdTreeSceneManager::LoadViewCells(const String &filename)
1250{
1251        // objects are set to invisible initially
1252        SetObjectsVisible(false);
1253
1254        const string bboxesFilename = mVisibilityManager->GetVisibilityEnvironment()->getViewCellsFileName();
1255
1256        // converter between view cell ids and Ogre entites
1257        GtpVisibilityPreprocessor::IndexedBoundingBoxContainer iboxes;
1258        OgreBoundingBoxConverter bconverter(this);
1259
1260        // load the view cells assigning the found objects to the pvss
1261        mViewCellsManager =
1262                GtpVisibilityPreprocessor::ViewCellsManager::LoadViewCells(filename, &mObjects, false, &bconverter);
1263
1264        return (mViewCellsManager != NULL);
1265}
1266//-------------------------------------------------------------------------
1267void KdTreeSceneManager::applyViewCellPvs(GtpVisibilityPreprocessor::ViewCell *vc,
1268                                                                                                        const bool load)
1269{       // NOTE: should not happen, rather apply view cell representing unbounded space then
1270        if (!vc)
1271        {       
1272                // set everything visible for savety
1273                SetObjectsVisible(true);
1274
1275                return;
1276        }
1277
1278        GtpVisibilityPreprocessor::ObjectPvsMap::const_iterator oit,
1279                oit_end = vc->GetPvs().mEntries.end();
1280
1281        //-- PVS of view cell
1282        for (oit = vc->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
1283        {
1284                if (!(*oit).first) continue;
1285
1286                OgreMeshInstance *omi = dynamic_cast<OgreMeshInstance *>((*oit).first);
1287                omi->GetMesh()->setVisible(load);
1288                //GtpVisibilityPreprocessor::Debug << "assigned id " << omi->GetId() << endl;
1289        }
1290}
1291//-------------------------------------------------------------------------
1292void KdTreeSceneManager::updatePvs(Camera *cam)
1293{
1294        if (!(mViewCellsLoaded && mUseViewCells))
1295                return;
1296
1297        const GtpVisibilityPreprocessor::Vector3 viewPoint =
1298                OgreTypeConverter::ConvertFromOgre(cam->getDerivedPosition());
1299
1300        GtpVisibilityPreprocessor::ViewCell *newElementary =
1301                mViewCellsManager->GetViewCell(viewPoint);
1302
1303        // elementary view cell did not change => apply same pvs
1304        if (mElementaryViewCell == newElementary)
1305                return;
1306
1307        mElementaryViewCell = newElementary;
1308        //LogManager::getSingleton().logMessage("unloading");
1309        //-- unload old pvs
1310        applyViewCellPvs(mCurrentViewCell, false);
1311
1312
1313        //-- the new view cell
1314
1315        GtpVisibilityPreprocessor::ViewCell *viewCell;
1316
1317
1318        if (mUseVisibilityFilter)
1319        {
1320                //-- compute new filtered cell
1321                GtpVisibilityPreprocessor::PrVs prvs;
1322                mViewCellsManager->GetPrVS(viewPoint, prvs, 5);
1323                viewCell = prvs.mViewCell;
1324        }
1325        else
1326        {
1327                viewCell = newElementary;
1328        }
1329        //LogManager::getSingleton().logMessage("loading");
1330        //-- load new pvs
1331        applyViewCellPvs(viewCell, true);
1332
1333        // store pvs
1334        mCurrentViewCell->SetPvs(viewCell->GetPvs());
1335
1336        // delete merge tree of filtered view cell
1337        if (mUseVisibilityFilter)
1338                mViewCellsManager->DeleteLocalMergeTree(viewCell);
1339}
1340
1341//-----------------------------------------------------------------------
1342void KdTreeSceneManager::WriteLog()
1343{
1344        std::stringstream d;
1345
1346        d << "Depth pass: " << StringConverter::toString(mUseDepthPass) << ", "
1347                << "Delay transparents: " << StringConverter::toString(mDelayRenderTransparents) << ", "
1348                << "Use optimization: " << StringConverter::toString(mHierarchyInterface->GetTestGeometryForVisibleLeaves()) << ", "
1349                << "Algorithm type: " << mVisibilityManager->GetCullingManagerType() << ", "
1350                << "Hierarchy nodes: " << (mKdTree ? mKdTree->getStats().mNumNodes : 0) << ", "
1351                << "Traversed nodes: " << mHierarchyInterface->GetNumTraversedNodes() << ", "
1352                << "Rendered nodes: " << mHierarchyInterface->GetNumRenderedNodes() << ", "
1353                << "Query culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumQueryCulledNodes() << ", "
1354                << "Frustum culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumFrustumCulledNodes() << ", "
1355                << "Queries issued: " << mVisibilityManager->GetCullingManager()->GetNumQueriesIssued() << ", "
1356                << "Found objects: " << (int)mVisibleNodes.size() << "\n"
1357                ;
1358
1359        LogManager::getSingleton().logMessage(d.str());
1360}
1361
1362/************************************************************************/
1363/* Factory for KdTreeSceneManager                                       */
1364/************************************************************************/
1365//-----------------------------------------------------------------------
1366//-----------------------------------------------------------------------
1367const String KdTreeSceneManagerFactory::FACTORY_TYPE_NAME = "KdTreeSceneManager";
1368//-----------------------------------------------------------------------
1369void KdTreeSceneManagerFactory::initMetaData(void) const
1370{
1371        mMetaData.typeName = FACTORY_TYPE_NAME;
1372        mMetaData.description = "Scene manager that organises the scene based on a kd-tree";
1373        mMetaData.sceneTypeMask = 0xFFFF; // support all types of scenes (hopefully)
1374        mMetaData.worldGeometrySupported = false;
1375}
1376//-----------------------------------------------------------------------
1377SceneManager* KdTreeSceneManagerFactory::createInstance(
1378        const String& instanceName)
1379{
1380        return new KdTreeSceneManager(instanceName, visManager);
1381}
1382//-----------------------------------------------------------------------
1383void KdTreeSceneManagerFactory::destroyInstance(SceneManager* instance)
1384{
1385        delete instance;
1386}
1387
1388} // namespace Ogre
1389
Note: See TracBrowser for help on using the repository browser.