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

Revision 1211, 33.9 KB checked in by szydlowski, 18 years ago (diff)

enhanced visibility (none/full/partial) implemented for internal culling

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