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

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