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

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