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

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