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

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