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

Revision 1206, 33.8 KB checked in by szydlowski, 18 years ago (diff)

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