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

Revision 1195, 32.9 KB checked in by szydlowski, 18 years ago (diff)

visualization workin' fine (TM)
demo recording/playback partially implemented

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