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

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