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

Revision 1204, 32.8 KB checked in by szydlowski, 18 years ago (diff)

Demo mode complete, added command line parsing for easy benchmark scripting

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