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

Revision 1676, 44.9 KB checked in by mattausch, 18 years ago (diff)

worked on pvs heuristics

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