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

Revision 2455, 75.5 KB checked in by mattausch, 18 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 "ViewCellsManager.h"
15#include <OgreConfigFile.h>
16#include "OgreTypeConverter.h"
17#include "OgreMeshInstance.h"
18#include "OgreBoundingBoxConverter.h"
19#include <OgreManualObject.h>
20#include "IntersectableWrapper.h"
21#include "IVReader.h"
22#include "ObjReader.h"
23#include "OgreOcclusionQueriesQueryManager.h"
24#include "VisibilityInfo.h"
25#include "Preprocessor.h"
26
27
28namespace Ogre {
29
30//-----------------------------------------------------------------------
31OcclusionCullingSceneManager::OcclusionCullingSceneManager(
32                                                                const String& name,
33                                                                GtpVisibility::VisibilityManager *visManager):
34TerrainSceneManager(name),
35mVisibilityManager(visManager),
36mShowVisualization(false),
37mRenderNodesForViz(false),
38mRenderNodesContentForViz(false),
39mVisualizeCulledNodes(false),
40mLeavePassesInQueue(0),
41mDelayRenderTransparents(true),
42mUseDepthPass(false),
43mIsDepthPassPhase(false),
44mUseItemBuffer(false),
45mIsItemBufferPhase(false),
46mCurrentEntityId(1),
47mEnableDepthWrite(true),
48mSkipTransparents(false),
49mRenderTransparentsForItemBuffer(true),
50mExecuteVertexProgramForAllPasses(false),
51mIsHierarchicalCulling(false),
52mViewCellsLoaded(false),
53mUseViewCells(false),
54mUseVisibilityFilter(false),
55mCurrentViewCell(NULL),
56mElementaryViewCell(NULL),
57mDeleteQueueAfterRendering(true),
58mNormalExecution(false),
59mShowViewCells(false),
60mViewCellsGeometryLoaded(false),
61mShowTerrain(false),
62mViewCellsFilename(""),
63mFilename("terrain"),
64mFlushRate(10),
65mCurrentFrame(0),
66mUseVisibilityQueries(true),
67mUseFromPointQueries(false),
68mQueryMode(NODE_QUERIES),
69mResetMaterialForQueries(false),
70mRenderPvsForViz(false)
71{
72        Ogre::LogManager::getSingleton().
73                logMessage("creating occlusion culling scene manager");
74
75        mHierarchyInterface = new OctreeHierarchyInterface(this, mDestRenderSystem);
76       
77        if (0)
78        {
79                mDisplayNodes = true;
80                mShowBoundingBoxes = true;
81                mShowBoxes = true;
82        }
83
84        // set maxdepth to reasonable value
85        mMaxDepth = 50;
86
87        mObjReader = new ObjReader(this);
88}
89//-----------------------------------------------------------------------
90void OcclusionCullingSceneManager::InitDepthPass()
91{
92        MaterialPtr depthMat =
93                MaterialManager::getSingleton().getByName("Visibility/DepthPass");
94
95        if (depthMat.isNull())
96    {
97                depthMat = MaterialManager::getSingleton().create(
98                "Visibility/DepthPass",
99                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
100
101        mDepthPass = depthMat->getTechnique(0)->getPass(0);
102                mDepthPass->setColourWriteEnabled(false);
103                mDepthPass->setDepthWriteEnabled(true);
104                mDepthPass->setLightingEnabled(false);
105        }
106        else
107        {
108                mDepthPass = depthMat->getTechnique(0)->getPass(0);
109        }
110}
111//-----------------------------------------------------------------------
112OcclusionCullingSceneManager::~OcclusionCullingSceneManager()
113{
114        CLEAR_CONTAINER(mObjects);
115
116        OGRE_DELETE(mHierarchyInterface);
117        OGRE_DELETE(mCurrentViewCell);
118
119        OGRE_DELETE(mObjReader);
120}
121//-----------------------------------------------------------------------
122void OcclusionCullingSceneManager::InitItemBufferPass()
123{
124        MaterialPtr itemBufferMat = MaterialManager::getSingleton().
125                getByName("Visibility/ItemBufferPass");
126
127        if (itemBufferMat.isNull())
128    {
129                // Init
130                itemBufferMat =
131                        MaterialManager::getSingleton().create("Visibility/ItemBufferPass",
132                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
133
134                mItemBufferPass = itemBufferMat->getTechnique(0)->getPass(0);
135                mItemBufferPass->setColourWriteEnabled(true);
136                mItemBufferPass->setDepthWriteEnabled(true);
137                mItemBufferPass->setLightingEnabled(true);
138                //mItemBufferPass->setLightingEnabled(false);
139        }
140        else
141        {
142                mItemBufferPass = itemBufferMat->getTechnique(0)->getPass(0);
143        }
144        //mItemBufferPass->setAmbient(1, 1, 0);
145}
146//-------------------------------------------------------------------------
147#if 1
148void OcclusionCullingSceneManager::setWorldGeometry(DataStreamPtr& stream,
149                                                                                                        const String& typeName)
150{
151        // Clear out any existing world resources (if not default)
152    if (ResourceGroupManager::getSingleton().getWorldResourceGroupName() !=
153        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME)
154    {
155        ResourceGroupManager::getSingleton().clearResourceGroup(
156            ResourceGroupManager::getSingleton().getWorldResourceGroupName());
157    }
158       
159        destroyLevelIndexes();
160    mTerrainPages.clear();
161
162    // Load the configuration
163    loadConfig(stream);
164
165        //////////////
166        // file loading
167
168        // load the scene
169        LoadScene(mFilename, mViewCellsFilename);
170       
171        // load view cells: load later ...
172        if (0) mViewCellsLoaded = LoadViewCells(mViewCellsFilename);
173
174        if (mShowTerrain)
175        {       
176                initLevelIndexes();
177
178                // Resize the octree, allow for 1 page for now
179                float max_x = mOptions.scale.x * mOptions.pageSize;
180                float max_y = mOptions.scale.y;// * mOptions.pageSize;
181                float max_z = mOptions.scale.z * mOptions.pageSize;
182
183        if (1)
184                {
185                        // keep octree equal at all sides so nodes adapt better to small objects
186                        float maxAxis = std::max(max_x, max_y);
187                        maxAxis = std::max(maxAxis, max_z);
188                        resize(AxisAlignedBox( 0, 0, 0, maxAxis, maxAxis, maxAxis));
189                }
190                else
191                {
192                        resize(AxisAlignedBox( 0, 0, 0, max_x, max_y, max_z));
193                }
194
195                setupTerrainMaterial();
196                setupTerrainPages();
197        }       
198 }
199#endif
200
201//-------------------------------------------------------------------------
202void OcclusionCullingSceneManager::loadConfig(DataStreamPtr& stream)
203{
204        // Set up the options
205        ConfigFile config;
206        String val;
207       
208        config.load(stream);
209       
210        LogManager::getSingleton().logMessage("****** OcclusionCullingSceneManager Options ********");
211
212        val = config.getSetting("DepthPass");
213
214    if (!val.empty())
215        {
216                if ( val == "yes" )
217                        mUseDepthPass = true;
218                else
219                        mUseDepthPass = false;
220        }
221
222        val = config.getSetting("ExecuteVertexProgramForDepth");
223
224        if (!val.empty())
225        {
226                if ( val == "yes" )
227                        mExecuteVertexProgramForAllPasses = true;
228                else
229                        mExecuteVertexProgramForAllPasses = false;
230        }
231
232        val = config.getSetting("UseVisibilityQueries");
233
234        if (!val.empty())
235        {
236                if ( val == "yes" )
237                        mUseVisibilityQueries = true;
238                else
239                        mUseVisibilityQueries = false;
240        }
241
242        val = config.getSetting("UseFromPointQueries");
243       
244        if (!val.empty())
245        {
246                if (val == "yes")
247                        mUseFromPointQueries = true;
248                else
249                        mUseFromPointQueries = false;
250        }
251
252        val = config.getSetting("QueryObjectsMode");
253
254        if (!val.empty())
255        {
256                if (val == "EXACT")
257                        mQueryMode = EXACT_QUERIES;
258                else if (val == "NODE")
259                        mQueryMode = NODE_QUERIES;
260                else
261                        mQueryMode = APPROXIMATE_QUERIES;
262        }
263
264        val = config.getSetting("ResetMaterialForQueries");
265
266        if (!val.empty())
267        {
268                if (val == "yes")
269                        mResetMaterialForQueries = true;
270                else
271                        mResetMaterialForQueries = false;
272        }
273
274        val = config.getSetting("FlushQueue");
275       
276        if (!val.empty())
277        {
278                if ( val == "yes" )
279                        mDeleteQueueAfterRendering = true;
280                else
281                        mDeleteQueueAfterRendering = false;
282        }
283
284        val = config.getSetting("Scene");
285
286    if (!val.empty())
287        {
288                mFilename = val.c_str();
289               
290                // load terrain instead of scene
291                if (mFilename == "terrain")
292                {
293                        mShowTerrain = true;
294                        LogManager::getSingleton().logMessage("loading terrain");
295                }
296                else
297                {
298                        mShowTerrain = false;
299                        LogManager::getSingleton().logMessage("loading geometry");
300                }
301        }
302
303        if (!mShowTerrain)
304        {
305                val = config.getSetting("ViewCells");
306
307                if (!val.empty())
308                {
309                        mViewCellsFilename = val;
310                }
311        }
312
313        /////////////
314        val = config.getSetting("OnlineCullingAlgorithm");
315               
316        if (!val.empty())
317        {
318                GtpVisibility::VisibilityEnvironment::CullingManagerType algorithm;
319
320                if (val == "CHC")
321                {
322                        algorithm =
323                                GtpVisibility::VisibilityEnvironment::COHERENT_HIERARCHICAL_CULLING;
324                        LogManager::getSingleton().logMessage("Using chc algorithm");
325                }
326                else if (val == "SWC")
327                {
328                         algorithm =
329                                 GtpVisibility::VisibilityEnvironment::STOP_AND_WAIT_CULLING;
330
331                         LogManager::getSingleton().logMessage("Using stop and wait algorithm");
332                 }
333                else if (val == "RUC")
334                {
335                         algorithm =
336                                 GtpVisibility::VisibilityEnvironment::RANDOM_UPDATE_CULLING;
337
338                         LogManager::getSingleton().logMessage("Using random update culling");
339                 }
340                 else if (val == "VFC")
341                 {
342                         algorithm =
343                                 GtpVisibility::VisibilityEnvironment::FRUSTUM_CULLING;
344
345                         LogManager::getSingleton().logMessage("Using frustum culling algorithm");
346                 }
347                 else // default rendering
348                 {
349                         algorithm =
350                                 GtpVisibility::VisibilityEnvironment::NUM_CULLING_MANAGERS;
351
352                         mNormalExecution = true;
353                         LogManager::getSingleton().logMessage("Using default octree scene manager rendering");
354                 }
355
356                 mVisibilityManager->SetCullingManager(algorithm);
357        }
358
359        /////////////
360        val = config.getSetting("TestGeometryForVisibleLeaves");
361
362        if (!val.empty())
363        {
364                if (val == "yes")
365                        mVisibilityManager->SetTestGeometryForVisibleLeaves(true);
366                else
367                        mVisibilityManager->SetTestGeometryForVisibleLeaves(false);
368        }
369
370        /////////////
371        val = config.getSetting("TestGeometryBounds");
372
373        if (!val.empty())
374        {
375                if (val == "yes")
376                        mHierarchyInterface->SetTestGeometryBounds(true);
377                else
378                        mHierarchyInterface->SetTestGeometryBounds(false);
379        }
380
381        /////////////
382        val = config.getSetting("AssumedVisibleFrames");
383
384        if (!val.empty())
385        {
386                mVisibilityManager->SetAssumedVisibilityForChc(atoi(val.c_str()));
387        }
388
389
390        /////////////
391        val = config.getSetting("RandomUpdateCandidates");
392
393        if (!val.empty())
394        {
395                mVisibilityManager->SetRandomUpdateCandidatesForRuc(atoi(val.c_str()));
396        }
397
398
399        /////////////
400        // output
401
402        if (mUseDepthPass)
403                LogManager::getSingleton().logMessage("using depth pass");
404        else
405                LogManager::getSingleton().logMessage("not using depth pass");
406       
407        if (mExecuteVertexProgramForAllPasses)
408                LogManager::getSingleton().logMessage("executing vertex program for passes");
409        else
410                LogManager::getSingleton().logMessage("not executing vertex program for passes");
411
412        if (mUseVisibilityQueries)
413                LogManager::getSingleton().logMessage("using visibility queries");
414        else
415                LogManager::getSingleton().logMessage("not using visibility queries");
416
417        if (mUseFromPointQueries)
418                LogManager::getSingleton().logMessage("using from point queries");
419        else
420                LogManager::getSingleton().logMessage("not using from point queries");
421
422        if (mQueryMode == EXACT_QUERIES)
423                LogManager::getSingleton().logMessage("using exact queries");
424        else if (mQueryMode == NODE_QUERIES)
425                LogManager::getSingleton().logMessage("using node queries");
426        else if (mQueryMode == APPROXIMATE_QUERIES)
427                LogManager::getSingleton().logMessage("using approximate queries");
428
429        if (mResetMaterialForQueries)
430                LogManager::getSingleton().logMessage("resetting material for queries");
431        else
432                LogManager::getSingleton().logMessage("resetting material for queries");
433
434        if (mDeleteQueueAfterRendering)
435                LogManager::getSingleton().logMessage("flushing queue after some frames");
436        else
437                LogManager::getSingleton().logMessage("not flushing queue after some frames");
438
439        if (mVisibilityManager->GetTestGeometryForVisibleLeaves())
440                LogManager::getSingleton().logMessage("test geometry for visible leaves");
441        else
442                LogManager::getSingleton().logMessage("not testing geometry for visible leaves");
443       
444        if (mHierarchyInterface->GetTestGeometryBounds())
445                LogManager::getSingleton().logMessage("test geometry bounds instead of bounding box");
446        else
447                LogManager::getSingleton().logMessage("not testing geometry bounds instead of bounding box");
448
449
450        /////////////
451        // terrain options
452
453        if (!mShowTerrain)
454                return;
455
456        val = config.getSetting("DetailTile");
457        if (!val.empty())
458                setDetailTextureRepeat(atoi(val.c_str()));
459
460        val = config.getSetting("MaxMipMapLevel");
461        if (!val.empty())
462                setMaxGeoMipMapLevel(atoi(val.c_str()));
463
464
465        val = config.getSetting("PageSize");
466        if (!val.empty())
467                setPageSize(atoi(val.c_str()));
468        else
469                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing option 'PageSize'",
470                "TerrainSceneManager::loadConfig");
471
472
473        val = config.getSetting("TileSize");
474        if (!val.empty())
475                setTileSize(atoi(val.c_str()));
476        else
477                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing option 'TileSize'",
478                "TerrainSceneManager::loadConfig");
479
480        Vector3 v = Vector3::UNIT_SCALE;
481
482        val = config.getSetting( "PageWorldX" );
483        if ( !val.empty() )
484                v.x = atof( val.c_str() );
485
486        val = config.getSetting( "MaxHeight" );
487        if ( !val.empty() )
488                v.y = atof( val.c_str() );
489
490        val = config.getSetting( "PageWorldZ" );
491        if ( !val.empty() )
492                v.z = atof( val.c_str() );
493
494        // Scale x/z relative to pagesize
495        v.x /= mOptions.pageSize;
496        v.z /= mOptions.pageSize;
497        setScale(v);
498
499        val = config.getSetting( "MaxPixelError" );
500        if ( !val.empty() )
501                setMaxPixelError(atoi( val.c_str() ));
502
503        mDetailTextureName = config.getSetting( "DetailTexture" );
504
505        mWorldTextureName = config.getSetting( "WorldTexture" );
506
507        if ( config.getSetting( "VertexColours" ) == "yes" )
508                mOptions.coloured = true;
509
510        if ( config.getSetting( "VertexNormals" ) == "yes" )
511                mOptions.lit = true;
512
513        if ( config.getSetting( "UseTriStrips" ) == "yes" )
514                setUseTriStrips(true);
515
516        if ( config.getSetting( "VertexProgramMorph" ) == "yes" )
517                setUseLODMorph(true);
518
519        val = config.getSetting( "LODMorphStart");
520        if ( !val.empty() )
521                setLODMorphStart(atof(val.c_str()));
522
523        val = config.getSetting( "CustomMaterialName" );
524        if ( !val.empty() )
525                setCustomMaterial(val);
526
527        val = config.getSetting( "MorphLODFactorParamName" );
528        if ( !val.empty() )
529                setCustomMaterialMorphFactorParam(val);
530
531        val = config.getSetting( "MorphLODFactorParamIndex" );
532        if ( !val.empty() )
533                setCustomMaterialMorphFactorParam(atoi(val.c_str()));
534
535        // Now scan through the remaining settings, looking for any PageSource
536        // prefixed items
537        String pageSourceName = config.getSetting("PageSource");
538        if (pageSourceName == "")
539        {
540                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing option 'PageSource'",
541                        "TerrainSceneManager::loadConfig");
542        }
543
544        TerrainPageSourceOptionList optlist;
545        ConfigFile::SettingsIterator setIt = config.getSettingsIterator();
546        while (setIt.hasMoreElements())
547        {
548                String name = setIt.peekNextKey();
549                String value = setIt.getNext();
550                if (StringUtil::startsWith(name, pageSourceName, false))
551                {
552                        optlist.push_back(TerrainPageSourceOption(name, value));
553                }
554        }
555
556        // set the page source
557        selectPageSource(pageSourceName, optlist);
558
559       
560        LogManager::getSingleton().logMessage("****** OcclusionCullingSceneManager Options Finished ********");
561}
562//-----------------------------------------------------------------------
563void OcclusionCullingSceneManager::MailPvsObjects()
564{
565        GtpVisibilityPreprocessor::ObjectPvsIterator pit =
566                        mCurrentViewCell->GetPvs().GetIterator();
567
568        while (pit.HasMoreEntries())
569        {               
570                GtpVisibilityPreprocessor::Intersectable *obj = pit.Next();
571
572                if (obj->Type() !=
573                        GtpVisibilityPreprocessor::Intersectable::ENGINE_INTERSECTABLE)
574                        continue;
575                       
576                EngineIntersectable *oi = static_cast<EngineIntersectable *>(obj);
577
578                EntityContainer *entries = oi->GetItem();
579                EntityContainer::const_iterator eit, eit_end = entries->end();
580
581                for (eit = entries->begin(); eit != eit_end; ++ eit)
582                {
583                        (*eit)->setUserAny(Any((int)0));
584                }
585        }
586}
587//-----------------------------------------------------------------------
588void OcclusionCullingSceneManager::ShowViewCellsGeometry()
589{/*
590        // show only current view cell
591        if (!mShowViewCells)
592        {
593                const int id = mCurrentViewCell->GetId();
594
595                MovableMap::iterator fit = mViewCellsGeometry.find(id);
596
597                if ((fit != mViewCellsGeometry.end()) && (*fit).second)
598                        (*fit).second->_updateRenderQueue(getRenderQueue());
599        }
600        else
601        {
602                MovableMap::const_iterator mit, mit_end = mViewCellsGeometry.end();
603
604                for (mit = mViewCellsGeometry.begin(); mit != mit_end; ++ mit)
605                {
606                        if ((*mit).second)
607                                (*mit).second->_updateRenderQueue(getRenderQueue());
608                }       
609        }*/
610}
611//-----------------------------------------------------------------------
612void OcclusionCullingSceneManager::RenderPvsEntry(GtpVisibilityPreprocessor::Intersectable *obj)
613{
614        switch (obj->Type())
615        {       
616                case GtpVisibilityPreprocessor::Intersectable::OGRE_MESH_INSTANCE:
617                        {
618                                OgreMeshInstance *omi = static_cast<OgreMeshInstance *>(obj);
619                                omi->GetEntity()->_updateRenderQueue(getRenderQueue());
620                        }
621                        break;
622
623                case GtpVisibilityPreprocessor::Intersectable::ENGINE_INTERSECTABLE:
624                        {
625                                EngineIntersectable *oi = static_cast<EngineIntersectable *>(obj);
626
627                                EntityContainer *entries = oi->GetItem();
628                                EntityContainer::const_iterator eit, eit_end = entries->end();
629
630                                for (eit = entries->begin(); eit != eit_end; ++ eit)
631                                {
632                                        Entity *ent = *eit;
633                                        // mailing hack
634                                        Any newAny = ent->getUserAny();
635                                        int flt = any_cast<int>(newAny);
636
637                                        if (any_cast<int>(newAny) == 0)
638                                        {
639                                                ent->setUserAny(Any((int)1));
640                                                ent->_updateRenderQueue(getRenderQueue());
641                                        }
642                                }
643                        }
644                        break;
645                default:
646                        break;
647        }       
648}
649//-----------------------------------------------------------------------
650void OcclusionCullingSceneManager::SetObjectVisible(GtpVisibilityPreprocessor::Intersectable *entry,
651                                                                                                        const bool visible)
652{
653        switch (entry->Type())
654        {
655        case GtpVisibilityPreprocessor::Intersectable::OGRE_MESH_INSTANCE:
656                {
657                        OgreMeshInstance *omi = static_cast<OgreMeshInstance *>(entry);
658                        omi->GetEntity()->setVisible(visible);
659                        //GtpVisibilityPreprocessor::Debug << "assigned id " << omi->GetId() << endl;
660                }
661                break;
662        case GtpVisibilityPreprocessor::Intersectable::ENGINE_INTERSECTABLE:
663                {
664                        EngineIntersectable *oi = static_cast<EngineIntersectable *>(entry);
665
666                        EntityContainer *entries = oi->GetItem();
667                        EntityContainer::const_iterator eit, eit_end = entries->end();
668                        for (eit = entries->begin(); eit != eit_end; ++ eit)
669                        {
670                                Entity *ent = *eit;
671                                ent->setVisible(visible);
672                        }
673                }
674                break;
675        default:
676                break;
677        }
678}
679//-----------------------------------------------------------------------
680void OcclusionCullingSceneManager::PrepareVisualization(Camera *cam)
681{
682        // add player camera for visualization purpose
683        try
684        {
685                Camera *c;
686                if ((c = getCamera("PlayerCam")) != NULL)
687                {
688                        getRenderQueue()->addRenderable(c);
689                }   
690    }
691    catch (...)
692    {
693        // ignore
694    }
695
696        if (mRenderPvsForViz)
697        {
698                // show current view cell geometry
699                if (mCurrentViewCell)// && mCurrentViewCell->GetMesh())
700                {
701                        //const bool showSingleViewCell = true;
702                        if (mViewCellsGeometryLoaded)
703                        {
704                                ShowViewCellsGeometry();
705                        }
706
707                        //////////
708                        //-- set PVS of view cell visible
709
710                        GtpVisibilityPreprocessor::ObjectPvsIterator pit =
711                                mCurrentViewCell->GetPvs().GetIterator();
712
713                        MailPvsObjects();
714
715                        while (pit.HasMoreEntries())
716                        {
717                                RenderPvsEntry(pit.Next());
718                        }       
719                }
720        }
721        else
722        {
723                // add bounding boxes of rendered objects
724                if (1)
725                {
726                        for (BoxList::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it)
727                        {
728                                getRenderQueue()->addRenderable(*it);
729                        }
730                }
731                if (mRenderNodesForViz || mRenderNodesContentForViz)
732                {
733                        // HACK: change node material so it is better suited for visualization
734                        MaterialPtr nodeMat = MaterialManager::getSingleton().getByName("Core/NodeMaterial");
735                        nodeMat->setAmbient(1, 1, 0);
736                        nodeMat->setLightingEnabled(true);
737                        nodeMat->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();
738
739                        for (NodeList::iterator it = mVisible.begin(); it != mVisible.end(); ++it)
740                        {
741                                if (mRenderNodesForViz)
742                                {
743                                        // render the visible leaf nodes
744                                        if ((*it)->numAttachedObjects() &&
745                                                !(*it)->numChildren() &&
746                                                ((*it)->getAttachedObject(0)->getMovableType() == "Entity") &&
747                                                (*it)->getAttachedObject(0)->isVisible())
748                                        {
749                                                getRenderQueue()->addRenderable((*it));
750                                                //(*it)->_addToRenderQueue(cam, getRenderQueue(), false);
751                                        }
752
753                                        // render bounding boxes of nodes
754                                        if (0) (*it)->_addBoundingBoxToQueue(getRenderQueue());
755                                }
756
757                                // add renderables itself
758                                if (mRenderNodesContentForViz)
759                                {
760                                        (*it)->_addToRenderQueue(cam, getRenderQueue(), false);
761                                }
762                        }
763                }
764        }
765}
766//-----------------------------------------------------------------------
767const Pass *OcclusionCullingSceneManager::_setPass(const Pass* pass, bool evenIfSuppressed)
768{
769        if (mNormalExecution)
770        {
771                return TerrainSceneManager::_setPass(pass, evenIfSuppressed);
772        }
773
774        // problem: setting vertex program is not efficient
775        //Pass *usedPass = ((mIsDepthPassPhase && !pass->hasVertexProgram()) ? mDepthPass : pass);
776       
777        // set depth fill pass if we currently do not make an aabb occlusion query
778        const bool useDepthPass =
779                mUseDepthPass && mIsDepthPassPhase && !mHierarchyInterface->IsBoundingBoxQuery();
780
781        const IlluminationRenderStage savedStage = mIlluminationStage;
782       
783        if (useDepthPass)
784        {
785                // set illumination stage to NONE so no shadow material is used
786                // for depth pass or for occlusion query
787                if (mIsDepthPassPhase || mHierarchyInterface->IsBoundingBoxQuery())
788                {
789                        mIlluminationStage = IRS_NONE;
790                }
791       
792                //////////////////
793                //-- set vertex program of current pass in order to set correct depth
794                if (mExecuteVertexProgramForAllPasses &&
795                        mIsDepthPassPhase &&
796                        pass->hasVertexProgram())
797                {
798                        // add vertex program of current pass to depth pass
799                        mDepthPass->setVertexProgram(pass->getVertexProgramName());
800
801                        if (mDepthPass->hasVertexProgram())
802                        {
803                                const GpuProgramPtr& prg = mDepthPass->getVertexProgram();
804                                // Load this program if not done already
805                                if (!prg->isLoaded())
806                                        prg->load();
807                                // Copy params
808                                mDepthPass->setVertexProgramParameters(pass->getVertexProgramParameters());
809                        }
810                }
811                else if (mDepthPass->hasVertexProgram())
812                {       // reset vertex program
813                        mDepthPass->setVertexProgram("");
814                }
815        }
816
817        // using depth pass instead
818        const Pass *usedPass = useDepthPass ? mDepthPass : pass;
819
820#if 0 // tmp matt: pass is now const
821        // save old depth write: needed for item buffer
822        const bool isDepthWrite = usedPass->getDepthWriteEnabled();
823
824        // global option which enables / disables depth writes
825        if (!mEnableDepthWrite)
826                usedPass->setDepthWriteEnabled(false);
827#endif
828
829        ///////////////
830        //-- set actual pass here
831
832        const Pass *result = SceneManager::_setPass(usedPass, evenIfSuppressed);
833
834
835        // reset depth write
836#if 0 // tmp matt: this is now a const function
837        if (!mEnableDepthWrite)
838                usedPass->setDepthWriteEnabled(isDepthWrite);
839#endif
840        // reset illumination stage
841        mIlluminationStage = savedStage;
842
843        return result;
844}
845//-----------------------------------------------------------------------
846void OcclusionCullingSceneManager::myFindVisibleObjects(Camera* cam,
847                                                                                                                bool onlyShadowCasters)
848{
849        if (mShowVisualization)
850    {
851                //////////////
852                //-- show visible scene nodes and octree bounding boxes from last frame
853
854                PrepareVisualization(cam);
855               
856                // lists only used for visualization
857                mVisible.clear();
858                mBoxes.clear();
859
860                return;
861        }
862       
863        ///////////
864        //-- set visibility according to pvs of current view cell
865
866        UpdatePvs(cam);
867
868        // standard rendering in first pass
869        // hierarchical culling interleaves identification
870        // and rendering of objects in _renderVisibibleObjects
871
872        // for the shadow pass we use only standard rendering
873        // because shadows have low occlusion anyway
874        if ((mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE &&
875                 mIlluminationStage == IRS_RENDER_TO_TEXTURE) ||
876                mNormalExecution)
877        {
878                TerrainSceneManager::_findVisibleObjects(cam, onlyShadowCasters);
879        }
880        else if (mUseDepthPass)
881        {
882                mVisible.clear();
883                mBoxes.clear();
884
885                // clear render queue before depth pass
886                getRenderQueue()->clear();
887
888                // render scene once in order to fill depth buffer
889                RenderHierarchicalCulling();
890        }
891}
892//-----------------------------------------------------------------------
893void OcclusionCullingSceneManager::_renderVisibleObjects()
894{
895        if (mNormalExecution)
896        {
897                // the standard octree rendering mode
898                TerrainSceneManager::_renderVisibleObjects();
899                //getRenderQueue()->clear(flushQueue);
900                return;
901        }
902
903        // clear render queue
904        // fully reset it after some frames
905        const bool flushQueue =
906                mDeleteQueueAfterRendering && ((mCurrentFrame % mFlushRate) == 0);
907       
908        ++ mCurrentFrame;
909
910        // create material for item buffer pass
911        InitItemBufferPass();
912
913        // save ambient light to reset later
914        ColourValue savedAmbient = mAmbientLight;
915
916        ////////////////////
917        //-- apply standard rendering for some modes
918        //-- (e.g., the visualization mode, the shadow pass)
919
920        // also go here if find visible object is disabled
921        // (then the render queue is already filled)
922        if (!mFindVisibleObjects ||
923                mUseDepthPass || mShowVisualization ||
924            (mShadowTechnique == SHADOWTYPE_TEXTURE_MODULATIVE &&
925             mIlluminationStage == IRS_RENDER_TO_TEXTURE))
926        {       
927                IlluminationRenderStage savedStage = mIlluminationStage;
928       
929                if (mShowVisualization)
930                        // disable illumination stage to prevent rendering shadows
931                        mIlluminationStage = IRS_NONE;
932               
933                // standard rendering for shadow maps because of performance
934                TerrainSceneManager::_renderVisibleObjects();
935
936                mIlluminationStage = savedStage;
937        }
938        else //-- the hierarchical culling algorithm
939        {
940                // note matt: this is also called in TerrainSceneManager: really necessary?
941                mDestRenderSystem->setLightingEnabled(false);
942
943                if (mUseItemBuffer)
944                {
945                        // don't render backgrounds for item buffer
946                        clearSpecialCaseRenderQueues();
947                        getRenderQueue()->clear();
948                }
949
950                ////////////////////
951                //-- hierarchical culling
952
953                // the objects of different layers (e.g., background, scene,
954                // overlay) must be identified and rendered one after another
955
956                // first render all early skies
957                clearSpecialCaseRenderQueues();
958                addSpecialCaseRenderQueue(RENDER_QUEUE_BACKGROUND);
959                addSpecialCaseRenderQueue(RENDER_QUEUE_SKIES_EARLY);
960                setSpecialCaseRenderQueueMode(SceneManager::SCRQM_INCLUDE);
961
962                TerrainSceneManager::_renderVisibleObjects();
963
964#ifdef GTP_VISIBILITY_MODIFIED_OGRE
965                // delete previously rendered content
966                _deleteRenderedQueueGroups();
967#endif
968
969                ///////////////////
970                //-- prepare queue for visible objects (i.e., all but overlay and skies late)
971
972                clearSpecialCaseRenderQueues();
973                addSpecialCaseRenderQueue(RENDER_QUEUE_SKIES_LATE);
974                addSpecialCaseRenderQueue(RENDER_QUEUE_OVERLAY);
975       
976                // exclude these queues from hierarchical rendering
977                setSpecialCaseRenderQueueMode(SceneManager::SCRQM_EXCLUDE);
978
979                // set all necessary parameters for
980                // hierarchical visibility culling and rendering
981                InitVisibilityCulling(mCameraInProgress);
982
983
984                /**
985                * the hierarchical culling algorithm
986                * for depth pass: we just find objects and update depth buffer
987                * for "delayed" rendering: we render some passes afterwards
988                * e.g., transparents, because they need front-to-back sorting
989                **/
990               
991                mVisibilityManager->ApplyVisibilityCulling();
992
993                // delete remaining renderables from queue:
994                // all which are not in mLeavePassesInQueue)
995#ifdef GTP_VISIBILITY_MODIFIED_OGRE
996                _deleteRenderedQueueGroups(mLeavePassesInQueue);
997#endif
998
999                /////////////
1000                //-- reset parameters needed during hierarchical rendering
1001               
1002                mIsItemBufferPhase = false;
1003                mSkipTransparents = false;
1004                mIsHierarchicalCulling = false;
1005               
1006                mLeavePassesInQueue = 0;
1007                       
1008                /////////////
1009                //-- now we can render all remaining queue objects
1010                //-- used for depth pass, transparents, overlay
1011
1012        clearSpecialCaseRenderQueues();
1013
1014                TerrainSceneManager::_renderVisibleObjects();
1015        } // end hierarchical culling
1016               
1017        // HACK: set the new render level index, important to avoid cracks
1018        // in terrain caused by LOD
1019        TerrainRenderable::NextRenderLevelIndex();
1020       
1021        // reset ambient light
1022        setAmbientLight(savedAmbient);
1023
1024        // remove rest from queue
1025        getRenderQueue()->clear(flushQueue);
1026
1027        if (0) WriteLog(); // write out stats
1028}
1029//-----------------------------------------------------------------------
1030void OcclusionCullingSceneManager::_updateSceneGraph(Camera* cam)
1031{
1032        if (!mNormalExecution)
1033        {
1034                mVisibilityManager->GetCullingManager()->SetHierarchyInterface(mHierarchyInterface);
1035                mHierarchyInterface->SetRenderSystem(mDestRenderSystem);
1036        }
1037
1038        TerrainSceneManager::_updateSceneGraph(cam);
1039}
1040//-----------------------------------------------------------------------
1041bool OcclusionCullingSceneManager::setOption(const String & key, const void * val)
1042{
1043        if (key == "UseDepthPass")
1044        {
1045                mUseDepthPass = (*static_cast<const bool *>(val));
1046                return true;
1047        }
1048        if (key == "PrepareVisualization")
1049        {
1050                mShowVisualization = (*static_cast<const bool *>(val));
1051                return true;
1052        }
1053        if (key == "RenderNodesForViz")
1054        {
1055                mRenderNodesForViz = (*static_cast<const bool *>(val));
1056                return true;
1057        }
1058        if (key == "RenderNodesContentForViz")
1059        {
1060                mRenderNodesContentForViz = (*static_cast<const bool *>(val));
1061                return true;
1062        }
1063        if (key == "RenderPvsForViz")
1064        {
1065                mRenderPvsForViz = (*static_cast<const bool *>(val));
1066                return true;
1067        }
1068        if (key == "SkyBoxEnabled")
1069        {
1070                mSkyBoxEnabled = (*static_cast<const bool *>(val));
1071                return true;
1072        }
1073        if (key == "SkyPlaneEnabled")
1074        {
1075                mSkyPlaneEnabled = (*static_cast<const bool *>(val));
1076                return true;
1077        }
1078        if (key == "SkyDomeEnabled")
1079        {
1080                mSkyDomeEnabled = (*static_cast<const bool *>(val));
1081                return true;
1082        }
1083        if (key == "VisualizeCulledNodes")
1084        {
1085                mVisualizeCulledNodes = (*static_cast<const bool *>(val));
1086                return true;
1087        }
1088        if (key == "DelayRenderTransparents")
1089        {
1090                mDelayRenderTransparents = (*static_cast<const bool *>(val));
1091                return true;
1092        }
1093        if (key == "DepthWrite")
1094        {
1095                mEnableDepthWrite = (*static_cast<const bool *>(val));
1096                return true;
1097        }
1098        if (key == "UseItemBuffer")
1099        {
1100                mUseItemBuffer = (*static_cast<const bool *>(val));
1101                return true;
1102        }
1103        if (key == "ExecuteVertexProgramForAllPasses")
1104        {
1105                mExecuteVertexProgramForAllPasses  = (*static_cast<const bool *>(val));
1106                return true;
1107        }
1108        if (key == "RenderTransparentsForItemBuffer")
1109        {
1110                mRenderTransparentsForItemBuffer  = (*static_cast<const bool *>(val));
1111                return true;
1112        }
1113        else if (key == "FlushQueue")
1114        {
1115                mDeleteQueueAfterRendering = (*static_cast<const bool *>(val));
1116                return true;
1117        }
1118        if (key == "NodeVizScale")
1119        {
1120                OctreeNode::setVizScale(*static_cast<const float *>(val));
1121                return true;
1122        }
1123        if (key == "UseViewCells")
1124        {       
1125                if (!mViewCellsLoaded)
1126                {
1127                        // try to load view cells
1128                        mViewCellsLoaded = LoadViewCells(mViewCellsFilename);   
1129                }
1130
1131                if (!mViewCellsLoaded)
1132                        return false;
1133               
1134                // only use this option if view cells are available
1135                mUseViewCells = *static_cast<const bool *>(val);
1136
1137                // reset view cell
1138                OGRE_DELETE(mCurrentViewCell);
1139                       
1140                if (mUseViewCells)
1141                {
1142                        mCurrentViewCell = mViewCellsManager->GenerateViewCell();
1143                }
1144               
1145                // view cell corresponding to leaf in the view cell hierarchy
1146                mElementaryViewCell = NULL;
1147
1148                // all objects are set to invisible per default
1149                SetObjectsVisible(!mUseViewCells);
1150
1151                MovableObjectIterator movit = getMovableObjectIterator("Entity");
1152                while (movit.hasMoreElements())
1153                {
1154                        Entity *ent = static_cast<Entity *>(movit.getNext());
1155                        ent->setVisible(!mUseViewCells);
1156                }
1157               
1158                return true;
1159        }
1160        if (key == "ShowViewCells")
1161        {
1162                // only use this option if view cells are available
1163                if (mViewCellsLoaded)
1164                {
1165                        mShowViewCells = *static_cast<const bool *>(val);
1166                        // if we decide use view cells
1167                        // all objects are set to invisible per default
1168                        VisualizeViewCells(mShowViewCells);
1169                }
1170
1171                return true;
1172        }
1173        if (key == "NormalExecution")
1174        {
1175                mNormalExecution = *static_cast<const bool *>(val);
1176                return true;
1177        }
1178        if (key == "ShowTerrain")
1179        {
1180                mShowTerrain = *static_cast<const bool *>(val);
1181                return true;
1182        }
1183        if (key == "UseVisibilityFilter")
1184        {
1185                mUseVisibilityFilter = *static_cast<const bool *>(val);
1186
1187                // set null => recomputation of the pvs
1188        mElementaryViewCell = NULL;
1189
1190                return true;
1191        }
1192        if (key == "UseVisibilityQueries")
1193        {
1194                mUseVisibilityQueries = *static_cast<const bool *>(val);
1195
1196                return true;
1197        }
1198        if (key == "UseFromPointQueries")
1199        {
1200                mUseFromPointQueries = *static_cast<const bool *>(val);
1201
1202                return true;
1203        }
1204        if (key == "QueryMode")
1205        {
1206                mQueryMode = *static_cast<const int *>(val);
1207
1208                return true;
1209        }
1210        if (key == "ResetMaterialForQueries")
1211        {
1212                mResetMaterialForQueries = *static_cast<const bool *>(val);
1213        }
1214        if (key == "UseFromPointQueries")
1215        {
1216                mUseFromPointQueries = *static_cast<const bool *>(val);
1217                return true;
1218        }
1219
1220        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
1221                setOption(key, val) || TerrainSceneManager::setOption(key, val);
1222}
1223//-----------------------------------------------------------------------
1224bool OcclusionCullingSceneManager::getOption(const String &key, void *val)
1225{
1226        if (key == "NumHierarchyNodes")
1227        {
1228                * static_cast<unsigned int *>(val) = (unsigned int)mNumOctants;
1229                return true;
1230        }
1231        if (key == "VisibilityManager")
1232        {
1233                * static_cast<GtpVisibility::VisibilityManager **>(val) = mVisibilityManager;
1234                return true;
1235        }
1236        if (key == "HierarchyInterface")
1237        {
1238                * static_cast<PlatformHierarchyInterface **>(val) = mHierarchyInterface;
1239                return true;
1240        }
1241        if (key == "ShowTerrain")
1242        {
1243                * static_cast<bool *>(val) = mShowTerrain;
1244                return true;
1245        }
1246        if (key == "UseDepthPass")
1247        {
1248                * static_cast<bool *>(val) = mUseDepthPass;
1249                return true;
1250        }
1251        if (key == "FlushQueue")
1252        {
1253                * static_cast<bool *>(val) = mDeleteQueueAfterRendering;
1254                return true;
1255        }
1256        if (key == "NormalExecution")
1257        {
1258                * static_cast<bool *>(val) = mNormalExecution;
1259                return true;
1260        }
1261        if (key == "Algorithm")
1262        {
1263                GtpVisibility::VisibilityEnvironment::CullingManagerType algorithm =
1264                        mVisibilityManager->GetCullingManagerType();
1265
1266                * static_cast<unsigned int *>(val) = (unsigned int)algorithm;
1267
1268                return true;
1269        }
1270
1271        if (key == "VisibleObjects")
1272        {
1273                if (mNormalExecution)
1274                        return false;
1275
1276                const bool fromPoint = false;
1277                const bool nodeVisibility = true;
1278               
1279                * static_cast<unsigned int *>(val) =
1280                        (unsigned int)QueryVisibleObjectsExact(mCameraInProgress,
1281                                                                                                   mCurrentViewport,
1282                                                                                                   fromPoint,
1283                                                                                                   nodeVisibility);
1284                return true;
1285        }
1286
1287        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
1288                getOption(key, val) && TerrainSceneManager::getOption(key, val);
1289}
1290//-----------------------------------------------------------------------
1291bool OcclusionCullingSceneManager::getOptionValues(const String & key,
1292                                                                                                        StringVector &refValueList)
1293{
1294        return TerrainSceneManager::getOptionValues( key, refValueList);
1295}
1296//-----------------------------------------------------------------------
1297bool OcclusionCullingSceneManager::getOptionKeys(StringVector & refKeys)
1298{
1299        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
1300                getOptionKeys(refKeys) || TerrainSceneManager::getOptionKeys(refKeys);
1301}
1302//-----------------------------------------------------------------------
1303void OcclusionCullingSceneManager::setVisibilityManager(GtpVisibility::
1304                                                                                                                 VisibilityManager *visManager)
1305{
1306        mVisibilityManager = visManager;
1307}
1308//-----------------------------------------------------------------------
1309GtpVisibility::VisibilityManager *OcclusionCullingSceneManager::getVisibilityManager( void )
1310{
1311        return mVisibilityManager;
1312}
1313//-----------------------------------------------------------------------
1314void OcclusionCullingSceneManager::WriteLog()
1315{
1316        std::stringstream d;
1317
1318        d << "Depth pass: " << StringConverter::toString(mUseDepthPass) << ", "
1319          << "Delay transparents: " << StringConverter::toString(mDelayRenderTransparents) << ", "
1320//        << "Use optimization: " << StringConverter::toString(mHierarchyInterface->GetTestGeometryForVisibleLeaves()) << ", "
1321          << "Algorithm type: " << mVisibilityManager->GetCullingManagerType() << ", "
1322          << "Hierarchy nodes: " << mNumOctants << ", "
1323          << "Traversed nodes: " << mHierarchyInterface->GetNumTraversedNodes() << ", "
1324          << "Rendered nodes: " << mHierarchyInterface->GetNumRenderedNodes() << ", "
1325          << "Query culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumQueryCulledNodes() << ", "
1326          << "Frustum culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumFrustumCulledNodes() << ", "
1327      << "Queries issued: " << mVisibilityManager->GetCullingManager()->GetNumQueriesIssued() << ", "
1328          << "Found objects: " << (int)mVisible.size() << "\n";
1329
1330        LogManager::getSingleton().logMessage(d.str());
1331}
1332//-----------------------------------------------------------------------
1333void OcclusionCullingSceneManager::renderBasicQueueGroupObjects(RenderQueueGroup* pGroup,
1334                                                                                                                                QueuedRenderableCollection::OrganisationMode om)
1335{
1336        if (mNormalExecution)
1337        {
1338                return TerrainSceneManager::renderBasicQueueGroupObjects(pGroup, om);
1339        }
1340
1341    // Basic render loop
1342    // Iterate through priorities
1343    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1344
1345    while (groupIt.hasMoreElements())
1346    {
1347        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1348
1349        // Sort the queue first
1350        pPriorityGrp->sort(mCameraInProgress);
1351
1352        // Do solids
1353        renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
1354
1355                // for correct rendering, transparents must be rendered
1356                // after hierarchical culling => don't render them now
1357
1358        if (!mSkipTransparents)
1359                {
1360                        // Do transparents (always descending)
1361                        renderObjects(pPriorityGrp->getTransparents(),
1362                                QueuedRenderableCollection::OM_SORT_DESCENDING, true);
1363                }
1364    } // for each priority
1365}
1366//-----------------------------------------------------------------------
1367bool OcclusionCullingSceneManager::validatePassForRendering(Pass* pass)
1368{
1369        if (mNormalExecution)
1370        {
1371                return TerrainSceneManager::validatePassForRendering(pass);
1372        }
1373
1374        // skip all but first pass if we are doing the depth pass
1375        if ((mIsDepthPassPhase || mIsItemBufferPhase) &&
1376                (pass->getIndex() > 0))
1377        {
1378                return false;
1379        }
1380        // all but first pass
1381        /*else if ((!mIsDepthPassPhase || mIsItemBufferPhase) && (pass->getIndex() != 0))
1382        {
1383                return false;
1384        }*/
1385
1386        return SceneManager::validatePassForRendering(pass);
1387}
1388//-----------------------------------------------------------------------
1389void OcclusionCullingSceneManager::_renderQueueGroupObjects(RenderQueueGroup* pGroup,
1390                                                                                                                        QueuedRenderableCollection::OrganisationMode om)
1391{
1392        if (mNormalExecution || !mIsItemBufferPhase)
1393        {
1394                TerrainSceneManager::_renderQueueGroupObjects(pGroup, om);
1395                return;
1396        }
1397
1398#ifdef  ITEM_BUFFER
1399
1400        ///////////////////
1401        //-- item buffer: render objects using false colors
1402
1403    // Iterate through priorities
1404    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1405
1406        while (groupIt.hasMoreElements())
1407    {
1408                RenderItemBuffer(groupIt.getNext());
1409        }
1410#endif // ITEM_BUFFER
1411}
1412#ifdef ITEM_BUFFER
1413//-----------------------------------------------------------------------
1414void OcclusionCullingSceneManager::RenderItemBuffer(RenderPriorityGroup* pGroup)
1415{
1416        // Do solids
1417        QueuedRenderableCollection solidObjs = pGroup->getSolidsBasic();//msz
1418
1419        // ----- SOLIDS LOOP -----
1420        RenderPriorityGroup::SolidRenderablePassMap::const_iterator ipass, ipassend;
1421        ipassend = solidObjs.end();
1422
1423        for (ipass = solidObjs.begin(); ipass != ipassend; ++ipass)
1424        {
1425                // Fast bypass if this group is now empty
1426                if (ipass->second->empty())
1427                        continue;
1428
1429                // Render only first pass of renderable as false color
1430                if (ipass->first->getIndex() > 0)
1431                        continue;
1432
1433                RenderPriorityGroup::RenderableList* rendList = ipass->second;
1434               
1435                RenderPriorityGroup::RenderableList::const_iterator irend, irendend;
1436                irendend = rendList->end();
1437                       
1438                for (irend = rendList->begin(); irend != irendend; ++irend)
1439                {
1440                        if (0)
1441                        {
1442                                std::stringstream d; d << "itembuffer, pass name: " <<
1443                                        ipass->first->getParent()->getParent()->getName();
1444
1445                                LogManager::getSingleton().logMessage(d.str());
1446                        }
1447                       
1448                        RenderSingleObjectForItemBuffer(*irend, ipass->first);
1449                }
1450        }
1451
1452        ///////////
1453        //-- TRANSPARENT LOOP: must be handled differently from solids
1454
1455        // transparents are treated either as solids or completely discarded
1456        if (mRenderTransparentsForItemBuffer)
1457        {
1458                QueuedRenderableCollection transpObjs = pGroup->getTransparents(); //msz
1459                RenderPriorityGroup::TransparentRenderablePassList::const_iterator
1460                        itrans, itransend;
1461
1462                itransend = transpObjs.end();
1463                for (itrans = transpObjs.begin(); itrans != itransend; ++itrans)
1464                {
1465                        // like for solids, render only first pass
1466                        if (itrans->pass->getIndex() == 0)
1467                        {       
1468                                RenderSingleObjectForItemBuffer(itrans->renderable, itrans->pass);
1469                        }
1470                }
1471        }
1472}
1473//-----------------------------------------------------------------------
1474void OcclusionCullingSceneManager::RenderSingleObjectForItemBuffer(Renderable *rend, Pass *pass)
1475{
1476        static LightList nullLightList;
1477       
1478        int col[4];
1479       
1480        // -- create color code out of object id
1481        col[0] = (rend->getId() >> 16) & 255;
1482        col[1] = (rend->getId() >> 8) & 255;
1483        col[2] = rend->getId() & 255;
1484//      col[3] = 255;
1485
1486        //mDestRenderSystem->setColour(col[0], col[1], col[2], col[3]);
1487   
1488        mItemBufferPass->setAmbient(ColourValue(col[0] / 255.0f,
1489                                                                                    col[1] / 255.0f,
1490                                                                                        col[2] / 255.0f, 1));
1491
1492        // set vertex program of current pass
1493        if (mExecuteVertexProgramForAllPasses && pass->hasVertexProgram())
1494        {
1495                mItemBufferPass->setVertexProgram(pass->getVertexProgramName());
1496
1497                if (mItemBufferPass->hasVertexProgram())
1498                {
1499                        const GpuProgramPtr& prg = mItemBufferPass->getVertexProgram();
1500                        // Load this program if not done already
1501                        if (!prg->isLoaded())
1502                                prg->load();
1503                        // Copy params
1504                        mItemBufferPass->setVertexProgramParameters(pass->getVertexProgramParameters());
1505                }
1506        }
1507        else if (mItemBufferPass->hasVertexProgram())
1508        {
1509                mItemBufferPass->setVertexProgram("");
1510        }
1511
1512        const Pass *usedPass = _setPass(mItemBufferPass);
1513
1514
1515        // render a single object, this will set up auto params if required
1516        renderSingleObject(rend, usedPass, false, &nullLightList);
1517}
1518#endif // ITEM_BUFFER
1519//-----------------------------------------------------------------------
1520GtpVisibility::VisibilityManager *OcclusionCullingSceneManager::GetVisibilityManager()
1521{
1522        return mVisibilityManager;
1523}
1524//-----------------------------------------------------------------------
1525void OcclusionCullingSceneManager::InitVisibilityCulling(Camera *cam)
1526{
1527        // reset culling manager stats
1528        mVisibilityManager->GetCullingManager()->InitFrame(mVisualizeCulledNodes);
1529
1530        // set depth pass flag before rendering
1531        mIsDepthPassPhase = mUseDepthPass;
1532
1533        // indicates that we use hierarchical culling from now on
1534        mIsHierarchicalCulling = true;
1535
1536        // item buffer needs full ambient lighting to use item colors as unique id
1537        if (mUseItemBuffer)
1538        {
1539                mIsItemBufferPhase = true;
1540                setAmbientLight(ColourValue(1,1,1,1));
1541        }
1542
1543
1544        // set passes which are stored in render queue
1545        // for rendering AFTER hierarchical culling, i.e., passes which need
1546        // a special rendering order
1547       
1548        mLeavePassesInQueue = 0;
1549
1550        // if we have the depth pass or use an item buffer, we leave no passes in the queue
1551        if (!mUseDepthPass && !mUseItemBuffer)
1552        {
1553                if (mShadowTechnique == SHADOWTYPE_STENCIL_ADDITIVE)
1554                {
1555                        // TODO: remove this pass because it should be processed during hierarchical culling
1556                        //mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_NOSHADOW;
1557
1558                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_DECAL;
1559                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_DIFFUSE_SPECULAR;
1560                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
1561
1562                        // just render ambient passes
1563                        /*** msz: no more IRS_AMBIENT, see OgreSceneManager.h ***/
1564                        // mIlluminationStage = IRS_AMBIENT;
1565                        //getRenderQueue()->setSplitPassesByLightingType(true);
1566                }
1567       
1568                if (mShadowTechnique == SHADOWTYPE_STENCIL_MODULATIVE)
1569                {
1570                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_NOSHADOW;
1571                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
1572                }
1573       
1574                // transparents should be rendered after hierarchical culling to
1575                // provide front-to-back ordering
1576                if (mDelayRenderTransparents)
1577                {
1578                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
1579                }
1580        }
1581
1582        // skip rendering transparents during the hierarchical culling
1583        // (because they will be rendered afterwards)
1584        mSkipTransparents =
1585                (mIsDepthPassPhase || (mLeavePassesInQueue & RenderPriorityGroup::TRANSPARENT_PASSES));
1586
1587        // -- initialise interface for rendering traversal of the hierarchy
1588        mHierarchyInterface->SetHierarchyRoot(mOctree);
1589       
1590        // possible two cameras (one for culling, one for rendering)
1591        mHierarchyInterface->InitTraversal(cam,
1592                                                                           mCullCamera ? getCamera("CullCamera") : NULL,
1593                                                                           mLeavePassesInQueue);
1594               
1595}
1596//-----------------------------------------------------------------------
1597OctreeHierarchyInterface *OcclusionCullingSceneManager::GetHierarchyInterface()
1598{
1599        return mHierarchyInterface;
1600}
1601//-----------------------------------------------------------------------
1602void OcclusionCullingSceneManager::endFrame()
1603{
1604        TerrainRenderable::ResetRenderLevelIndex();
1605}
1606//-----------------------------------------------------------------------
1607Entity* OcclusionCullingSceneManager::createEntity(const String& entityName,
1608                                                                                                        const String& meshName)
1609{
1610        Entity *ent = SceneManager::createEntity(entityName, meshName);
1611
1612        for (int i = 0; i < (int)ent->getNumSubEntities(); ++i)
1613        {
1614                ent->getSubEntity(i)->setId(mCurrentEntityId);
1615        }
1616
1617        // increase counter of entity id values
1618        ++ mCurrentEntityId;
1619
1620        return ent;
1621}
1622//-----------------------------------------------------------------------
1623void OcclusionCullingSceneManager::renderAdditiveStencilShadowedQueueGroupObjects(
1624        RenderQueueGroup* pGroup, QueuedRenderableCollection::OrganisationMode om)
1625{
1626        if (mNormalExecution || !mIsHierarchicalCulling)
1627        {
1628                // render the rest of the passes
1629                TerrainSceneManager::renderAdditiveStencilShadowedQueueGroupObjects(pGroup, om);
1630                return;
1631        }
1632       
1633        // only render solid passes during hierarchical culling
1634        RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1635        LightList lightList;
1636
1637        while (groupIt.hasMoreElements())
1638        {
1639                RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1640
1641                // Sort the queue first
1642                pPriorityGrp->sort(mCameraInProgress);
1643
1644                // Clear light list
1645                lightList.clear();
1646
1647                // Render all the ambient passes first, no light iteration, no lights
1648                /*** msz: no more IRS_AMBIENT, see OgreSceneManager.h ***/
1649                // mIlluminationStage = IRS_AMBIENT;
1650
1651                OctreeSceneManager::renderObjects(pPriorityGrp->getSolidsBasic(), om, false, &lightList);
1652                // Also render any objects which have receive shadows disabled
1653                OctreeSceneManager::renderObjects(pPriorityGrp->getSolidsNoShadowReceive(), om, true);
1654#if 0           
1655                std::stringstream d;
1656                d << " solid size: " << (int)pPriorityGrp->_getSolidPasses().size()
1657                        << " solid no shadow size: " << (int)pPriorityGrp->_getSolidPassesNoShadow().size()
1658                        << "difspec size: " << (int)pPriorityGrp->_getSolidPassesDiffuseSpecular().size()
1659                        << " decal size: " << (int)pPriorityGrp->_getSolidPassesDecal().size();
1660                LogManager::getSingleton().logMessage(d.str());
1661#endif
1662        }
1663}
1664//-----------------------------------------------------------------------
1665void OcclusionCullingSceneManager::renderModulativeStencilShadowedQueueGroupObjects(
1666        RenderQueueGroup* pGroup, QueuedRenderableCollection::OrganisationMode om)
1667{
1668   if (mNormalExecution || !mIsHierarchicalCulling)
1669   {
1670           TerrainSceneManager::renderModulativeStencilShadowedQueueGroupObjects(pGroup, om);
1671           return;
1672   }
1673
1674   // Iterate through priorities
1675   RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1676
1677   while (groupIt.hasMoreElements())
1678   {
1679           RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1680
1681           // Sort the queue first
1682           pPriorityGrp->sort(mCameraInProgress);
1683           // Do (shadowable) solids
1684           OctreeSceneManager::renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
1685   }
1686}
1687//-------------------------------------------------------------------------
1688void OcclusionCullingSceneManager::SetObjectsVisible(const bool visible)
1689{
1690        GtpVisibilityPreprocessor::ObjectContainer::iterator it, it_end = mObjects.end();
1691
1692        for (it = mObjects.begin(); it != it_end; ++ it)
1693        {
1694                GtpVisibilityPreprocessor::Intersectable *entry = *it;
1695
1696                SetObjectVisible(entry, visible);
1697        }
1698}
1699//-----------------------------------------------------------------------
1700bool OcclusionCullingSceneManager::LoadViewCells(const String &filename)
1701{
1702        // no filename specified
1703        if (filename == "")
1704                return false;
1705
1706        // view cells already loaded
1707        if (mViewCellsLoaded)
1708                return true;
1709
1710        // converter between view cell ids and Ogre entites
1711        OctreeBoundingBoxConverter bconverter(this);
1712
1713        // load the view cells assigning the found objects to the pvss
1714        const bool finalizeViewCells = false;
1715
1716        // load the view cells assigning the found objects to the pvss
1717        mViewCellsManager =
1718                GtpVisibilityPreprocessor::ViewCellsManager::
1719                        LoadViewCells(filename, mObjects, false, &bconverter);
1720       
1721        LogManager::getSingleton().logMessage("******** view cells loaded *********");
1722
1723        // objects are set to invisible initially
1724        SetObjectsVisible(false);
1725
1726        if (finalizeViewCells)
1727        {
1728                CreateViewCellsGeometry();
1729        }
1730
1731        return (mViewCellsManager != NULL);
1732}
1733//-------------------------------------------------------------------------
1734void OcclusionCullingSceneManager::ApplyViewCellPvs(GtpVisibilityPreprocessor::ViewCell *vc,
1735                                                                                                        const bool load)
1736{       
1737        // NOTE: should not encounter NULL view cell,
1738        // rather apply view cell representing unbounded space then
1739        if (!vc)
1740        {       
1741                LogManager::getSingleton().logMessage("error: should not come here");
1742                // question: if no view cell, set everything visible?
1743                SetObjectsVisible(false);
1744                return;
1745        }
1746               
1747        ////////////
1748        //-- set PVS of view cell to visible
1749
1750        GtpVisibilityPreprocessor::ObjectPvsIterator pit = vc->GetPvs().GetIterator();
1751
1752        while (pit.HasMoreEntries())
1753        {               
1754                GtpVisibilityPreprocessor::Intersectable *obj = pit.Next();
1755
1756                // no associated geometry found
1757                if (!obj) continue;
1758       
1759                SetObjectVisible(obj, load);
1760        }
1761}
1762//-------------------------------------------------------------------------
1763void OcclusionCullingSceneManager::UpdatePvs(Camera *cam)
1764{
1765        if (!(mViewCellsLoaded && mUseViewCells))
1766                return;
1767
1768        const GtpVisibilityPreprocessor::Vector3 viewPoint =
1769                OgreTypeConverter::ConvertFromOgre(cam->getDerivedPosition());
1770
1771        GtpVisibilityPreprocessor::ViewCell *newElementary =
1772                mViewCellsManager->GetViewCell(viewPoint);
1773
1774        // elementary view cell did not change => don't change pvs
1775        if (mElementaryViewCell == newElementary)
1776                return;
1777
1778        mElementaryViewCell = newElementary;
1779       
1780
1781        //////////////
1782        //-- unload old pvs
1783
1784        ApplyViewCellPvs(mCurrentViewCell, false);
1785
1786        // the new view cell
1787        GtpVisibilityPreprocessor::ViewCell *viewCell;
1788               
1789        if (mUseVisibilityFilter)
1790        {       
1791                ////////////
1792                //-- compute new filtered cell
1793
1794                GtpVisibilityPreprocessor::PrVs prvs;
1795                mViewCellsManager->GetPrVS(viewPoint, prvs, 5);
1796                viewCell = prvs.mViewCell;
1797        }
1798        else
1799        {
1800                viewCell = newElementary;
1801        }
1802
1803        ///////////////
1804        //-- load new pvs
1805
1806        ApplyViewCellPvs(viewCell, true);
1807
1808        if (viewCell)
1809        {
1810                // store current view cell
1811                mCurrentViewCell->SetPvs(viewCell->GetPvs());
1812                mCurrentViewCell->SetMesh(viewCell->GetMesh());
1813                mCurrentViewCell->SetId(viewCell->GetId());
1814
1815                // delete merge tree of filtered view cell
1816                if (mUseVisibilityFilter)
1817                        mViewCellsManager->DeleteLocalMergeTree(viewCell);
1818        }
1819}
1820//-------------------------------------------------------------------------
1821void OcclusionCullingSceneManager::CreateViewCellsGeometry()
1822{
1823        //LogManager::getSingleton().logMessage("creating view cells geometry");
1824        if (mViewCellsGeometryLoaded) return;
1825
1826        GtpVisibilityPreprocessor::ViewCellContainer viewCells =
1827                mViewCellsManager->GetViewCells();
1828
1829        GtpVisibilityPreprocessor::ViewCellContainer::const_iterator it, it_end = viewCells.end();
1830        for (it = viewCells.begin(); it != it_end; ++ it)
1831        {
1832                GtpVisibilityPreprocessor::ViewCell *viewCell = *it;
1833
1834                ManualObject *manual =
1835                        OgreTypeConverter::ConvertToOgre(viewCell->GetMesh(), this);
1836               
1837                if (manual)
1838                {
1839                        mViewCellsGeometry[viewCell->GetId()] = manual;
1840
1841                        // attach to scene node
1842                        getRootSceneNode()->createChildSceneNode()->attachObject(manual);
1843                        manual->setQueryFlags(0); // returned by no query
1844       
1845                        // initialy set to invisible
1846                        manual->setVisible(false);
1847                }
1848        }
1849       
1850        mViewCellsGeometryLoaded = true;
1851}
1852//-------------------------------------------------------------------------
1853void OcclusionCullingSceneManager::VisualizeViewCells(const bool visualize)
1854{
1855        MovableMap::const_iterator mit, mit_end = mViewCellsGeometry.end();
1856                       
1857        for (mit = mViewCellsGeometry.begin(); mit != mit_end; ++ mit)
1858        {
1859                if ((*mit).second)
1860                        (*mit).second->setVisible(visualize);
1861        }       
1862}
1863#if 0
1864//-------------------------------------------------------------------------
1865void OcclusionCullingSceneManager::TestVisible(SceneNode *node)
1866{
1867        // first test for scene node, then for octant (part of the hierarchy)
1868        if (!node->mVisibleChildren)
1869        {
1870                node->setVisible(false);
1871        }
1872
1873        node->getOctant()->mVisibleChildren --;
1874}
1875//-------------------------------------------------------------------------
1876void OcclusionCullingSceneManager::TestVisible(Octree *octant)
1877{
1878        // first test for scene node, then for octant (part of the hierarchy)
1879        if (!octant->mVisibleChildren)
1880        {
1881                octant->setVisible(false);
1882        }
1883}
1884
1885//-------------------------------------------------------------------------
1886void OcclusionCullingSceneManager::UpdateVisibility(Entity *ent)
1887{
1888        if (!ent->isVisible())
1889        {
1890                bool visible = TestVisible(ent->getParentNode());
1891               
1892                if (!visible)
1893                        visible = TestVisible(octant->getParentNode());
1894
1895                if (!visible)
1896                        mHierarchyInterface->pullupVisibility();
1897        }
1898}
1899#endif
1900// splits strings containing multiple file names
1901static int SplitFilenames(const std::string str,
1902                                                  std::vector<std::string> &filenames)
1903{
1904        int pos = 0;
1905
1906        while(1)
1907        {
1908                int npos = (int)str.find(';', pos);
1909               
1910                if (npos < 0 || npos - pos < 1)
1911                        break;
1912                filenames.push_back(std::string(str, pos, npos - pos));
1913                pos = npos + 1;
1914        }
1915       
1916        filenames.push_back(std::string(str, pos, str.size() - pos));
1917        return (int)filenames.size();
1918}
1919//-----------------------------------------------------------------------
1920bool OcclusionCullingSceneManager::LoadScene(const String &filename,
1921                                                                                         const String &viewCellsFilename)
1922{
1923        using namespace std;
1924
1925        // use leaf nodes of the original spatial hierarchy as occludees
1926        vector<string> filenames;
1927        const int files = SplitFilenames(filename, filenames);
1928       
1929        stringstream d;
1930        d << "number of input files: " << files << "\n";
1931        LogManager::getSingleton().logMessage(d.str());
1932
1933        bool result = false;
1934        vector<string>::const_iterator fit, fit_end = filenames.end();
1935        int i = 0;
1936
1937        if (filename == "terrain" || filename == "")
1938        {
1939                LogManager::getSingleton().logMessage("not loading scene");
1940
1941                // terrain hack
1942                return false;
1943        }
1944
1945        for (fit = filenames.begin(); fit != fit_end; ++ fit, ++ i)
1946        {
1947                const string fn = *fit;
1948
1949                if (strstr(fn.c_str(), ".obj"))
1950                {
1951                        // load iv files
1952                        if (!LoadSceneObj(filename, viewCellsFilename, getRootSceneNode()))
1953                        {
1954                                LogManager::getSingleton().logMessage("error loading file");
1955                                return false;
1956            }
1957                }
1958                else if (strstr(fn.c_str(), ".iv") || strstr(fn.c_str(), ".wrl"))
1959                {
1960                        // load iv files
1961                        if (!LoadSceneIV(fn, getRootSceneNode(), i))
1962                        {
1963                                // terrain hack
1964                                LogManager::getSingleton().logMessage("error loading file");
1965                        }
1966                }
1967                       
1968                // at least one piece of geometry loaded
1969                result = true;
1970        }
1971
1972        return result;
1973}
1974//-----------------------------------------------------------------------
1975bool OcclusionCullingSceneManager::LoadSceneIV(const String &filename,
1976                                                                                           SceneNode *root,
1977                                                                                           const int index)
1978{
1979        IVReader ivReader;
1980
1981        Timer *timer = PlatformManager::getSingleton().createTimer();
1982        timer->reset();
1983
1984        if (1)
1985        {
1986                std::string logFilename = "IVLog" + Ogre::StringConverter().toString(index) + ".log";
1987               
1988                Log *log = LogManager::getSingleton().createLog(logFilename);
1989                ivReader.setLog(log);
1990        }
1991
1992        if (ivReader.loadFile(filename.c_str()))
1993        {
1994                SceneNode *node = root->createChildSceneNode("IVSceneNode" + index);
1995
1996                ivReader.buildTree(this, node);
1997                ivReader.collapse();
1998               
1999                std::stringstream d;
2000                d << "loaded " << filename << " in " << timer->getMilliseconds() * 1e-3 << " secs";
2001                LogManager::getSingleton().logMessage(d.str());
2002               
2003                PlatformManager::getSingleton().destroyTimer(timer);
2004
2005                /*if (USE_STATIC_GEOMETRY)
2006                {
2007                        //-- bake into static geometry
2008                        BakeSceneIntoStaticGeometry("staticVienna", "Vienna");
2009                }*/
2010       
2011                return true;
2012        }
2013
2014        return false;
2015}
2016//-----------------------------------------------------------------------
2017void OcclusionCullingSceneManager::RenderHierarchicalCulling(const bool fillRenderQueue)
2018{
2019        // create material for depth pass
2020        InitDepthPass();
2021
2022        ////////////////////
2023        //-- hierarchical culling
2024
2025        // set all necessary parameters for
2026        // hierarchical visibility culling and rendering
2027        InitVisibilityCulling(mCameraInProgress);
2028
2029
2030        /**
2031        * the hierarchical culling algorithm
2032        * for depth pass: we just find objects and update depth buffer
2033        * for "delayed" rendering: we render some passes afterwards
2034        * e.g., transparents, because they need front-to-back sorting
2035        **/
2036               
2037        mVisibilityManager->ApplyVisibilityCulling();
2038
2039        // delete remaining renderables from queue:
2040        // all which are not in mLeavePassesInQueue)
2041        _deleteRenderedQueueGroups(mLeavePassesInQueue);
2042
2043        /////////////
2044        //-- reset parameters needed for special rendering
2045               
2046        mIsDepthPassPhase = false;
2047        mIsItemBufferPhase = false;
2048        mSkipTransparents = false;
2049        mIsHierarchicalCulling = false;
2050        mLeavePassesInQueue = 0;
2051               
2052        if (fillRenderQueue)
2053        {
2054                // the shaded geometry is rendered in a second pass
2055                // add visible nodes found by the visibility culling algorithm
2056                NodeList::const_iterator it, it_end = mVisible.end();
2057        for (it = mVisible.begin(); it != it_end; ++ it)
2058                {
2059                        (*it)->_addToRenderQueue(mCameraInProgress, getRenderQueue(), false);
2060                }
2061        }
2062}
2063//-----------------------------------------------------------------------
2064bool OcclusionCullingSceneManager::LoadSceneObj(const String &filename,
2065                                                                                                const String &viewCellsFile,
2066                                                                                                SceneNode *root)
2067{
2068        Timer *timer = PlatformManager::getSingleton().createTimer();
2069        timer->reset();
2070
2071        if (!mObjReader->LoadFile(filename.c_str(), viewCellsFile, root))
2072        {
2073                PlatformManager::getSingleton().destroyTimer(timer);
2074                return false;
2075        }
2076
2077        std::stringstream d;
2078        d << "loaded " << filename << " in " << timer->getMilliseconds() * 1e-3 << " secs";
2079        LogManager::getSingleton().logMessage(d.str());
2080               
2081        PlatformManager::getSingleton().destroyTimer(timer);
2082
2083        return true;
2084}
2085
2086//-----------------------------------------------------------------------
2087void OcclusionCullingSceneManager::_renderScene(Camera* camera,
2088                                                                                                Viewport* vp,
2089                                                                                                bool includeOverlays)
2090{
2091        if (mNormalExecution)
2092        {
2093                TerrainSceneManager::_renderScene(camera, vp, includeOverlays);
2094                return;
2095        }
2096
2097    Root::getSingleton()._setCurrentSceneManager(this);
2098        mActiveQueuedRenderableVisitor->targetSceneMgr = this;
2099
2100    if (isShadowTechniqueInUse())
2101    {
2102        // Prepare shadow materials
2103        initShadowVolumeMaterials();
2104    }
2105
2106    // Perform a quick pre-check to see whether we should override far distance
2107    // When using stencil volumes we have to use infinite far distance
2108    // to prevent dark caps getting clipped
2109    if (isShadowTechniqueStencilBased() &&
2110        camera->getProjectionType() == PT_PERSPECTIVE &&
2111        camera->getFarClipDistance() != 0 &&
2112        mDestRenderSystem->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE) &&
2113        mShadowUseInfiniteFarPlane)
2114    {
2115        // infinite far distance
2116        camera->setFarClipDistance(0);
2117    }
2118
2119    mCameraInProgress = camera;
2120
2121
2122    // Update controllers
2123    ControllerManager::getSingleton().updateAllControllers();
2124
2125    // Update the scene, only do this once per frame
2126    unsigned long thisFrameNumber = Root::getSingleton().getCurrentFrameNumber();
2127    if (thisFrameNumber != mLastFrameNumber)
2128    {
2129        // Update animations
2130        _applySceneAnimations();
2131        mLastFrameNumber = thisFrameNumber;
2132    }
2133
2134    // Update scene graph for this camera (can happen multiple times per frame)
2135    _updateSceneGraph(camera);
2136
2137    // Auto-track nodes
2138    AutoTrackingSceneNodes::iterator atsni, atsniend;
2139    atsniend = mAutoTrackingSceneNodes.end();
2140    for (atsni = mAutoTrackingSceneNodes.begin(); atsni != atsniend; ++atsni)
2141    {
2142        (*atsni)->_autoTrack();
2143    }
2144    // Auto-track camera if required
2145    camera->_autoTrack();
2146
2147
2148    // Are we using any shadows at all?
2149    if (isShadowTechniqueInUse() &&
2150        mIlluminationStage != IRS_RENDER_TO_TEXTURE &&
2151                vp->getShadowsEnabled() &&
2152                mFindVisibleObjects)
2153    {
2154        // Locate any lights which could be affecting the frustum
2155        findLightsAffectingFrustum(camera);
2156        if (isShadowTechniqueTextureBased())
2157        {
2158            // *******
2159            // WARNING
2160            // *******
2161            // This call will result in re-entrant calls to this method
2162            // therefore anything which comes before this is NOT
2163            // guaranteed persistent. Make sure that anything which
2164            // MUST be specific to this camera / target is done
2165            // AFTER THIS POINT
2166            prepareShadowTextures(camera, vp);
2167            // reset the cameras because of the re-entrant call
2168            mCameraInProgress = camera;
2169        }
2170    }
2171
2172    // Invert vertex winding?
2173    if (camera->isReflected())
2174    {
2175        mDestRenderSystem->setInvertVertexWinding(true);
2176    }
2177    else
2178    {
2179        mDestRenderSystem->setInvertVertexWinding(false);
2180    }
2181
2182    // Tell params about viewport
2183    mAutoParamDataSource.setCurrentViewport(vp);
2184    // Set the viewport
2185    setViewport(vp);
2186
2187    // Tell params about camera
2188    mAutoParamDataSource.setCurrentCamera(camera);
2189    // Set autoparams for finite dir light extrusion
2190    mAutoParamDataSource.setShadowDirLightExtrusionDistance(mShadowDirLightExtrudeDist);
2191
2192    // Tell params about current ambient light
2193    mAutoParamDataSource.setAmbientLightColour(mAmbientLight);
2194        // Tell rendersystem
2195        mDestRenderSystem->setAmbientLight(mAmbientLight.r, mAmbientLight.g, mAmbientLight.b);
2196
2197    // Tell params about render target
2198    mAutoParamDataSource.setCurrentRenderTarget(vp->getTarget());
2199
2200
2201    // Set camera window clipping planes (if any)
2202    if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_USER_CLIP_PLANES))
2203    {
2204        if (camera->isWindowSet()) 
2205        {
2206            const std::vector<Plane>& planeList =
2207                camera->getWindowPlanes();
2208            for (ushort i = 0; i < 4; ++i)
2209            {
2210                mDestRenderSystem->enableClipPlane(i, true);
2211                mDestRenderSystem->setClipPlane(i, planeList[i]);
2212            }
2213        }
2214        else
2215        {
2216            for (ushort i = 0; i < 4; ++i)
2217            {
2218                mDestRenderSystem->enableClipPlane(i, false);
2219            }
2220        }
2221    }
2222
2223        mDestRenderSystem->_beginGeometryCount();
2224    // Begin the frame
2225    mDestRenderSystem->_beginFrame();
2226
2227    // Set rasterisation mode
2228    mDestRenderSystem->_setPolygonMode(camera->getPolygonMode());
2229
2230        // Set initial camera state
2231        mDestRenderSystem->_setProjectionMatrix(mCameraInProgress->getProjectionMatrixRS());
2232        mDestRenderSystem->_setViewMatrix(mCameraInProgress->getViewMatrix(true));
2233
2234        // Prepare render queue for receiving new objects
2235#ifdef GAMETOOLS_ILLUMINATION_MODULE
2236        if (mFindVisibleObjects)
2237                prepareRenderQueue();
2238#else
2239                prepareRenderQueue();
2240#endif
2241
2242    if (mFindVisibleObjects)
2243    {
2244        // Parse the scene and tag visibles
2245        myFindVisibleObjects(camera,
2246            mIlluminationStage == IRS_RENDER_TO_TEXTURE? true : false);
2247    }
2248    // Add overlays, if viewport deems it
2249    if (vp->getOverlaysEnabled() && mIlluminationStage != IRS_RENDER_TO_TEXTURE)
2250    {
2251        OverlayManager::getSingleton()._queueOverlaysForRendering(camera, getRenderQueue(), vp);
2252    }
2253    // Queue skies, if viewport seems it
2254    if (vp->getSkiesEnabled() && mFindVisibleObjects && mIlluminationStage != IRS_RENDER_TO_TEXTURE)
2255    {
2256        _queueSkiesForRendering(camera);
2257    }
2258
2259    // Render scene content
2260    _renderVisibleObjects();
2261
2262    // End frame
2263    mDestRenderSystem->_endFrame();
2264
2265    // Notify camera or vis faces
2266    camera->_notifyRenderedFaces(mDestRenderSystem->_getFaceCount());
2267}
2268//-----------------------------------------------------------------------
2269int OcclusionCullingSceneManager::QueryVisibleObjectsExact(Camera *camera,
2270                                                                                                                   Viewport* vp,
2271                                                                                                                   const bool fromPoint,
2272                                                                                                                   const bool nodeVisibility)
2273{
2274        const int itemBufferMode = 0;
2275        const bool relativeVisibility = false;
2276        const bool approximateVisibility = false;
2277
2278        int queryModes = 0;
2279
2280        if (nodeVisibility)
2281                queryModes |= GtpVisibility::QueryManager::NODE_VISIBILITY;
2282        else
2283                queryModes |= GtpVisibility::QueryManager::GEOMETRY_VISIBILITY;
2284
2285        OcclusionQueriesQueryManager *queryManager =
2286                new OcclusionQueriesQueryManager(mHierarchyInterface,
2287                                                                                 vp,
2288                                                                                 queryModes,
2289                                                                                 itemBufferMode);
2290
2291        mVisibilityManager->SetQueryManager(queryManager);
2292
2293        NodeInfoContainer visibleNodes;
2294        MeshInfoContainer visibleGeometry;
2295        PatchInfoContainer visiblePatches;
2296
2297        if (fromPoint)
2298        {
2299                queryManager->ComputeFromPointVisibility(camera->getDerivedPosition(),
2300                                                                                                 &visibleNodes,
2301                                                                                                 &visibleGeometry,
2302                                                                                                 &visiblePatches,
2303                                                                                                 relativeVisibility,
2304                                                                                                 approximateVisibility);
2305        }
2306        else
2307        {
2308                queryManager->ComputeCameraVisibility(*camera,
2309                                                                                          &visibleNodes,
2310                                                                                          &visibleGeometry,
2311                                                                                          &visiblePatches,
2312                                                                                          relativeVisibility,
2313                                                                                          approximateVisibility);
2314        }
2315               
2316        if (0)
2317        {
2318                std::stringstream d;
2319                d << "Query mode: " << queryModes
2320                  << " visible nodes: " << (int)visibleNodes.size()
2321                  << " visible geometry: " << (int)visibleGeometry.size();
2322
2323                LogManager::getSingleton().logMessage(d.str());
2324        }
2325
2326        ///////////////////////
2327        //-- put items in render queue
2328
2329        getRenderQueue()->clear();
2330
2331        if (!nodeVisibility)
2332        {
2333                //////////////////
2334                //-- apply queries on geometry level
2335
2336                MeshInfoContainer::iterator geomIt, geomIt_end = visibleGeometry.end();
2337
2338                for (geomIt = visibleGeometry.begin(); geomIt != geomIt_end; ++geomIt)
2339                {
2340                        MovableObject *mo = (*geomIt).GetSource();
2341
2342                        // add if not 0
2343                        if (!(*geomIt).GetVisiblePixels())
2344                                continue;
2345
2346                        mo->_notifyCurrentCamera(camera);
2347
2348                        if (mo->isVisible())
2349                        {
2350                                mo->_updateRenderQueue(getRenderQueue());
2351                        }
2352                }
2353        }
2354        else
2355        {
2356                ////////////////
2357                //-- apply queries on node level
2358
2359                NodeInfoContainer::iterator nodesIt, nodesIt_end = visibleNodes.end();
2360
2361                for (nodesIt = visibleNodes.begin(); nodesIt != nodesIt_end; ++ nodesIt)
2362                {
2363                        if (!(*nodesIt).GetVisiblePixels())
2364                                continue;
2365
2366                        Octree *octree = static_cast<Octree *>((*nodesIt).GetSource());
2367
2368                        NodeList::iterator nIt, nIt_end = octree->mNodes.end();
2369
2370                        for (nIt = octree->mNodes.begin(); nIt != nIt_end; ++ nIt)
2371                        {
2372                                (*nIt)->_addToRenderQueue(camera, getRenderQueue(), false);
2373                        }
2374                }
2375        }
2376
2377    delete queryManager;
2378
2379        if (nodeVisibility)
2380                return (int)visibleNodes.size();
2381        else
2382                return (int)visibleGeometry.size();
2383}
2384//-----------------------------------------------------------------------
2385void OcclusionCullingSceneManager::RenderDepthForQuery(Camera* camera,
2386                                                                                                           Viewport* vp)
2387{
2388    Root::getSingleton()._setCurrentSceneManager(this);
2389        mActiveQueuedRenderableVisitor->targetSceneMgr = this;
2390
2391    mCameraInProgress = camera;
2392
2393    // Update scene graph for this camera (can happen multiple times per frame)
2394    _updateSceneGraph(camera);
2395
2396    // Invert vertex winding?
2397    if (camera->isReflected())
2398    {
2399        mDestRenderSystem->setInvertVertexWinding(true);
2400    }
2401    else
2402    {
2403        mDestRenderSystem->setInvertVertexWinding(false);
2404    }
2405
2406    // Tell params about viewport
2407    mAutoParamDataSource.setCurrentViewport(vp);
2408    // Set the viewport
2409    setViewport(vp);
2410
2411    // Tell params about camera
2412    mAutoParamDataSource.setCurrentCamera(camera);
2413    // Set autoparams for finite dir light extrusion
2414    mAutoParamDataSource.setShadowDirLightExtrusionDistance(mShadowDirLightExtrudeDist);
2415
2416    // Tell params about current ambient light
2417    mAutoParamDataSource.setAmbientLightColour(mAmbientLight);
2418        // Tell rendersystem
2419        mDestRenderSystem->setAmbientLight(mAmbientLight.r, mAmbientLight.g, mAmbientLight.b);
2420
2421    // Tell params about render target
2422    mAutoParamDataSource.setCurrentRenderTarget(vp->getTarget());
2423
2424
2425    // Set camera window clipping planes (if any)
2426    if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_USER_CLIP_PLANES))
2427    {
2428        if (camera->isWindowSet()) 
2429        {
2430                        const std::vector<Plane>& planeList = camera->getWindowPlanes();
2431
2432            for (ushort i = 0; i < 4; ++ i)
2433            {
2434                mDestRenderSystem->enableClipPlane(i, true);
2435                mDestRenderSystem->setClipPlane(i, planeList[i]);
2436            }
2437        }
2438        else
2439        {
2440            for (ushort i = 0; i < 4; ++i)
2441            {
2442                mDestRenderSystem->enableClipPlane(i, false);
2443            }
2444        }
2445    }
2446
2447        // Prepare render queue for receiving new objects
2448        prepareRenderQueue();
2449
2450        // Begin the frame
2451    mDestRenderSystem->_beginFrame();
2452
2453    // Set rasterisation mode
2454    mDestRenderSystem->_setPolygonMode(camera->getPolygonMode());
2455
2456        // Set initial camera state
2457        mDestRenderSystem->_setProjectionMatrix(mCameraInProgress->getProjectionMatrixRS());
2458        mDestRenderSystem->_setViewMatrix(mCameraInProgress->getViewMatrix(true));
2459
2460        //////////////
2461        //-- Render scene in order fill depth buffer
2462
2463        // don't have to fill queue, just render depth
2464        const bool fillQueue = false;
2465
2466        RenderHierarchicalCulling(fillQueue);
2467   
2468    // End frame
2469    mDestRenderSystem->_endFrame();
2470}
2471//-----------------------------------------------------------------------
2472const String OcclusionCullingSceneManagerFactory::FACTORY_TYPE_NAME = "OcclusionCullingSceneManager";
2473//-----------------------------------------------------------------------
2474void OcclusionCullingSceneManagerFactory::initMetaData(void) const
2475{
2476        mMetaData.typeName = FACTORY_TYPE_NAME;
2477        mMetaData.description = "Scene manager organising the scene on the basis of an octree with advanced occlusion culling (TM).";
2478        mMetaData.sceneTypeMask = 0xFFFF; // support all types
2479        mMetaData.worldGeometrySupported = false;
2480}
2481//-----------------------------------------------------------------------
2482SceneManager *OcclusionCullingSceneManagerFactory::createInstance(
2483                const String& instanceName)
2484{
2485        OcclusionCullingSceneManager* tsm =
2486                new OcclusionCullingSceneManager(instanceName, visManager);
2487       
2488        // Create & register default sources (one per manager)
2489        HeightmapTerrainPageSource* ps = new HeightmapTerrainPageSource();
2490        mTerrainPageSources.push_back(ps);
2491        tsm->registerPageSource("Heightmap", ps);
2492
2493        return tsm;
2494}
2495//-----------------------------------------------------------------------
2496void OcclusionCullingSceneManager::AddVisibleMeshGeometryToQueue(
2497                                                const MeshInfoContainer &visibleGeometry,
2498                                                Camera *cam)
2499{
2500        MeshInfoContainer::const_iterator geomIt, geomIt_end = visibleGeometry.end();
2501
2502        for (geomIt = visibleGeometry.begin(); geomIt != geomIt_end; ++geomIt)
2503        {
2504                MovableObject *mo = (*geomIt).GetSource();
2505
2506                // add if not 0
2507                if (!(*geomIt).GetVisiblePixels())
2508                        continue;
2509
2510                mo->_notifyCurrentCamera(cam);
2511
2512                if (mo->isVisible())
2513                {
2514                        mo->_updateRenderQueue(getRenderQueue());
2515                }
2516        }
2517}
2518//-----------------------------------------------------------------------
2519void OcclusionCullingSceneManager::AddVisibleNodeGeometryToQueue(
2520                                                const NodeInfoContainer &visibleNodes,
2521                                                Camera *cam)
2522{
2523        ////////////////
2524        //-- apply queries on node level
2525
2526        NodeInfoContainer::const_iterator nodesIt, nodesIt_end = visibleNodes.end();
2527
2528        for (nodesIt = visibleNodes.begin(); nodesIt != nodesIt_end; ++ nodesIt)
2529        {
2530                if (!(*nodesIt).GetVisiblePixels())
2531                        continue;
2532
2533                Octree *octree = static_cast<Octree *>((*nodesIt).GetSource());
2534
2535                NodeList::iterator nIt, nIt_end = octree->mNodes.end();
2536
2537                for (nIt = octree->mNodes.begin(); nIt != nIt_end; ++ nIt)
2538                {
2539                        (*nIt)->_addToRenderQueue(cam, getRenderQueue(), false);
2540                }
2541        }
2542}
2543//-----------------------------------------------------------------------
2544void OcclusionCullingSceneManager::_findVisibleObjects(Camera* cam,
2545                                                                                                           bool onlyShadowCasters)                                                                               
2546{
2547        if (mNormalExecution || (!mUseVisibilityQueries == 0))
2548        {
2549                TerrainSceneManager::_findVisibleObjects(cam, onlyShadowCasters);
2550                return;
2551        }
2552
2553        // don't need shading, render only depth
2554        // note:have to disable deph write for nodes!
2555    bool savedUseDepthPass = mUseDepthPass;
2556        if (mResetMaterialForQueries) mUseDepthPass = true;
2557
2558        // lists only used for visualization
2559        getRenderQueue()->clear();
2560        mVisible.clear();
2561        mBoxes.clear();
2562
2563        const int itemBufferMode = 0;
2564        const bool relativeVisibility = false;
2565        bool approximateVisibility = false;
2566
2567        int queryModes = 0;
2568
2569        if (mQueryMode != 0)
2570        {
2571                queryModes |= GtpVisibility::QueryManager::NODE_VISIBILITY;
2572
2573                if (mQueryMode == 2)
2574                        approximateVisibility = true;
2575        }
2576        else
2577        {
2578                queryModes |= GtpVisibility::QueryManager::GEOMETRY_VISIBILITY;
2579        }       
2580                       
2581
2582        OcclusionQueriesQueryManager *queryManager =
2583                new OcclusionQueriesQueryManager(mHierarchyInterface,
2584                                                                                 cam->getViewport(),
2585                                                                                 queryModes,
2586                                                                                 itemBufferMode);
2587
2588        mVisibilityManager->SetQueryManager(queryManager);
2589
2590        NodeInfoContainer visibleNodes;
2591        MeshInfoContainer visibleGeometry;
2592        PatchInfoContainer visiblePatches;
2593
2594        if (mUseFromPointQueries)
2595        {
2596                queryManager->ComputeFromPointVisibility(cam->getDerivedPosition(),
2597                                                                                                 &visibleNodes,
2598                                                                                                 &visibleGeometry,
2599                                                                                                 &visiblePatches,
2600                                                                                                 relativeVisibility,
2601                                                                                                 approximateVisibility);
2602        }
2603        else
2604        {
2605                queryManager->ComputeCameraVisibility(*cam,
2606                                                                                          &visibleNodes,
2607                                                                                          &visibleGeometry,
2608                                                                                          &visiblePatches,
2609                                                                                          relativeVisibility,
2610                                                                                          approximateVisibility);
2611        }
2612               
2613        if (0)
2614        {
2615                std::stringstream d;
2616                d << "Query mode: " << queryModes
2617                  << " visible nodes: " << (int)visibleNodes.size()
2618                  << " visible geometry: " << (int)visibleGeometry.size();
2619
2620                LogManager::getSingleton().logMessage(d.str());
2621        }
2622
2623        ///////////////////////
2624        //-- put items in render queue
2625       
2626        if (mQueryMode != EXACT_QUERIES)
2627        {
2628                ////////////
2629                //-- apply queries on geometry level
2630
2631                AddVisibleNodeGeometryToQueue(visibleNodes, cam);
2632        }
2633        else
2634        {
2635                AddVisibleMeshGeometryToQueue(visibleGeometry, cam);
2636        }
2637
2638        // reset depth pass
2639        mUseDepthPass = savedUseDepthPass;
2640
2641        delete queryManager;
2642}
2643
2644//-----------------------------------------------------------------------
2645void OcclusionCullingSceneManagerFactory::destroyInstance(SceneManager* instance)
2646{
2647        delete instance;
2648}
2649
2650} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.