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

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

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

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