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

Revision 1273, 34.8 KB checked in by szydlowski, 18 years ago (diff)

Added the KdTerrainSceneManager?, a subclass of the KdTreeSceneManager? capable of rendering terrain like the TerrainSceneManager? from Ogre.
All the *Kd*Terrain* classes are identical to their octree counterparts, save prefixing all classes and structures with Kd to avoid namespace clashes.
This was necessary, since the TerrainSceneManager? was hard coded in these classes, and all references had to be replaced with the KdTerrainSceneManager?.
Also added a comprehensive README for the demo application.

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