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

Revision 931, 35.5 KB checked in by mattausch, 18 years ago (diff)

added bounding boxes to xml description

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