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

Revision 2123, 53.3 KB checked in by mattausch, 17 years ago (diff)

worded on obj loading in Ogre

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