source: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreOcclusionCullingSceneManager.cpp @ 1610

Revision 1610, 40.3 KB checked in by mattausch, 18 years ago (diff)

removed vsposp bug

Line 
1#include "OgreOcclusionCullingSceneManager.h"
2#include "OgreVisibilityOptionsManager.h"
3#include <OgreMath.h>
4#include <OgreIteratorWrappers.h>
5#include <OgreRenderSystem.h>
6#include <OgreCamera.h>
7#include <OgreLogManager.h>
8#include <OgreStringConverter.h>
9#include <OgreEntity.h>
10#include <OgreSubEntity.h>
11#include <OgreMaterialManager.h>
12#include <OgreIteratorWrappers.h>
13#include <OgreHeightmapTerrainPageSource.h>
14#include "VspBspTree.h"
15#include "Containers.h"
16#include "ViewCellsManager.h"
17#include <OgreConfigFile.h>
18#include "OgreTypeConverter.h"
19#include "OgreMeshInstance.h"
20#include "common.h"
21#include "OgreBoundingBoxConverter.h"
22#include <OgreManualObject.h>
23
24
25namespace Ogre {
26
27//-----------------------------------------------------------------------
28OcclusionCullingSceneManager::OcclusionCullingSceneManager(const String& name,
29                                                        GtpVisibility::VisibilityManager *visManager):
30TerrainSceneManager(name),
31mVisibilityManager(visManager),
32mShowVisualization(false),
33mRenderNodesForViz(false),
34mRenderNodesContentForViz(false),
35mVisualizeCulledNodes(false),
36mLeavePassesInQueue(0),
37mDelayRenderTransparents(true),
38mUseDepthPass(false),
39mIsDepthPassPhase(false),
40mUseItemBuffer(false),
41mIsItemBufferPhase(false),
42mCurrentEntityId(1),
43mEnableDepthWrite(true),
44mSkipTransparents(false),
45mRenderTransparentsForItemBuffer(true),
46mExecuteVertexProgramForAllPasses(false),
47mIsHierarchicalCulling(false),
48mViewCellsLoaded(false),
49mUseViewCells(false),
50mUseVisibilityFilter(false),
51mCurrentViewCell(NULL),
52mElementaryViewCell(NULL),
53mDeleteQueueAfterRendering(true),
54mNormalExecution(false),
55mShowViewCells(false)
56{
57        Ogre::LogManager::getSingleton().logMessage("creating occlusion culling scene manager");
58
59        mHierarchyInterface = new OctreeHierarchyInterface(this, mDestRenderSystem);
60       
61        if (0)
62        {
63                mDisplayNodes = true;
64                mShowBoundingBoxes = true;
65                mShowBoxes = true;
66        }
67
68        // TODO: set maxdepth to reasonable value
69        mMaxDepth = 50;
70}
71//-----------------------------------------------------------------------
72void OcclusionCullingSceneManager::InitDepthPass()
73{
74        MaterialPtr depthMat =
75                MaterialManager::getSingleton().getByName("Visibility/DepthPass");
76
77        if (depthMat.isNull())
78    {
79                depthMat = MaterialManager::getSingleton().create(
80                "Visibility/DepthPass",
81                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
82
83        mDepthPass = depthMat->getTechnique(0)->getPass(0);
84                mDepthPass->setColourWriteEnabled(false);
85                mDepthPass->setDepthWriteEnabled(true);
86                mDepthPass->setLightingEnabled(false);
87        }
88        else
89        {
90                mDepthPass = depthMat->getTechnique(0)->getPass(0);
91        }
92}
93//-----------------------------------------------------------------------
94OcclusionCullingSceneManager::~OcclusionCullingSceneManager()
95{
96        OGRE_DELETE(mHierarchyInterface);
97        CLEAR_CONTAINER(mObjects);
98        OGRE_DELETE(mCurrentViewCell);
99}
100//-----------------------------------------------------------------------
101void OcclusionCullingSceneManager::InitItemBufferPass()
102{
103        MaterialPtr itemBufferMat = MaterialManager::getSingleton().
104                getByName("Visibility/ItemBufferPass");
105
106        if (itemBufferMat.isNull())
107    {
108                // Init
109                itemBufferMat =
110                        MaterialManager::getSingleton().create("Visibility/ItemBufferPass",
111                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
112
113                mItemBufferPass = itemBufferMat->getTechnique(0)->getPass(0);
114                mItemBufferPass->setColourWriteEnabled(true);
115                mItemBufferPass->setDepthWriteEnabled(true);
116                mItemBufferPass->setLightingEnabled(true);
117                //mItemBufferPass->setLightingEnabled(false);
118        }
119        else
120        {
121                mItemBufferPass = itemBufferMat->getTechnique(0)->getPass(0);
122        }
123        //mItemBufferPass->setAmbient(1, 1, 0);
124}
125//-------------------------------------------------------------------------
126#if 1
127void OcclusionCullingSceneManager::setWorldGeometry( DataStreamPtr& stream, const String& typeName )
128{
129    // Clear out any existing world resources (if not default)
130    if (ResourceGroupManager::getSingleton().getWorldResourceGroupName() !=
131        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME)
132    {
133        ResourceGroupManager::getSingleton().clearResourceGroup(
134            ResourceGroupManager::getSingleton().getWorldResourceGroupName());
135    }
136       
137        destroyLevelIndexes();
138    mTerrainPages.clear();
139
140    // Load the configuration
141    loadConfig(stream);
142        initLevelIndexes();
143
144    // Resize the octree, allow for 1 page for now
145    float max_x = mOptions.scale.x * mOptions.pageSize;
146    float max_y = mOptions.scale.y;
147    float max_z = mOptions.scale.z * mOptions.pageSize;
148
149        float maxAxis = std::max(max_x, max_y);
150        maxAxis = std::max(maxAxis, max_z);
151        resize( AxisAlignedBox( 0, 0, 0, maxAxis, maxAxis, maxAxis ) );
152   
153    setupTerrainMaterial();
154    setupTerrainPages();
155
156 }
157#endif
158//-----------------------------------------------------------------------
159void OcclusionCullingSceneManager::PrepareVisualization(Camera *cam)
160{
161        // add player camera for visualization purpose
162        try
163        {
164                Camera *c;
165                if ((c = getCamera("PlayerCam")) != NULL)
166                {
167                        getRenderQueue()->addRenderable(c);
168                }   
169    }
170    catch (...)
171    {
172        // ignore
173    }
174
175        // add bounding boxes of rendered objects
176        if (0)
177        for (BoxList::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it)
178        {
179                getRenderQueue()->addRenderable(*it);
180        }
181
182        // set old view cell geometry to invisible
183    if (mCurrentViewCell && mCurrentViewCell->GetMesh())
184        {
185                //const bool showSingleViewCell = true;
186                if (!mShowViewCells)
187                {
188                        const int id = mCurrentViewCell->GetId();
189                        mViewCellsGeometry[id]->_updateRenderQueue(getRenderQueue());
190                }
191                else
192                {
193                        MovableObjectsMap::const_iterator mit, mit_end = mViewCellsGeometry.end();
194                       
195                        for (mit = mViewCellsGeometry.begin(); mit != mit_end; ++ mit)
196                        {
197                                (*mit).second->_updateRenderQueue(getRenderQueue());
198                        }       
199                }
200
201                GtpVisibilityPreprocessor::ObjectPvsMap::const_iterator
202                        oit, oit_end = mCurrentViewCell->GetPvs().mEntries.end();
203                       
204                for (oit = mCurrentViewCell->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
205                {
206                        OgreMeshInstance *obj = static_cast<OgreMeshInstance *>((*oit).first);
207                        obj->GetEntity()->_updateRenderQueue(getRenderQueue());
208                }       
209        }
210/*
211    if (mRenderNodesForViz || mRenderNodesContentForViz)
212        {
213                // HACK: change node material so it is better suited for visualization
214                MaterialPtr nodeMat = MaterialManager::getSingleton().getByName("Core/NodeMaterial");
215                nodeMat->setAmbient(1, 1, 0);
216                nodeMat->setLightingEnabled(true);
217                nodeMat->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();
218
219                for (NodeList::iterator it = mVisible.begin(); it != mVisible.end(); ++it)
220                {
221                        if (mRenderNodesForViz)
222                        {
223                                // render the visible leaf nodes
224                                if ((*it)->numAttachedObjects() &&
225                                        !(*it)->numChildren() &&
226                                        ((*it)->getAttachedObject(0)->getMovableType() == "Entity") &&
227                                        (*it)->getAttachedObject(0)->isVisible())
228                                {
229                                        //getRenderQueue()->addRenderable((*it));
230                                        (*it)->_addToRenderQueue(cam, getRenderQueue(), false);
231                                }
232
233                                // add bounding boxes instead of node itself
234                                if (0)
235                                        (*it)->_addBoundingBoxToQueue(getRenderQueue());
236                        }
237
238                        // add renderables itself
239                        if (mRenderNodesContentForViz)
240                        {
241                                (*it)->_addToRenderQueue(cam, getRenderQueue(), false);
242                        }
243                }
244        }*/
245}
246//-----------------------------------------------------------------------
247const Pass *OcclusionCullingSceneManager::_setPass(const Pass* pass, bool evenIfSuppressed)
248{
249        if (mNormalExecution)
250        {
251                return SceneManager::_setPass(pass);
252        }
253
254        // TODO: setting vertex program is not efficient
255        //Pass *usedPass = ((mIsDepthPassPhase && !pass->hasVertexProgram()) ? mDepthPass : pass);
256       
257        // set depth fill pass if we currently do not make an aabb occlusion query
258        const bool useDepthPass =
259                (mIsDepthPassPhase && !mHierarchyInterface->IsBoundingBoxQuery());
260
261        const IlluminationRenderStage savedStage = mIlluminationStage;
262       
263        // set illumination stage to NONE so no shadow material is used
264        // for depth pass or for occlusion query
265        if (mIsDepthPassPhase || mHierarchyInterface->IsBoundingBoxQuery())
266        {
267                mIlluminationStage = IRS_NONE;
268        }
269       
270        // --- set vertex program of current pass in order to set correct depth
271        if (mExecuteVertexProgramForAllPasses &&
272                mIsDepthPassPhase &&
273                pass->hasVertexProgram())
274        {
275                // add vertex program of current pass to depth pass
276                mDepthPass->setVertexProgram(pass->getVertexProgramName());
277
278                if (mDepthPass->hasVertexProgram())
279                {
280                        const GpuProgramPtr& prg = mDepthPass->getVertexProgram();
281                        // Load this program if not done already
282                        if (!prg->isLoaded())
283                                prg->load();
284                        // Copy params
285                        mDepthPass->setVertexProgramParameters(pass->getVertexProgramParameters());
286                }
287        }
288        else if (mDepthPass->hasVertexProgram()) // reset vertex program
289        {
290                mDepthPass->setVertexProgram("");
291        }
292       
293        const Pass *usedPass = useDepthPass ? mDepthPass : pass;
294
295        // save old depth write: needed for item buffer
296        const bool IsDepthWrite = usedPass->getDepthWriteEnabled();
297
298        // global option which enables / disables depth writes
299        if (!mEnableDepthWrite)
300        {
301                //usedPass->setDepthWriteEnabled(false);
302        }
303        //else if (mIsItemBufferPass) {usedPass = mItemBufferPass;}
304       
305
306        //-- set actual pass here
307
308        const Pass *result = SceneManager::_setPass(usedPass);
309
310
311        // reset depth write
312        if (!mEnableDepthWrite)
313        {
314                //usedPass->setDepthWriteEnabled(IsDepthWrite);
315        }
316
317        // reset illumination stage
318        mIlluminationStage = savedStage;
319
320        return result;
321}
322//-----------------------------------------------------------------------
323void OcclusionCullingSceneManager::_findVisibleObjects(Camera* cam,
324                                                                                                                bool onlyShadowCasters)
325{
326        if (mShowVisualization)
327    {
328                //////////////
329                //-- show visible scene nodes and octree bounding boxes from last frame
330                PrepareVisualization(cam);
331        }
332        else
333        {       
334                // hierarchical culling interleaves identification
335                // and rendering of objects in _renderVisibibleObjects
336
337                // for the shadow pass we use only standard rendering
338                // because shadows have low occlusion snyway
339                if (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE &&
340                        mIlluminationStage == IRS_RENDER_TO_TEXTURE)
341                {
342                        OctreeSceneManager::_findVisibleObjects(cam, onlyShadowCasters);
343                }
344
345                // only shadow casters will be rendered in shadow texture pass
346                if (0) mHierarchyInterface->SetOnlyShadowCasters(onlyShadowCasters);
347
348                ///////////
349                //-- set visibility according to pvs of current view cell
350
351                UpdatePvs(cam);
352
353                if (mNormalExecution)
354                {
355                        OctreeSceneManager::_findVisibleObjects(cam, onlyShadowCasters);
356                        //return;
357                }
358        }
359               
360        // lists only used for visualization
361        mVisible.clear();
362        mBoxes.clear();
363}
364//-----------------------------------------------------------------------
365void OcclusionCullingSceneManager::_renderVisibleObjects()
366{
367        if (mNormalExecution)
368        {
369                // the standard octree rendering mode
370                TerrainSceneManager::_renderVisibleObjects();
371                getRenderQueue()->clear(mDeleteQueueAfterRendering);
372                return;
373        }
374
375        InitDepthPass();          // create material for depth pass
376        InitItemBufferPass(); // create material for item buffer pass
377
378        // save ambient light to reset later
379        ColourValue savedAmbient = mAmbientLight;
380
381        ////////////////////
382        //-- apply standard rendering for some modes
383        //-- (e.g., the visualization mode, the shadow pass)
384
385        if (mShowVisualization ||
386           (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE &&
387            mIlluminationStage == IRS_RENDER_TO_TEXTURE))
388        {       
389                IlluminationRenderStage savedStage = mIlluminationStage;
390       
391                if (mShowVisualization)
392                {
393                        // disable illumination stage to prevent rendering shadows
394                        mIlluminationStage = IRS_NONE;
395                }
396
397                // standard rendering for shadow maps because of performance
398                TerrainSceneManager::_renderVisibleObjects();
399
400                mIlluminationStage = savedStage;
401        }
402        else //-- the hierarchical culling algorithm
403        {
404                // note matt: this is also called in TerrainSceneManager: really necessary?
405                mDestRenderSystem -> setLightingEnabled(false);
406
407                if (mUseItemBuffer)
408                {
409                        // don't render backgrounds for item buffer
410                        clearSpecialCaseRenderQueues();
411                        getRenderQueue()->clear();
412                }
413
414                ////////////////////
415                //-- hierarchical culling
416
417                // the objects of different layers (e.g., background, scene,
418                // overlay) must be identified and rendered one after another
419
420                // first render all early skies
421                clearSpecialCaseRenderQueues();
422                addSpecialCaseRenderQueue(RENDER_QUEUE_BACKGROUND);
423                addSpecialCaseRenderQueue(RENDER_QUEUE_SKIES_EARLY);
424                setSpecialCaseRenderQueueMode(SceneManager::SCRQM_INCLUDE);
425
426                TerrainSceneManager::_renderVisibleObjects();
427
428#ifdef GTP_VISIBILITY_MODIFIED_OGRE
429                // delete previously rendered content
430                _deleteRenderedQueueGroups();
431#endif
432
433                ///////////////////
434                //-- prepare queue for visible objects (i.e., all but overlay and skies late)
435
436                clearSpecialCaseRenderQueues();
437                addSpecialCaseRenderQueue(RENDER_QUEUE_SKIES_LATE);
438                addSpecialCaseRenderQueue(RENDER_QUEUE_OVERLAY);
439       
440                // exclude this queues from hierarchical rendering
441                setSpecialCaseRenderQueueMode(SceneManager::SCRQM_EXCLUDE);
442
443                // set all necessary parameters for
444                // hierarchical visibility culling and rendering
445                InitVisibilityCulling(mCameraInProgress);
446
447
448                /**
449                * the hierarchical culling algorithm
450                * for depth pass: we just find objects and update depth buffer
451                * for "delayed" rendering: we render some passes afterwards
452                * e.g., transparents, because they need front-to-back sorting
453                **/
454               
455                mVisibilityManager->ApplyVisibilityCulling();
456
457                // delete remaining renderables from queue:
458                // all which are not in mLeavePassesInQueue)
459#ifdef GTP_VISIBILITY_MODIFIED_OGRE
460                _deleteRenderedQueueGroups(mLeavePassesInQueue);
461#endif
462
463                /////////////
464                //-- reset parameters needed for special rendering
465               
466                mIsDepthPassPhase = false;
467                mIsItemBufferPhase = false;
468                mSkipTransparents = false;
469                mIsHierarchicalCulling = false;
470               
471                mLeavePassesInQueue = 0;
472               
473                if (mUseDepthPass) // the shaded geometry is rendered in a second pass
474                {
475                        // add visible nodes found by the visibility culling algorithm
476                        NodeList::const_iterator it, it_end = mVisible.end();
477
478                        //getRenderQueue()->clear();
479                        for (it = mVisible.begin(); it != it_end; ++ it)
480                        {
481                                (*it)->_addToRenderQueue(mCameraInProgress, getRenderQueue(), false);
482                        }
483                }
484               
485                /////////////
486                //-- now we can render all remaining queue objects
487                //-- used for depth pass, transparents, overlay
488
489        clearSpecialCaseRenderQueues();
490
491                TerrainSceneManager::_renderVisibleObjects();
492        } // end hierarchical culling
493               
494        // HACK: set the new render level index, important to avoid cracks
495        // in terrain caused by LOD
496        TerrainRenderable::NextRenderLevelIndex();
497       
498        // reset ambient light
499        setAmbientLight(savedAmbient);
500
501        // almost same effect as below
502        getRenderQueue()->clear(mDeleteQueueAfterRendering);
503
504        if (0)
505        {
506                if (!mDeleteQueueAfterRendering)
507                        getRenderQueue()->clear(true); // finally clear render queue
508                else
509                        OGRE_DELETE(mRenderQueue); // HACK: should rather only be cleared ...
510        }
511
512        if (0) WriteLog(); // write out stats
513}
514
515//-----------------------------------------------------------------------
516void OcclusionCullingSceneManager::_updateSceneGraph(Camera* cam)
517{
518        if (mNormalExecution)
519        {
520                OctreeSceneManager::_updateSceneGraph(cam);
521                return;
522        }
523
524        mVisibilityManager->GetCullingManager()->SetHierarchyInterface(mHierarchyInterface);
525        mHierarchyInterface->SetRenderSystem(mDestRenderSystem);
526
527        TerrainSceneManager::_updateSceneGraph(cam);
528}
529//-----------------------------------------------------------------------
530bool OcclusionCullingSceneManager::setOption(const String & key, const void * val)
531{
532        if (key == "UseDepthPass")
533        {
534                mUseDepthPass = (*static_cast<const bool *>(val));
535                return true;
536        }
537        if (key == "PrepareVisualization")
538        {
539                mShowVisualization = (*static_cast<const bool *>(val));
540                return true;
541        }
542        if (key == "RenderNodesForViz")
543        {
544                mRenderNodesForViz = (*static_cast<const bool *>(val));
545                return true;
546        }
547        if (key == "RenderNodesContentForViz")
548        {
549                mRenderNodesContentForViz = (*static_cast<const bool *>(val));
550                return true;
551        }
552        if (key == "SkyBoxEnabled")
553        {
554                mSkyBoxEnabled = (*static_cast<const bool *>(val));
555                return true;
556        }
557        if (key == "SkyPlaneEnabled")
558        {
559                mSkyPlaneEnabled = (*static_cast<const bool *>(val));
560                return true;
561        }
562        if (key == "SkyDomeEnabled")
563        {
564                mSkyDomeEnabled = (*static_cast<const bool *>(val));
565                return true;
566        }
567        if (key == "VisualizeCulledNodes")
568        {
569                mVisualizeCulledNodes = (*static_cast<const bool *>(val));
570                return true;
571        }
572        if (key == "DelayRenderTransparents")
573        {
574                mDelayRenderTransparents = (*static_cast<const bool *>(val));
575                return true;
576        }
577        if (key == "DepthWrite")
578        {
579                mEnableDepthWrite = (*static_cast<const bool *>(val));
580                return true;
581        }
582        if (key == "UseItemBuffer")
583        {
584                mUseItemBuffer = (*static_cast<const bool *>(val));
585                return true;
586        }
587        if (key == "ExecuteVertexProgramForAllPasses")
588        {
589                mExecuteVertexProgramForAllPasses  = (*static_cast<const bool *>(val));
590                return true;
591        }
592        if (key == "RenderTransparentsForItemBuffer")
593        {
594                mRenderTransparentsForItemBuffer  = (*static_cast<const bool *>(val));
595                return true;
596        }
597        else if (key == "DeleteRenderQueue")
598        {
599                mDeleteQueueAfterRendering = (*static_cast<const bool *>(val));
600                return true;
601        }
602        if (key == "NodeVizScale")
603        {
604                OctreeNode::setVizScale(*static_cast<const float *>(val));
605                return true;
606        }
607        if (key == "LoadViewCells")
608        {
609                if (!mViewCellsLoaded)
610                {
611                        String filename(static_cast<const char *>(val));
612                        mViewCellsLoaded = LoadViewCells(filename);     
613                }
614
615                return mViewCellsLoaded;
616        }
617        if (key == "UseViewCells")
618        {
619                // only use this option if view cells are available
620                if (mViewCellsLoaded)
621                {
622                        mUseViewCells = *static_cast<const bool *>(val);
623
624                        // reset view cell
625                        OGRE_DELETE(mCurrentViewCell);
626                       
627                        if (mUseViewCells)
628                        {
629                                mCurrentViewCell = mViewCellsManager->GenerateViewCell();
630                        }
631                        // view cell corresponding to leaf in the view cell hierarchy
632                        mElementaryViewCell = NULL;
633
634                        // if we decide use view cells
635                        // all objects are set to invisible per default
636                        SetObjectsVisible(!mUseViewCells);
637                }
638
639                return true;
640        }
641        if (key == "ShowViewCells")
642        {
643                // only use this option if view cells are available
644                if (mViewCellsLoaded)
645                {
646                        mShowViewCells = *static_cast<const bool *>(val);
647                        // if we decide use view cells
648                        // all objects are set to invisible per default
649                        VisualizeViewCells(mShowViewCells);
650                }
651
652                return true;
653        }
654        if (key == "NormalExecution")
655        {
656                mNormalExecution = *static_cast<const bool *>(val);
657                return true;
658        }
659        if (key == "UseVisibilityFilter")
660        {
661                mUseVisibilityFilter = *static_cast<const bool *>(val);
662                // set null =>recomputation of the pvs
663        mElementaryViewCell = NULL;
664                return true;
665        }
666
667        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
668                setOption(key, val) || TerrainSceneManager::setOption(key, val);
669}
670//-----------------------------------------------------------------------
671bool OcclusionCullingSceneManager::getOption(const String & key, void *val)
672{
673        if (key == "NumHierarchyNodes")
674        {
675                * static_cast<unsigned int *>(val) = (unsigned int)mNumOctants;
676                return true;
677        }
678        if (key == "VisibilityManager")
679        {
680                * static_cast<GtpVisibility::VisibilityManager **>(val) =
681                        (GtpVisibility::VisibilityManager *)mVisibilityManager;
682                return true;
683        }
684        if (key == "HierarchInterface")
685        {
686                * static_cast<GtpVisibility::HierarchyInterface **>(val) =
687                        (GtpVisibility::HierarchyInterface *)mHierarchyInterface;
688                return true;
689        }
690
691        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
692                getOption(key, val) && TerrainSceneManager::getOption(key, val);
693}
694//-----------------------------------------------------------------------
695bool OcclusionCullingSceneManager::getOptionValues(const String & key,
696                                                                                                        StringVector &refValueList)
697{
698        return TerrainSceneManager::getOptionValues( key, refValueList);
699}
700//-----------------------------------------------------------------------
701bool OcclusionCullingSceneManager::getOptionKeys(StringVector & refKeys)
702{
703        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
704                getOptionKeys(refKeys) || TerrainSceneManager::getOptionKeys(refKeys);
705}
706//-----------------------------------------------------------------------
707void OcclusionCullingSceneManager::setVisibilityManager(GtpVisibility::
708                                                                                                                 VisibilityManager *visManager)
709{
710        mVisibilityManager = visManager;
711}
712//-----------------------------------------------------------------------
713GtpVisibility::VisibilityManager *OcclusionCullingSceneManager::getVisibilityManager( void )
714{
715        return mVisibilityManager;
716}
717//-----------------------------------------------------------------------
718void OcclusionCullingSceneManager::WriteLog()
719{
720        std::stringstream d;
721
722        d << "Depth pass: " << StringConverter::toString(mUseDepthPass) << ", "
723          << "Delay transparents: " << StringConverter::toString(mDelayRenderTransparents) << ", "
724          << "Use optimization: " << StringConverter::toString(mHierarchyInterface->GetTestGeometryForVisibleLeaves()) << ", "
725          << "Algorithm type: " << mVisibilityManager->GetCullingManagerType() << ", "
726          << "Hierarchy nodes: " << mNumOctants << ", "
727          << "Traversed nodes: " << mHierarchyInterface->GetNumTraversedNodes() << ", "
728          << "Rendered nodes: " << mHierarchyInterface->GetNumRenderedNodes() << ", "
729          << "Query culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumQueryCulledNodes() << ", "
730          << "Frustum culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumFrustumCulledNodes() << ", "
731      << "Queries issued: " << mVisibilityManager->GetCullingManager()->GetNumQueriesIssued() << ", "
732          << "Found objects: " << (int)mVisible.size() << "\n";
733
734        LogManager::getSingleton().logMessage(d.str());
735}
736//-----------------------------------------------------------------------
737void OcclusionCullingSceneManager::renderBasicQueueGroupObjects(RenderQueueGroup* pGroup,
738                                                                                                                                QueuedRenderableCollection::OrganisationMode om)
739{
740    // Basic render loop
741    // Iterate through priorities
742    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
743
744    while (groupIt.hasMoreElements())
745    {
746        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
747
748        // Sort the queue first
749        pPriorityGrp->sort(mCameraInProgress);
750
751        // Do solids
752        renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
753
754                // for correct rendering, transparents must be rendered
755                // after hierarchical culling => don't render them now
756
757        if (mNormalExecution || !mSkipTransparents)
758                {
759                        // Do transparents (always descending)
760                        renderObjects(pPriorityGrp->getTransparents(),
761                                QueuedRenderableCollection::OM_SORT_DESCENDING, true);
762                }
763
764
765    } // for each priority
766}
767
768//-----------------------------------------------------------------------
769bool OcclusionCullingSceneManager::validatePassForRendering(Pass* pass)
770{
771        if (mNormalExecution)
772        {
773                return SceneManager::validatePassForRendering(pass);
774        }
775
776        // skip all but first pass if we are doing the depth pass
777        if ((mIsDepthPassPhase || mIsItemBufferPhase) && (pass->getIndex() > 0))
778        {
779                return false;
780        }
781        // all but first pass
782        /*else if ((!mIsDepthPassPhase || mIsItemBufferPhase) && (pass->getIndex() != 0))
783        {
784                return false;
785        }*/
786
787        return SceneManager::validatePassForRendering(pass);
788}
789//-----------------------------------------------------------------------
790void OcclusionCullingSceneManager::_renderQueueGroupObjects(RenderQueueGroup* pGroup,
791                                                                                                                        QueuedRenderableCollection::OrganisationMode om)
792{
793        if (mNormalExecution || !mIsItemBufferPhase)
794        {
795                TerrainSceneManager::_renderQueueGroupObjects(pGroup, om);
796                return;
797        }
798#ifdef  ITEM_BUFFER
799        //-- item buffer
800        //-- item buffer: render objects using false colors
801
802    // Iterate through priorities
803    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
804
805        while (groupIt.hasMoreElements())
806    {
807                RenderItemBuffer(groupIt.getNext());
808        }
809#endif // ITEM_BUFFER
810}
811#ifdef ITEM_BUFFER
812//-----------------------------------------------------------------------
813void OcclusionCullingSceneManager::RenderItemBuffer(RenderPriorityGroup* pGroup)
814{
815        // Do solids
816        QueuedRenderableCollection solidObjs = pGroup->getSolidsBasic();//msz
817
818        // ----- SOLIDS LOOP -----
819        RenderPriorityGroup::SolidRenderablePassMap::const_iterator ipass, ipassend;
820        ipassend = solidObjs.end();
821
822        for (ipass = solidObjs.begin(); ipass != ipassend; ++ipass)
823        {
824                // Fast bypass if this group is now empty
825                if (ipass->second->empty())
826                        continue;
827
828                // Render only first pass of renderable as false color
829                if (ipass->first->getIndex() > 0)
830                        continue;
831
832                RenderPriorityGroup::RenderableList* rendList = ipass->second;
833               
834                RenderPriorityGroup::RenderableList::const_iterator irend, irendend;
835                irendend = rendList->end();
836                       
837                for (irend = rendList->begin(); irend != irendend; ++irend)
838                {
839                        if (0)
840                        {
841                                std::stringstream d; d << "itembuffer, pass name: " <<
842                                        ipass->first->getParent()->getParent()->getName();
843
844                                LogManager::getSingleton().logMessage(d.str());
845                        }
846                       
847                        RenderSingleObjectForItemBuffer(*irend, ipass->first);
848                }
849        }
850
851        //-- TRANSPARENT LOOP: must be handled differently from solids
852
853        // transparents are treated either as solids or completely discarded
854        if (mRenderTransparentsForItemBuffer)
855        {
856                QueuedRenderableCollection transpObjs = pGroup->getTransparents(); //msz
857                RenderPriorityGroup::TransparentRenderablePassList::const_iterator
858                        itrans, itransend;
859
860                itransend = transpObjs.end();
861                for (itrans = transpObjs.begin(); itrans != itransend; ++itrans)
862                {
863                        // like for solids, render only first pass
864                        if (itrans->pass->getIndex() == 0)
865                        {       
866                                RenderSingleObjectForItemBuffer(itrans->renderable, itrans->pass);
867                        }
868                }
869        }
870}
871//-----------------------------------------------------------------------
872void OcclusionCullingSceneManager::RenderSingleObjectForItemBuffer(Renderable *rend, Pass *pass)
873{
874        static LightList nullLightList;
875       
876        int col[4];
877       
878        // -- create color code out of object id
879        col[0] = (rend->getId() >> 16) & 255;
880        col[1] = (rend->getId() >> 8) & 255;
881        col[2] = rend->getId() & 255;
882//      col[3] = 255;
883
884        //mDestRenderSystem->setColour(col[0], col[1], col[2], col[3]);
885   
886        mItemBufferPass->setAmbient(ColourValue(col[0] / 255.0f,
887                                                                                    col[1] / 255.0f,
888                                                                                        col[2] / 255.0f, 1));
889
890        // set vertex program of current pass
891        if (mExecuteVertexProgramForAllPasses && pass->hasVertexProgram())
892        {
893                mItemBufferPass->setVertexProgram(pass->getVertexProgramName());
894
895                if (mItemBufferPass->hasVertexProgram())
896                {
897                        const GpuProgramPtr& prg = mItemBufferPass->getVertexProgram();
898                        // Load this program if not done already
899                        if (!prg->isLoaded())
900                                prg->load();
901                        // Copy params
902                        mItemBufferPass->setVertexProgramParameters(pass->getVertexProgramParameters());
903                }
904        }
905        else if (mItemBufferPass->hasVertexProgram())
906        {
907                mItemBufferPass->setVertexProgram("");
908        }
909
910        const Pass *usedPass = _setPass(mItemBufferPass);
911
912
913        // render a single object, this will set up auto params if required
914        renderSingleObject(rend, usedPass, false, &nullLightList);
915}
916#endif // ITEM_BUFFER
917//-----------------------------------------------------------------------
918GtpVisibility::VisibilityManager *OcclusionCullingSceneManager::GetVisibilityManager()
919{
920        return mVisibilityManager;
921}
922//-----------------------------------------------------------------------
923void OcclusionCullingSceneManager::InitVisibilityCulling(Camera *cam)
924{
925        // reset culling manager stats
926        mVisibilityManager->GetCullingManager()->InitFrame(mVisualizeCulledNodes);
927
928        // set depth pass flag before rendering
929        mIsDepthPassPhase = mUseDepthPass;
930
931        mIsHierarchicalCulling = true; // during hierarchical culling
932
933        // item buffer needs full ambient lighting to use item colors as unique id
934        if (mUseItemBuffer)
935        {
936                mIsItemBufferPhase = true;
937                setAmbientLight(ColourValue(1,1,1,1));
938        }
939
940
941        // set passes which are stored in render queue
942        // for rendering AFTER hierarchical culling, i.e., passes which need
943        // a special rendering order
944       
945        mLeavePassesInQueue = 0;
946
947        // if we have the depth pass or use an item buffer, no passes are left in the queue
948        if (1 && !mUseDepthPass && !mUseItemBuffer)
949        {
950                if (mShadowTechnique == SHADOWTYPE_STENCIL_ADDITIVE)
951                {
952                        // TODO: remove this pass because it should be processed during hierarchical culling
953                        //mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_NOSHADOW;
954
955                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_DECAL;
956                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_DIFFUSE_SPECULAR;
957                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
958
959                        // just render ambient passes
960                        /*** msz: no more IRS_AMBIENT, see OgreSceneManager.h ***/
961                        // mIlluminationStage = IRS_AMBIENT;
962                        //getRenderQueue()->setSplitPassesByLightingType(true);
963                }
964       
965                if (mShadowTechnique == SHADOWTYPE_STENCIL_MODULATIVE)
966                {
967                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_NOSHADOW;
968                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
969                }
970       
971                // transparents should be rendered after hierarchical culling to
972                // provide front-to-back ordering
973                if (mDelayRenderTransparents)
974                {
975                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
976                }
977        }
978
979        // skip rendering transparents during the hierarchical culling
980        // (because they will be rendered afterwards)
981        mSkipTransparents =
982                (mIsDepthPassPhase || (mLeavePassesInQueue & RenderPriorityGroup::TRANSPARENT_PASSES));
983
984        // -- initialise interface for rendering traversal of the hierarchy
985        mHierarchyInterface->SetHierarchyRoot(mOctree);
986       
987        // possible two cameras (one for culling, one for rendering)
988        mHierarchyInterface->InitTraversal(mCameraInProgress,
989                                                                           mCullCamera ? getCamera("CullCamera") : NULL,
990                                                                           mLeavePassesInQueue);
991               
992}
993//-----------------------------------------------------------------------
994OctreeHierarchyInterface *OcclusionCullingSceneManager::GetHierarchyInterface()
995{
996        return mHierarchyInterface;
997}
998//-----------------------------------------------------------------------
999void OcclusionCullingSceneManager::endFrame()
1000{
1001        TerrainRenderable::ResetRenderLevelIndex();
1002}
1003//-----------------------------------------------------------------------
1004Entity* OcclusionCullingSceneManager::createEntity(const String& entityName,
1005                                                                                                        const String& meshName)
1006{
1007        Entity *ent = SceneManager::createEntity(entityName, meshName);
1008
1009        for (int i = 0; i < (int)ent->getNumSubEntities(); ++i)
1010        {
1011                ent->getSubEntity(i)->setId(mCurrentEntityId);
1012        }
1013
1014        // increase counter of entity id values
1015        ++ mCurrentEntityId;
1016
1017        return ent;
1018}
1019//-----------------------------------------------------------------------
1020void OcclusionCullingSceneManager::renderAdditiveStencilShadowedQueueGroupObjects(
1021        RenderQueueGroup* pGroup, QueuedRenderableCollection::OrganisationMode om)
1022{
1023        // only render solid passes during hierarchical culling
1024        if (mIsHierarchicalCulling)
1025        {
1026                RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1027            LightList lightList;
1028
1029                while (groupIt.hasMoreElements())
1030                {
1031                        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1032
1033                        // Sort the queue first
1034                        pPriorityGrp->sort(mCameraInProgress);
1035
1036                        // Clear light list
1037                        lightList.clear();
1038
1039                        // Render all the ambient passes first, no light iteration, no lights
1040                        /*** msz: no more IRS_AMBIENT, see OgreSceneManager.h ***/
1041                        // mIlluminationStage = IRS_AMBIENT;
1042
1043                        OctreeSceneManager::renderObjects(pPriorityGrp->getSolidsBasic(), om, false, &lightList);
1044                        // Also render any objects which have receive shadows disabled
1045                        OctreeSceneManager::renderObjects(pPriorityGrp->getSolidsNoShadowReceive(), om, true);
1046#if 0           
1047                        std::stringstream d;
1048                        d << " solid size: " << (int)pPriorityGrp->_getSolidPasses().size()
1049                                << " solid no shadow size: " << (int)pPriorityGrp->_getSolidPassesNoShadow().size()
1050                                << "difspec size: " << (int)pPriorityGrp->_getSolidPassesDiffuseSpecular().size()
1051                                << " decal size: " << (int)pPriorityGrp->_getSolidPassesDecal().size();
1052                        LogManager::getSingleton().logMessage(d.str());
1053#endif
1054                }
1055        }
1056        else // render the rest of the passes
1057        {
1058                OctreeSceneManager::renderAdditiveStencilShadowedQueueGroupObjects(pGroup, om);
1059        }
1060}
1061//-----------------------------------------------------------------------
1062void OcclusionCullingSceneManager::renderModulativeStencilShadowedQueueGroupObjects(
1063        RenderQueueGroup* pGroup, QueuedRenderableCollection::OrganisationMode om)
1064{
1065   if (mIsHierarchicalCulling)
1066   {
1067           // Iterate through priorities
1068           RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1069
1070           while (groupIt.hasMoreElements())
1071           {
1072                   RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1073
1074                   // Sort the queue first
1075                   pPriorityGrp->sort(mCameraInProgress);
1076                   // Do (shadowable) solids
1077                   OctreeSceneManager::renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
1078           }
1079   }
1080   else
1081   {
1082           OctreeSceneManager::renderModulativeStencilShadowedQueueGroupObjects(pGroup, om);
1083   }
1084}
1085//-------------------------------------------------------------------------
1086void OcclusionCullingSceneManager::SetObjectsVisible(const bool visible)
1087{
1088        GtpVisibilityPreprocessor::ObjectContainer::iterator it, it_end = mObjects.end();
1089
1090        for (it = mObjects.begin(); it != it_end; ++ it)
1091        {
1092                OgreMeshInstance *omi = static_cast<OgreMeshInstance *>(*it);
1093                Entity *ent = omi->GetEntity();
1094               
1095                ent->setVisible(visible);
1096        }
1097}
1098//-----------------------------------------------------------------------
1099bool OcclusionCullingSceneManager::LoadViewCells(const String &filename)
1100{
1101        // objects are set to invisible initially
1102        SetObjectsVisible(false);
1103       
1104        // converter between view cell ids and Ogre entites
1105        GtpVisibilityPreprocessor::IndexedBoundingBoxContainer iboxes;
1106        OctreeBoundingBoxConverter bconverter(this);
1107
1108        // load the view cells assigning the found objects to the pvss
1109        const bool finalizeViewCells = true;
1110        mViewCellsManager =
1111                GtpVisibilityPreprocessor::ViewCellsManager::LoadViewCells(filename, &mObjects, true, &bconverter);
1112
1113        if (finalizeViewCells)
1114        {
1115                CreateViewCellsGeometry();
1116        }
1117
1118        return (mViewCellsManager != NULL);
1119}
1120//-------------------------------------------------------------------------
1121void OcclusionCullingSceneManager::ApplyViewCellPvs(GtpVisibilityPreprocessor::ViewCell *vc,
1122                                                                                                        const bool load)
1123{       // NOTE: should not encounter NULL view cell,
1124        // rather apply view cell representing unbounded space then
1125        if (!vc)
1126        {       
1127                // if no there is no view cell, set everything visible
1128                SetObjectsVisible(true);
1129
1130                return;
1131        }
1132               
1133        GtpVisibilityPreprocessor::ObjectPvsMap::const_iterator oit,
1134                        oit_end = vc->GetPvs().mEntries.end();
1135
1136        ////////////
1137        //-- set PVS of view cell to visible
1138
1139        for (oit = vc->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
1140        {
1141                // no associated geometry found
1142                if (!(*oit).first) continue;
1143
1144                OgreMeshInstance *omi = dynamic_cast<OgreMeshInstance *>((*oit).first);
1145                omi->GetEntity()->setVisible(load);
1146                //GtpVisibilityPreprocessor::Debug << "assigned id " << omi->GetId() << endl;
1147        }
1148}
1149//-------------------------------------------------------------------------
1150void OcclusionCullingSceneManager::UpdatePvs(Camera *cam)
1151{
1152        if (!(mViewCellsLoaded && mUseViewCells))
1153                return;
1154
1155        const GtpVisibilityPreprocessor::Vector3 viewPoint =
1156                OgreTypeConverter::ConvertFromOgre(cam->getDerivedPosition());
1157
1158        GtpVisibilityPreprocessor::ViewCell *newElementary =
1159                mViewCellsManager->GetViewCell(viewPoint);
1160
1161        // elementary view cell did not change => apply same pvs
1162        if (mElementaryViewCell == newElementary)
1163                return;
1164
1165        mElementaryViewCell = newElementary;
1166       
1167
1168        //////////////
1169        //-- unload old pvs
1170
1171        ApplyViewCellPvs(mCurrentViewCell, false);
1172
1173        // the new view cell
1174        GtpVisibilityPreprocessor::ViewCell *viewCell;
1175               
1176        if (mUseVisibilityFilter)
1177        {       
1178                ////////////
1179                //-- compute new filtered cell
1180
1181                GtpVisibilityPreprocessor::PrVs prvs;
1182                mViewCellsManager->GetPrVS(viewPoint, prvs, 5);
1183                viewCell = prvs.mViewCell;
1184        }
1185        else
1186        {
1187                viewCell = newElementary;
1188        }
1189
1190        ///////////////
1191        //-- load new pvs
1192
1193        ApplyViewCellPvs(viewCell, true);
1194
1195        // store pvs
1196        if (viewCell)
1197        {
1198                mCurrentViewCell->SetPvs(viewCell->GetPvs());
1199                mCurrentViewCell->SetMesh(viewCell->GetMesh());
1200                mCurrentViewCell->SetId(viewCell->GetId());
1201
1202                // delete merge tree of filtered view cell
1203                if (mUseVisibilityFilter)
1204                        mViewCellsManager->DeleteLocalMergeTree(viewCell);
1205        }
1206}
1207//-------------------------------------------------------------------------
1208void OcclusionCullingSceneManager::CreateViewCellsGeometry()
1209{
1210        LogManager::getSingleton().logMessage("creating view cells geometry");
1211
1212        GtpVisibilityPreprocessor::ViewCellContainer viewCells = mViewCellsManager->GetViewCells();
1213
1214        GtpVisibilityPreprocessor::ViewCellContainer::const_iterator it, it_end = viewCells.end();
1215        for (it = viewCells.begin(); it != it_end; ++ it)
1216        {
1217                GtpVisibilityPreprocessor::ViewCell *viewCell = *it;
1218
1219                std::stringstream str;
1220                str << "processing view cell with id : " << viewCell->GetId();
1221                LogManager::getSingleton().logMessage(str.str());
1222                ManualObject *manual = OgreTypeConverter::ConvertToOgre(viewCell->GetMesh(), this);
1223                mViewCellsGeometry[viewCell->GetId()] = manual;
1224
1225                // attach to scene node
1226                getRootSceneNode()->createChildSceneNode()->attachObject(manual);
1227                manual->setQueryFlags(0); // returned by no query
1228       
1229                // initialy set to invisible
1230                manual->setVisible(false);
1231        }
1232}
1233//-------------------------------------------------------------------------
1234void OcclusionCullingSceneManager::VisualizeViewCells(const bool visualize)
1235{
1236        MovableObjectsMap::const_iterator mit, mit_end = mViewCellsGeometry.end();
1237                       
1238        for (mit = mViewCellsGeometry.begin(); mit != mit_end; ++ mit)
1239        {
1240                (*mit).second->setVisible(visualize);
1241        }       
1242}
1243#if 0
1244//-------------------------------------------------------------------------
1245void OcclusionCullingSceneManager::TestVisible(SceneNode *node)
1246{
1247        // first test for scene node, then for octant (part of the hierarchy)
1248        if (!node->mVisibleChildren)
1249        {
1250                node->setVisible(false);
1251        }
1252
1253        node->getOctant()->mVisibleChildren --;
1254}
1255//-------------------------------------------------------------------------
1256void OcclusionCullingSceneManager::TestVisible(Octree *octant)
1257{
1258        // first test for scene node, then for octant (part of the hierarchy)
1259        if (!octant->mVisibleChildren)
1260        {
1261                octant->setVisible(false);
1262        }
1263}
1264
1265//-------------------------------------------------------------------------
1266void OcclusionCullingSceneManager::UpdateVisibility(Entity *ent)
1267{
1268        if (!ent->isVisible())
1269        {
1270                bool visible = TestVisible(ent->getParentNode());
1271               
1272                if (!visible)
1273                        visible = TestVisible(octant->getParentNode());
1274
1275                if (!visible)
1276                        mHierarchyInterface->pullupVisibility();
1277        }
1278}
1279#endif
1280//-----------------------------------------------------------------------
1281const String OcclusionCullingSceneManagerFactory::FACTORY_TYPE_NAME = "OcclusionCullingSceneManager";
1282//-----------------------------------------------------------------------
1283void OcclusionCullingSceneManagerFactory::initMetaData(void) const
1284{
1285        mMetaData.typeName = FACTORY_TYPE_NAME;
1286        mMetaData.description = "Scene manager organising the scene on the basis of an octree with advanced occlusion culling (TM).";
1287        mMetaData.sceneTypeMask = 0xFFFF; // support all types
1288        mMetaData.worldGeometrySupported = false;
1289}
1290//-----------------------------------------------------------------------
1291SceneManager *OcclusionCullingSceneManagerFactory::createInstance(
1292                const String& instanceName)
1293{
1294        OcclusionCullingSceneManager* tsm = new OcclusionCullingSceneManager(instanceName, visManager);
1295       
1296        // Create & register default sources (one per manager)
1297        HeightmapTerrainPageSource* ps = new HeightmapTerrainPageSource();
1298        mTerrainPageSources.push_back(ps);
1299        tsm->registerPageSource("Heightmap", ps);
1300
1301        return tsm;
1302}
1303//-----------------------------------------------------------------------
1304void OcclusionCullingSceneManagerFactory::destroyInstance(SceneManager* instance)
1305{
1306        delete instance;
1307}
1308
1309} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.