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

Revision 975, 36.6 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//-----------------------------------------------------------------------
[897]209const Pass *OcclusionCullingSceneManager::_setPass(Pass* pass)
[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
223        Pass *usedPass = useDepthPass ? mDepthPass : pass;
[675]224               
[925]225
226        const IlluminationRenderStage savedStage = mIlluminationStage;
[675]227       
228        // set illumination stage to NONE so no shadow material is used
229        // for depth pass or for occlusion query
230        if (mIsDepthPassPhase || mHierarchyInterface->IsBoundingBoxQuery())
231        {
232                mIlluminationStage = IRS_NONE;
233        }
234       
235        // --- set vertex program of current pass in order to set correct depth
[868]236        if (mExecuteVertexProgramForAllPasses &&
237                mIsDepthPassPhase &&
238                pass->hasVertexProgram())
[675]239        {
240                // add vertex program of current pass to depth pass
241                mDepthPass->setVertexProgram(pass->getVertexProgramName());
242
243                if (mDepthPass->hasVertexProgram())
244                {
245                        const GpuProgramPtr& prg = mDepthPass->getVertexProgram();
246                        // Load this program if not done already
247                        if (!prg->isLoaded())
248                                prg->load();
249                        // Copy params
250                        mDepthPass->setVertexProgramParameters(pass->getVertexProgramParameters());
251                }
252        }
[868]253        else if (mDepthPass->hasVertexProgram()) // reset vertex program
[675]254        {
255                mDepthPass->setVertexProgram("");
256        }
257       
[868]258        // save old depth write: needed for item buffer
259        const bool IsDepthWrite = usedPass->getDepthWriteEnabled();
[675]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       
[868]268
269        //-- set actual pass here
[897]270        const Pass *result = SceneManager::_setPass(usedPass);
[675]271
[868]272
[675]273        // reset depth write
274        if (!mEnableDepthWrite)
275        {
276                usedPass->setDepthWriteEnabled(IsDepthWrite);
277        }
278
279        // reset illumination stage
280        mIlluminationStage = savedStage;
281
282        return result;
283}
284//-----------------------------------------------------------------------
[897]285void OcclusionCullingSceneManager::_findVisibleObjects(Camera* cam,
286                                                                                                                bool onlyShadowCasters)
[675]287{
[868]288        if (NORMAL_RENDER_HACK)
289        {
290                OctreeSceneManager::_findVisibleObjects(cam, onlyShadowCasters);
291                return;
292        }
293
[903]294
[675]295        //-- show visible scene nodes and octree bounding boxes from last frame
296        if (mShowVisualization)
297    {
298                PrepareVisualization(cam);
299        }
300        else
301        {       
302                // for hierarchical culling, we interleave identification
303                // and rendering of objects in _renderVisibibleObjects
304
305                // for the shadow pass we use only standard rendering
306                // because of low occlusion
307                if (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE &&
308                        mIlluminationStage == IRS_RENDER_TO_TEXTURE)
309                {
[868]310                        OctreeSceneManager::_findVisibleObjects(cam, onlyShadowCasters);
[675]311                }
[903]312
[675]313                // only shadow casters will be rendered in shadow texture pass
[868]314                if (0) mHierarchyInterface->SetOnlyShadowCasters(onlyShadowCasters);
[903]315
316
317                //-- apply view cell pvs
318                updatePvs(cam);
[675]319        }
320       
321       
322        // -- delete lists stored for visualization
323        mVisible.clear();
324        mBoxes.clear();
325}
326//-----------------------------------------------------------------------
[720]327void OcclusionCullingSceneManager::_renderVisibleObjects()
[675]328{
[868]329        if (NORMAL_RENDER_HACK)
330        {
331                OctreeSceneManager::_renderVisibleObjects();
[675]332
[868]333                return;
334        }
335
[675]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)
[868]351                {
[675]352                        // disable illumination stage to prevent rendering shadows
353                        mIlluminationStage = IRS_NONE;
[868]354                }
[675]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        {
[868]363                // this is also called in TerrainSceneManager: really
364                // nexessary?
365                mDestRenderSystem -> setLightingEnabled(false);
366
[675]367                // don't render backgrounds for item buffer
368                if (mUseItemBuffer)
369                {
370                        clearSpecialCaseRenderQueues();
371                        getRenderQueue()->clear();
372                }
373
374                //-- hierarchical culling
375                // the objects of different layers (e.g., background, scene,
376                // overlay) must be identified and rendered one after another
377
378                //-- render all early skies
379                clearSpecialCaseRenderQueues();
380                addSpecialCaseRenderQueue(RENDER_QUEUE_BACKGROUND);
381                addSpecialCaseRenderQueue(RENDER_QUEUE_SKIES_EARLY);
382                setSpecialCaseRenderQueueMode(SceneManager::SCRQM_INCLUDE);
383
384                TerrainSceneManager::_renderVisibleObjects();
385
386#ifdef GTP_VISIBILITY_MODIFIED_OGRE
387                // delete previously rendered content
388                _deleteRenderedQueueGroups();
389#endif
390
391                //-- prepare queue for visible objects (i.e., all but overlay and skies late)
392                clearSpecialCaseRenderQueues();
393                addSpecialCaseRenderQueue(RENDER_QUEUE_SKIES_LATE);
394                addSpecialCaseRenderQueue(RENDER_QUEUE_OVERLAY);
[897]395       
[675]396                // exclude this queues from hierarchical rendering
397                setSpecialCaseRenderQueueMode(SceneManager::SCRQM_EXCLUDE);
398
[903]399
[675]400                // set all necessary parameters for
401                // hierarchical visibility culling and rendering
402                InitVisibilityCulling(mCameraInProgress);
403
[897]404
[675]405                /**
406                * the hierarchical culling algorithm
407                * for depth pass: we just find objects and update depth buffer
408                * for "delayed" rendering: we render some passes afterwards
409                * e.g., transparents, because they need front-to-back sorting
410                **/
411               
412                mVisibilityManager->ApplyVisibilityCulling();
413
[868]414                // delete remaining renderables from queue:
415                // all which are not in mLeavePassesInQueue)
[675]416#ifdef GTP_VISIBILITY_MODIFIED_OGRE
417                _deleteRenderedQueueGroups(mLeavePassesInQueue);
418#endif
419
420                //-- reset parameters
421                mIsDepthPassPhase = false;
422                mIsItemBufferPhase = false;
423                mSkipTransparents = false;
[868]424                mIsHierarchicalCulling = false;
425               
[675]426                mLeavePassesInQueue = 0;
[897]427               
[868]428#if 1   
[675]429                // add visible nodes found by the visibility culling algorithm
430                if (mUseDepthPass)
431                {
[868]432                        NodeList::const_iterator it, it_end = mVisible.end();
433
434                        //getRenderQueue()->clear();
435                        for (it = mVisible.begin(); it != it_end; ++ it)
[675]436                        {
437                                (*it)->_addToRenderQueue(mCameraInProgress, getRenderQueue(), false);
438                        }
439                }
[868]440#endif 
[675]441                //-- now we can render all remaining queue objects
[868]442                //-- used for depth pass, transparents, overlay
[675]443                clearSpecialCaseRenderQueues();
444
445                TerrainSceneManager::_renderVisibleObjects();
[868]446        } // hierarchical culling
[675]447               
448        // HACK: set the new render level index, important to avoid cracks
449        // in terrain caused by LOD
450        TerrainRenderable::NextRenderLevelIndex();
451       
452        // reset ambient light
453        setAmbientLight(savedAmbient);
454
455        getRenderQueue()->clear(); // finally clear render queue
[868]456        if (0) OGRE_DELETE(mRenderQueue); // HACK: should rather only be cleared ...
[675]457
[868]458        if (0) WriteLog(); // write out stats
[675]459}
460
461//-----------------------------------------------------------------------
[720]462void OcclusionCullingSceneManager::_updateSceneGraph(Camera* cam)
[675]463{
[868]464        if (NORMAL_RENDER_HACK)
465        {
466                OctreeSceneManager::_updateSceneGraph(cam);
467                return;
468        }
469
[675]470        mVisibilityManager->GetCullingManager()->SetHierarchyInterface(mHierarchyInterface);
471        mHierarchyInterface->SetRenderSystem(mDestRenderSystem);
472
473        TerrainSceneManager::_updateSceneGraph(cam);
474}
475//-----------------------------------------------------------------------
[720]476bool OcclusionCullingSceneManager::setOption(const String & key, const void * val)
[675]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
524        if (key == "DepthWrite")
525        {
526                mEnableDepthWrite = (*static_cast<const bool *>(val));
527                return true;
528        }
529        if (key == "UseItemBuffer")
530        {
531                mUseItemBuffer = (*static_cast<const bool *>(val));
532                return true;
533        }
534        if (key == "ExecuteVertexProgramForAllPasses")
535        {
536                mExecuteVertexProgramForAllPasses  = (*static_cast<const bool *>(val));
537                return true;
538        }
539        if (key == "RenderTransparentsForItemBuffer")
540        {
541                mRenderTransparentsForItemBuffer  = (*static_cast<const bool *>(val));
542                return true;
543        }
544        if (key == "NodeVizScale")
545        {
546                OctreeNode::setVizScale(*static_cast<const float *>(val));
547                return true;
548        }
[903]549        if (key == "LoadViewCells")
550        {
551                if (!mViewCellsLoaded)
552                {
[938]553                        String filename(static_cast<const char *>(val));
554                        mViewCellsLoaded = LoadViewCells(filename);     
[903]555                }
[675]556
[938]557                return mViewCellsLoaded;
[903]558        }
559        if (key == "UseViewCells")
560        {
[938]561                if (mViewCellsLoaded)
562                {
563                        mUseViewCells = *static_cast<const bool *>(val);
[903]564
[938]565                        // reset view cell
566                        OGRE_DELETE(mCurrentViewCell);
567
568                        if (mUseViewCells)
569                                mCurrentViewCell = mViewCellsManager->GenerateViewCell();
570
571                        mElementaryViewCell = NULL;
572
573                        // if using view cells, all objects are set to false initially
574                        SetObjectsVisible(!mUseViewCells);
575                }
576
[903]577                return true;
578        }
579        if (key == "UseVisibilityFilter")
[675]580        {
[903]581                mUseVisibilityFilter = *static_cast<const bool *>(val);
582                // set null =>recomputation of the pvs
583        mElementaryViewCell = NULL;
584                return true;
585        }
[675]586
587        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
588                setOption(key, val) || TerrainSceneManager::setOption(key, val);
589}
590//-----------------------------------------------------------------------
[720]591bool OcclusionCullingSceneManager::getOption(const String & key, void *val)
[675]592{
593        if (key == "NumHierarchyNodes")
594        {
595                * static_cast<unsigned int *>(val) = (unsigned int)mNumOctants;
596                return true;
597        }
[925]598        if (key == "VisibilityManager")
599        {
600                * static_cast<GtpVisibility::VisibilityManager **>(val) =
601                        (GtpVisibility::VisibilityManager *)mVisibilityManager;
602                return true;
603        }
604        if (key == "HierarchInterface")
605        {
606                * static_cast<GtpVisibility::HierarchyInterface **>(val) =
607                        (GtpVisibility::HierarchyInterface *)mHierarchyInterface;
608                return true;
609        }
610
[675]611        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
612                getOption(key, val) && TerrainSceneManager::getOption(key, val);
613}
614//-----------------------------------------------------------------------
[720]615bool OcclusionCullingSceneManager::getOptionValues(const String & key,
[675]616                                                                                                        StringVector &refValueList)
617{
618        return TerrainSceneManager::getOptionValues( key, refValueList);
619}
620//-----------------------------------------------------------------------
[720]621bool OcclusionCullingSceneManager::getOptionKeys(StringVector & refKeys)
[675]622{
623        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
624                getOptionKeys(refKeys) || TerrainSceneManager::getOptionKeys(refKeys);
625}
626//-----------------------------------------------------------------------
[720]627void OcclusionCullingSceneManager::setVisibilityManager(GtpVisibility::
[675]628                                                                                                                 VisibilityManager *visManager)
629{
630        mVisibilityManager = visManager;
631}
632//-----------------------------------------------------------------------
[720]633GtpVisibility::VisibilityManager *OcclusionCullingSceneManager::getVisibilityManager( void )
[675]634{
635        return mVisibilityManager;
636}
637//-----------------------------------------------------------------------
[720]638void OcclusionCullingSceneManager::WriteLog()
[675]639{
640        std::stringstream d;
641
642        d << "Depth pass: " << StringConverter::toString(mUseDepthPass) << ", "
643          << "Delay transparents: " << StringConverter::toString(mDelayRenderTransparents) << ", "
644          << "Use optimization: " << StringConverter::toString(mHierarchyInterface->GetTestGeometryForVisibleLeaves()) << ", "
645          << "Algorithm type: " << mVisibilityManager->GetCullingManagerType() << ", "
646          << "Hierarchy nodes: " << mNumOctants << ", "
647          << "Traversed nodes: " << mHierarchyInterface->GetNumTraversedNodes() << ", "
648          << "Rendered nodes: " << mHierarchyInterface->GetNumRenderedNodes() << ", "
649          << "Query culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumQueryCulledNodes() << ", "
650          << "Frustum culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumFrustumCulledNodes() << ", "
[868]651      << "Queries issued: " << mVisibilityManager->GetCullingManager()->GetNumQueriesIssued() << ", "
652          << "Found objects: " << (int)mVisible.size() << "\n";
[675]653
654        LogManager::getSingleton().logMessage(d.str());
655}
656//-----------------------------------------------------------------------
[925]657void OcclusionCullingSceneManager::renderBasicQueueGroupObjects(RenderQueueGroup* pGroup,
658                                                                                                                                QueuedRenderableCollection::OrganisationMode om)
[675]659{
[925]660    // Basic render loop
661    // Iterate through priorities
662    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
663
664    while (groupIt.hasMoreElements())
665    {
666        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
667
668        // Sort the queue first
669        pPriorityGrp->sort(mCameraInProgress);
670
671        // Do solids
672        renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
673
674                // for correct rendering, transparents must be rendered after hierarchical culling
675                // => do nothing
676
677        // Do transparents (always descending)
678                if (NORMAL_RENDER_HACK || !mSkipTransparents)
679                {
680                        renderObjects(pPriorityGrp->getTransparents(),
681                        QueuedRenderableCollection::OM_SORT_DESCENDING, true);
682                }
683
684
685    }// for each priority
[675]686}
[925]687
[675]688//-----------------------------------------------------------------------
[720]689bool OcclusionCullingSceneManager::validatePassForRendering(Pass* pass)
[675]690{
[868]691        if (NORMAL_RENDER_HACK)
692        {
693                return SceneManager::validatePassForRendering(pass);
694        }
695
[675]696        // skip all but first pass if we are doing the depth pass
[868]697        if ((mIsDepthPassPhase || mIsItemBufferPhase) && (pass->getIndex() > 0))
[675]698        {
699                return false;
700        }
[868]701        // all but first pass
702        /*else if ((!mIsDepthPassPhase || mIsItemBufferPhase) && (pass->getIndex() != 0))
703        {
704                return false;
705        }*/
[675]706
707        return SceneManager::validatePassForRendering(pass);
708}
709//-----------------------------------------------------------------------
[897]710void OcclusionCullingSceneManager::_renderQueueGroupObjects(RenderQueueGroup* pGroup,
711                                                                                                                        QueuedRenderableCollection::OrganisationMode om)
[675]712{
[868]713        if (NORMAL_RENDER_HACK || !mIsItemBufferPhase)
[675]714        {
[897]715                TerrainSceneManager::_renderQueueGroupObjects(pGroup, om);
[675]716                return;
717        }
[897]718#ifdef  ITEM_BUFFER
719        //-- item buffer
[868]720        //-- item buffer: render objects using false colors
[675]721
722    // Iterate through priorities
723    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
724
725        while (groupIt.hasMoreElements())
726    {
727                RenderItemBuffer(groupIt.getNext());
728        }
[897]729#endif // ITEM_BUFFER
[675]730}
[897]731#ifdef ITEM_BUFFER
[675]732//-----------------------------------------------------------------------
[720]733void OcclusionCullingSceneManager::RenderItemBuffer(RenderPriorityGroup* pGroup)
[675]734{
735        // Do solids
[897]736        QueuedRenderableCollection solidObjs = pGroup->getSolidsBasic();//msz
[675]737
738        // ----- SOLIDS LOOP -----
739        RenderPriorityGroup::SolidRenderablePassMap::const_iterator ipass, ipassend;
740        ipassend = solidObjs.end();
741
742        for (ipass = solidObjs.begin(); ipass != ipassend; ++ipass)
743        {
744                // Fast bypass if this group is now empty
745                if (ipass->second->empty())
746                        continue;
747
[868]748                // Render only first pass of renderable as false color
[675]749                if (ipass->first->getIndex() > 0)
750                        continue;
751
752                RenderPriorityGroup::RenderableList* rendList = ipass->second;
753               
754                RenderPriorityGroup::RenderableList::const_iterator irend, irendend;
755                irendend = rendList->end();
756                       
757                for (irend = rendList->begin(); irend != irendend; ++irend)
758                {
[868]759                        if (0)
760                        {
761                        std::stringstream d; d << "itembuffer, pass name: " <<
762                                ipass->first->getParent()->getParent()->getName();
763                               
764                        LogManager::getSingleton().logMessage(d.str());
765                        }
[675]766                       
767                        RenderSingleObjectForItemBuffer(*irend, ipass->first);
768                }
769        }
770
[868]771        //-- TRANSPARENT LOOP: must be handled differently from solids
[675]772
773        // transparents are treated either as solids or completely discarded
774        if (mRenderTransparentsForItemBuffer)
775        {
[897]776                QueuedRenderableCollection transpObjs = pGroup->getTransparents(); //msz
[675]777                RenderPriorityGroup::TransparentRenderablePassList::const_iterator
778                        itrans, itransend;
779
780                itransend = transpObjs.end();
781                for (itrans = transpObjs.begin(); itrans != itransend; ++itrans)
782                {
783                        // like for solids, render only first pass
784                        if (itrans->pass->getIndex() == 0)
785                        {       
786                                RenderSingleObjectForItemBuffer(itrans->renderable, itrans->pass);
787                        }
788                }
789        }
790}
791//-----------------------------------------------------------------------
[720]792void OcclusionCullingSceneManager::RenderSingleObjectForItemBuffer(Renderable *rend, Pass *pass)
[675]793{
794        static LightList nullLightList;
795       
796        int col[4];
797       
798        // -- create color code out of object id
799        col[0] = (rend->getId() >> 16) & 255;
800        col[1] = (rend->getId() >> 8) & 255;
801        col[2] = rend->getId() & 255;
802//      col[3] = 255;
803
804        //mDestRenderSystem->setColour(col[0], col[1], col[2], col[3]);
805   
806        mItemBufferPass->setAmbient(ColourValue(col[0] / 255.0f,
807                                                                                    col[1] / 255.0f,
808                                                                                        col[2] / 255.0f, 1));
809
810        // set vertex program of current pass
811        if (mExecuteVertexProgramForAllPasses && pass->hasVertexProgram())
812        {
813                mItemBufferPass->setVertexProgram(pass->getVertexProgramName());
814
815                if (mItemBufferPass->hasVertexProgram())
816                {
817                        const GpuProgramPtr& prg = mItemBufferPass->getVertexProgram();
818                        // Load this program if not done already
819                        if (!prg->isLoaded())
820                                prg->load();
821                        // Copy params
822                        mItemBufferPass->setVertexProgramParameters(pass->getVertexProgramParameters());
823                }
824        }
825        else if (mItemBufferPass->hasVertexProgram())
826        {
827                mItemBufferPass->setVertexProgram("");
828        }
829
[897]830        const Pass *usedPass = _setPass(mItemBufferPass);
[675]831
832
[903]833        // render a single object, this will set up auto params if required
[675]834        renderSingleObject(rend, usedPass, false, &nullLightList);
835}
[897]836#endif // ITEM_BUFFER
[675]837//-----------------------------------------------------------------------
[720]838GtpVisibility::VisibilityManager *OcclusionCullingSceneManager::GetVisibilityManager()
[675]839{
840        return mVisibilityManager;
841}
842//-----------------------------------------------------------------------
[720]843void OcclusionCullingSceneManager::InitVisibilityCulling(Camera *cam)
[675]844{
845        // reset culling manager stats
846        mVisibilityManager->GetCullingManager()->InitFrame(mVisualizeCulledNodes);
847
848        // set depth pass flag before rendering
849        mIsDepthPassPhase = mUseDepthPass;
850
[868]851        mIsHierarchicalCulling = true; // during hierarchical culling
852
[675]853        // item buffer needs full ambient lighting to use item colors as unique id
854        if (mUseItemBuffer)
855        {
856                mIsItemBufferPhase = true;
857                setAmbientLight(ColourValue(1,1,1,1));
858        }
859
860
861        // set passes which are stored in render queue
862        // for rendering AFTER hierarchical culling, i.e., passes which need
863        // a special rendering order
[868]864       
[675]865        mLeavePassesInQueue = 0;
866
[897]867        // if we have the depth pass or use an item buffer, no passes are left in the queue
868        if (1 && !mUseDepthPass && !mUseItemBuffer)
[675]869        {
870                if (mShadowTechnique == SHADOWTYPE_STENCIL_ADDITIVE)
871                {
872                        // TODO: remove this pass because it should be processed during hierarchical culling
873                        //mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_NOSHADOW;
874
875                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_DECAL;
876                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_DIFFUSE_SPECULAR;
877                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
878
[903]879                        // just render ambient passes
[897]880                        /*** msz: no more IRS_AMBIENT, see OgreSceneManager.h ***/
881                        // mIlluminationStage = IRS_AMBIENT;
[925]882                        //getRenderQueue()->setSplitPassesByLightingType(true);
[675]883                }
884       
885                if (mShadowTechnique == SHADOWTYPE_STENCIL_MODULATIVE)
886                {
887                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_NOSHADOW;
888                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
889                }
890       
891                // transparents should be rendered after hierarchical culling to
892                // provide front-to-back ordering
893                if (mDelayRenderTransparents)
894                {
895                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
896                }
897        }
898
[868]899        // skip rendering transparents during the hierarchical culling
[675]900        // (because they will be rendered afterwards)
[868]901        mSkipTransparents =
902                (mIsDepthPassPhase || (mLeavePassesInQueue & RenderPriorityGroup::TRANSPARENT_PASSES));
[675]903
904        // -- initialise interface for rendering traversal of the hierarchy
905        mHierarchyInterface->SetHierarchyRoot(mOctree);
906       
907        // possible two cameras (one for culling, one for rendering)
908        mHierarchyInterface->InitTraversal(mCameraInProgress,
909                                                                           mCullCamera ? getCamera("CullCamera") : NULL,
910                                                                           mLeavePassesInQueue);
911               
912}
913//-----------------------------------------------------------------------
[720]914OctreeHierarchyInterface *OcclusionCullingSceneManager::GetHierarchyInterface()
[675]915{
916        return mHierarchyInterface;
917}
918//-----------------------------------------------------------------------
[720]919void OcclusionCullingSceneManager::endFrame()
[675]920{
921        TerrainRenderable::ResetRenderLevelIndex();
922}
923//-----------------------------------------------------------------------
[720]924Entity* OcclusionCullingSceneManager::createEntity(const String& entityName,
[675]925                                                                                                        const String& meshName)
926{
927        Entity *ent = SceneManager::createEntity(entityName, meshName);
928
929        for (int i = 0; i < (int)ent->getNumSubEntities(); ++i)
930        {
931                ent->getSubEntity(i)->setId(mCurrentEntityId);
932        }
933
934        // increase counter of entity id values
935        ++ mCurrentEntityId;
936
937        return ent;
938}
939//-----------------------------------------------------------------------
[897]940void OcclusionCullingSceneManager::renderAdditiveStencilShadowedQueueGroupObjects(
941        RenderQueueGroup* pGroup, QueuedRenderableCollection::OrganisationMode om)
[675]942{
943        // only render solid passes during hierarchical culling
944        if (mIsHierarchicalCulling)
945        {
946                RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
947            LightList lightList;
948
949                while (groupIt.hasMoreElements())
950                {
951                        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
952
953                        // Sort the queue first
954                        pPriorityGrp->sort(mCameraInProgress);
955
956                        // Clear light list
957                        lightList.clear();
958
959                        // Render all the ambient passes first, no light iteration, no lights
[897]960                        /*** msz: no more IRS_AMBIENT, see OgreSceneManager.h ***/
961                        // mIlluminationStage = IRS_AMBIENT;
[675]962
[897]963                        OctreeSceneManager::renderObjects(pPriorityGrp->getSolidsBasic(), om, false, &lightList);
[675]964                        // Also render any objects which have receive shadows disabled
[897]965                        OctreeSceneManager::renderObjects(pPriorityGrp->getSolidsNoShadowReceive(), om, true);
[903]966#if 0           
967                        std::stringstream d;
968                        d << " solid size: " << (int)pPriorityGrp->_getSolidPasses().size()
969                                << " solid no shadow size: " << (int)pPriorityGrp->_getSolidPassesNoShadow().size()
970                                << "difspec size: " << (int)pPriorityGrp->_getSolidPassesDiffuseSpecular().size()
971                                << " decal size: " << (int)pPriorityGrp->_getSolidPassesDecal().size();
972                        LogManager::getSingleton().logMessage(d.str());
973#endif
[675]974                }
975        }
[903]976        else // render the rest of the passes
[675]977        {
[897]978                OctreeSceneManager::renderAdditiveStencilShadowedQueueGroupObjects(pGroup, om);
[675]979        }
980}
981//-----------------------------------------------------------------------
[897]982void OcclusionCullingSceneManager::renderModulativeStencilShadowedQueueGroupObjects(
983        RenderQueueGroup* pGroup, QueuedRenderableCollection::OrganisationMode om)
[675]984{
985   if (mIsHierarchicalCulling)
986   {
987           // Iterate through priorities
988           RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
989
990           while (groupIt.hasMoreElements())
991           {
992                   RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
993
994                   // Sort the queue first
995                   pPriorityGrp->sort(mCameraInProgress);
996
997                   // Do (shadowable) solids
[897]998                   OctreeSceneManager::renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
[675]999           }
1000   }
1001   else
1002   {
[931]1003           OctreeSceneManager::renderModulativeStencilShadowedQueueGroupObjects(pGroup, om);
[675]1004   }
1005}
[903]1006//-------------------------------------------------------------------------
1007void OcclusionCullingSceneManager::SetObjectsVisible(const bool visible)
1008{
1009        GtpVisibilityPreprocessor::ObjectContainer::iterator it, it_end = mObjects.end();
[828]1010
[903]1011        for (it = mObjects.begin(); it != it_end; ++ it)
1012        {
1013                OgreMeshInstance *omi = static_cast<OgreMeshInstance *>(*it);
1014                Entity *ent = omi->GetMesh();
[944]1015               
[903]1016                ent->setVisible(visible);
1017        }
1018}
1019//-----------------------------------------------------------------------
[938]1020bool OcclusionCullingSceneManager::LoadViewCells(const String &filename)
[863]1021{
[938]1022        // objects are set to invisible initially
[903]1023        SetObjectsVisible(false);
[938]1024       
[931]1025        const string bboxesFilename = mVisibilityManager->GetVisibilityEnvironment()->getViewCellsFileName();
[903]1026
[938]1027        // converter between view cell ids and Ogre entites
[931]1028        GtpVisibilityPreprocessor::IndexedBoundingBoxContainer iboxes;
1029        OgreBoundingBoxConverter bconverter(this);
1030
[938]1031       
1032        GtpVisibilityPreprocessor::Environment *env =
1033                mVisibilityManager->GetVisibilityEnvironment()->GetPreprocessorEnvironment();
1034
[863]1035        // load the view cells assigning the found objects to the pvss
[903]1036        mViewCellsManager =
[944]1037                GtpVisibilityPreprocessor::ViewCellsManager::LoadViewCells(filename, &mObjects, env, false, &bconverter);
[903]1038
[938]1039        return (mViewCellsManager != NULL);
[863]1040}
[903]1041//-------------------------------------------------------------------------
1042void OcclusionCullingSceneManager::applyViewCellPvs(GtpVisibilityPreprocessor::ViewCell *vc,
1043                                                                                                        const bool load)
1044{       // NOTE: should not happen, rather apply view cell representing unbounded space then
1045        if (!vc)
1046        {       
1047                // set everything visible for savety
1048                SetObjectsVisible(true);
[944]1049
[903]1050                return;
1051        }
[944]1052               
[903]1053        GtpVisibilityPreprocessor::ObjectPvsMap::const_iterator oit,
1054                        oit_end = vc->GetPvs().mEntries.end();
1055
1056        //-- PVS of view cell
1057        for (oit = vc->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
1058        {
1059                if (!(*oit).first) continue;
1060
1061                OgreMeshInstance *omi = dynamic_cast<OgreMeshInstance*>((*oit).first);
1062                omi->GetMesh()->setVisible(load);
[944]1063                //GtpVisibilityPreprocessor::Debug << "assigned id " << omi->GetId() << endl;
[863]1064        }
1065}
[903]1066//-------------------------------------------------------------------------
1067void OcclusionCullingSceneManager::updatePvs(Camera *cam)
1068{
[938]1069        if (!(mViewCellsLoaded && mUseViewCells))
1070                return;
[863]1071
[938]1072        const GtpVisibilityPreprocessor::Vector3 viewPoint =
1073                OgreTypeConverter::ConvertFromOgre(cam->getDerivedPosition());
[903]1074
[938]1075        GtpVisibilityPreprocessor::ViewCell *newElementary =
1076                mViewCellsManager->GetViewCell(viewPoint);
[903]1077
[938]1078        // elementary view cell did not change => apply same pvs
1079        if (mElementaryViewCell == newElementary)
1080                return;
[903]1081
[938]1082        mElementaryViewCell = newElementary;
[944]1083        //LogManager::getSingleton().logMessage("unloading");
[938]1084        //-- unload old pvs
1085        applyViewCellPvs(mCurrentViewCell, false);
[903]1086
1087
[938]1088        //-- the new view cell
[903]1089               
[938]1090        GtpVisibilityPreprocessor::ViewCell *viewCell;
[903]1091
1092               
[938]1093        if (mUseVisibilityFilter)
1094        {
1095                //-- compute new filtered cell
1096                GtpVisibilityPreprocessor::PrVs prvs;
1097                mViewCellsManager->GetPrVS(viewPoint, prvs, 5);
1098                viewCell = prvs.mViewCell;
1099        }
1100        else
1101        {
1102                viewCell = newElementary;
1103        }
[944]1104        //LogManager::getSingleton().logMessage("loading");
[938]1105        //-- load new pvs
[944]1106        applyViewCellPvs(viewCell, true);
[903]1107
[938]1108        // store pvs
1109        mCurrentViewCell->SetPvs(viewCell->GetPvs());
[903]1110
[938]1111        // delete merge tree of filtered view cell
1112        if (mUseVisibilityFilter)
1113                mViewCellsManager->DeleteLocalMergeTree(viewCell);
[903]1114}
[955]1115#if 0
[951]1116//-------------------------------------------------------------------------
1117void OcclusionCullingSceneManager::TestVisible(SceneNode *node)
1118{
1119        // first test for scene node, then for octant (part of the hierarchy)
1120        if (!node->mVisibleChildren)
1121                node->setVisible(false);
[903]1122
[951]1123        node->getOctant()->mVisibleChildren --;
1124}
1125//-------------------------------------------------------------------------
1126void OcclusionCullingSceneManager::TestVisible(Octree *octant)
1127{
1128        // first test for scene node, then for octant (part of the hierarchy)
1129        if (!octant->mVisibleChildren)
1130                octant->setVisible(false);
1131}
[903]1132
[951]1133//-------------------------------------------------------------------------
1134void OcclusionCullingSceneManager::UpdateVisibility(Entity *ent)
1135{
1136        if (!ent->isVisible())
1137        {
1138                bool visible = TestVisible(ent->getParentNode());
1139               
1140                if (!visible)
1141                        visible = TestVisible(octant->getParentNode());
[903]1142
[951]1143                if (!visible)
1144                        mHierarchyInterface->pullupVisibility();
1145        }
1146}
[955]1147#endif
[903]1148//-----------------------------------------------------------------------
1149const String OcclusionCullingSceneManagerFactory::FACTORY_TYPE_NAME = "OcclusionCullingSceneManager";
1150//-----------------------------------------------------------------------
1151void OcclusionCullingSceneManagerFactory::initMetaData(void) const
1152{
1153        mMetaData.typeName = FACTORY_TYPE_NAME;
1154        mMetaData.description = "Scene manager organising the scene on the basis of an octree with advanced occlusion culling (TM).";
1155        mMetaData.sceneTypeMask = 0xFFFF; // support all types
1156        mMetaData.worldGeometrySupported = false;
1157}
1158//-----------------------------------------------------------------------
[925]1159SceneManager *OcclusionCullingSceneManagerFactory::createInstance(
1160                const String& instanceName)
[903]1161{
[925]1162        OcclusionCullingSceneManager* tsm = new OcclusionCullingSceneManager(instanceName, visManager);
1163       
1164        // Create & register default sources (one per manager)
1165        HeightmapTerrainPageSource* ps = new HeightmapTerrainPageSource();
1166        mTerrainPageSources.push_back(ps);
1167        tsm->registerPageSource("Heightmap", ps);
1168
1169        return tsm;
[903]1170}
1171//-----------------------------------------------------------------------
1172void OcclusionCullingSceneManagerFactory::destroyInstance(SceneManager* instance)
1173{
1174        delete instance;
1175}
1176
[675]1177} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.