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

Revision 2115, 49.7 KB checked in by mattausch, 17 years ago (diff)

changed pvs loading: loading objects in a first pass

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