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

Revision 2102, 52.1 KB checked in by mattausch, 17 years ago (diff)
Line 
1#include "OgreOcclusionCullingSceneManager.h"
2#include "OgreVisibilityOptionsManager.h"
3#include <OgreMath.h>
4#include <OgreIteratorWrappers.h>
5#include <OgreRenderSystem.h>
6#include <OgreCamera.h>
7#include <OgreLogManager.h>
8#include <OgreStringConverter.h>
9#include <OgreEntity.h>
10#include <OgreSubEntity.h>
11#include <OgreMaterialManager.h>
12#include <OgreIteratorWrappers.h>
13#include <OgreHeightmapTerrainPageSource.h>
14#include "VspBspTree.h"
15#include "Containers.h"
16#include "ViewCellsManager.h"
17#include <OgreConfigFile.h>
18#include "OgreTypeConverter.h"
19#include "OgreMeshInstance.h"
20#include "common.h"
21#include "OgreBoundingBoxConverter.h"
22#include <OgreManualObject.h>
23#include "IntersectableWrapper.h"
24#include "IVReader.h"
25
26
27namespace Ogre {
28
29//-----------------------------------------------------------------------
30OcclusionCullingSceneManager::OcclusionCullingSceneManager(
31                                                                const String& name,
32                                                                GtpVisibility::VisibilityManager *visManager):
33TerrainSceneManager(name),
34mVisibilityManager(visManager),
35mShowVisualization(false),
36mRenderNodesForViz(false),
37mRenderNodesContentForViz(false),
38mVisualizeCulledNodes(false),
39mLeavePassesInQueue(0),
40mDelayRenderTransparents(true),
41mUseDepthPass(false),
42mIsDepthPassPhase(false),
43mUseItemBuffer(false),
44mIsItemBufferPhase(false),
45mCurrentEntityId(1),
46mEnableDepthWrite(true),
47mSkipTransparents(false),
48mRenderTransparentsForItemBuffer(true),
49mExecuteVertexProgramForAllPasses(false),
50mIsHierarchicalCulling(false),
51mViewCellsLoaded(false),
52mUseViewCells(false),
53mUseVisibilityFilter(false),
54mCurrentViewCell(NULL),
55mElementaryViewCell(NULL),
56mDeleteQueueAfterRendering(true),
57mNormalExecution(false),
58mShowViewCells(false),
59mViewCellsGeometryLoaded(false),
60mShowTerrain(false),
61mViewCellsFilename(""),
62mFilename("terrain")
63{
64        Ogre::LogManager::getSingleton().
65                logMessage("creating occlusion culling scene manager");
66
67        mHierarchyInterface = new OctreeHierarchyInterface(this, mDestRenderSystem);
68       
69        if (0)
70        {
71                mDisplayNodes = true;
72                mShowBoundingBoxes = true;
73                mShowBoxes = true;
74        }
75
76        // TODO: set maxdepth to reasonable value
77        mMaxDepth = 50;
78}
79//-----------------------------------------------------------------------
80void OcclusionCullingSceneManager::InitDepthPass()
81{
82        MaterialPtr depthMat =
83                MaterialManager::getSingleton().getByName("Visibility/DepthPass");
84
85        if (depthMat.isNull())
86    {
87                depthMat = MaterialManager::getSingleton().create(
88                "Visibility/DepthPass",
89                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
90
91        mDepthPass = depthMat->getTechnique(0)->getPass(0);
92                mDepthPass->setColourWriteEnabled(false);
93                mDepthPass->setDepthWriteEnabled(true);
94                mDepthPass->setLightingEnabled(false);
95        }
96        else
97        {
98                mDepthPass = depthMat->getTechnique(0)->getPass(0);
99        }
100}
101//-----------------------------------------------------------------------
102OcclusionCullingSceneManager::~OcclusionCullingSceneManager()
103{
104        OGRE_DELETE(mHierarchyInterface);
105        CLEAR_CONTAINER(mObjects);
106        OGRE_DELETE(mCurrentViewCell);
107}
108//-----------------------------------------------------------------------
109void OcclusionCullingSceneManager::InitItemBufferPass()
110{
111        MaterialPtr itemBufferMat = MaterialManager::getSingleton().
112                getByName("Visibility/ItemBufferPass");
113
114        if (itemBufferMat.isNull())
115    {
116                // Init
117                itemBufferMat =
118                        MaterialManager::getSingleton().create("Visibility/ItemBufferPass",
119                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
120
121                mItemBufferPass = itemBufferMat->getTechnique(0)->getPass(0);
122                mItemBufferPass->setColourWriteEnabled(true);
123                mItemBufferPass->setDepthWriteEnabled(true);
124                mItemBufferPass->setLightingEnabled(true);
125                //mItemBufferPass->setLightingEnabled(false);
126        }
127        else
128        {
129                mItemBufferPass = itemBufferMat->getTechnique(0)->getPass(0);
130        }
131        //mItemBufferPass->setAmbient(1, 1, 0);
132}
133//-------------------------------------------------------------------------
134#if 1
135void OcclusionCullingSceneManager::setWorldGeometry(DataStreamPtr& stream,
136                                                                                                        const String& typeName)
137{
138        // Clear out any existing world resources (if not default)
139    if (ResourceGroupManager::getSingleton().getWorldResourceGroupName() !=
140        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME)
141    {
142        ResourceGroupManager::getSingleton().clearResourceGroup(
143            ResourceGroupManager::getSingleton().getWorldResourceGroupName());
144    }
145       
146        destroyLevelIndexes();
147    mTerrainPages.clear();
148
149    // Load the configuration
150    loadConfig(stream);
151
152        //////////////
153        // file loading
154
155        // load the scene
156        LoadScene(mFilename);
157       
158        // load view cells
159        //mViewCellsLoaded = LoadViewCells(mViewCellsFilename);
160
161        if (mShowTerrain)
162        {       
163                initLevelIndexes();
164
165                // Resize the octree, allow for 1 page for now
166                float max_x = mOptions.scale.x * mOptions.pageSize;
167                float max_y = mOptions.scale.y;// * mOptions.pageSize;
168                float max_z = mOptions.scale.z * mOptions.pageSize;
169
170                float maxAxis = std::max(max_x, max_y);
171                maxAxis = std::max(maxAxis, max_z);
172                //resize(AxisAlignedBox( 0, 0, 0, maxAxis, maxAxis, maxAxis));
173                resize(AxisAlignedBox( 0, 0, 0, max_x, max_y, max_z ));
174
175                setupTerrainMaterial();
176                setupTerrainPages();
177        }       
178 }
179#endif
180
181//-------------------------------------------------------------------------
182void OcclusionCullingSceneManager::loadConfig(DataStreamPtr& stream)
183{
184        // Set up the options
185        ConfigFile config;
186        String val;
187
188        config.load(stream);
189
190        std::stringstream d;
191               
192        val = config.getSetting("DepthPass");
193
194    if (!val.empty())
195        {
196                mUseDepthPass = atoi(val.c_str());
197        }
198
199        val = config.getSetting("FlushQueue");
200       
201        if (!val.empty())
202        {
203                mDeleteQueueAfterRendering = atoi(val.c_str());
204        }
205
206        val = config.getSetting("Scene");
207
208    if (!val.empty())
209        {
210                mFilename = val.c_str();
211               
212                // load terrain instead of scene
213                if (mFilename == "terrain")
214                {
215                        mShowTerrain = true;
216                        LogManager::getSingleton().logMessage("loading terrain");
217                }
218        }
219
220        if (!mShowTerrain)
221        {
222                val = config.getSetting("ViewCells");
223
224                if (!val.empty())
225                {
226                        mViewCellsFilename = val;
227                }
228        }
229
230        val = config.getSetting("OnlineCullingAlgorithm");
231               
232        if (!val.empty())
233        {
234                GtpVisibility::VisibilityEnvironment::CullingManagerType algorithm;
235
236                if (val == "CHC")
237                {
238                        algorithm =
239                                GtpVisibility::VisibilityEnvironment::COHERENT_HIERARCHICAL_CULLING;
240                }
241                else if (val == "SWC")
242                {
243                         algorithm =
244                                 GtpVisibility::VisibilityEnvironment::STOP_AND_WAIT_CULLING;
245                 }
246                 else if (val == "VFC")
247                 {
248                         algorithm =
249                                 GtpVisibility::VisibilityEnvironment::FRUSTUM_CULLING;
250                 }
251                 else // default rendering
252                 {
253                         algorithm =
254                                 GtpVisibility::VisibilityEnvironment::NUM_CULLING_MANAGERS;
255
256                         mNormalExecution = true;
257                 }
258
259                 mVisibilityManager->SetCullingManager(algorithm);
260
261                 d << "setting algorithm to: " << algorithm;
262                 LogManager::getSingleton().logMessage(d.str());
263        }
264
265        /////////////
266        // terrain options
267
268        if (!mShowTerrain)
269                return;
270
271        val = config.getSetting("DetailTile");
272        if (!val.empty())
273                setDetailTextureRepeat(atoi(val.c_str()));
274
275        val = config.getSetting("MaxMipMapLevel");
276        if (!val.empty())
277                setMaxGeoMipMapLevel(atoi(val.c_str()));
278
279
280        val = config.getSetting("PageSize");
281        if (!val.empty())
282                setPageSize(atoi(val.c_str()));
283        else
284                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing option 'PageSize'",
285                "TerrainSceneManager::loadConfig");
286
287
288        val = config.getSetting("TileSize");
289        if (!val.empty())
290                setTileSize(atoi(val.c_str()));
291        else
292                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing option 'TileSize'",
293                "TerrainSceneManager::loadConfig");
294
295        Vector3 v = Vector3::UNIT_SCALE;
296
297        val = config.getSetting( "PageWorldX" );
298        if ( !val.empty() )
299                v.x = atof( val.c_str() );
300
301        val = config.getSetting( "MaxHeight" );
302        if ( !val.empty() )
303                v.y = atof( val.c_str() );
304
305        val = config.getSetting( "PageWorldZ" );
306        if ( !val.empty() )
307                v.z = atof( val.c_str() );
308
309        // Scale x/z relative to pagesize
310        v.x /= mOptions.pageSize;
311        v.z /= mOptions.pageSize;
312        setScale(v);
313
314        val = config.getSetting( "MaxPixelError" );
315        if ( !val.empty() )
316                setMaxPixelError(atoi( val.c_str() ));
317
318        mDetailTextureName = config.getSetting( "DetailTexture" );
319
320        mWorldTextureName = config.getSetting( "WorldTexture" );
321
322        if ( config.getSetting( "VertexColours" ) == "yes" )
323                mOptions.coloured = true;
324
325        if ( config.getSetting( "VertexNormals" ) == "yes" )
326                mOptions.lit = true;
327
328        if ( config.getSetting( "UseTriStrips" ) == "yes" )
329                setUseTriStrips(true);
330
331        if ( config.getSetting( "VertexProgramMorph" ) == "yes" )
332                setUseLODMorph(true);
333
334        val = config.getSetting( "LODMorphStart");
335        if ( !val.empty() )
336                setLODMorphStart(atof(val.c_str()));
337
338        val = config.getSetting( "CustomMaterialName" );
339        if ( !val.empty() )
340                setCustomMaterial(val);
341
342        val = config.getSetting( "MorphLODFactorParamName" );
343        if ( !val.empty() )
344                setCustomMaterialMorphFactorParam(val);
345
346        val = config.getSetting( "MorphLODFactorParamIndex" );
347        if ( !val.empty() )
348                setCustomMaterialMorphFactorParam(atoi(val.c_str()));
349
350        // Now scan through the remaining settings, looking for any PageSource
351        // prefixed items
352        String pageSourceName = config.getSetting("PageSource");
353        if (pageSourceName == "")
354        {
355                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing option 'PageSource'",
356                        "TerrainSceneManager::loadConfig");
357        }
358        TerrainPageSourceOptionList optlist;
359        ConfigFile::SettingsIterator setIt = config.getSettingsIterator();
360        while (setIt.hasMoreElements())
361        {
362                String name = setIt.peekNextKey();
363                String value = setIt.getNext();
364                if (StringUtil::startsWith(name, pageSourceName, false))
365                {
366                        optlist.push_back(TerrainPageSourceOption(name, value));
367                }
368        }
369        // set the page source
370        selectPageSource(pageSourceName, optlist);
371}
372//-----------------------------------------------------------------------
373void OcclusionCullingSceneManager::PrepareVisualization(Camera *cam)
374{
375        // add player camera for visualization purpose
376        try
377        {
378                Camera *c;
379                if ((c = getCamera("PlayerCam")) != NULL)
380                {
381                        getRenderQueue()->addRenderable(c);
382                }   
383    }
384    catch (...)
385    {
386        // ignore
387    }
388
389        // add bounding boxes of rendered objects
390        if (0)
391        for (BoxList::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it)
392        {
393                getRenderQueue()->addRenderable(*it);
394        }
395
396        // set old view cell geometry to invisible
397    if (mCurrentViewCell && mCurrentViewCell->GetMesh())
398        {
399                //const bool showSingleViewCell = true;
400                if (mViewCellsGeometryLoaded)
401                {
402                        if (!mShowViewCells)
403                        {
404                                const int id = mCurrentViewCell->GetId();
405
406                                MovableMap::iterator fit = mViewCellsGeometry.find(id);
407
408                                if ((fit != mViewCellsGeometry.end()) && (*fit).second)
409                                        (*fit).second->_updateRenderQueue(getRenderQueue());
410                        }
411                        else
412                        {
413                                MovableMap::const_iterator mit, mit_end = mViewCellsGeometry.end();
414
415                                for (mit = mViewCellsGeometry.begin(); mit != mit_end; ++ mit)
416                                {
417                                        if ((*mit).second)
418                                                (*mit).second->_updateRenderQueue(getRenderQueue());
419                                }       
420                        }
421                }
422               
423
424                //////////
425                //-- set PVS of view cell visible
426
427                GtpVisibilityPreprocessor::ObjectPvsIterator pit =
428                        mCurrentViewCell->GetPvs().GetIterator();
429
430                while (pit.HasMoreEntries())
431                {               
432                        GtpVisibilityPreprocessor::ObjectPvsEntry entry = pit.Next();
433                        GtpVisibilityPreprocessor::Intersectable *obj = entry.mObject;
434
435                        if (obj->Type() !=
436                                GtpVisibilityPreprocessor::Intersectable::ENGINE_INTERSECTABLE)
437                                continue;
438                       
439                        EngineIntersectable *oi = static_cast<EngineIntersectable *>(obj);
440
441                        EntityContainer *entries = oi->GetItem();
442                        EntityContainer::const_iterator eit, eit_end = entries->end();
443
444                        for (eit = entries->begin(); eit != eit_end; ++ eit)
445                        {
446                                (*eit)->setUserAny(Any((int)0));
447                        }
448                }
449
450                pit = mCurrentViewCell->GetPvs().GetIterator();
451
452                while (pit.HasMoreEntries())
453                {               
454                        GtpVisibilityPreprocessor::ObjectPvsEntry entry = pit.Next();
455                        GtpVisibilityPreprocessor::Intersectable *obj = entry.mObject;
456
457                        switch (obj->Type())
458                        {       
459                        case GtpVisibilityPreprocessor::Intersectable::OGRE_MESH_INSTANCE:
460                                {
461                                        OgreMeshInstance *omi = static_cast<OgreMeshInstance *>(obj);
462                                        omi->GetEntity()->_updateRenderQueue(getRenderQueue());
463                                }
464                                break;
465
466                        case GtpVisibilityPreprocessor::Intersectable::ENGINE_INTERSECTABLE:
467                                {
468                                        EngineIntersectable *oi = static_cast<EngineIntersectable *>(obj);
469
470                                        EntityContainer *entries = oi->GetItem();
471                                        EntityContainer::const_iterator eit, eit_end = entries->end();
472
473                                        for (eit = entries->begin(); eit != eit_end; ++ eit)
474                                        {
475                                       
476                                                Entity *ent = *eit;
477                                                Any newAny = ent->getUserAny();
478
479                                                int flt = any_cast<int>(newAny);
480                                       
481                                                if (any_cast<int>(newAny) == 0)
482                                                {
483                                                        ent->setUserAny(Any((int)1));
484                                                        ent->_updateRenderQueue(getRenderQueue());
485                                                }
486
487                                        }
488                                }
489                                break;
490                        default:
491                                break;
492                        }
493                }       
494        }
495/*
496   if (mRenderNodesForViz || mRenderNodesContentForViz)
497        {
498                // HACK: change node material so it is better suited for visualization
499                MaterialPtr nodeMat = MaterialManager::getSingleton().getByName("Core/NodeMaterial");
500                nodeMat->setAmbient(1, 1, 0);
501                nodeMat->setLightingEnabled(true);
502                nodeMat->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();
503
504                for (NodeList::iterator it = mVisible.begin(); it != mVisible.end(); ++it)
505                {
506                        if (mRenderNodesForViz)
507                        {
508                                // render the visible leaf nodes
509                                if ((*it)->numAttachedObjects() &&
510                                        !(*it)->numChildren() &&
511                                        ((*it)->getAttachedObject(0)->getMovableType() == "Entity") &&
512                                        (*it)->getAttachedObject(0)->isVisible())
513                                {
514                                        //getRenderQueue()->addRenderable((*it));
515                                        (*it)->_addToRenderQueue(cam, getRenderQueue(), false);
516                                }
517
518                                // add bounding boxes instead of node itself
519                                if (0)
520                                        (*it)->_addBoundingBoxToQueue(getRenderQueue());
521                        }
522
523                        // add renderables itself
524                        if (mRenderNodesContentForViz)
525                        {
526                                (*it)->_addToRenderQueue(cam, getRenderQueue(), false);
527                        }
528                }
529        }*/
530}
531//-----------------------------------------------------------------------
532const Pass *OcclusionCullingSceneManager::_setPass(const Pass* pass, bool evenIfSuppressed)
533{
534        if (mNormalExecution)
535        {
536                return SceneManager::_setPass(pass);
537        }
538
539        // TODO: setting vertex program is not efficient
540        //Pass *usedPass = ((mIsDepthPassPhase && !pass->hasVertexProgram()) ? mDepthPass : pass);
541       
542        // set depth fill pass if we currently do not make an aabb occlusion query
543        const bool useDepthPass =
544                (mIsDepthPassPhase && !mHierarchyInterface->IsBoundingBoxQuery());
545
546        const IlluminationRenderStage savedStage = mIlluminationStage;
547       
548        // set illumination stage to NONE so no shadow material is used
549        // for depth pass or for occlusion query
550        if (mIsDepthPassPhase || mHierarchyInterface->IsBoundingBoxQuery())
551        {
552                mIlluminationStage = IRS_NONE;
553        }
554       
555        // --- set vertex program of current pass in order to set correct depth
556        if (mExecuteVertexProgramForAllPasses &&
557                mIsDepthPassPhase &&
558                pass->hasVertexProgram())
559        {
560                // add vertex program of current pass to depth pass
561                mDepthPass->setVertexProgram(pass->getVertexProgramName());
562
563                if (mDepthPass->hasVertexProgram())
564                {
565                        const GpuProgramPtr& prg = mDepthPass->getVertexProgram();
566                        // Load this program if not done already
567                        if (!prg->isLoaded())
568                                prg->load();
569                        // Copy params
570                        mDepthPass->setVertexProgramParameters(pass->getVertexProgramParameters());
571                }
572        }
573        else if (mDepthPass->hasVertexProgram()) // reset vertex program
574        {
575                mDepthPass->setVertexProgram("");
576        }
577       
578        const Pass *usedPass = useDepthPass ? mDepthPass : pass;
579
580        // save old depth write: needed for item buffer
581        const bool IsDepthWrite = usedPass->getDepthWriteEnabled();
582
583        // global option which enables / disables depth writes
584        if (!mEnableDepthWrite)
585        {
586                //usedPass->setDepthWriteEnabled(false);
587        }
588        //else if (mIsItemBufferPass) {usedPass = mItemBufferPass;}
589
590        //-- set actual pass here
591        const Pass *result = SceneManager::_setPass(usedPass);
592
593
594        // reset depth write
595        if (!mEnableDepthWrite)
596        {
597                //usedPass->setDepthWriteEnabled(IsDepthWrite);
598        }
599
600        // reset illumination stage
601        mIlluminationStage = savedStage;
602
603        return result;
604}
605//-----------------------------------------------------------------------
606void OcclusionCullingSceneManager::_findVisibleObjects(Camera* cam,
607                                                                                                                bool onlyShadowCasters)
608{
609        if (mShowVisualization)
610    {
611                //////////////
612                //-- show visible scene nodes and octree bounding boxes from last frame
613                PrepareVisualization(cam);
614        }
615        else
616        {       
617                // hierarchical culling interleaves identification
618                // and rendering of objects in _renderVisibibleObjects
619
620                // for the shadow pass we use only standard rendering
621                // because shadows have low occlusion snyway
622                if (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE &&
623                        mIlluminationStage == IRS_RENDER_TO_TEXTURE)
624                {
625                        OctreeSceneManager::_findVisibleObjects(cam, onlyShadowCasters);
626                }
627
628                // only shadow casters will be rendered in shadow texture pass
629                if (0) mHierarchyInterface->SetOnlyShadowCasters(onlyShadowCasters);
630
631                ///////////
632                //-- set visibility according to pvs of current view cell
633
634                UpdatePvs(cam);
635
636                if (mNormalExecution)
637                {
638                        OctreeSceneManager::_findVisibleObjects(cam, onlyShadowCasters);
639                        //return;
640                }
641        }
642               
643        // lists only used for visualization
644        mVisible.clear();
645        mBoxes.clear();
646}
647//-----------------------------------------------------------------------
648void OcclusionCullingSceneManager::_renderVisibleObjects()
649{
650        if (mNormalExecution)
651        {
652                // the standard octree rendering mode
653                TerrainSceneManager::_renderVisibleObjects();
654                getRenderQueue()->clear(mDeleteQueueAfterRendering);
655                return;
656        }
657
658        InitDepthPass();          // create material for depth pass
659        InitItemBufferPass(); // create material for item buffer pass
660
661        // save ambient light to reset later
662        ColourValue savedAmbient = mAmbientLight;
663
664        ////////////////////
665        //-- apply standard rendering for some modes
666        //-- (e.g., the visualization mode, the shadow pass)
667
668        if (mShowVisualization ||
669            (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE &&
670             mIlluminationStage == IRS_RENDER_TO_TEXTURE))
671        {       
672                IlluminationRenderStage savedStage = mIlluminationStage;
673       
674                if (mShowVisualization)
675                {
676                        // disable illumination stage to prevent rendering shadows
677                        mIlluminationStage = IRS_NONE;
678                }
679
680                // standard rendering for shadow maps because of performance
681                TerrainSceneManager::_renderVisibleObjects();
682
683                mIlluminationStage = savedStage;
684        }
685        else //-- the hierarchical culling algorithm
686        {
687                // note matt: this is also called in TerrainSceneManager: really necessary?
688                mDestRenderSystem -> setLightingEnabled(false);
689
690                if (mUseItemBuffer)
691                {
692                        // don't render backgrounds for item buffer
693                        clearSpecialCaseRenderQueues();
694                        getRenderQueue()->clear();
695                }
696
697                ////////////////////
698                //-- hierarchical culling
699
700                // the objects of different layers (e.g., background, scene,
701                // overlay) must be identified and rendered one after another
702
703                // first render all early skies
704                clearSpecialCaseRenderQueues();
705                addSpecialCaseRenderQueue(RENDER_QUEUE_BACKGROUND);
706                addSpecialCaseRenderQueue(RENDER_QUEUE_SKIES_EARLY);
707                setSpecialCaseRenderQueueMode(SceneManager::SCRQM_INCLUDE);
708
709                TerrainSceneManager::_renderVisibleObjects();
710
711#ifdef GTP_VISIBILITY_MODIFIED_OGRE
712                // delete previously rendered content
713                _deleteRenderedQueueGroups();
714#endif
715
716                ///////////////////
717                //-- prepare queue for visible objects (i.e., all but overlay and skies late)
718
719                clearSpecialCaseRenderQueues();
720                addSpecialCaseRenderQueue(RENDER_QUEUE_SKIES_LATE);
721                addSpecialCaseRenderQueue(RENDER_QUEUE_OVERLAY);
722       
723                // exclude this queues from hierarchical rendering
724                setSpecialCaseRenderQueueMode(SceneManager::SCRQM_EXCLUDE);
725
726                // set all necessary parameters for
727                // hierarchical visibility culling and rendering
728                InitVisibilityCulling(mCameraInProgress);
729
730
731                /**
732                * the hierarchical culling algorithm
733                * for depth pass: we just find objects and update depth buffer
734                * for "delayed" rendering: we render some passes afterwards
735                * e.g., transparents, because they need front-to-back sorting
736                **/
737               
738                mVisibilityManager->ApplyVisibilityCulling();
739
740                // delete remaining renderables from queue:
741                // all which are not in mLeavePassesInQueue)
742#ifdef GTP_VISIBILITY_MODIFIED_OGRE
743                _deleteRenderedQueueGroups(mLeavePassesInQueue);
744#endif
745
746                /////////////
747                //-- reset parameters needed for special rendering
748               
749                mIsDepthPassPhase = false;
750                mIsItemBufferPhase = false;
751                mSkipTransparents = false;
752                mIsHierarchicalCulling = false;
753               
754                mLeavePassesInQueue = 0;
755               
756                 // the shaded geometry is rendered in a second pass
757                if (mUseDepthPass)
758                {
759                        // add visible nodes found by the visibility culling algorithm
760                        NodeList::const_iterator it, it_end = mVisible.end();
761
762                        //getRenderQueue()->clear();
763                        for (it = mVisible.begin(); it != it_end; ++ it)
764                        {
765                                (*it)->_addToRenderQueue(mCameraInProgress, getRenderQueue(), false);
766                        }
767                }
768               
769                /////////////
770                //-- now we can render all remaining queue objects
771                //-- used for depth pass, transparents, overlay
772
773        clearSpecialCaseRenderQueues();
774
775                TerrainSceneManager::_renderVisibleObjects();
776        } // end hierarchical culling
777               
778        // HACK: set the new render level index, important to avoid cracks
779        // in terrain caused by LOD
780        TerrainRenderable::NextRenderLevelIndex();
781       
782        // reset ambient light
783        setAmbientLight(savedAmbient);
784
785        // almost same effect as below
786        getRenderQueue()->clear(mDeleteQueueAfterRendering);
787
788        if (0) WriteLog(); // write out stats
789}
790
791//-----------------------------------------------------------------------
792void OcclusionCullingSceneManager::_updateSceneGraph(Camera* cam)
793{
794        if (mNormalExecution)
795        {
796                OctreeSceneManager::_updateSceneGraph(cam);
797                return;
798        }
799
800        mVisibilityManager->GetCullingManager()->SetHierarchyInterface(mHierarchyInterface);
801        mHierarchyInterface->SetRenderSystem(mDestRenderSystem);
802
803        TerrainSceneManager::_updateSceneGraph(cam);
804}
805//-----------------------------------------------------------------------
806bool OcclusionCullingSceneManager::setOption(const String & key, const void * val)
807{
808        if (key == "UseDepthPass")
809        {
810                mUseDepthPass = (*static_cast<const bool *>(val));
811                return true;
812        }
813        if (key == "PrepareVisualization")
814        {
815                mShowVisualization = (*static_cast<const bool *>(val));
816                return true;
817        }
818        if (key == "RenderNodesForViz")
819        {
820                mRenderNodesForViz = (*static_cast<const bool *>(val));
821                return true;
822        }
823        if (key == "RenderNodesContentForViz")
824        {
825                mRenderNodesContentForViz = (*static_cast<const bool *>(val));
826                return true;
827        }
828        if (key == "SkyBoxEnabled")
829        {
830                mSkyBoxEnabled = (*static_cast<const bool *>(val));
831                return true;
832        }
833        if (key == "SkyPlaneEnabled")
834        {
835                mSkyPlaneEnabled = (*static_cast<const bool *>(val));
836                return true;
837        }
838        if (key == "SkyDomeEnabled")
839        {
840                mSkyDomeEnabled = (*static_cast<const bool *>(val));
841                return true;
842        }
843        if (key == "VisualizeCulledNodes")
844        {
845                mVisualizeCulledNodes = (*static_cast<const bool *>(val));
846                return true;
847        }
848        if (key == "DelayRenderTransparents")
849        {
850                mDelayRenderTransparents = (*static_cast<const bool *>(val));
851                return true;
852        }
853        if (key == "DepthWrite")
854        {
855                mEnableDepthWrite = (*static_cast<const bool *>(val));
856                return true;
857        }
858        if (key == "UseItemBuffer")
859        {
860                mUseItemBuffer = (*static_cast<const bool *>(val));
861                return true;
862        }
863        if (key == "ExecuteVertexProgramForAllPasses")
864        {
865                mExecuteVertexProgramForAllPasses  = (*static_cast<const bool *>(val));
866                return true;
867        }
868        if (key == "RenderTransparentsForItemBuffer")
869        {
870                mRenderTransparentsForItemBuffer  = (*static_cast<const bool *>(val));
871                return true;
872        }
873        else if (key == "DeleteRenderQueue")
874        {
875                mDeleteQueueAfterRendering = (*static_cast<const bool *>(val));
876                return true;
877        }
878        if (key == "NodeVizScale")
879        {
880                OctreeNode::setVizScale(*static_cast<const float *>(val));
881                return true;
882        }
883        if (key == "UseViewCells")
884        {       
885                if (!mViewCellsLoaded)
886                {
887                        // try to load view cells
888                        mViewCellsLoaded = LoadViewCells(mViewCellsFilename);   
889                }
890
891                if (!mViewCellsLoaded)
892                        return false;
893               
894                // only use this option if view cells are available
895                mUseViewCells = *static_cast<const bool *>(val);
896
897                // reset view cell
898                OGRE_DELETE(mCurrentViewCell);
899                       
900                if (mUseViewCells)
901                {
902                        mCurrentViewCell = mViewCellsManager->GenerateViewCell();
903                }
904               
905                // view cell corresponding to leaf in the view cell hierarchy
906                mElementaryViewCell = NULL;
907
908                // with view cells all objects are set to invisible per default
909                SetObjectsVisible(!mUseViewCells);
910
911                MovableObjectIterator movit = getMovableObjectIterator("Entity");
912                while (movit.hasMoreElements())
913                {
914                        Entity *ent = static_cast<Entity *>(movit.getNext());
915                        ent->setVisible(!mUseViewCells);
916                }
917               
918                return true;
919        }
920        if (key == "ShowViewCells")
921        {
922                // only use this option if view cells are available
923                if (mViewCellsLoaded)
924                {
925                        mShowViewCells = *static_cast<const bool *>(val);
926                        // if we decide use view cells
927                        // all objects are set to invisible per default
928                        VisualizeViewCells(mShowViewCells);
929                }
930
931                return true;
932        }
933        if (key == "NormalExecution")
934        {
935                mNormalExecution = *static_cast<const bool *>(val);
936                return true;
937        }
938        if (key == "UseVisibilityFilter")
939        {
940                mUseVisibilityFilter = *static_cast<const bool *>(val);
941
942                // set null => recomputation of the pvs
943        mElementaryViewCell = NULL;
944                return true;
945        }
946        if (key == "ViewCellsLoaded")
947        {
948                return mViewCellsLoaded;
949        }
950
951        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
952                setOption(key, val) || TerrainSceneManager::setOption(key, val);
953}
954//-----------------------------------------------------------------------
955bool OcclusionCullingSceneManager::getOption(const String &key, void *val)
956{
957        if (key == "NumHierarchyNodes")
958        {
959                * static_cast<unsigned int *>(val) = (unsigned int)mNumOctants;
960                return true;
961        }
962        if (key == "VisibilityManager")
963        {
964                * static_cast<GtpVisibility::VisibilityManager **>(val) =
965                        (GtpVisibility::VisibilityManager *)mVisibilityManager;
966                return true;
967        }
968        if (key == "HierarchInterface")
969        {
970                * static_cast<GtpVisibility::HierarchyInterface **>(val) =
971                        (GtpVisibility::HierarchyInterface *)mHierarchyInterface;
972                return true;
973        }
974        if (key == "ShowTerrain")
975        {
976                * static_cast<bool *>(val) = (bool *)mShowTerrain;
977                return true;
978        }
979        if (key == "UseDepthPass")
980        {
981                * static_cast<bool *>(val) = (bool *)mUseDepthPass;
982                return true;
983        }
984        if (key == "AlgorithmType")
985        {
986                GtpVisibility::VisibilityEnvironment::CullingManagerType algorithm =
987                        mVisibilityManager->GetCullingManagerType();
988
989                * static_cast<unsigned int *>(val) =
990                        (unsigned int)algorithm;
991                return true;
992        }
993
994        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
995                getOption(key, val) && TerrainSceneManager::getOption(key, val);
996}
997//-----------------------------------------------------------------------
998bool OcclusionCullingSceneManager::getOptionValues(const String & key,
999                                                                                                        StringVector &refValueList)
1000{
1001        return TerrainSceneManager::getOptionValues( key, refValueList);
1002}
1003//-----------------------------------------------------------------------
1004bool OcclusionCullingSceneManager::getOptionKeys(StringVector & refKeys)
1005{
1006        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
1007                getOptionKeys(refKeys) || TerrainSceneManager::getOptionKeys(refKeys);
1008}
1009//-----------------------------------------------------------------------
1010void OcclusionCullingSceneManager::setVisibilityManager(GtpVisibility::
1011                                                                                                                 VisibilityManager *visManager)
1012{
1013        mVisibilityManager = visManager;
1014}
1015//-----------------------------------------------------------------------
1016GtpVisibility::VisibilityManager *OcclusionCullingSceneManager::getVisibilityManager( void )
1017{
1018        return mVisibilityManager;
1019}
1020//-----------------------------------------------------------------------
1021void OcclusionCullingSceneManager::WriteLog()
1022{
1023        std::stringstream d;
1024
1025        d << "Depth pass: " << StringConverter::toString(mUseDepthPass) << ", "
1026          << "Delay transparents: " << StringConverter::toString(mDelayRenderTransparents) << ", "
1027          << "Use optimization: " << StringConverter::toString(mHierarchyInterface->GetTestGeometryForVisibleLeaves()) << ", "
1028          << "Algorithm type: " << mVisibilityManager->GetCullingManagerType() << ", "
1029          << "Hierarchy nodes: " << mNumOctants << ", "
1030          << "Traversed nodes: " << mHierarchyInterface->GetNumTraversedNodes() << ", "
1031          << "Rendered nodes: " << mHierarchyInterface->GetNumRenderedNodes() << ", "
1032          << "Query culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumQueryCulledNodes() << ", "
1033          << "Frustum culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumFrustumCulledNodes() << ", "
1034      << "Queries issued: " << mVisibilityManager->GetCullingManager()->GetNumQueriesIssued() << ", "
1035          << "Found objects: " << (int)mVisible.size() << "\n";
1036
1037        LogManager::getSingleton().logMessage(d.str());
1038}
1039//-----------------------------------------------------------------------
1040void OcclusionCullingSceneManager::renderBasicQueueGroupObjects(RenderQueueGroup* pGroup,
1041                                                                                                                                QueuedRenderableCollection::OrganisationMode om)
1042{
1043    // Basic render loop
1044    // Iterate through priorities
1045    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1046
1047    while (groupIt.hasMoreElements())
1048    {
1049        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1050
1051        // Sort the queue first
1052        pPriorityGrp->sort(mCameraInProgress);
1053
1054        // Do solids
1055        renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
1056
1057                // for correct rendering, transparents must be rendered
1058                // after hierarchical culling => don't render them now
1059
1060        if (mNormalExecution || !mSkipTransparents)
1061                {
1062                        // Do transparents (always descending)
1063                        renderObjects(pPriorityGrp->getTransparents(),
1064                                QueuedRenderableCollection::OM_SORT_DESCENDING, true);
1065                }
1066
1067
1068    } // for each priority
1069}
1070
1071//-----------------------------------------------------------------------
1072bool OcclusionCullingSceneManager::validatePassForRendering(Pass* pass)
1073{
1074        if (mNormalExecution)
1075        {
1076                return SceneManager::validatePassForRendering(pass);
1077        }
1078
1079        // skip all but first pass if we are doing the depth pass
1080        if ((mIsDepthPassPhase || mIsItemBufferPhase) && (pass->getIndex() > 0))
1081        {
1082                return false;
1083        }
1084        // all but first pass
1085        /*else if ((!mIsDepthPassPhase || mIsItemBufferPhase) && (pass->getIndex() != 0))
1086        {
1087                return false;
1088        }*/
1089
1090        return SceneManager::validatePassForRendering(pass);
1091}
1092//-----------------------------------------------------------------------
1093void OcclusionCullingSceneManager::_renderQueueGroupObjects(RenderQueueGroup* pGroup,
1094                                                                                                                        QueuedRenderableCollection::OrganisationMode om)
1095{
1096        if (mNormalExecution || !mIsItemBufferPhase)
1097        {
1098                TerrainSceneManager::_renderQueueGroupObjects(pGroup, om);
1099                return;
1100        }
1101#ifdef  ITEM_BUFFER
1102        //-- item buffer
1103        //-- render objects using false colors
1104
1105    // Iterate through priorities
1106    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1107
1108        while (groupIt.hasMoreElements())
1109    {
1110                RenderItemBuffer(groupIt.getNext());
1111        }
1112#endif // ITEM_BUFFER
1113}
1114#ifdef ITEM_BUFFER
1115//-----------------------------------------------------------------------
1116void OcclusionCullingSceneManager::RenderItemBuffer(RenderPriorityGroup* pGroup)
1117{
1118        // Do solids
1119        QueuedRenderableCollection solidObjs = pGroup->getSolidsBasic();//msz
1120
1121        // ----- SOLIDS LOOP -----
1122        RenderPriorityGroup::SolidRenderablePassMap::const_iterator ipass, ipassend;
1123        ipassend = solidObjs.end();
1124
1125        for (ipass = solidObjs.begin(); ipass != ipassend; ++ipass)
1126        {
1127                // Fast bypass if this group is now empty
1128                if (ipass->second->empty())
1129                        continue;
1130
1131                // Render only first pass of renderable as false color
1132                if (ipass->first->getIndex() > 0)
1133                        continue;
1134
1135                RenderPriorityGroup::RenderableList* rendList = ipass->second;
1136               
1137                RenderPriorityGroup::RenderableList::const_iterator irend, irendend;
1138                irendend = rendList->end();
1139                       
1140                for (irend = rendList->begin(); irend != irendend; ++irend)
1141                {
1142                        if (0)
1143                        {
1144                                std::stringstream d; d << "itembuffer, pass name: " <<
1145                                        ipass->first->getParent()->getParent()->getName();
1146
1147                                LogManager::getSingleton().logMessage(d.str());
1148                        }
1149                       
1150                        RenderSingleObjectForItemBuffer(*irend, ipass->first);
1151                }
1152        }
1153
1154        ///////////
1155        //-- TRANSPARENT LOOP: must be handled differently from solids
1156
1157        // transparents are treated either as solids or completely discarded
1158        if (mRenderTransparentsForItemBuffer)
1159        {
1160                QueuedRenderableCollection transpObjs = pGroup->getTransparents(); //msz
1161                RenderPriorityGroup::TransparentRenderablePassList::const_iterator
1162                        itrans, itransend;
1163
1164                itransend = transpObjs.end();
1165                for (itrans = transpObjs.begin(); itrans != itransend; ++itrans)
1166                {
1167                        // like for solids, render only first pass
1168                        if (itrans->pass->getIndex() == 0)
1169                        {       
1170                                RenderSingleObjectForItemBuffer(itrans->renderable, itrans->pass);
1171                        }
1172                }
1173        }
1174}
1175//-----------------------------------------------------------------------
1176void OcclusionCullingSceneManager::RenderSingleObjectForItemBuffer(Renderable *rend, Pass *pass)
1177{
1178        static LightList nullLightList;
1179       
1180        int col[4];
1181       
1182        // -- create color code out of object id
1183        col[0] = (rend->getId() >> 16) & 255;
1184        col[1] = (rend->getId() >> 8) & 255;
1185        col[2] = rend->getId() & 255;
1186//      col[3] = 255;
1187
1188        //mDestRenderSystem->setColour(col[0], col[1], col[2], col[3]);
1189   
1190        mItemBufferPass->setAmbient(ColourValue(col[0] / 255.0f,
1191                                                                                    col[1] / 255.0f,
1192                                                                                        col[2] / 255.0f, 1));
1193
1194        // set vertex program of current pass
1195        if (mExecuteVertexProgramForAllPasses && pass->hasVertexProgram())
1196        {
1197                mItemBufferPass->setVertexProgram(pass->getVertexProgramName());
1198
1199                if (mItemBufferPass->hasVertexProgram())
1200                {
1201                        const GpuProgramPtr& prg = mItemBufferPass->getVertexProgram();
1202                        // Load this program if not done already
1203                        if (!prg->isLoaded())
1204                                prg->load();
1205                        // Copy params
1206                        mItemBufferPass->setVertexProgramParameters(pass->getVertexProgramParameters());
1207                }
1208        }
1209        else if (mItemBufferPass->hasVertexProgram())
1210        {
1211                mItemBufferPass->setVertexProgram("");
1212        }
1213
1214        const Pass *usedPass = _setPass(mItemBufferPass);
1215
1216
1217        // render a single object, this will set up auto params if required
1218        renderSingleObject(rend, usedPass, false, &nullLightList);
1219}
1220#endif // ITEM_BUFFER
1221//-----------------------------------------------------------------------
1222GtpVisibility::VisibilityManager *OcclusionCullingSceneManager::GetVisibilityManager()
1223{
1224        return mVisibilityManager;
1225}
1226//-----------------------------------------------------------------------
1227void OcclusionCullingSceneManager::InitVisibilityCulling(Camera *cam)
1228{
1229        // reset culling manager stats
1230        mVisibilityManager->GetCullingManager()->InitFrame(mVisualizeCulledNodes);
1231
1232        // set depth pass flag before rendering
1233        mIsDepthPassPhase = mUseDepthPass;
1234
1235        mIsHierarchicalCulling = true; // during hierarchical culling
1236
1237        // item buffer needs full ambient lighting to use item colors as unique id
1238        if (mUseItemBuffer)
1239        {
1240                mIsItemBufferPhase = true;
1241                setAmbientLight(ColourValue(1,1,1,1));
1242        }
1243
1244
1245        // set passes which are stored in render queue
1246        // for rendering AFTER hierarchical culling, i.e., passes which need
1247        // a special rendering order
1248       
1249        mLeavePassesInQueue = 0;
1250
1251        // if we have the depth pass or use an item buffer, no passes are left in the queue
1252        if (1 && !mUseDepthPass && !mUseItemBuffer)
1253        {
1254                if (mShadowTechnique == SHADOWTYPE_STENCIL_ADDITIVE)
1255                {
1256                        // TODO: remove this pass because it should be processed during hierarchical culling
1257                        //mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_NOSHADOW;
1258
1259                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_DECAL;
1260                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_DIFFUSE_SPECULAR;
1261                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
1262
1263                        // just render ambient passes
1264                        /*** msz: no more IRS_AMBIENT, see OgreSceneManager.h ***/
1265                        // mIlluminationStage = IRS_AMBIENT;
1266                        //getRenderQueue()->setSplitPassesByLightingType(true);
1267                }
1268       
1269                if (mShadowTechnique == SHADOWTYPE_STENCIL_MODULATIVE)
1270                {
1271                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_NOSHADOW;
1272                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
1273                }
1274       
1275                // transparents should be rendered after hierarchical culling to
1276                // provide front-to-back ordering
1277                if (mDelayRenderTransparents)
1278                {
1279                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
1280                }
1281        }
1282
1283        // skip rendering transparents during the hierarchical culling
1284        // (because they will be rendered afterwards)
1285        mSkipTransparents =
1286                (mIsDepthPassPhase || (mLeavePassesInQueue & RenderPriorityGroup::TRANSPARENT_PASSES));
1287
1288        // -- initialise interface for rendering traversal of the hierarchy
1289        mHierarchyInterface->SetHierarchyRoot(mOctree);
1290       
1291        // possible two cameras (one for culling, one for rendering)
1292        mHierarchyInterface->InitTraversal(mCameraInProgress,
1293                                                                           mCullCamera ? getCamera("CullCamera") : NULL,
1294                                                                           mLeavePassesInQueue);
1295               
1296}
1297//-----------------------------------------------------------------------
1298OctreeHierarchyInterface *OcclusionCullingSceneManager::GetHierarchyInterface()
1299{
1300        return mHierarchyInterface;
1301}
1302//-----------------------------------------------------------------------
1303void OcclusionCullingSceneManager::endFrame()
1304{
1305        TerrainRenderable::ResetRenderLevelIndex();
1306}
1307//-----------------------------------------------------------------------
1308Entity* OcclusionCullingSceneManager::createEntity(const String& entityName,
1309                                                                                                        const String& meshName)
1310{
1311        Entity *ent = SceneManager::createEntity(entityName, meshName);
1312
1313        for (int i = 0; i < (int)ent->getNumSubEntities(); ++i)
1314        {
1315                ent->getSubEntity(i)->setId(mCurrentEntityId);
1316        }
1317
1318        // increase counter of entity id values
1319        ++ mCurrentEntityId;
1320
1321        return ent;
1322}
1323//-----------------------------------------------------------------------
1324void OcclusionCullingSceneManager::renderAdditiveStencilShadowedQueueGroupObjects(
1325        RenderQueueGroup* pGroup, QueuedRenderableCollection::OrganisationMode om)
1326{
1327        // only render solid passes during hierarchical culling
1328        if (mIsHierarchicalCulling)
1329        {
1330                RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1331            LightList lightList;
1332
1333                while (groupIt.hasMoreElements())
1334                {
1335                        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1336
1337                        // Sort the queue first
1338                        pPriorityGrp->sort(mCameraInProgress);
1339
1340                        // Clear light list
1341                        lightList.clear();
1342
1343                        // Render all the ambient passes first, no light iteration, no lights
1344                        /*** msz: no more IRS_AMBIENT, see OgreSceneManager.h ***/
1345                        // mIlluminationStage = IRS_AMBIENT;
1346
1347                        OctreeSceneManager::renderObjects(pPriorityGrp->getSolidsBasic(), om, false, &lightList);
1348                        // Also render any objects which have receive shadows disabled
1349                        OctreeSceneManager::renderObjects(pPriorityGrp->getSolidsNoShadowReceive(), om, true);
1350#if 0           
1351                        std::stringstream d;
1352                        d << " solid size: " << (int)pPriorityGrp->_getSolidPasses().size()
1353                                << " solid no shadow size: " << (int)pPriorityGrp->_getSolidPassesNoShadow().size()
1354                                << "difspec size: " << (int)pPriorityGrp->_getSolidPassesDiffuseSpecular().size()
1355                                << " decal size: " << (int)pPriorityGrp->_getSolidPassesDecal().size();
1356                        LogManager::getSingleton().logMessage(d.str());
1357#endif
1358                }
1359        }
1360        else // render the rest of the passes
1361        {
1362                OctreeSceneManager::renderAdditiveStencilShadowedQueueGroupObjects(pGroup, om);
1363        }
1364}
1365//-----------------------------------------------------------------------
1366void OcclusionCullingSceneManager::renderModulativeStencilShadowedQueueGroupObjects(
1367        RenderQueueGroup* pGroup, QueuedRenderableCollection::OrganisationMode om)
1368{
1369   if (mIsHierarchicalCulling)
1370   {
1371           // Iterate through priorities
1372           RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1373
1374           while (groupIt.hasMoreElements())
1375           {
1376                   RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1377
1378                   // Sort the queue first
1379                   pPriorityGrp->sort(mCameraInProgress);
1380                   // Do (shadowable) solids
1381                   OctreeSceneManager::renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
1382           }
1383   }
1384   else
1385   {
1386           OctreeSceneManager::renderModulativeStencilShadowedQueueGroupObjects(pGroup, om);
1387   }
1388}
1389//-------------------------------------------------------------------------
1390void OcclusionCullingSceneManager::SetObjectsVisible(const bool visible)
1391{
1392        GtpVisibilityPreprocessor::ObjectContainer::iterator it, it_end = mObjects.end();
1393
1394        for (it = mObjects.begin(); it != it_end; ++ it)
1395        {
1396                GtpVisibilityPreprocessor::Intersectable *entry = *it;
1397
1398                switch (entry->Type())
1399                {
1400                        case GtpVisibilityPreprocessor::Intersectable::OGRE_MESH_INSTANCE:
1401                                {
1402                                        OgreMeshInstance *omi = static_cast<OgreMeshInstance *>(entry);
1403                                        omi->GetEntity()->setVisible(visible);
1404                                        //GtpVisibilityPreprocessor::Debug << "assigned id " << omi->GetId() << endl;
1405                                }
1406                                break;
1407                        case GtpVisibilityPreprocessor::Intersectable::ENGINE_INTERSECTABLE:
1408                                {
1409                                        EngineIntersectable *oi = static_cast<EngineIntersectable *>(entry);
1410
1411                                        EntityContainer *entries = oi->GetItem();
1412                                        EntityContainer::const_iterator eit,
1413                                                eit_end = entries->end();
1414                                        for (eit = entries->begin(); eit != eit_end; ++ eit)
1415                                        {
1416                                                Entity *ent = *eit;
1417                                                ent->setVisible(visible);
1418                                        }
1419                                }
1420                                break;
1421                        default:
1422                                break;
1423                }
1424        }
1425}
1426//-----------------------------------------------------------------------
1427bool OcclusionCullingSceneManager::LoadViewCells(const String &filename)
1428{
1429        // no filename specified
1430        if (filename == "")
1431                return false;
1432
1433        // view cells already loaded
1434        if (mViewCellsLoaded)
1435                return true;
1436
1437        // converter between view cell ids and Ogre entites
1438        OctreeBoundingBoxConverter bconverter(this);
1439
1440        // load the view cells assigning the found objects to the pvss
1441        const bool finalizeViewCells = false;
1442
1443        mViewCellsManager = GtpVisibilityPreprocessor::
1444                ViewCellsManager::LoadViewCells(filename,
1445                                                                                &mObjects,
1446                                                                                true,
1447                                                                                &bconverter);
1448       
1449        Ogre::LogManager::getSingleton().logMessage("******** view cells loaded *********");
1450
1451        // objects are set to invisible initially
1452        SetObjectsVisible(false);
1453
1454        if (finalizeViewCells)
1455        {
1456                CreateViewCellsGeometry();
1457        }
1458
1459        return (mViewCellsManager != NULL);
1460}
1461//-------------------------------------------------------------------------
1462void OcclusionCullingSceneManager::ApplyViewCellPvs(GtpVisibilityPreprocessor::ViewCell *vc,
1463                                                                                                        const bool load)
1464{       
1465        // NOTE: should not encounter NULL view cell,
1466        // rather apply view cell representing unbounded space then
1467        if (!vc)
1468        {       
1469                LogManager::getSingleton().logMessage("error: should not come here");
1470                // question: if no view cell, set everything visible?
1471                //SetObjectsVisible(true);
1472                SetObjectsVisible(false);
1473                return;
1474        }
1475               
1476        GtpVisibilityPreprocessor::ObjectPvsIterator pit = vc->GetPvs().GetIterator();
1477
1478        ////////////
1479        //-- set PVS of view cell to visible
1480
1481        //std::stringstream d; d << "appying new view cell pvs: " << vc->GetPvs().GetSize();
1482        //LogManager::getSingleton().logMessage(d.str());
1483
1484        while (pit.HasMoreEntries())
1485        {               
1486                GtpVisibilityPreprocessor::ObjectPvsEntry entry = pit.Next();
1487                GtpVisibilityPreprocessor::Intersectable *obj = entry.mObject;
1488
1489                // no associated geometry found
1490                if (!obj) continue;
1491       
1492                switch (obj->Type())
1493                {
1494                        case GtpVisibilityPreprocessor::Intersectable::OGRE_MESH_INSTANCE:
1495                                {
1496                                        OgreMeshInstance *omi = static_cast<OgreMeshInstance *>(obj);
1497                                        omi->GetEntity()->setVisible(load);
1498                                }                               
1499                                break;
1500                        case GtpVisibilityPreprocessor::Intersectable::ENGINE_INTERSECTABLE:
1501                                {
1502                                        EngineIntersectable *oi = static_cast<EngineIntersectable *>(obj);
1503
1504                                        EntityContainer *entries = oi->GetItem();
1505
1506                                        EntityContainer::const_iterator eit, eit_end = entries->end();
1507
1508                                        for (eit = entries->begin(); eit != eit_end; ++ eit)
1509                                        {
1510                                                Entity *ent = *eit;
1511                                                ent->setVisible(load);                                 
1512                                        }
1513                                }
1514                                break;
1515                        default:
1516                                LogManager::getSingleton().logMessage("error: should not come here");
1517                                break;
1518                }
1519        }
1520}
1521//-------------------------------------------------------------------------
1522void OcclusionCullingSceneManager::UpdatePvs(Camera *cam)
1523{
1524        if (!(mViewCellsLoaded && mUseViewCells))
1525                return;
1526
1527        const GtpVisibilityPreprocessor::Vector3 viewPoint =
1528                OgreTypeConverter::ConvertFromOgre(cam->getDerivedPosition());
1529
1530        //std::stringstream d; d << "vp: " << viewPoint;
1531        //LogManager::getSingleton().logMessage(d.str());
1532
1533        GtpVisibilityPreprocessor::ViewCell *newElementary =
1534                mViewCellsManager->GetViewCell(viewPoint);
1535
1536        // elementary view cell did not change => don't change pvs
1537        if (mElementaryViewCell == newElementary)
1538                return;
1539
1540        mElementaryViewCell = newElementary;
1541       
1542
1543        //////////////
1544        //-- unload old pvs
1545
1546        ApplyViewCellPvs(mCurrentViewCell, false);
1547
1548        // the new view cell
1549        GtpVisibilityPreprocessor::ViewCell *viewCell;
1550               
1551        if (mUseVisibilityFilter)
1552        {       
1553                ////////////
1554                //-- compute new filtered cell
1555
1556                GtpVisibilityPreprocessor::PrVs prvs;
1557                mViewCellsManager->GetPrVS(viewPoint, prvs, 5);
1558                viewCell = prvs.mViewCell;
1559        }
1560        else
1561        {
1562                viewCell = newElementary;
1563        }
1564
1565        ///////////////
1566        //-- load new pvs
1567
1568        ApplyViewCellPvs(viewCell, true);
1569
1570        if (viewCell)
1571        {
1572                // store current view cell
1573                mCurrentViewCell->SetPvs(viewCell->GetPvs());
1574                mCurrentViewCell->SetMesh(viewCell->GetMesh());
1575                mCurrentViewCell->SetId(viewCell->GetId());
1576
1577                // delete merge tree of filtered view cell
1578                if (mUseVisibilityFilter)
1579                        mViewCellsManager->DeleteLocalMergeTree(viewCell);
1580        }
1581}
1582//-------------------------------------------------------------------------
1583void OcclusionCullingSceneManager::CreateViewCellsGeometry()
1584{
1585        //LogManager::getSingleton().logMessage("creating view cells geometry");
1586        if (mViewCellsGeometryLoaded) return;
1587
1588        GtpVisibilityPreprocessor::ViewCellContainer viewCells =
1589                mViewCellsManager->GetViewCells();
1590
1591        GtpVisibilityPreprocessor::ViewCellContainer::const_iterator it, it_end = viewCells.end();
1592        for (it = viewCells.begin(); it != it_end; ++ it)
1593        {
1594                GtpVisibilityPreprocessor::ViewCell *viewCell = *it;
1595
1596                ManualObject *manual =
1597                        OgreTypeConverter::ConvertToOgre(viewCell->GetMesh(), this);
1598               
1599                if (manual)
1600                {
1601                        mViewCellsGeometry[viewCell->GetId()] = manual;
1602
1603                        // attach to scene node
1604                        getRootSceneNode()->createChildSceneNode()->attachObject(manual);
1605                        manual->setQueryFlags(0); // returned by no query
1606       
1607                        // initialy set to invisible
1608                        manual->setVisible(false);
1609                }
1610        }
1611       
1612        mViewCellsGeometryLoaded = true;
1613}
1614//-------------------------------------------------------------------------
1615void OcclusionCullingSceneManager::VisualizeViewCells(const bool visualize)
1616{
1617        MovableMap::const_iterator mit, mit_end = mViewCellsGeometry.end();
1618                       
1619        for (mit = mViewCellsGeometry.begin(); mit != mit_end; ++ mit)
1620        {
1621                if ((*mit).second)
1622                        (*mit).second->setVisible(visualize);
1623        }       
1624}
1625#if 0
1626//-------------------------------------------------------------------------
1627void OcclusionCullingSceneManager::TestVisible(SceneNode *node)
1628{
1629        // first test for scene node, then for octant (part of the hierarchy)
1630        if (!node->mVisibleChildren)
1631        {
1632                node->setVisible(false);
1633        }
1634
1635        node->getOctant()->mVisibleChildren --;
1636}
1637//-------------------------------------------------------------------------
1638void OcclusionCullingSceneManager::TestVisible(Octree *octant)
1639{
1640        // first test for scene node, then for octant (part of the hierarchy)
1641        if (!octant->mVisibleChildren)
1642        {
1643                octant->setVisible(false);
1644        }
1645}
1646
1647//-------------------------------------------------------------------------
1648void OcclusionCullingSceneManager::UpdateVisibility(Entity *ent)
1649{
1650        if (!ent->isVisible())
1651        {
1652                bool visible = TestVisible(ent->getParentNode());
1653               
1654                if (!visible)
1655                        visible = TestVisible(octant->getParentNode());
1656
1657                if (!visible)
1658                        mHierarchyInterface->pullupVisibility();
1659        }
1660}
1661#endif
1662// splits strings containing multiple file names
1663static int SplitFilenames(const std::string str,
1664                                                  std::vector<std::string> &filenames)
1665{
1666        int pos = 0;
1667
1668        while(1)
1669        {
1670                int npos = (int)str.find(';', pos);
1671               
1672                if (npos < 0 || npos - pos < 1)
1673                        break;
1674                filenames.push_back(std::string(str, pos, npos - pos));
1675                pos = npos + 1;
1676        }
1677       
1678        filenames.push_back(std::string(str, pos, str.size() - pos));
1679        return (int)filenames.size();
1680}
1681//-----------------------------------------------------------------------
1682bool OcclusionCullingSceneManager::LoadScene(const String &filename)
1683{
1684        using namespace std;
1685        // use leaf nodes of the original spatial hierarchy as occludees
1686        vector<string> filenames;
1687        const int files = SplitFilenames(filename, filenames);
1688       
1689        std::stringstream d;
1690        d << "number of input files: " << files << "\n";
1691        LogManager::getSingleton().logMessage(d.str());
1692
1693        bool result = false;
1694        vector<string>::const_iterator fit, fit_end = filenames.end();
1695        int i = 0;
1696
1697        if (filename == "terrain")
1698        {
1699                LogManager::getSingleton().logMessage("loading terrain");
1700
1701                // terrain hack
1702                return false;
1703        }
1704/*
1705        for (fit = filenames.begin(); fit != fit_end; ++ fit, ++ i)
1706        {
1707                const string fn = *fit;
1708
1709                if (strstr(fn.c_str(), ".iv") || strstr(fn.c_str(), ".wrl"))
1710                {
1711                        // load iv files
1712                        if (!LoadSceneIV(fn, getRootSceneNode(), i))
1713                        {
1714                                // terrain hack
1715                                LogManager::getSingleton().logMessage("error loading file");
1716                        }
1717                }
1718                       
1719                // at least one piece of geometry loaded
1720                result = true;
1721        }
1722*/      result=true;
1723        return result;
1724}
1725//-----------------------------------------------------------------------
1726bool OcclusionCullingSceneManager::LoadSceneIV(const String &filename,
1727                                                                                           SceneNode *root,
1728                                                                                           const int index)
1729{
1730        IVReader ivReader;
1731
1732        Timer *timer = PlatformManager::getSingleton().createTimer();
1733        timer->reset();
1734
1735        if (1)
1736        {
1737                std::string logFilename = "IVLog" + Ogre::StringConverter().toString(index) + ".log";
1738               
1739                Log *log = LogManager::getSingleton().createLog(logFilename);
1740                ivReader.setLog(log);
1741        }
1742       
1743        //viennaNode->translate(Vector3(-300, -300, 0));
1744
1745        if (ivReader.loadFile(filename.c_str()))
1746        {
1747                SceneNode *node = root->createChildSceneNode("IVSceneNode" + index);
1748
1749                ivReader.buildTree(this, node);
1750               
1751                ivReader.collapse();
1752
1753                std::stringstream d;
1754                d << "loaded " << filename << " in " << timer->getMilliseconds() * 1e-3 << " secs";
1755                LogManager::getSingleton().logMessage(d.str());
1756               
1757                PlatformManager::getSingleton().destroyTimer(timer);
1758
1759                //-- bake into static geometry
1760                /*if (USE_STATIC_GEOMETRY)
1761                {
1762                        BakeSceneIntoStaticGeometry("staticVienna", "Vienna");
1763                }*/
1764       
1765                return true;
1766        }
1767
1768        return false;
1769}
1770//-----------------------------------------------------------------------
1771const String OcclusionCullingSceneManagerFactory::FACTORY_TYPE_NAME = "OcclusionCullingSceneManager";
1772//-----------------------------------------------------------------------
1773void OcclusionCullingSceneManagerFactory::initMetaData(void) const
1774{
1775        mMetaData.typeName = FACTORY_TYPE_NAME;
1776        mMetaData.description = "Scene manager organising the scene on the basis of an octree with advanced occlusion culling (TM).";
1777        mMetaData.sceneTypeMask = 0xFFFF; // support all types
1778        mMetaData.worldGeometrySupported = false;
1779}
1780//-----------------------------------------------------------------------
1781SceneManager *OcclusionCullingSceneManagerFactory::createInstance(
1782                const String& instanceName)
1783{
1784        OcclusionCullingSceneManager* tsm =
1785                new OcclusionCullingSceneManager(instanceName, visManager);
1786       
1787        // Create & register default sources (one per manager)
1788        HeightmapTerrainPageSource* ps = new HeightmapTerrainPageSource();
1789        mTerrainPageSources.push_back(ps);
1790        tsm->registerPageSource("Heightmap", ps);
1791
1792        return tsm;
1793}
1794//-----------------------------------------------------------------------
1795void OcclusionCullingSceneManagerFactory::destroyInstance(SceneManager* instance)
1796{
1797        delete instance;
1798}
1799
1800} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.