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

Revision 2160, 62.3 KB checked in by mattausch, 17 years ago (diff)

depth pass now done in findVisibleObjects. This makes it possible to process the objects found in this method, e.g., with the illumination modules

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