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

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

saving and loading entities to file

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