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

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