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

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