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

Revision 1816, 49.3 KB checked in by mattausch, 18 years ago (diff)

changed scenemanager: options are directly given to it

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