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

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