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

Revision 1258, 35.0 KB checked in by szydlowski, 18 years ago (diff)

pre-big-changes-backup (TM)
working state before attempt to include terrain rendering

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