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

Revision 1823, 52.8 KB checked in by mattausch, 18 years ago (diff)

changed occlusion culling scene manager
the configuration goes to the scene manager directly (only terrainculling.cfg)

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(const String& name,
31                                                        GtpVisibility::VisibilityManager *visManager):
32TerrainSceneManager(name),
33mVisibilityManager(visManager),
34mShowVisualization(false),
35mRenderNodesForViz(false),
36mRenderNodesContentForViz(false),
37mVisualizeCulledNodes(false),
38mLeavePassesInQueue(0),
39mDelayRenderTransparents(true),
40mUseDepthPass(false),
41mIsDepthPassPhase(false),
42mUseItemBuffer(false),
43mIsItemBufferPhase(false),
44mCurrentEntityId(1),
45mEnableDepthWrite(true),
46mSkipTransparents(false),
47mRenderTransparentsForItemBuffer(true),
48mExecuteVertexProgramForAllPasses(false),
49mIsHierarchicalCulling(false),
50mViewCellsLoaded(false),
51mUseViewCells(false),
52mUseVisibilityFilter(false),
53mCurrentViewCell(NULL),
54mElementaryViewCell(NULL),
55mDeleteQueueAfterRendering(true),
56mNormalExecution(false),
57mShowViewCells(false),
58mViewCellsGeometryLoaded(false),
59mShowTerrain(false),
60mViewCellsFilename(""),
61mFilename("terrain")
62{
63        Ogre::LogManager::getSingleton().
64                logMessage("creating occlusion culling scene manager");
65
66        mHierarchyInterface = new OctreeHierarchyInterface(this, mDestRenderSystem);
67       
68        if (0)
69        {
70                mDisplayNodes = true;
71                mShowBoundingBoxes = true;
72                mShowBoxes = true;
73        }
74
75        // TODO: set maxdepth to reasonable value
76        mMaxDepth = 50;
77}
78//-----------------------------------------------------------------------
79void OcclusionCullingSceneManager::InitDepthPass()
80{
81        MaterialPtr depthMat =
82                MaterialManager::getSingleton().getByName("Visibility/DepthPass");
83
84        if (depthMat.isNull())
85    {
86                depthMat = MaterialManager::getSingleton().create(
87                "Visibility/DepthPass",
88                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
89
90        mDepthPass = depthMat->getTechnique(0)->getPass(0);
91                mDepthPass->setColourWriteEnabled(false);
92                mDepthPass->setDepthWriteEnabled(true);
93                mDepthPass->setLightingEnabled(false);
94        }
95        else
96        {
97                mDepthPass = depthMat->getTechnique(0)->getPass(0);
98        }
99}
100//-----------------------------------------------------------------------
101OcclusionCullingSceneManager::~OcclusionCullingSceneManager()
102{
103        OGRE_DELETE(mHierarchyInterface);
104        CLEAR_CONTAINER(mObjects);
105        OGRE_DELETE(mCurrentViewCell);
106}
107//-----------------------------------------------------------------------
108void OcclusionCullingSceneManager::InitItemBufferPass()
109{
110        MaterialPtr itemBufferMat = MaterialManager::getSingleton().
111                getByName("Visibility/ItemBufferPass");
112
113        if (itemBufferMat.isNull())
114    {
115                // Init
116                itemBufferMat =
117                        MaterialManager::getSingleton().create("Visibility/ItemBufferPass",
118                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
119
120                mItemBufferPass = itemBufferMat->getTechnique(0)->getPass(0);
121                mItemBufferPass->setColourWriteEnabled(true);
122                mItemBufferPass->setDepthWriteEnabled(true);
123                mItemBufferPass->setLightingEnabled(true);
124                //mItemBufferPass->setLightingEnabled(false);
125        }
126        else
127        {
128                mItemBufferPass = itemBufferMat->getTechnique(0)->getPass(0);
129        }
130        //mItemBufferPass->setAmbient(1, 1, 0);
131}
132//-------------------------------------------------------------------------
133#if 1
134void OcclusionCullingSceneManager::setWorldGeometry(DataStreamPtr& stream,
135                                                                                                        const String& typeName)
136{
137    // Clear out any existing world resources (if not default)
138    if (ResourceGroupManager::getSingleton().getWorldResourceGroupName() !=
139        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME)
140    {
141        ResourceGroupManager::getSingleton().clearResourceGroup(
142            ResourceGroupManager::getSingleton().getWorldResourceGroupName());
143    }
144       
145        destroyLevelIndexes();
146    mTerrainPages.clear();
147
148    // Load the configuration
149    loadConfig(stream);
150
151        // apply parameters for file loading
152
153        // loas the scene
154        LoadScene(mFilename);
155
156        // load view cells
157        mViewCellsLoaded = LoadViewCells(mViewCellsFilename);
158
159        if (mShowTerrain)
160        {       
161                initLevelIndexes();
162
163                // Resize the octree, allow for 1 page for now
164                float max_x = mOptions.scale.x * mOptions.pageSize;
165                float max_y = mOptions.scale.y;// * mOptions.pageSize;
166                float max_z = mOptions.scale.z * mOptions.pageSize;
167
168                float maxAxis = std::max(max_x, max_y);
169                maxAxis = std::max(maxAxis, max_z);
170                //resize(AxisAlignedBox( 0, 0, 0, maxAxis, maxAxis, maxAxis));
171                resize( AxisAlignedBox( 0, 0, 0, max_x, max_y, max_z ) );
172
173                setupTerrainMaterial();
174                setupTerrainPages();
175        }       
176 }
177#endif
178//-------------------------------------------------------------------------
179void OcclusionCullingSceneManager::loadConfig(DataStreamPtr& stream)
180{
181        // Set up the options
182        ConfigFile config;
183        String val;
184
185        config.load(stream);
186
187        std::stringstream d;
188               
189        val = config.getSetting("DepthPass");
190
191    if (!val.empty())
192        {
193                mUseDepthPass = atoi(val.c_str());
194        }
195
196        val = config.getSetting("FlushQueue");
197       
198        if (!val.empty())
199        {
200                mDeleteQueueAfterRendering = atoi(val.c_str());
201        }
202
203        val = config.getSetting("Scene");
204
205    if (!val.empty())
206        {
207                mFilename = val.c_str();
208               
209                if (mFilename == "terrain")
210                {
211                        mShowTerrain = true;
212                        LogManager::getSingleton().logMessage("creating terrain");
213                }
214        }
215
216        if (!mShowTerrain)
217        {
218                val = config.getSetting("ViewCells");
219
220                if (!val.empty())
221                {
222                        mViewCellsFilename = val.c_str();
223                        d << "view cells file name: " << mViewCellsFilename;
224                        LogManager::getSingleton().logMessage(d.str());
225                }
226        }
227       
228        val = config.getSetting("OnlineCullingAlgorithm");
229               
230        if (!val.empty())
231        {
232                GtpVisibility::VisibilityEnvironment::CullingManagerType algorithm;
233
234                if (val == "CHC")
235                {
236                        algorithm =
237                                GtpVisibility::VisibilityEnvironment::COHERENT_HIERARCHICAL_CULLING;
238                }
239                else if (val == "SWC")
240                {
241                         algorithm =
242                                 GtpVisibility::VisibilityEnvironment::STOP_AND_WAIT_CULLING;
243                 }
244                 else if (val == "VFC")
245                 {
246                         algorithm =
247                                 GtpVisibility::VisibilityEnvironment::FRUSTUM_CULLING;
248                 }
249                 else // default rendering
250                 {
251                         algorithm =
252                                 GtpVisibility::VisibilityEnvironment::NUM_CULLING_MANAGERS;
253
254                         mNormalExecution = true;
255                 }
256
257                 mVisibilityManager->SetCullingManager(algorithm);
258
259                 d << "setting algorithm to: " << algorithm;
260                 LogManager::getSingleton().logMessage(d.str());
261        }
262
263        /////////////////////////////////////////
264        // terrain options
265
266        if (!mShowTerrain)
267                return;
268
269        val = config.getSetting( "DetailTile" );
270        if ( !val.empty() )
271                setDetailTextureRepeat(atoi(val.c_str()));
272
273        val = config.getSetting( "MaxMipMapLevel" );
274        if ( !val.empty() )
275                setMaxGeoMipMapLevel(atoi( val.c_str() ));
276
277
278        val = config.getSetting( "PageSize" );
279        if ( !val.empty() )
280                setPageSize(atoi( val.c_str() ));
281        else
282                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing option 'PageSize'",
283                "TerrainSceneManager::loadConfig");
284
285
286        val = config.getSetting( "TileSize" );
287        if ( !val.empty() )
288                setTileSize(atoi( val.c_str() ));
289        else
290                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing option 'TileSize'",
291                "TerrainSceneManager::loadConfig");
292
293        Vector3 v = Vector3::UNIT_SCALE;
294
295        val = config.getSetting( "PageWorldX" );
296        if ( !val.empty() )
297                v.x = atof( val.c_str() );
298
299        val = config.getSetting( "MaxHeight" );
300        if ( !val.empty() )
301                v.y = atof( val.c_str() );
302
303        val = config.getSetting( "PageWorldZ" );
304        if ( !val.empty() )
305                v.z = atof( val.c_str() );
306
307        // Scale x/z relative to pagesize
308        v.x /= mOptions.pageSize;
309        v.z /= mOptions.pageSize;
310        setScale(v);
311
312        val = config.getSetting( "MaxPixelError" );
313        if ( !val.empty() )
314                setMaxPixelError(atoi( val.c_str() ));
315
316        mDetailTextureName = config.getSetting( "DetailTexture" );
317
318        mWorldTextureName = config.getSetting( "WorldTexture" );
319
320        if ( config.getSetting( "VertexColours" ) == "yes" )
321                mOptions.coloured = true;
322
323        if ( config.getSetting( "VertexNormals" ) == "yes" )
324                mOptions.lit = true;
325
326        if ( config.getSetting( "UseTriStrips" ) == "yes" )
327                setUseTriStrips(true);
328
329        if ( config.getSetting( "VertexProgramMorph" ) == "yes" )
330                setUseLODMorph(true);
331
332        val = config.getSetting( "LODMorphStart");
333        if ( !val.empty() )
334                setLODMorphStart(atof(val.c_str()));
335
336        val = config.getSetting( "CustomMaterialName" );
337        if ( !val.empty() )
338                setCustomMaterial(val);
339
340        val = config.getSetting( "MorphLODFactorParamName" );
341        if ( !val.empty() )
342                setCustomMaterialMorphFactorParam(val);
343
344        val = config.getSetting( "MorphLODFactorParamIndex" );
345        if ( !val.empty() )
346                setCustomMaterialMorphFactorParam(atoi(val.c_str()));
347
348        // Now scan through the remaining settings, looking for any PageSource
349        // prefixed items
350        String pageSourceName = config.getSetting("PageSource");
351        if (pageSourceName == "")
352        {
353                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing option 'PageSource'",
354                        "TerrainSceneManager::loadConfig");
355        }
356        TerrainPageSourceOptionList optlist;
357        ConfigFile::SettingsIterator setIt = config.getSettingsIterator();
358        while (setIt.hasMoreElements())
359        {
360                String name = setIt.peekNextKey();
361                String value = setIt.getNext();
362                if (StringUtil::startsWith(name, pageSourceName, false))
363                {
364                        optlist.push_back(TerrainPageSourceOption(name, value));
365                }
366        }
367        // set the page source
368        selectPageSource(pageSourceName, optlist);
369}
370//-----------------------------------------------------------------------
371void OcclusionCullingSceneManager::PrepareVisualization(Camera *cam)
372{
373        // add player camera for visualization purpose
374        try
375        {
376                Camera *c;
377                if ((c = getCamera("PlayerCam")) != NULL)
378                {
379                        getRenderQueue()->addRenderable(c);
380                }   
381    }
382    catch (...)
383    {
384        // ignore
385    }
386
387        // add bounding boxes of rendered objects
388        if (0)
389        for (BoxList::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it)
390        {
391                getRenderQueue()->addRenderable(*it);
392        }
393
394        // set old view cell geometry to invisible
395    if (mCurrentViewCell && mCurrentViewCell->GetMesh())
396        {
397                //const bool showSingleViewCell = true;
398                if (mViewCellsGeometryLoaded)
399                {
400                        if (!mShowViewCells)
401                        {
402                                const int id = mCurrentViewCell->GetId();
403
404                                MovableMap::iterator fit = mViewCellsGeometry.find(id);
405
406                                if ((fit != mViewCellsGeometry.end()) && (*fit).second)
407                                        (*fit).second->_updateRenderQueue(getRenderQueue());
408                        }
409                        else
410                        {
411                                MovableMap::const_iterator mit, mit_end = mViewCellsGeometry.end();
412
413                                for (mit = mViewCellsGeometry.begin(); mit != mit_end; ++ mit)
414                                {
415                                        if ((*mit).second)
416                                                (*mit).second->_updateRenderQueue(getRenderQueue());
417                                }       
418                        }
419                }
420               
421
422                //////////
423                //-- set PVS of view cell visible
424
425                GtpVisibilityPreprocessor::ObjectPvsIterator pit =
426                        mCurrentViewCell->GetPvs().GetIterator();
427
428                while (pit.HasMoreEntries())
429                {               
430                        GtpVisibilityPreprocessor::ObjectPvsEntry entry = pit.Next();
431                        GtpVisibilityPreprocessor::Intersectable *obj = entry.mObject;
432
433                        if (obj->Type() ==
434                                GtpVisibilityPreprocessor::Intersectable::OBJECTS_INTERSECTABLE)
435                        {
436                                ObjectsIntersectable *oi = dynamic_cast<ObjectsIntersectable *>(obj);
437
438                                EntityContainer *entries = oi->GetItem();
439                                EntityContainer::const_iterator eit, eit_end = entries->end();
440
441                                for (eit = entries->begin(); eit != eit_end; ++ eit)
442                                {
443                                        (*eit)->setUserAny(Any((int)0));
444                                }
445                        }
446                }
447
448                pit = mCurrentViewCell->GetPvs().GetIterator();
449
450                while (pit.HasMoreEntries())
451                {               
452                        GtpVisibilityPreprocessor::ObjectPvsEntry entry = pit.Next();
453                        GtpVisibilityPreprocessor::Intersectable *obj = entry.mObject;
454
455                        switch (obj->Type())
456                        {       
457                        case GtpVisibilityPreprocessor::Intersectable::OGRE_MESH_INSTANCE:
458                                {
459                                        OgreMeshInstance *omi = dynamic_cast<OgreMeshInstance *>(obj);
460                                        omi->GetEntity()->_updateRenderQueue(getRenderQueue());
461                                }
462                                break;
463
464                        case GtpVisibilityPreprocessor::Intersectable::OBJECTS_INTERSECTABLE:
465                                {
466                                        ObjectsIntersectable *oi = dynamic_cast<ObjectsIntersectable *>(obj);
467
468                                        EntityContainer *entries = oi->GetItem();
469                                        EntityContainer::const_iterator eit, eit_end = entries->end();
470
471                                        for (eit = entries->begin(); eit != eit_end; ++ eit)
472                                        {
473                                                //OgreMeshInstance *omi = dynamic_cast<OgreMeshInstance *>(*eit);
474                                                Entity *ent = *eit;
475                                                Any newAny = ent->getUserAny();
476
477                                                int flt = any_cast<int>(newAny);
478                                                //std::stringstream d; d << "any: " << flt << " ";
479                                                //Ogre::LogManager::getSingleton().logMessage(d.str());
480                                                if (any_cast<int>(newAny) == 0)
481                                                {
482                                                        ent->setUserAny(Any((int)1));
483                                                        ent->_updateRenderQueue(getRenderQueue());
484                                                }
485
486                                                //GtpVisibilityPreprocessor::Debug << "assigned id " << omi->GetId() << endl;
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                // only use this option if view cells are available
886                if (mViewCellsLoaded)
887                {
888                        mUseViewCells = *static_cast<const bool *>(val);
889
890                        // reset view cell
891                        OGRE_DELETE(mCurrentViewCell);
892                       
893                        if (mUseViewCells)
894                        {
895                                mCurrentViewCell = mViewCellsManager->GenerateViewCell();
896                        }
897                        // view cell corresponding to leaf in the view cell hierarchy
898                        mElementaryViewCell = NULL;
899
900                        // if we decide use view cells
901                        // all objects are set to invisible per default
902                        SetObjectsVisible(!mUseViewCells);
903
904                        MovableObjectIterator movit = getMovableObjectIterator("Entity");
905                        while (movit.hasMoreElements())
906                        {
907                                Entity *ent = static_cast<Entity *>(movit.getNext());
908                                ent->setVisible(!mUseViewCells);
909                        }
910                }
911
912                return true;
913        }
914        if (key == "ShowViewCells")
915        {
916                // only use this option if view cells are available
917                if (mViewCellsLoaded)
918                {
919                        mShowViewCells = *static_cast<const bool *>(val);
920                        // if we decide use view cells
921                        // all objects are set to invisible per default
922                        VisualizeViewCells(mShowViewCells);
923                }
924
925                return true;
926        }
927        if (key == "NormalExecution")
928        {
929                mNormalExecution = *static_cast<const bool *>(val);
930                return true;
931        }
932        if (key == "UseVisibilityFilter")
933        {
934                mUseVisibilityFilter = *static_cast<const bool *>(val);
935
936                // set null => recomputation of the pvs
937        mElementaryViewCell = NULL;
938                return true;
939        }
940        if (key == "ViewCellsLoaded")
941        {
942                return mViewCellsLoaded;
943        }
944
945        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
946                setOption(key, val) || TerrainSceneManager::setOption(key, val);
947}
948//-----------------------------------------------------------------------
949bool OcclusionCullingSceneManager::getOption(const String &key, void *val)
950{
951        if (key == "NumHierarchyNodes")
952        {
953                * static_cast<unsigned int *>(val) = (unsigned int)mNumOctants;
954                return true;
955        }
956        if (key == "VisibilityManager")
957        {
958                * static_cast<GtpVisibility::VisibilityManager **>(val) =
959                        (GtpVisibility::VisibilityManager *)mVisibilityManager;
960                return true;
961        }
962        if (key == "HierarchInterface")
963        {
964                * static_cast<GtpVisibility::HierarchyInterface **>(val) =
965                        (GtpVisibility::HierarchyInterface *)mHierarchyInterface;
966                return true;
967        }
968        if (key == "ShowTerrain")
969        {
970                * static_cast<bool *>(val) = (bool *)mShowTerrain;
971                return true;
972        }
973        if (key == "UseDepthPass")
974        {
975                * static_cast<bool *>(val) = (bool *)mUseDepthPass;
976                return true;
977        }
978        if (key == "AlgorithmType")
979        {
980                GtpVisibility::VisibilityEnvironment::CullingManagerType algorithm =
981                        mVisibilityManager->GetCullingManagerType();
982
983                * static_cast<unsigned int *>(val) =
984                        (unsigned int)algorithm;
985                return true;
986        }
987
988        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
989                getOption(key, val) && TerrainSceneManager::getOption(key, val);
990}
991//-----------------------------------------------------------------------
992bool OcclusionCullingSceneManager::getOptionValues(const String & key,
993                                                                                                        StringVector &refValueList)
994{
995        return TerrainSceneManager::getOptionValues( key, refValueList);
996}
997//-----------------------------------------------------------------------
998bool OcclusionCullingSceneManager::getOptionKeys(StringVector & refKeys)
999{
1000        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
1001                getOptionKeys(refKeys) || TerrainSceneManager::getOptionKeys(refKeys);
1002}
1003//-----------------------------------------------------------------------
1004void OcclusionCullingSceneManager::setVisibilityManager(GtpVisibility::
1005                                                                                                                 VisibilityManager *visManager)
1006{
1007        mVisibilityManager = visManager;
1008}
1009//-----------------------------------------------------------------------
1010GtpVisibility::VisibilityManager *OcclusionCullingSceneManager::getVisibilityManager( void )
1011{
1012        return mVisibilityManager;
1013}
1014//-----------------------------------------------------------------------
1015void OcclusionCullingSceneManager::WriteLog()
1016{
1017        std::stringstream d;
1018
1019        d << "Depth pass: " << StringConverter::toString(mUseDepthPass) << ", "
1020          << "Delay transparents: " << StringConverter::toString(mDelayRenderTransparents) << ", "
1021          << "Use optimization: " << StringConverter::toString(mHierarchyInterface->GetTestGeometryForVisibleLeaves()) << ", "
1022          << "Algorithm type: " << mVisibilityManager->GetCullingManagerType() << ", "
1023          << "Hierarchy nodes: " << mNumOctants << ", "
1024          << "Traversed nodes: " << mHierarchyInterface->GetNumTraversedNodes() << ", "
1025          << "Rendered nodes: " << mHierarchyInterface->GetNumRenderedNodes() << ", "
1026          << "Query culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumQueryCulledNodes() << ", "
1027          << "Frustum culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumFrustumCulledNodes() << ", "
1028      << "Queries issued: " << mVisibilityManager->GetCullingManager()->GetNumQueriesIssued() << ", "
1029          << "Found objects: " << (int)mVisible.size() << "\n";
1030
1031        LogManager::getSingleton().logMessage(d.str());
1032}
1033//-----------------------------------------------------------------------
1034void OcclusionCullingSceneManager::renderBasicQueueGroupObjects(RenderQueueGroup* pGroup,
1035                                                                                                                                QueuedRenderableCollection::OrganisationMode om)
1036{
1037    // Basic render loop
1038    // Iterate through priorities
1039    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1040
1041    while (groupIt.hasMoreElements())
1042    {
1043        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1044
1045        // Sort the queue first
1046        pPriorityGrp->sort(mCameraInProgress);
1047
1048        // Do solids
1049        renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
1050
1051                // for correct rendering, transparents must be rendered
1052                // after hierarchical culling => don't render them now
1053
1054        if (mNormalExecution || !mSkipTransparents)
1055                {
1056                        // Do transparents (always descending)
1057                        renderObjects(pPriorityGrp->getTransparents(),
1058                                QueuedRenderableCollection::OM_SORT_DESCENDING, true);
1059                }
1060
1061
1062    } // for each priority
1063}
1064
1065//-----------------------------------------------------------------------
1066bool OcclusionCullingSceneManager::validatePassForRendering(Pass* pass)
1067{
1068        if (mNormalExecution)
1069        {
1070                return SceneManager::validatePassForRendering(pass);
1071        }
1072
1073        // skip all but first pass if we are doing the depth pass
1074        if ((mIsDepthPassPhase || mIsItemBufferPhase) && (pass->getIndex() > 0))
1075        {
1076                return false;
1077        }
1078        // all but first pass
1079        /*else if ((!mIsDepthPassPhase || mIsItemBufferPhase) && (pass->getIndex() != 0))
1080        {
1081                return false;
1082        }*/
1083
1084        return SceneManager::validatePassForRendering(pass);
1085}
1086//-----------------------------------------------------------------------
1087void OcclusionCullingSceneManager::_renderQueueGroupObjects(RenderQueueGroup* pGroup,
1088                                                                                                                        QueuedRenderableCollection::OrganisationMode om)
1089{
1090        if (mNormalExecution || !mIsItemBufferPhase)
1091        {
1092                TerrainSceneManager::_renderQueueGroupObjects(pGroup, om);
1093                return;
1094        }
1095#ifdef  ITEM_BUFFER
1096        //-- item buffer
1097        //-- render objects using false colors
1098
1099    // Iterate through priorities
1100    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1101
1102        while (groupIt.hasMoreElements())
1103    {
1104                RenderItemBuffer(groupIt.getNext());
1105        }
1106#endif // ITEM_BUFFER
1107}
1108#ifdef ITEM_BUFFER
1109//-----------------------------------------------------------------------
1110void OcclusionCullingSceneManager::RenderItemBuffer(RenderPriorityGroup* pGroup)
1111{
1112        // Do solids
1113        QueuedRenderableCollection solidObjs = pGroup->getSolidsBasic();//msz
1114
1115        // ----- SOLIDS LOOP -----
1116        RenderPriorityGroup::SolidRenderablePassMap::const_iterator ipass, ipassend;
1117        ipassend = solidObjs.end();
1118
1119        for (ipass = solidObjs.begin(); ipass != ipassend; ++ipass)
1120        {
1121                // Fast bypass if this group is now empty
1122                if (ipass->second->empty())
1123                        continue;
1124
1125                // Render only first pass of renderable as false color
1126                if (ipass->first->getIndex() > 0)
1127                        continue;
1128
1129                RenderPriorityGroup::RenderableList* rendList = ipass->second;
1130               
1131                RenderPriorityGroup::RenderableList::const_iterator irend, irendend;
1132                irendend = rendList->end();
1133                       
1134                for (irend = rendList->begin(); irend != irendend; ++irend)
1135                {
1136                        if (0)
1137                        {
1138                                std::stringstream d; d << "itembuffer, pass name: " <<
1139                                        ipass->first->getParent()->getParent()->getName();
1140
1141                                LogManager::getSingleton().logMessage(d.str());
1142                        }
1143                       
1144                        RenderSingleObjectForItemBuffer(*irend, ipass->first);
1145                }
1146        }
1147
1148        ///////////
1149        //-- TRANSPARENT LOOP: must be handled differently from solids
1150
1151        // transparents are treated either as solids or completely discarded
1152        if (mRenderTransparentsForItemBuffer)
1153        {
1154                QueuedRenderableCollection transpObjs = pGroup->getTransparents(); //msz
1155                RenderPriorityGroup::TransparentRenderablePassList::const_iterator
1156                        itrans, itransend;
1157
1158                itransend = transpObjs.end();
1159                for (itrans = transpObjs.begin(); itrans != itransend; ++itrans)
1160                {
1161                        // like for solids, render only first pass
1162                        if (itrans->pass->getIndex() == 0)
1163                        {       
1164                                RenderSingleObjectForItemBuffer(itrans->renderable, itrans->pass);
1165                        }
1166                }
1167        }
1168}
1169//-----------------------------------------------------------------------
1170void OcclusionCullingSceneManager::RenderSingleObjectForItemBuffer(Renderable *rend, Pass *pass)
1171{
1172        static LightList nullLightList;
1173       
1174        int col[4];
1175       
1176        // -- create color code out of object id
1177        col[0] = (rend->getId() >> 16) & 255;
1178        col[1] = (rend->getId() >> 8) & 255;
1179        col[2] = rend->getId() & 255;
1180//      col[3] = 255;
1181
1182        //mDestRenderSystem->setColour(col[0], col[1], col[2], col[3]);
1183   
1184        mItemBufferPass->setAmbient(ColourValue(col[0] / 255.0f,
1185                                                                                    col[1] / 255.0f,
1186                                                                                        col[2] / 255.0f, 1));
1187
1188        // set vertex program of current pass
1189        if (mExecuteVertexProgramForAllPasses && pass->hasVertexProgram())
1190        {
1191                mItemBufferPass->setVertexProgram(pass->getVertexProgramName());
1192
1193                if (mItemBufferPass->hasVertexProgram())
1194                {
1195                        const GpuProgramPtr& prg = mItemBufferPass->getVertexProgram();
1196                        // Load this program if not done already
1197                        if (!prg->isLoaded())
1198                                prg->load();
1199                        // Copy params
1200                        mItemBufferPass->setVertexProgramParameters(pass->getVertexProgramParameters());
1201                }
1202        }
1203        else if (mItemBufferPass->hasVertexProgram())
1204        {
1205                mItemBufferPass->setVertexProgram("");
1206        }
1207
1208        const Pass *usedPass = _setPass(mItemBufferPass);
1209
1210
1211        // render a single object, this will set up auto params if required
1212        renderSingleObject(rend, usedPass, false, &nullLightList);
1213}
1214#endif // ITEM_BUFFER
1215//-----------------------------------------------------------------------
1216GtpVisibility::VisibilityManager *OcclusionCullingSceneManager::GetVisibilityManager()
1217{
1218        return mVisibilityManager;
1219}
1220//-----------------------------------------------------------------------
1221void OcclusionCullingSceneManager::InitVisibilityCulling(Camera *cam)
1222{
1223        // reset culling manager stats
1224        mVisibilityManager->GetCullingManager()->InitFrame(mVisualizeCulledNodes);
1225
1226        // set depth pass flag before rendering
1227        mIsDepthPassPhase = mUseDepthPass;
1228
1229        mIsHierarchicalCulling = true; // during hierarchical culling
1230
1231        // item buffer needs full ambient lighting to use item colors as unique id
1232        if (mUseItemBuffer)
1233        {
1234                mIsItemBufferPhase = true;
1235                setAmbientLight(ColourValue(1,1,1,1));
1236        }
1237
1238
1239        // set passes which are stored in render queue
1240        // for rendering AFTER hierarchical culling, i.e., passes which need
1241        // a special rendering order
1242       
1243        mLeavePassesInQueue = 0;
1244
1245        // if we have the depth pass or use an item buffer, no passes are left in the queue
1246        if (1 && !mUseDepthPass && !mUseItemBuffer)
1247        {
1248                if (mShadowTechnique == SHADOWTYPE_STENCIL_ADDITIVE)
1249                {
1250                        // TODO: remove this pass because it should be processed during hierarchical culling
1251                        //mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_NOSHADOW;
1252
1253                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_DECAL;
1254                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_DIFFUSE_SPECULAR;
1255                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
1256
1257                        // just render ambient passes
1258                        /*** msz: no more IRS_AMBIENT, see OgreSceneManager.h ***/
1259                        // mIlluminationStage = IRS_AMBIENT;
1260                        //getRenderQueue()->setSplitPassesByLightingType(true);
1261                }
1262       
1263                if (mShadowTechnique == SHADOWTYPE_STENCIL_MODULATIVE)
1264                {
1265                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_NOSHADOW;
1266                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
1267                }
1268       
1269                // transparents should be rendered after hierarchical culling to
1270                // provide front-to-back ordering
1271                if (mDelayRenderTransparents)
1272                {
1273                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
1274                }
1275        }
1276
1277        // skip rendering transparents during the hierarchical culling
1278        // (because they will be rendered afterwards)
1279        mSkipTransparents =
1280                (mIsDepthPassPhase || (mLeavePassesInQueue & RenderPriorityGroup::TRANSPARENT_PASSES));
1281
1282        // -- initialise interface for rendering traversal of the hierarchy
1283        mHierarchyInterface->SetHierarchyRoot(mOctree);
1284       
1285        // possible two cameras (one for culling, one for rendering)
1286        mHierarchyInterface->InitTraversal(mCameraInProgress,
1287                                                                           mCullCamera ? getCamera("CullCamera") : NULL,
1288                                                                           mLeavePassesInQueue);
1289               
1290}
1291//-----------------------------------------------------------------------
1292OctreeHierarchyInterface *OcclusionCullingSceneManager::GetHierarchyInterface()
1293{
1294        return mHierarchyInterface;
1295}
1296//-----------------------------------------------------------------------
1297void OcclusionCullingSceneManager::endFrame()
1298{
1299        TerrainRenderable::ResetRenderLevelIndex();
1300}
1301//-----------------------------------------------------------------------
1302Entity* OcclusionCullingSceneManager::createEntity(const String& entityName,
1303                                                                                                        const String& meshName)
1304{
1305        Entity *ent = SceneManager::createEntity(entityName, meshName);
1306
1307        for (int i = 0; i < (int)ent->getNumSubEntities(); ++i)
1308        {
1309                ent->getSubEntity(i)->setId(mCurrentEntityId);
1310        }
1311
1312        // increase counter of entity id values
1313        ++ mCurrentEntityId;
1314
1315        return ent;
1316}
1317//-----------------------------------------------------------------------
1318void OcclusionCullingSceneManager::renderAdditiveStencilShadowedQueueGroupObjects(
1319        RenderQueueGroup* pGroup, QueuedRenderableCollection::OrganisationMode om)
1320{
1321        // only render solid passes during hierarchical culling
1322        if (mIsHierarchicalCulling)
1323        {
1324                RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1325            LightList lightList;
1326
1327                while (groupIt.hasMoreElements())
1328                {
1329                        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1330
1331                        // Sort the queue first
1332                        pPriorityGrp->sort(mCameraInProgress);
1333
1334                        // Clear light list
1335                        lightList.clear();
1336
1337                        // Render all the ambient passes first, no light iteration, no lights
1338                        /*** msz: no more IRS_AMBIENT, see OgreSceneManager.h ***/
1339                        // mIlluminationStage = IRS_AMBIENT;
1340
1341                        OctreeSceneManager::renderObjects(pPriorityGrp->getSolidsBasic(), om, false, &lightList);
1342                        // Also render any objects which have receive shadows disabled
1343                        OctreeSceneManager::renderObjects(pPriorityGrp->getSolidsNoShadowReceive(), om, true);
1344#if 0           
1345                        std::stringstream d;
1346                        d << " solid size: " << (int)pPriorityGrp->_getSolidPasses().size()
1347                                << " solid no shadow size: " << (int)pPriorityGrp->_getSolidPassesNoShadow().size()
1348                                << "difspec size: " << (int)pPriorityGrp->_getSolidPassesDiffuseSpecular().size()
1349                                << " decal size: " << (int)pPriorityGrp->_getSolidPassesDecal().size();
1350                        LogManager::getSingleton().logMessage(d.str());
1351#endif
1352                }
1353        }
1354        else // render the rest of the passes
1355        {
1356                OctreeSceneManager::renderAdditiveStencilShadowedQueueGroupObjects(pGroup, om);
1357        }
1358}
1359//-----------------------------------------------------------------------
1360void OcclusionCullingSceneManager::renderModulativeStencilShadowedQueueGroupObjects(
1361        RenderQueueGroup* pGroup, QueuedRenderableCollection::OrganisationMode om)
1362{
1363   if (mIsHierarchicalCulling)
1364   {
1365           // Iterate through priorities
1366           RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1367
1368           while (groupIt.hasMoreElements())
1369           {
1370                   RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1371
1372                   // Sort the queue first
1373                   pPriorityGrp->sort(mCameraInProgress);
1374                   // Do (shadowable) solids
1375                   OctreeSceneManager::renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
1376           }
1377   }
1378   else
1379   {
1380           OctreeSceneManager::renderModulativeStencilShadowedQueueGroupObjects(pGroup, om);
1381   }
1382}
1383//-------------------------------------------------------------------------
1384void OcclusionCullingSceneManager::SetObjectsVisible(const bool visible)
1385{
1386        GtpVisibilityPreprocessor::ObjectContainer::iterator it, it_end = mObjects.end();
1387
1388        for (it = mObjects.begin(); it != it_end; ++ it)
1389        {
1390                GtpVisibilityPreprocessor::Intersectable *entry = *it;
1391
1392                switch (entry->Type())
1393                {
1394                        case GtpVisibilityPreprocessor::Intersectable::OGRE_MESH_INSTANCE:
1395                                {
1396                                        OgreMeshInstance *omi = dynamic_cast<OgreMeshInstance *>(entry);
1397                                        omi->GetEntity()->setVisible(visible);
1398                                        //GtpVisibilityPreprocessor::Debug << "assigned id " << omi->GetId() << endl;
1399                                }
1400                                break;
1401                        case GtpVisibilityPreprocessor::Intersectable::OBJECTS_INTERSECTABLE:
1402                                {
1403                                        //GtpVisibilityPreprocessor::ObjectsIntersectable *oi =
1404                                        //      dynamic_cast<GtpVisibilityPreprocessor::ObjectsIntersectable *>(entry);
1405                                        ObjectsIntersectable *oi = dynamic_cast<ObjectsIntersectable *>(entry);
1406
1407                                        //GtpVisibilityPreprocessor::ObjectContainer *entries = oi->GetItem();
1408                                        EntityContainer *entries = oi->GetItem();
1409                                        EntityContainer::const_iterator eit,
1410                                                eit_end = entries->end();
1411                                        for (eit = entries->begin(); eit != eit_end; ++ eit)
1412                                        {
1413                                                //OgreMeshInstance *omi = dynamic_cast<OgreMeshInstance *>(*eit);
1414                                                Entity *ent = *eit;
1415                                                ent->setVisible(visible);
1416                                                //GtpVisibilityPreprocessor::Debug << "assigned id " << omi->GetId() << endl;
1417                                        }
1418                                }
1419                                break;
1420                        default:
1421                                break;
1422                }
1423        }
1424}
1425//-----------------------------------------------------------------------
1426bool OcclusionCullingSceneManager::LoadViewCells(const String &filename)
1427{
1428        if (filename == "")
1429                return false;
1430
1431        if (mViewCellsLoaded)
1432                return true;
1433
1434        // converter between view cell ids and Ogre entites
1435        OctreeBoundingBoxConverter bconverter(this);
1436
1437        // load the view cells assigning the found objects to the pvss
1438        const bool finalizeViewCells = true;
1439
1440        mViewCellsManager = GtpVisibilityPreprocessor::
1441                ViewCellsManager::LoadViewCells(filename,
1442                                                                                &mObjects,
1443                                                                                true,
1444                                                                                &bconverter);
1445
1446        // objects are set to invisible initially
1447        SetObjectsVisible(false);
1448
1449        if (finalizeViewCells)
1450        {
1451                CreateViewCellsGeometry();
1452        }
1453
1454        return (mViewCellsManager != NULL);
1455}
1456//-------------------------------------------------------------------------
1457void OcclusionCullingSceneManager::ApplyViewCellPvs(GtpVisibilityPreprocessor::ViewCell *vc,
1458                                                                                                        const bool load)
1459{       // NOTE: should not encounter NULL view cell,
1460        // rather apply view cell representing unbounded space then
1461        if (!vc)
1462        {       
1463                // if no there is no view cell, set everything visible
1464                //SetObjectsVisible(true);
1465                SetObjectsVisible(false);
1466                return;
1467        }
1468               
1469        GtpVisibilityPreprocessor::ObjectPvsIterator pit = vc->GetPvs().GetIterator();
1470
1471        ////////////
1472        //-- set PVS of view cell to visible
1473
1474        while (pit.HasMoreEntries())
1475        {               
1476                GtpVisibilityPreprocessor::ObjectPvsEntry entry = pit.Next();
1477                GtpVisibilityPreprocessor::Intersectable *obj = entry.mObject;
1478
1479                // no associated geometry found
1480                if (!obj) continue;
1481       
1482                switch (obj->Type())
1483                {
1484                        case GtpVisibilityPreprocessor::Intersectable::OGRE_MESH_INSTANCE:
1485                                {
1486                                        OgreMeshInstance *omi = dynamic_cast<OgreMeshInstance *>(obj);
1487                                        omi->GetEntity()->setVisible(load);
1488                                        //GtpVisibilityPreprocessor::Debug << "assigned id " << omi->GetId() << endl;
1489                                }
1490                                break;
1491                        case GtpVisibilityPreprocessor::Intersectable::OBJECTS_INTERSECTABLE:
1492                                {
1493                                        //GtpVisibilityPreprocessor::ObjectsIntersectable *oi =
1494                                        //      dynamic_cast<GtpVisibilityPreprocessor::ObjectsIntersectable *>(entry);
1495                                        ObjectsIntersectable *oi = dynamic_cast<ObjectsIntersectable *>(obj);
1496
1497                                        //GtpVisibilityPreprocessor::ObjectContainer *entries = oi->GetItem();
1498                                        EntityContainer *entries = oi->GetItem();
1499
1500                                        EntityContainer::const_iterator eit, eit_end = entries->end();
1501
1502                                        for (eit = entries->begin(); eit != eit_end; ++ eit)
1503                                        {
1504                                                //OgreMeshInstance *omi = dynamic_cast<OgreMeshInstance *>(*eit);
1505                                                //omi->GetEntity()->setVisible(load);
1506                                                Entity *ent = *eit;
1507                                                ent->setVisible(load);                                 
1508                                                //GtpVisibilityPreprocessor::Debug << "assigned id " << omi->GetId() << endl;
1509                                        }
1510                                }
1511                                break;
1512                        default:
1513                                break;
1514                }
1515        }
1516}
1517//-------------------------------------------------------------------------
1518void OcclusionCullingSceneManager::UpdatePvs(Camera *cam)
1519{
1520        if (!(mViewCellsLoaded && mUseViewCells))
1521                return;
1522
1523        const GtpVisibilityPreprocessor::Vector3 viewPoint =
1524                OgreTypeConverter::ConvertFromOgre(cam->getDerivedPosition());
1525
1526        GtpVisibilityPreprocessor::ViewCell *newElementary =
1527                mViewCellsManager->GetViewCell(viewPoint);
1528
1529        // elementary view cell did not change => apply same pvs
1530        if (mElementaryViewCell == newElementary)
1531                return;
1532
1533        mElementaryViewCell = newElementary;
1534       
1535
1536        //////////////
1537        //-- unload old pvs
1538
1539        ApplyViewCellPvs(mCurrentViewCell, false);
1540
1541        // the new view cell
1542        GtpVisibilityPreprocessor::ViewCell *viewCell;
1543               
1544        if (mUseVisibilityFilter)
1545        {       
1546                ////////////
1547                //-- compute new filtered cell
1548
1549                GtpVisibilityPreprocessor::PrVs prvs;
1550                mViewCellsManager->GetPrVS(viewPoint, prvs, 5);
1551                viewCell = prvs.mViewCell;
1552        }
1553        else
1554        {
1555                viewCell = newElementary;
1556        }
1557
1558        ///////////////
1559        //-- load new pvs
1560
1561        ApplyViewCellPvs(viewCell, true);
1562
1563        // store pvs
1564        if (viewCell)
1565        {
1566                mCurrentViewCell->SetPvs(viewCell->GetPvs());
1567                mCurrentViewCell->SetMesh(viewCell->GetMesh());
1568                mCurrentViewCell->SetId(viewCell->GetId());
1569
1570                // delete merge tree of filtered view cell
1571                if (mUseVisibilityFilter)
1572                        mViewCellsManager->DeleteLocalMergeTree(viewCell);
1573        }
1574}
1575//-------------------------------------------------------------------------
1576void OcclusionCullingSceneManager::CreateViewCellsGeometry()
1577{
1578        //LogManager::getSingleton().logMessage("creating view cells geometry");
1579        if (mViewCellsGeometryLoaded) return;
1580
1581        GtpVisibilityPreprocessor::ViewCellContainer viewCells = mViewCellsManager->GetViewCells();
1582
1583        GtpVisibilityPreprocessor::ViewCellContainer::const_iterator it, it_end = viewCells.end();
1584        for (it = viewCells.begin(); it != it_end; ++ it)
1585        {
1586                GtpVisibilityPreprocessor::ViewCell *viewCell = *it;
1587
1588                //std::stringstream str;
1589                //str << "processing view cell with id : " << viewCell->GetId();
1590                //LogManager::getSingleton().logMessage(str.str());
1591                ManualObject *manual = OgreTypeConverter::ConvertToOgre(viewCell->GetMesh(), this);
1592               
1593                if (manual)
1594                {
1595                        mViewCellsGeometry[viewCell->GetId()] = manual;
1596
1597                        // attach to scene node
1598                        getRootSceneNode()->createChildSceneNode()->attachObject(manual);
1599                        manual->setQueryFlags(0); // returned by no query
1600       
1601                        // initialy set to invisible
1602                        manual->setVisible(false);
1603                }
1604        }
1605       
1606        mViewCellsGeometryLoaded = true;
1607}
1608//-------------------------------------------------------------------------
1609void OcclusionCullingSceneManager::VisualizeViewCells(const bool visualize)
1610{
1611        MovableMap::const_iterator mit, mit_end = mViewCellsGeometry.end();
1612                       
1613        for (mit = mViewCellsGeometry.begin(); mit != mit_end; ++ mit)
1614        {
1615                if ((*mit).second)
1616                        (*mit).second->setVisible(visualize);
1617        }       
1618}
1619#if 0
1620//-------------------------------------------------------------------------
1621void OcclusionCullingSceneManager::TestVisible(SceneNode *node)
1622{
1623        // first test for scene node, then for octant (part of the hierarchy)
1624        if (!node->mVisibleChildren)
1625        {
1626                node->setVisible(false);
1627        }
1628
1629        node->getOctant()->mVisibleChildren --;
1630}
1631//-------------------------------------------------------------------------
1632void OcclusionCullingSceneManager::TestVisible(Octree *octant)
1633{
1634        // first test for scene node, then for octant (part of the hierarchy)
1635        if (!octant->mVisibleChildren)
1636        {
1637                octant->setVisible(false);
1638        }
1639}
1640
1641//-------------------------------------------------------------------------
1642void OcclusionCullingSceneManager::UpdateVisibility(Entity *ent)
1643{
1644        if (!ent->isVisible())
1645        {
1646                bool visible = TestVisible(ent->getParentNode());
1647               
1648                if (!visible)
1649                        visible = TestVisible(octant->getParentNode());
1650
1651                if (!visible)
1652                        mHierarchyInterface->pullupVisibility();
1653        }
1654}
1655#endif
1656// splits strings containing multiple file names
1657static int SplitFilenames(const std::string str,
1658                                                  std::vector<std::string> &filenames)
1659{
1660        int pos = 0;
1661
1662        while(1)
1663        {
1664                int npos = (int)str.find(';', pos);
1665               
1666                if (npos < 0 || npos - pos < 1)
1667                        break;
1668                filenames.push_back(std::string(str, pos, npos - pos));
1669                pos = npos + 1;
1670        }
1671       
1672        filenames.push_back(std::string(str, pos, str.size() - pos));
1673        return (int)filenames.size();
1674}
1675//-----------------------------------------------------------------------
1676bool OcclusionCullingSceneManager::LoadScene(const String &filename)
1677{
1678        using namespace std;
1679        // use leaf nodes of the original spatial hierarchy as occludees
1680        vector<string> filenames;
1681        const int files = SplitFilenames(filename, filenames);
1682       
1683        std::stringstream d;
1684        d << "number of input files: " << files << "\n";
1685        LogManager::getSingleton().logMessage(d.str());
1686
1687        bool result = false;
1688        vector<string>::const_iterator fit, fit_end = filenames.end();
1689        int i = 0;
1690
1691        if (filename == "terrain")
1692        {
1693                LogManager::getSingleton().logMessage("loading terrain");
1694
1695                // terrain hack
1696                return false;
1697        }
1698
1699        for (fit = filenames.begin(); fit != fit_end; ++ fit, ++ i)
1700        {
1701                const string fn = *fit;
1702
1703                if (strstr(fn.c_str(), ".iv") || strstr(fn.c_str(), ".wrl"))
1704                {
1705                        // load iv files
1706                        if (!LoadSceneIV(fn, getRootSceneNode(), i))
1707                        {
1708                                // terrain hack
1709                                LogManager::getSingleton().logMessage("error loading file");
1710                        }
1711                }
1712                       
1713                // at least one piece of geometry loaded
1714                result = true;
1715        }
1716       
1717        return result;
1718}
1719//-----------------------------------------------------------------------
1720bool OcclusionCullingSceneManager::LoadSceneIV(const String &filename,
1721                                                                                           SceneNode *root,
1722                                                                                           const int index)
1723{
1724        IVReader ivReader;
1725
1726        Timer *timer = PlatformManager::getSingleton().createTimer();
1727        timer->reset();
1728
1729        if (1)
1730        {
1731                std::string logFilename = "IVLog" + Ogre::StringConverter().toString(index) + ".log";
1732               
1733                Log *log = LogManager::getSingleton().createLog(logFilename);
1734                ivReader.setLog(log);
1735        }
1736       
1737        //viennaNode->translate(Vector3(-300, -300, 0));
1738
1739        if (ivReader.loadFile(filename.c_str()))
1740        {
1741                SceneNode *node = root->createChildSceneNode("IVSceneNode" + index);
1742
1743                ivReader.buildTree(this, node);
1744               
1745                ivReader.collapse();
1746
1747                std::stringstream d;
1748                d << "loaded " << filename << " in " << timer->getMilliseconds() * 1e-3 << " secs";
1749                LogManager::getSingleton().logMessage(d.str());
1750               
1751                PlatformManager::getSingleton().destroyTimer(timer);
1752
1753                //-- bake into static geometry
1754                /*if (USE_STATIC_GEOMETRY)
1755                {
1756                        BakeSceneIntoStaticGeometry("staticVienna", "Vienna");
1757                }*/
1758       
1759                return true;
1760        }
1761
1762        return false;
1763}
1764//-----------------------------------------------------------------------
1765const String OcclusionCullingSceneManagerFactory::FACTORY_TYPE_NAME = "OcclusionCullingSceneManager";
1766//-----------------------------------------------------------------------
1767void OcclusionCullingSceneManagerFactory::initMetaData(void) const
1768{
1769        mMetaData.typeName = FACTORY_TYPE_NAME;
1770        mMetaData.description = "Scene manager organising the scene on the basis of an octree with advanced occlusion culling (TM).";
1771        mMetaData.sceneTypeMask = 0xFFFF; // support all types
1772        mMetaData.worldGeometrySupported = false;
1773}
1774//-----------------------------------------------------------------------
1775SceneManager *OcclusionCullingSceneManagerFactory::createInstance(
1776                const String& instanceName)
1777{
1778        OcclusionCullingSceneManager* tsm = new OcclusionCullingSceneManager(instanceName, visManager);
1779       
1780        // Create & register default sources (one per manager)
1781        HeightmapTerrainPageSource* ps = new HeightmapTerrainPageSource();
1782        mTerrainPageSources.push_back(ps);
1783        tsm->registerPageSource("Heightmap", ps);
1784
1785        return tsm;
1786}
1787//-----------------------------------------------------------------------
1788void OcclusionCullingSceneManagerFactory::destroyInstance(SceneManager* instance)
1789{
1790        delete instance;
1791}
1792
1793} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.