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

Revision 1304, 40.1 KB checked in by szydlowski, 18 years ago (diff)

final touches

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_RECURSIVE),
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                        {
686                                // determine visibility
687                                mKdTree->queueVisibleObjects(KDCAMPTR_CAST(cam), getRenderQueue(), onlyShadowCasters, mShowBoxes, mVisibleNodes);
688                                // apply view cell pvs
689                                updatePvs(cam);
690                        }
691                }
692        }
693        else
694        {
695                //-- show visible scene nodes and octree bounding boxes from last frame
696                if (mShowVisualization)
697                {
698                        PrepareVisualization(cam);
699                }
700                else
701                {       
702                        // for hierarchical culling, we interleave identification
703                        // and rendering of objects in _renderVisibibleObjects
704
705                        // for the shadow pass we use only standard rendering
706                        // because of low occlusion
707                        if (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE &&
708                                mIlluminationStage == IRS_RENDER_TO_TEXTURE)
709                        {
710                                getRenderQueue()->clear();
711                                if (mKdTree)
712                                        mKdTree->queueVisibleObjects(KDCAMPTR_CAST(cam), getRenderQueue(), onlyShadowCasters, mShowBoxes, mVisibleNodes);
713                        }
714
715                        // only shadow casters will be rendered in shadow texture pass
716                        if (0) mHierarchyInterface->SetOnlyShadowCasters(onlyShadowCasters);
717
718
719                        //-- apply view cell pvs -
720                        updatePvs(cam);
721                }
722                mVisibleNodes.clear(); 
723        }
724}
725
726void KdTreeSceneManager::_renderVisibleObjects()
727{
728        if (mRenderMethod == KdTree::KDRM_INTERNAL)
729        {
730                SceneManager::_renderVisibleObjects();
731        }
732        else
733        {
734                InitDepthPass();          // create material for depth pass
735                InitItemBufferPass(); // create material for item buffer pass
736
737                // save ambient light to reset later
738                ColourValue savedAmbient = mAmbientLight;
739
740                //-- apply standard rendering for some modes (e.g., visualization, shadow pass)
741
742                if (mShowVisualization ||
743                        (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE &&
744                        mIlluminationStage == IRS_RENDER_TO_TEXTURE))
745                {       
746                        IlluminationRenderStage savedStage = mIlluminationStage;
747
748                        if (mShowVisualization)
749                        {
750                                // disable illumination stage to prevent rendering shadows
751                                mIlluminationStage = IRS_NONE;
752                        }
753
754                        // standard rendering for shadow maps because of performance
755                        SceneManager::_renderVisibleObjects();
756
757                        mIlluminationStage = savedStage;
758                }
759                else //-- the hierarchical culling algorithm
760                {
761                        // this is also called in TerrainSceneManager: really necessary?
762                        //mDestRenderSystem -> setLightingEnabled(false);
763
764                        // don't render backgrounds for item buffer
765                        if (mUseItemBuffer)
766                        {
767                                clearSpecialCaseRenderQueues();
768                                getRenderQueue()->clear();
769                        }
770
771                        //-- hierarchical culling
772
773                        // the objects of different layers (e.g., background, scene,
774                        // overlay) must be identified and rendered one after another
775
776                        //-- render all early skies
777                        clearSpecialCaseRenderQueues();
778                        addSpecialCaseRenderQueue(RENDER_QUEUE_BACKGROUND);
779                        addSpecialCaseRenderQueue(RENDER_QUEUE_SKIES_EARLY);
780                        setSpecialCaseRenderQueueMode(SceneManager::SCRQM_INCLUDE);
781
782                        SceneManager::_renderVisibleObjects();
783
784#ifdef GTP_VISIBILITY_MODIFIED_OGRE
785                        // delete previously rendered content
786                        _deleteRenderedQueueGroups();
787#endif
788
789                        //-- prepare queue for visible objects (i.e., all but overlay and skies late)
790                        clearSpecialCaseRenderQueues();
791                        addSpecialCaseRenderQueue(RENDER_QUEUE_SKIES_LATE);
792                        addSpecialCaseRenderQueue(RENDER_QUEUE_OVERLAY);
793
794                        // exclude this queues from hierarchical rendering
795                        setSpecialCaseRenderQueueMode(SceneManager::SCRQM_EXCLUDE);
796
797
798                        // set all necessary parameters for
799                        // hierarchical visibility culling and rendering
800                        InitVisibilityCulling(mCameraInProgress);
801
802
803                        /**
804                        * the hierarchical culling algorithm
805                        * for depth pass: we just find objects and update depth buffer
806                        * for "delayed" rendering: we render some passes afterwards
807                        * e.g., transparents, because they need front-to-back sorting
808                        **/
809
810                        mVisibilityManager->ApplyVisibilityCulling();
811
812                        // delete remaining renderables from queue:
813                        // all which are not in mLeavePassesInQueue
814#ifdef GTP_VISIBILITY_MODIFIED_OGRE
815                        _deleteRenderedQueueGroups(mLeavePassesInQueue);
816#endif
817
818                        //-- reset parameters
819                        mIsDepthPassPhase = false;
820                        mIsItemBufferPhase = false;
821                        mSkipTransparents = false;
822                        mIsHierarchicalCulling = false;
823
824                        mLeavePassesInQueue = 0;
825
826                        // add visible nodes found by the visibility culling algorithm
827                        if (mUseDepthPass)
828                        {
829                                KdTree::NodeList::const_iterator it, end = mVisibleNodes.end();
830                                for (it = mVisibleNodes.begin(); it != end; it++)
831                                {
832                                        (*it)->queueVisibleObjects(mHierarchyInterface->GetFrameId(), mCameraInProgress,
833                                                getRenderQueue(), false, mShowBoxes);
834                                }
835                        }
836
837                        //-- now we can render all remaining queue objects
838                        //-- used for depth pass, transparents, overlay
839                        clearSpecialCaseRenderQueues();
840
841                        SceneManager::_renderVisibleObjects();
842                } // hierarchical culling
843
844
845                // reset ambient light
846                setAmbientLight(savedAmbient);
847
848
849                // almost same effect as below
850                getRenderQueue()->clear(mDeleteQueueAfterRendering);
851
852                //if (!mDeleteQueueAfterRendering)
853                //      getRenderQueue()->clear(true); // finally clear render queue
854                //else
855                //      OGRE_DELETE(mRenderQueue); // HACK: should rather only be cleared ...
856
857                if (0) WriteLog(); // write out stats
858        }
859}
860
861
862void KdTreeSceneManager::_renderNode(KdTree::NodePtr node, Camera * cam,
863                                                                         bool onlyShadowCasters, int leavePassesInQueue)
864{
865        RenderQueueGroup *currentGroup =
866                getRenderQueue()->getQueueGroup(getRenderQueue()->getDefaultQueueGroup());
867        currentGroup->clear(leavePassesInQueue);
868
869        node->queueVisibleObjects(mHierarchyInterface->GetFrameId(), cam, getRenderQueue(),
870                onlyShadowCasters, mShowBoxes);
871        mVisibleNodes.push_back(node);
872
873        _renderQueueGroupObjects(currentGroup, QueuedRenderableCollection::OM_PASS_GROUP);
874}
875
876//-----------------------------------------------------------------------
877const Pass *KdTreeSceneManager::_setPass(const Pass* pass, bool evenIfSuppressed)
878{
879        if (mRenderMethod == KdTree::KDRM_INTERNAL)
880        {
881                return SceneManager::_setPass(pass);
882        }
883
884        // TODO: setting vertex program is not efficient
885        //Pass *usedPass = ((mIsDepthPassPhase && !pass->hasVertexProgram()) ? mDepthPass : pass);
886
887        // set depth fill pass if we currently do not make an aabb occlusion query
888        const bool useDepthPass =
889                (mIsDepthPassPhase && !mHierarchyInterface->IsBoundingBoxQuery());
890
891        const IlluminationRenderStage savedStage = mIlluminationStage;
892
893        // set illumination stage to NONE so no shadow material is used
894        // for depth pass or for occlusion query
895        if (mIsDepthPassPhase || mHierarchyInterface->IsBoundingBoxQuery())
896        {
897                mIlluminationStage = IRS_NONE;
898        }
899
900        // --- set vertex program of current pass in order to set correct depth
901        if (mExecuteVertexProgramForAllPasses &&
902                mIsDepthPassPhase &&
903                pass->hasVertexProgram())
904        {
905                // add vertex program of current pass to depth pass
906                mDepthPass->setVertexProgram(pass->getVertexProgramName());
907
908                if (mDepthPass->hasVertexProgram())
909                {
910                        const GpuProgramPtr& prg = mDepthPass->getVertexProgram();
911                        // Load this program if not done already
912                        if (!prg->isLoaded())
913                                prg->load();
914                        // Copy params
915                        mDepthPass->setVertexProgramParameters(pass->getVertexProgramParameters());
916                }
917        }
918        else if (mDepthPass->hasVertexProgram()) // reset vertex program
919        {
920                mDepthPass->setVertexProgram("");
921        }
922
923        const Pass *usedPass = useDepthPass ? mDepthPass : pass;
924
925        // save old depth write: needed for item buffer
926        const bool IsDepthWrite = usedPass->getDepthWriteEnabled();
927
928        // global option which enables / disables depth writes
929        if (!mEnableDepthWrite)
930        {
931                //      usedPass->setDepthWriteEnabled(false);
932        }
933        //else if (mIsItemBufferPass) {usedPass = mItemBufferPass;}
934
935
936        //-- set actual pass here
937        const Pass *result = SceneManager::_setPass(usedPass);
938
939
940        // reset depth write
941        if (!mEnableDepthWrite)
942        {
943                //      usedPass->setDepthWriteEnabled(IsDepthWrite);
944        }
945
946        // reset illumination stage
947        mIlluminationStage = savedStage;
948
949        return result;
950}
951//-----------------------------------------------------------------------
952void KdTreeSceneManager::renderBasicQueueGroupObjects(RenderQueueGroup* pGroup,
953                                                                                                          QueuedRenderableCollection::OrganisationMode om)
954{
955        // Basic render loop
956        // Iterate through priorities
957        RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
958
959        while (groupIt.hasMoreElements())
960        {
961                RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
962
963                // Sort the queue first
964                pPriorityGrp->sort(mCameraInProgress);
965
966                // Do solids
967                renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
968
969                // for correct rendering, transparents must be rendered after hierarchical culling
970                // => do nothing
971
972                // Do transparents (always descending)
973                if (mRenderMethod == KdTree::KDRM_INTERNAL || !mSkipTransparents)
974                {
975                        renderObjects(pPriorityGrp->getTransparents(),
976                                QueuedRenderableCollection::OM_SORT_DESCENDING, true);
977                }
978
979
980        }// for each priority
981}
982//-----------------------------------------------------------------------
983bool KdTreeSceneManager::validatePassForRendering(Pass* pass)
984{
985        if (mRenderMethod == KdTree::KDRM_INTERNAL)
986        {
987                return SceneManager::validatePassForRendering(pass);
988        }
989
990        // skip all but first pass if we are doing the depth pass
991        if ((mIsDepthPassPhase || mIsItemBufferPhase) && (pass->getIndex() > 0))
992        {
993                return false;
994        }
995        // all but first pass
996        /*else if ((!mIsDepthPassPhase || mIsItemBufferPhase) && (pass->getIndex() != 0))
997        {
998        return false;
999        }*/
1000
1001        return SceneManager::validatePassForRendering(pass);
1002}
1003//-----------------------------------------------------------------------
1004void KdTreeSceneManager::_renderQueueGroupObjects(RenderQueueGroup* pGroup,
1005                                                                                                  QueuedRenderableCollection::OrganisationMode om)
1006{
1007        if (mRenderMethod == KdTree::KDRM_INTERNAL || !mIsItemBufferPhase)
1008        {
1009                SceneManager::_renderQueueGroupObjects(pGroup, om);
1010                return;
1011        }
1012#ifdef  ITEM_BUFFER
1013        //-- item buffer
1014        //-- item buffer: render objects using false colors
1015
1016        // Iterate through priorities
1017        RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1018
1019        while (groupIt.hasMoreElements())
1020        {
1021                RenderItemBuffer(groupIt.getNext());
1022        }
1023#endif // ITEM_BUFFER
1024}
1025//-----------------------------------------------------------------------
1026void KdTreeSceneManager::renderAdditiveStencilShadowedQueueGroupObjects(
1027        RenderQueueGroup* pGroup, QueuedRenderableCollection::OrganisationMode om)
1028{
1029        // only render solid passes during hierarchical culling
1030        if (mIsHierarchicalCulling)
1031        {
1032                RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1033                LightList lightList;
1034
1035                while (groupIt.hasMoreElements())
1036                {
1037                        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1038
1039                        // Sort the queue first
1040                        pPriorityGrp->sort(mCameraInProgress);
1041
1042                        // Clear light list
1043                        lightList.clear();
1044
1045                        // Render all the ambient passes first, no light iteration, no lights
1046                        /*** msz: no more IRS_AMBIENT, see OgreSceneManager.h ***/
1047                        // mIlluminationStage = IRS_AMBIENT;
1048
1049                        SceneManager::renderObjects(pPriorityGrp->getSolidsBasic(), om, false, &lightList);
1050                        // Also render any objects which have receive shadows disabled
1051                        SceneManager::renderObjects(pPriorityGrp->getSolidsNoShadowReceive(), om, true);
1052                }
1053        }
1054        else // render the rest of the passes
1055        {
1056                SceneManager::renderAdditiveStencilShadowedQueueGroupObjects(pGroup, om);
1057        }
1058}
1059//-----------------------------------------------------------------------
1060void KdTreeSceneManager::renderModulativeStencilShadowedQueueGroupObjects(
1061        RenderQueueGroup* pGroup, QueuedRenderableCollection::OrganisationMode om)
1062{
1063        if (mIsHierarchicalCulling)
1064        {
1065                // Iterate through priorities
1066                RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1067
1068                while (groupIt.hasMoreElements())
1069                {
1070                        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1071
1072                        // Sort the queue first
1073                        pPriorityGrp->sort(mCameraInProgress);
1074
1075                        // Do (shadowable) solids
1076                        SceneManager::renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
1077                }
1078        }
1079        else
1080        {
1081                SceneManager::renderModulativeStencilShadowedQueueGroupObjects(pGroup, om);
1082        }
1083}
1084//-----------------------------------------------------------------------
1085void KdTreeSceneManager::InitDepthPass()
1086{
1087        MaterialPtr depthMat = MaterialManager::getSingleton().getByName("Visibility/DepthPass");
1088
1089        if (depthMat.isNull())
1090        {
1091                depthMat = MaterialManager::getSingleton().create(
1092                        "Visibility/DepthPass",
1093                        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
1094
1095                mDepthPass = depthMat->getTechnique(0)->getPass(0);
1096                mDepthPass->setColourWriteEnabled(false);
1097                mDepthPass->setDepthWriteEnabled(true);
1098                mDepthPass->setLightingEnabled(false);
1099        }
1100        else
1101        {
1102                mDepthPass = depthMat->getTechnique(0)->getPass(0);
1103        }
1104}
1105//-----------------------------------------------------------------------
1106void KdTreeSceneManager::InitItemBufferPass()
1107{
1108        MaterialPtr itemBufferMat = MaterialManager::getSingleton().
1109                getByName("Visibility/ItemBufferPass");
1110
1111        if (itemBufferMat.isNull())
1112        {
1113                // Init
1114                itemBufferMat = MaterialManager::getSingleton().create("Visibility/ItemBufferPass",
1115                        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
1116
1117                mItemBufferPass = itemBufferMat->getTechnique(0)->getPass(0);
1118                mItemBufferPass->setColourWriteEnabled(true);
1119                mItemBufferPass->setDepthWriteEnabled(true);
1120                mItemBufferPass->setLightingEnabled(true);
1121                //mItemBufferPass->setLightingEnabled(false);
1122        }
1123        else
1124        {
1125                mItemBufferPass = itemBufferMat->getTechnique(0)->getPass(0);
1126        }
1127        //mItemBufferPass->setAmbient(1, 1, 0);
1128}
1129//-----------------------------------------------------------------------
1130void KdTreeSceneManager::PrepareVisualization(Camera *cam)
1131{
1132        // add player camera for visualization purpose
1133        try
1134        {
1135                Camera *c;
1136                if ((c = getCamera("PlayerCam")) != NULL)
1137                {
1138                        getRenderQueue()->addRenderable(c);
1139                }   
1140        }
1141        catch (...)
1142        {
1143                // ignore
1144        }
1145
1146        if (mRenderNodesForViz || mRenderNodesContentForViz)
1147        {
1148                RenderQueue * queue = getRenderQueue();
1149                unsigned long frameid = 0;
1150
1151                if (mRenderMethod == KdTree::KDRM_INTERNAL)
1152                        frameid = Root::getSingleton().getCurrentFrameNumber();
1153                else
1154                        frameid = mHierarchyInterface->GetFrameId();
1155
1156                for (KdTree::NodeList::iterator it = mVisibleNodes.begin(); it != mVisibleNodes.end(); ++it)
1157                {
1158                        if (mRenderNodesForViz && (*it)->isLeaf())
1159                        {
1160                                WireBoundingBox * wirebox = (*it)->getWireBoundingBox();
1161                                wirebox->setMaterial("KdTree/BoxViz");
1162                                getRenderQueue()->addRenderable(wirebox);
1163                        }
1164                        // add renderables itself
1165                        if (mRenderNodesContentForViz)
1166                        {
1167                                (*it)->queueVisibleObjects(frameid, cam, queue, false, false);
1168                        }
1169                }
1170        }       
1171}
1172//-----------------------------------------------------------------------
1173void KdTreeSceneManager::InitVisibilityCulling(Camera *cam)
1174{
1175        // reset culling manager stats
1176        mVisibilityManager->GetCullingManager()->InitFrame(mVisualizeCulledNodes);
1177
1178        // set depth pass flag before rendering
1179        mIsDepthPassPhase = mUseDepthPass;
1180
1181        mIsHierarchicalCulling = true; // during hierarchical culling
1182
1183        // item buffer needs full ambient lighting to use item colors as unique id
1184        if (mUseItemBuffer)
1185        {
1186                mIsItemBufferPhase = true;
1187                setAmbientLight(ColourValue(1,1,1,1));
1188        }
1189
1190
1191        // set passes which are stored in render queue
1192        // for rendering AFTER hierarchical culling, i.e., passes which need
1193        // a special rendering order
1194
1195        mLeavePassesInQueue = 0;
1196
1197        // if we have the depth pass or use an item buffer, no passes are left in the queue
1198        if (1 && !mUseDepthPass && !mUseItemBuffer)
1199        {
1200                if (mShadowTechnique == SHADOWTYPE_STENCIL_ADDITIVE)
1201                {
1202                        // TODO: remove this pass because it should be processed during hierarchical culling
1203                        //mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_NOSHADOW;
1204
1205                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_DECAL;
1206                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_DIFFUSE_SPECULAR;
1207                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
1208
1209                        // just render ambient passes
1210                        /*** msz: no more IRS_AMBIENT, see OgreSceneManager.h ***/
1211                        // mIlluminationStage = IRS_AMBIENT;
1212                        //getRenderQueue()->setSplitPassesByLightingType(true);
1213                }
1214
1215                if (mShadowTechnique == SHADOWTYPE_STENCIL_MODULATIVE)
1216                {
1217                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_NOSHADOW;
1218                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
1219                }
1220
1221                // transparents should be rendered after hierarchical culling to
1222                // provide front-to-back ordering
1223                if (mDelayRenderTransparents)
1224                {
1225                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
1226                }
1227        }
1228
1229        // skip rendering transparents during the hierarchical culling
1230        // (because they will be rendered afterwards)
1231        mSkipTransparents =
1232                (mIsDepthPassPhase || (mLeavePassesInQueue & RenderPriorityGroup::TRANSPARENT_PASSES));
1233
1234        // -- initialise interface for rendering traversal of the hierarchy
1235        mHierarchyInterface->SetHierarchyRoot(mKdTree->getRoot());
1236
1237        // possible two cameras (one for culling, one for rendering)
1238        mHierarchyInterface->InitTraversal(mCameraInProgress,
1239                /*mCullCamera ? getCamera("CullCamera") : */NULL,
1240                mLeavePassesInQueue);
1241
1242}
1243
1244//-------------------------------------------------------------------------
1245void KdTreeSceneManager::SetObjectsVisible(const bool visible)
1246{
1247        GtpVisibilityPreprocessor::ObjectContainer::iterator it, it_end = mObjects.end();
1248
1249        for (it = mObjects.begin(); it != it_end; ++ it)
1250        {
1251                OgreMeshInstance *omi = static_cast<OgreMeshInstance *>(*it);
1252                Entity *ent = omi->GetMesh();
1253
1254                ent->setVisible(visible);
1255        }
1256}
1257//-----------------------------------------------------------------------
1258bool KdTreeSceneManager::LoadViewCells(const String &filename)
1259{
1260        // objects are set to invisible initially
1261        SetObjectsVisible(false);
1262
1263        const string bboxesFilename = mVisibilityManager->GetVisibilityEnvironment()->getViewCellsFileName();
1264
1265        // converter between view cell ids and Ogre entites
1266        GtpVisibilityPreprocessor::IndexedBoundingBoxContainer iboxes;
1267        OgreBoundingBoxConverter bconverter(this);
1268
1269        // load the view cells assigning the found objects to the pvss
1270        mViewCellsManager =
1271                GtpVisibilityPreprocessor::ViewCellsManager::LoadViewCells(filename, &mObjects, false, &bconverter);
1272
1273        return (mViewCellsManager != NULL);
1274}
1275//-------------------------------------------------------------------------
1276void KdTreeSceneManager::applyViewCellPvs(GtpVisibilityPreprocessor::ViewCell *vc,
1277                                                                                                        const bool load)
1278{       // NOTE: should not happen, rather apply view cell representing unbounded space then
1279        if (!vc)
1280        {       
1281                // set everything visible for savety
1282                SetObjectsVisible(true);
1283
1284                return;
1285        }
1286
1287        GtpVisibilityPreprocessor::ObjectPvsMap::const_iterator oit,
1288                oit_end = vc->GetPvs().mEntries.end();
1289
1290        //-- PVS of view cell
1291        for (oit = vc->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
1292        {
1293                if (!(*oit).first) continue;
1294
1295                OgreMeshInstance *omi = dynamic_cast<OgreMeshInstance *>((*oit).first);
1296                omi->GetMesh()->setVisible(load);
1297                //GtpVisibilityPreprocessor::Debug << "assigned id " << omi->GetId() << endl;
1298        }
1299}
1300//-------------------------------------------------------------------------
1301void KdTreeSceneManager::updatePvs(Camera *cam)
1302{
1303        if (!(mViewCellsLoaded && mUseViewCells))
1304                return;
1305
1306        const GtpVisibilityPreprocessor::Vector3 viewPoint =
1307                OgreTypeConverter::ConvertFromOgre(cam->getDerivedPosition());
1308
1309        GtpVisibilityPreprocessor::ViewCell *newElementary =
1310                mViewCellsManager->GetViewCell(viewPoint);
1311
1312        // elementary view cell did not change => apply same pvs
1313        if (mElementaryViewCell == newElementary)
1314                return;
1315
1316        mElementaryViewCell = newElementary;
1317        //LogManager::getSingleton().logMessage("unloading");
1318        //-- unload old pvs
1319        applyViewCellPvs(mCurrentViewCell, false);
1320
1321
1322        //-- the new view cell
1323
1324        GtpVisibilityPreprocessor::ViewCell *viewCell;
1325
1326
1327        if (mUseVisibilityFilter)
1328        {
1329                //-- compute new filtered cell
1330                GtpVisibilityPreprocessor::PrVs prvs;
1331                mViewCellsManager->GetPrVS(viewPoint, prvs, 5);
1332                viewCell = prvs.mViewCell;
1333        }
1334        else
1335        {
1336                viewCell = newElementary;
1337        }
1338        //LogManager::getSingleton().logMessage("loading");
1339        //-- load new pvs
1340        applyViewCellPvs(viewCell, true);
1341
1342        // store pvs
1343        mCurrentViewCell->SetPvs(viewCell->GetPvs());
1344
1345        // delete merge tree of filtered view cell
1346        if (mUseVisibilityFilter)
1347                mViewCellsManager->DeleteLocalMergeTree(viewCell);
1348}
1349
1350//-----------------------------------------------------------------------
1351void KdTreeSceneManager::WriteLog()
1352{
1353        std::stringstream d;
1354
1355        d << "Depth pass: " << StringConverter::toString(mUseDepthPass) << ", "
1356                << "Delay transparents: " << StringConverter::toString(mDelayRenderTransparents) << ", "
1357                << "Use optimization: " << StringConverter::toString(mHierarchyInterface->GetTestGeometryForVisibleLeaves()) << ", "
1358                << "Algorithm type: " << mVisibilityManager->GetCullingManagerType() << ", "
1359                << "Hierarchy nodes: " << (mKdTree ? mKdTree->getStats().mNumNodes : 0) << ", "
1360                << "Traversed nodes: " << mHierarchyInterface->GetNumTraversedNodes() << ", "
1361                << "Rendered nodes: " << mHierarchyInterface->GetNumRenderedNodes() << ", "
1362                << "Query culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumQueryCulledNodes() << ", "
1363                << "Frustum culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumFrustumCulledNodes() << ", "
1364                << "Queries issued: " << mVisibilityManager->GetCullingManager()->GetNumQueriesIssued() << ", "
1365                << "Found objects: " << (int)mVisibleNodes.size() << "\n"
1366                ;
1367
1368        LogManager::getSingleton().logMessage(d.str());
1369}
1370
1371/************************************************************************/
1372/* Factory for KdTreeSceneManager                                       */
1373/************************************************************************/
1374//-----------------------------------------------------------------------
1375//-----------------------------------------------------------------------
1376const String KdTreeSceneManagerFactory::FACTORY_TYPE_NAME = "KdTreeSceneManager";
1377//-----------------------------------------------------------------------
1378void KdTreeSceneManagerFactory::initMetaData(void) const
1379{
1380        mMetaData.typeName = FACTORY_TYPE_NAME;
1381        mMetaData.description = "Scene manager that organises the scene based on a kd-tree";
1382        mMetaData.sceneTypeMask = 0xFFFF; // support all types of scenes (hopefully)
1383        mMetaData.worldGeometrySupported = false;
1384}
1385//-----------------------------------------------------------------------
1386SceneManager* KdTreeSceneManagerFactory::createInstance(
1387        const String& instanceName)
1388{
1389        return new KdTreeSceneManager(instanceName, visManager);
1390}
1391//-----------------------------------------------------------------------
1392void KdTreeSceneManagerFactory::destroyInstance(SceneManager* instance)
1393{
1394        delete instance;
1395}
1396
1397} // namespace Ogre
1398
Note: See TracBrowser for help on using the repository browser.