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

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