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

Revision 1304, 36.9 KB checked in by szydlowski, 18 years ago (diff)

final touches

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