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

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