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

Revision 925, 38.9 KB checked in by mattausch, 18 years ago (diff)

update for ogre 1.2
OcclusionCullingSceneManager? is the only scenemanager in the solution now

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