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

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