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

Revision 897, 36.3 KB checked in by mattausch, 19 years ago (diff)

updated to ogre 1.2

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                /**
369                * the hierarchical culling algorithm
370                * for depth pass: we just find objects and update depth buffer
371                * for "delayed" rendering: we render some passes afterwards
372                * e.g., transparents, because they need front-to-back sorting
373                **/
374       
375                mVisibilityManager->ApplyVisibilityCulling();
376       
377                // delete remaining renderables from queue:
378                // all which are not in mLeavePassesInQueue)
379#ifdef GTP_VISIBILITY_MODIFIED_OGRE
380                _deleteRenderedQueueGroups(mLeavePassesInQueue);
381#endif
382
383                //-- reset parameters
384                mIsDepthPassPhase = false;
385                mIsItemBufferPhase = false;
386                mSkipTransparents = false;
387                mIsHierarchicalCulling = false;
388
389                mLeavePassesInQueue = 0;
390
391#if 1   
392                // add visible nodes found by the visibility culling algorithm
393                if (mUseDepthPass)
394                {
395                        NodeList::const_iterator it, it_end = mVisible.end();
396
397                        //getRenderQueue()->clear();
398                        for (it = mVisible.begin(); it != it_end; ++ it)
399                        {
400                                (*it)->_addToRenderQueue(mCameraInProgress, getRenderQueue(), false);
401                        }
402                }
403#endif 
404                //-- now we can render all remaining queue objects
405                //-- used for depth pass, transparents, overlay
406                clearSpecialCaseRenderQueues();
407       
408                //-- we render all remaining queue objects
409                // used for depth pass, transparents, overlay
410                clearSpecialCaseRenderQueues();
411                OctreeSceneManager::_renderVisibleObjects();
412       
413        }   // hierarchical culling
414
415        // reset ambient light
416        setAmbientLight(savedAmbient);
417
418        getRenderQueue()->clear(); // finally clear render queue
419        if (0) OGRE_DELETE(mRenderQueue); // HACK: should rather only be cleared ...
420
421        if (0) WriteLog(); // write out stats
422}
423
424//-----------------------------------------------------------------------
425void VisibilityOctreeSceneManager::_updateSceneGraph(Camera* cam)
426{
427        if (NORMAL_RENDER_HACK)
428        {
429                OctreeSceneManager::_updateSceneGraph(cam);
430                return;
431        }
432
433        mVisibilityManager->GetCullingManager()->SetHierarchyInterface(mHierarchyInterface);
434        mHierarchyInterface->SetRenderSystem(mDestRenderSystem);
435
436        OctreeSceneManager::_updateSceneGraph(cam);
437}
438//-----------------------------------------------------------------------
439bool VisibilityOctreeSceneManager::setOption(const String & key, const void * val)
440{
441        if (key == "UseDepthPass")
442        {
443                mUseDepthPass = (*static_cast<const bool *>(val));
444                return true;
445        }
446        if (key == "PrepareVisualization")
447        {
448                mShowVisualization = (*static_cast<const bool *>(val));
449                return true;
450        }
451        if (key == "RenderNodesForViz")
452        {
453                mRenderNodesForViz = (*static_cast<const bool *>(val));
454                return true;
455        }
456        if (key == "RenderNodesContentForViz")
457        {
458                mRenderNodesContentForViz = (*static_cast<const bool *>(val));
459                return true;
460        }
461        if (key == "SkyBoxEnabled")
462        {
463                mSkyBoxEnabled = (*static_cast<const bool *>(val));
464                return true;
465        }
466        if (key == "SkyPlaneEnabled")
467        {
468                mSkyPlaneEnabled = (*static_cast<const bool *>(val));
469                return true;
470        }
471        if (key == "SkyDomeEnabled")
472        {
473                mSkyDomeEnabled = (*static_cast<const bool *>(val));
474                return true;
475        }
476        if (key == "VisualizeCulledNodes")
477        {
478                mVisualizeCulledNodes = (*static_cast<const bool *>(val));
479                return true;
480        }
481        if (key == "DelayRenderTransparents")
482        {
483                mDelayRenderTransparents = (*static_cast<const bool *>(val));
484                return true;
485        }
486
487        if (key == "DepthWrite")
488        {
489                mEnableDepthWrite = (*static_cast<const bool *>(val));
490                return true;
491        }
492        if (key == "UseItemBuffer")
493        {
494                mUseItemBuffer = (*static_cast<const bool *>(val));
495                return true;
496        }
497        if (key == "ExecuteVertexProgramForAllPasses")
498        {
499                mExecuteVertexProgramForAllPasses  = (*static_cast<const bool *>(val));
500                return true;
501        }
502        if (key == "RenderTransparentsForItemBuffer")
503        {
504                mRenderTransparentsForItemBuffer  = (*static_cast<const bool *>(val));
505                return true;
506        }
507        if (key == "NodeVizScale")
508        {
509                OctreeNode::setVizScale(*static_cast<const float *>(val));
510                return true;
511        }
512        if (key == "LoadViewCells")
513        {
514                if (!mViewCellsLoaded)
515                {
516                        LoadViewCells(static_cast<const char *>(val));
517                        mViewCellsLoaded = true;       
518                }
519
520                return true;
521        }
522        if (key == "UseViewCells")
523        {
524                mUseViewCells = *static_cast<const bool *>(val);
525
526                // reset view cell
527                OGRE_DELETE(mCurrentViewCell);
528                if (mUseViewCells)
529                        mCurrentViewCell =  mViewCellsManager->GenerateViewCell();
530                mElementaryViewCell = NULL;
531                // if using view cells, all objects are set to false initially
532                SetObjectsVisible(!mUseViewCells);
533               
534                return true;
535        }
536        if (key == "UseVisibilityFilter")
537        {
538                mUseVisibilityFilter = *static_cast<const bool *>(val);
539                // set null =>recomputation of the pvs
540        mElementaryViewCell = NULL;
541                return true;
542        }
543       
544        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
545                setOption(key, val) || OctreeSceneManager::setOption(key, val);
546}
547//-----------------------------------------------------------------------
548bool VisibilityOctreeSceneManager::getOption(const String & key, void *val)
549{
550        if (key == "NumHierarchyNodes")
551        {
552                * static_cast<unsigned int *>(val) = (unsigned int)mNumOctants;
553                return true;
554        }
555
556        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
557                getOption(key, val) && OctreeSceneManager::getOption(key, val);
558}
559//-----------------------------------------------------------------------
560bool VisibilityOctreeSceneManager::getOptionValues(const String & key, StringVector  &refValueList)
561{
562        return OctreeSceneManager::getOptionValues( key, refValueList );
563}
564//-----------------------------------------------------------------------
565bool VisibilityOctreeSceneManager::getOptionKeys(StringVector & refKeys)
566{
567        return  VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
568                getOptionKeys (refKeys) || OctreeSceneManager::getOptionKeys(refKeys);
569}
570//-----------------------------------------------------------------------
571void VisibilityOctreeSceneManager::setVisibilityManager(GtpVisibility::VisibilityManager *visManager)
572{
573    mVisibilityManager = visManager;
574}
575//-----------------------------------------------------------------------
576GtpVisibility::VisibilityManager *VisibilityOctreeSceneManager::getVisibilityManager()
577{
578        return mVisibilityManager;
579}
580//-----------------------------------------------------------------------
581void VisibilityOctreeSceneManager::WriteLog()
582{
583        std::stringstream d;
584
585        d << "Depth pass: " << StringConverter::toString(mUseDepthPass) << ", "
586          << "Delay transparents: " << StringConverter::toString(mDelayRenderTransparents) << ", "
587          << "Use optimization: " << StringConverter::toString(mHierarchyInterface->GetTestGeometryForVisibleLeaves()) << ", "
588          << "Algorithm type: " << mVisibilityManager->GetCullingManagerType() << ", "
589          << "Hierarchy nodes: " << mNumOctants << ", "
590          << "Traversed nodes: " << mHierarchyInterface->GetNumTraversedNodes() << ", "
591          << "Rendered nodes: " << mHierarchyInterface->GetNumRenderedNodes() << ", "
592          << "Query culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumQueryCulledNodes() << ", "
593          << "Frustum culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumFrustumCulledNodes() << ", "
594      << "Queries issued: " << mVisibilityManager->GetCullingManager()->GetNumQueriesIssued() << ", "
595          << "Found objects: " << (int)mVisible.size() << "\n";
596
597        LogManager::getSingleton().logMessage(d.str());
598}
599//-----------------------------------------------------------------------
600void VisibilityOctreeSceneManager::renderObjects(
601                        const QueuedRenderableCollection& objs,
602                        QueuedRenderableCollection::OrganisationMode om,
603            bool doLightIteration, const LightList* manualLightList)
604{
605        // for correct rendering, transparents must be rendered after hierarchical culling
606        // => do nothing
607        if (NORMAL_RENDER_HACK || !mSkipTransparents)
608        {
609                OctreeSceneManager::renderObjects(objs, om, doLightIteration, manualLightList);
610        }
611}
612//-----------------------------------------------------------------------
613bool VisibilityOctreeSceneManager::validatePassForRendering(Pass* pass)
614{
615        if (NORMAL_RENDER_HACK)
616        {
617                return SceneManager::validatePassForRendering(pass);
618        }
619
620        // skip all but first pass if we are doing the depth pass
621        if ((mIsDepthPassPhase || mIsItemBufferPhase) && (pass->getIndex() > 0))
622        {
623                return false;
624        }
625        // all but first pass
626        /*else if ((!mIsDepthPassPhase || mIsItemBufferPhase) && (pass->getIndex() != 0))
627        {
628                return false;
629        }*/
630
631        return SceneManager::validatePassForRendering(pass);
632}
633//-----------------------------------------------------------------------
634void VisibilityOctreeSceneManager::_renderQueueGroupObjects(
635        RenderQueueGroup* pGroup, QueuedRenderableCollection::OrganisationMode om)
636{
637        if (NORMAL_RENDER_HACK || !mIsItemBufferPhase)
638        {
639                OctreeSceneManager::_renderQueueGroupObjects(pGroup, om);
640                return;
641        }
642#ifdef ITEM_BUFFER
643        //-- renders item buffer
644
645    // Iterate through priorities
646    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
647
648        while (groupIt.hasMoreElements())
649    {
650                RenderItemBuffer(groupIt.getNext());
651        }
652#endif // ITEM_BUFFER
653}
654#ifdef ITEM_BUFFER
655//-----------------------------------------------------------------------
656void VisibilityOctreeSceneManager::RenderItemBuffer(RenderPriorityGroup* pGroup)
657{
658        // Do solids
659        RenderPriorityGroup::SolidRenderablePassMap solidObjs = pGroup->_getSolidPasses();
660
661        // ----- SOLIDS LOOP -----
662        RenderPriorityGroup::SolidRenderablePassMap::const_iterator ipass, ipassend;
663        ipassend = solidObjs.end();
664
665        for (ipass = solidObjs.begin(); ipass != ipassend; ++ipass)
666        {
667                // Fast bypass if this group is now empty
668                if (ipass->second->empty())
669                        continue;
670
671                // Render only first pass of renderable as false color
672                if (ipass->first->getIndex() > 0)
673                        continue;
674
675                RenderPriorityGroup::RenderableList* rendList = ipass->second;
676               
677                RenderPriorityGroup::RenderableList::const_iterator irend, irendend;
678                irendend = rendList->end();
679                       
680                for (irend = rendList->begin(); irend != irendend; ++irend)
681                {
682                        if (0)
683                        {
684                        std::stringstream d; d << "itembuffer, pass name: " <<
685                                ipass->first->getParent()->getParent()->getName();
686                               
687                        LogManager::getSingleton().logMessage(d.str());
688                        }
689                       
690                        RenderSingleObjectForItemBuffer(*irend, ipass->first);
691                }
692        }
693
694        //-- TRANSPARENT LOOP: must be handled differently from solids
695
696        // transparents are treated either as solids or completely discarded
697        if (mRenderTransparentsForItemBuffer)
698        {
699                RenderPriorityGroup::TransparentRenderablePassList transpObjs =
700                        pGroup->_getTransparentPasses();
701                RenderPriorityGroup::TransparentRenderablePassList::const_iterator
702                        itrans, itransend;
703
704                itransend = transpObjs.end();
705                for (itrans = transpObjs.begin(); itrans != itransend; ++itrans)
706                {
707                        // like for solids, render only first pass
708                        if (itrans->pass->getIndex() == 0)
709                        {       
710                                RenderSingleObjectForItemBuffer(itrans->renderable, itrans->pass);
711                        }
712                }
713        }
714}
715//-----------------------------------------------------------------------
716void VisibilityOctreeSceneManager::RenderSingleObjectForItemBuffer(Renderable *rend, Pass *pass)
717{
718        static LightList nullLightList;
719       
720        int col[4];
721       
722        // -- create color code out of object id
723        col[0] = (rend->getId() >> 16) & 255;
724        col[1] = (rend->getId() >> 8) & 255;
725        col[2] = rend->getId() & 255;
726//      col[3] = 255;
727
728        //mDestRenderSystem->setColour(col[0], col[1], col[2], col[3]);
729   
730        mItemBufferPass->setAmbient(ColourValue(col[0] / 255.0f,
731                                                                                    col[1] / 255.0f,
732                                                                                        col[2] / 255.0f, 1));
733
734        // set vertex program of current pass
735        if (mExecuteVertexProgramForAllPasses && pass->hasVertexProgram())
736        {
737                mItemBufferPass->setVertexProgram(pass->getVertexProgramName());
738
739                if (mItemBufferPass->hasVertexProgram())
740                {
741                        const GpuProgramPtr& prg = mItemBufferPass->getVertexProgram();
742                        // Load this program if not done already
743                        if (!prg->isLoaded())
744                                prg->load();
745                        // Copy params
746                        mItemBufferPass->setVertexProgramParameters(pass->getVertexProgramParameters());
747                }
748        }
749        else if (mItemBufferPass->hasVertexProgram())
750        {
751                mItemBufferPass->setVertexProgram("");
752        }
753
754        Pass *usedPass = setPass(mItemBufferPass);
755
756
757        // render a single object, this will set up auto params if required
758        renderSingleObject(rend, usedPass, false, &nullLightList);
759}
760#endif // ITEM_BUFFER
761//-----------------------------------------------------------------------
762GtpVisibility::VisibilityManager *VisibilityOctreeSceneManager::GetVisibilityManager()
763{
764        return mVisibilityManager;
765}
766//-----------------------------------------------------------------------
767void VisibilityOctreeSceneManager::InitVisibilityCulling(Camera *cam)
768{
769        // reset culling manager stats
770        mVisibilityManager->GetCullingManager()->InitFrame(mVisualizeCulledNodes);
771
772        // set depth pass flag before rendering
773        mIsDepthPassPhase = mUseDepthPass;
774
775        mIsHierarchicalCulling = true; // during hierarchical culling
776
777        // item buffer needs full ambient lighting to use item colors as unique id
778        if (mUseItemBuffer)
779        {
780                mIsItemBufferPhase = true;
781                setAmbientLight(ColourValue(1,1,1,1));
782        }
783
784
785        // set passes which are stored in render queue
786        // for rendering AFTER hierarchical culling, i.e., passes which need
787        // a special rendering order
788       
789        mLeavePassesInQueue = 0;
790
791        if (!mUseDepthPass && !mUseItemBuffer)
792        {
793                if (mShadowTechnique == SHADOWTYPE_STENCIL_ADDITIVE)
794                {
795                        // TODO: remove this pass because it should be processed during hierarchical culling
796                        //mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_NOSHADOW;
797
798                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_DECAL;
799                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_DIFFUSE_SPECULAR;
800                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
801
802                        // just render ambient passes
803                        /*** msz: no more IRS_AMBIENT, see OgreSceneManager.h ***/
804                        // mIlluminationStage = IRS_AMBIENT;
805                        getRenderQueue()->setSplitPassesByLightingType(true);
806                }
807       
808                if (mShadowTechnique == SHADOWTYPE_STENCIL_MODULATIVE)
809                {
810                        mLeavePassesInQueue |= RenderPriorityGroup::SOLID_PASSES_NOSHADOW;
811                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
812                }
813       
814                // transparents should be rendered after hierarchical culling to
815                // provide front-to-back ordering
816                if (mDelayRenderTransparents)
817                {
818                        mLeavePassesInQueue |= RenderPriorityGroup::TRANSPARENT_PASSES;
819                }
820        }
821
822        // skip rendering transparents during the hierarchical culling
823        // (because they will be rendered afterwards)
824        mSkipTransparents =
825                (mIsDepthPassPhase || (mLeavePassesInQueue & RenderPriorityGroup::TRANSPARENT_PASSES));
826
827        // -- initialise interface for rendering traversal of the hierarchy
828        mHierarchyInterface->SetHierarchyRoot(mOctree);
829       
830        // possible two cameras (one for culling, one for rendering)
831        mHierarchyInterface->InitTraversal(mCameraInProgress,
832                                                        mCullCamera ? getCamera("CullCamera") : NULL,
833                                                        mLeavePassesInQueue);
834               
835        //std::stringstream d; d << "leave passes in queue: " << mLeavePassesInQueue;
836        //LogManager::getSingleton().logMessage(d.str());
837}
838//-----------------------------------------------------------------------
839OctreeHierarchyInterface *VisibilityOctreeSceneManager::GetHierarchyInterface()
840{
841        return mHierarchyInterface;
842}
843//-----------------------------------------------------------------------
844Entity* VisibilityOctreeSceneManager::createEntity(const String& entityName,
845                                                                                                        const String& meshName)
846{
847        Entity *ent = SceneManager::createEntity(entityName, meshName);
848
849        for (int i = 0; i < (int)ent->getNumSubEntities(); ++i)
850        {
851                ent->getSubEntity(i)->setId(mCurrentEntityId);
852        }
853
854        // increase counter of entity id values
855        ++ mCurrentEntityId;
856
857        return ent;
858}
859//-----------------------------------------------------------------------
860void VisibilityOctreeSceneManager::renderAdditiveStencilShadowedQueueGroupObjects(
861        RenderQueueGroup* pGroup, QueuedRenderableCollection::OrganisationMode om)
862{
863        // only render solid passes during hierarchical culling
864        if (mIsHierarchicalCulling)
865        {
866                RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
867            LightList lightList;
868
869                while (groupIt.hasMoreElements())
870                {
871                        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
872
873                        // Sort the queue first
874                        pPriorityGrp->sort(mCameraInProgress);
875
876                        // Clear light list
877                        lightList.clear();
878
879                        // Render all the ambient passes first, no light iteration, no lights
880                        /*** msz: no more IRS_AMBIENT, see OgreSceneManager.h ***/
881                        // mIlluminationStage = IRS_AMBIENT;
882
883                        OctreeSceneManager::renderObjects(pPriorityGrp->getSolidsBasic(), om, false, &lightList);
884                        // Also render any objects which have receive shadows disabled
885                        OctreeSceneManager::renderObjects(pPriorityGrp->getSolidsNoShadowReceive(), om, true);         
886#if 0           
887                        std::stringstream d;
888                        d << " solid size: " << (int)pPriorityGrp->_getSolidPasses().size()
889                                << " solid no shadow size: " << (int)pPriorityGrp->_getSolidPassesNoShadow().size()
890                                << "difspec size: " << (int)pPriorityGrp->_getSolidPassesDiffuseSpecular().size()
891                                << " decal size: " << (int)pPriorityGrp->_getSolidPassesDecal().size();
892                        LogManager::getSingleton().logMessage(d.str());
893#endif
894                }
895        }
896        else // render the rest of the passes
897        {
898                OctreeSceneManager::renderAdditiveStencilShadowedQueueGroupObjects(pGroup, om);
899        }
900}
901//-----------------------------------------------------------------------
902void VisibilityOctreeSceneManager::renderModulativeStencilShadowedQueueGroupObjects(
903        RenderQueueGroup* pGroup, QueuedRenderableCollection::OrganisationMode om)
904{
905   if (mIsHierarchicalCulling)
906   {
907           // Iterate through priorities
908           RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
909
910           while (groupIt.hasMoreElements())
911           {
912                   RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
913
914                   // Sort the queue first
915                   pPriorityGrp->sort(mCameraInProgress);
916
917                   // Do (shadowable) solids
918                   OctreeSceneManager::renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
919           }
920   }
921   else
922   {
923           SceneManager::renderModulativeStencilShadowedQueueGroupObjects(pGroup, om);
924   }
925}
926//-------------------------------------------------------------------------
927void VisibilityOctreeSceneManager::SetObjectsVisible(const bool visible)
928{
929        GtpVisibilityPreprocessor::ObjectContainer::iterator it, it_end = mObjects.end();
930
931        for (it = mObjects.begin(); it != it_end; ++ it)
932        {
933                OgreMeshInstance *omi = static_cast<OgreMeshInstance *>(*it);
934                Entity *ent = omi->GetMesh();
935                ent->setVisible(visible);
936        }
937}
938//-------------------------------------------------------------------------
939void VisibilityOctreeSceneManager::loadVisibilityConfig(const String& filename)
940{
941        // TODO matt
942        // Set up the options
943        ConfigFile config;
944        String val;
945
946        config.load(filename);
947
948        val = config.getSetting("Algorithm");
949
950    if (!val.empty())
951        {
952                 VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).setOption("Algorithm", val.c_str());
953        }
954
955        val = config.getSetting("UseDepthPass");
956
957        if (!val.empty())
958        {
959                 setOption("UseDepthPass", val.c_str());
960        }
961}
962//-------------------------------------------------------------------------
963inline static AxisAlignedBox EnlargeBox(const AxisAlignedBox &box)
964{
965        const float eps = 1e-3f;
966        const Vector3 veps(eps, eps, eps);
967        Vector3 max = box.getMaximum();
968        Vector3 min = box.getMinimum();
969
970        return AxisAlignedBox(min - veps, max + veps);
971}
972//-----------------------------------------------------------------------
973Entity *VisibilityOctreeSceneManager::FindCorrespondingObject(const AxisAlignedBox &box)
974{
975        list<SceneNode *> sceneNodeList;
976        AxisAlignedBox mybox = EnlargeBox(box);
977        //AxisAlignedBox dummy(Vector3(-50000, -50000, -50000), Vector3(50000, 50000, 50000));
978       
979        // get intersecting scene nodes
980        findNodesIn(mybox, sceneNodeList, NULL);
981       
982
983        list<SceneNode *>::const_iterator sit, sit_end = sceneNodeList.end();
984
985        float overlap = 0;//GtpVisibilityPreprocessor::Limits::Small;
986
987        Entity *bestFittingObj = NULL;
988        float bestFit = overlap;
989
990        // perfect fit threshold
991        const float thresh = 1.0 - GtpVisibilityPreprocessor::Limits::Small;
992
993       
994        // find the bbox which is closest to the current bbox
995        for (sit = sceneNodeList.begin(); sit != sceneNodeList.end(); ++ sit)
996        {
997                SceneNode *sn = *sit;
998                SceneNode::ObjectIterator oit = sn->getAttachedObjectIterator();
999
1000        while (oit.hasMoreElements())
1001                {
1002                        MovableObject *mo = oit.getNext();
1003
1004                        // we are only interested in scene entities
1005                        if (mo->getMovableType() != "Entity")
1006                        {
1007                                continue;
1008                        }
1009                         
1010                        const AxisAlignedBox bbox = EnlargeBox(mo->getWorldBoundingBox());
1011                                       
1012
1013                        // compute measure how much aabbs overlap
1014                        overlap = RatioOfOverlap(OgreTypeConverter::ConvertFromOgre(mybox),
1015                                                                         OgreTypeConverter::ConvertFromOgre(bbox));
1016       
1017                         if (overlap > bestFit)
1018                         {
1019                                 bestFit = overlap;
1020                       
1021                                 bestFittingObj = static_cast<Entity *>(mo);
1022
1023                                 // perfect fit => object found, eraly exit
1024                                 if (overlap >= thresh)
1025                                         return bestFittingObj;                         
1026                         }
1027                }
1028        }
1029
1030        if (0)
1031        {
1032                std::stringstream d;
1033                if (bestFittingObj)
1034                        d << "best fit: " << bestFit;     
1035                else
1036                        d << "warning, objects do not fit\n" << box;
1037       
1038                Ogre::LogManager::getSingleton().logMessage(d.str());
1039        }
1040
1041        return bestFittingObj;
1042}
1043//-----------------------------------------------------------------------
1044void VisibilityOctreeSceneManager::LoadViewCells(string filename)
1045{
1046        // the objects are set to invisible a prioriy
1047        SetObjectsVisible(false);
1048
1049        // identify the corresponding Ogre meshes using the bounding boxes
1050        IdentifyObjects(mObjects);
1051
1052        // load the view cells assigning the found objects to the pvss
1053        mViewCellsManager =
1054                GtpVisibilityPreprocessor::ViewCellsManager::LoadViewCells(filename, &mObjects);
1055
1056        std::stringstream d;
1057        d << "view cells loaded" << endl;
1058        Ogre::LogManager::getSingleton().logMessage(d.str());
1059}
1060//-----------------------------------------------------------------------
1061void VisibilityOctreeSceneManager::IdentifyObjects(GtpVisibilityPreprocessor::ObjectContainer &objects)
1062{
1063        const string bboxesFilename = "boxes.out";
1064
1065        GtpVisibilityPreprocessor::IndexedBoundingBoxContainer iboxes;
1066        mViewCellsManager->LoadBoundingBoxes(bboxesFilename, iboxes);
1067
1068        GtpVisibilityPreprocessor::IndexedBoundingBoxContainer::
1069                const_iterator iit, iit_end = iboxes.end();
1070
1071        for (iit = iboxes.begin(); iit != iit_end; ++ iit)
1072        {
1073                  const GtpVisibilityPreprocessor::AxisAlignedBox3 box = (*iit).second;
1074                  const AxisAlignedBox currentBox = OgreTypeConverter::ConvertToOgre(box);
1075                 
1076                  Entity *ent = FindCorrespondingObject(currentBox);
1077
1078                  // create new mesh instance
1079                  OgreMeshInstance *omi = new OgreMeshInstance(ent);
1080                  omi->SetId((*iit).first);
1081                  objects.push_back(omi);
1082        }
1083}
1084//-------------------------------------------------------------------------
1085void VisibilityOctreeSceneManager::applyViewCellPvs(GtpVisibilityPreprocessor::ViewCell *vc,
1086                                                                                                        const bool load)
1087{       // NOTE: should not happen, rather apply view cell representing unbounded space then
1088        if (!vc)
1089        {       
1090                // set everything visible for savety
1091                SetObjectsVisible(true);
1092
1093                return;
1094        }
1095
1096        GtpVisibilityPreprocessor::ObjectPvsMap::const_iterator oit,
1097                        oit_end = vc->GetPvs().mEntries.end();
1098
1099        //-- PVS of view cell
1100        for (oit = vc->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
1101        {
1102                if (!(*oit).first) continue;
1103
1104                OgreMeshInstance *omi = dynamic_cast<OgreMeshInstance*>((*oit).first);
1105                omi->GetMesh()->setVisible(load);
1106                //GtpVisibilityPreprocessor::Debug << "here45 " << omi->GetId() << endl;
1107        }
1108}
1109//-------------------------------------------------------------------------
1110void VisibilityOctreeSceneManager::updatePvs(Camera *cam)
1111{
1112        if (mViewCellsLoaded && mUseViewCells)
1113        {
1114                const GtpVisibilityPreprocessor::Vector3 viewPoint =
1115                        OgreTypeConverter::ConvertFromOgre(cam->getDerivedPosition());
1116
1117                GtpVisibilityPreprocessor::ViewCell *newElementary =
1118                        mViewCellsManager->GetViewCell(viewPoint);
1119
1120                // elementary view cell did not change => apply same pvs
1121                if (mElementaryViewCell == newElementary)
1122                        return;
1123
1124                mElementaryViewCell = newElementary;
1125
1126                //-- unload old pvs
1127                applyViewCellPvs(mCurrentViewCell, false);
1128
1129
1130                //-- the new view cell
1131               
1132                GtpVisibilityPreprocessor::ViewCell *viewCell;
1133
1134               
1135                if (mUseVisibilityFilter)
1136                {
1137                        //-- compute new filtered cell
1138                        GtpVisibilityPreprocessor::PrVs prvs;
1139                        mViewCellsManager->GetPrVS(viewPoint, prvs);
1140                        viewCell = prvs.mViewCell;
1141                }
1142                else
1143                {
1144                        viewCell = newElementary;
1145                }
1146                       
1147                //-- load new pvs
1148                applyViewCellPvs(viewCell, true);
1149
1150                // store pvs
1151                mCurrentViewCell->SetPvs(viewCell->GetPvs());
1152
1153                // delete merge tree of filtered view cell
1154                if (mUseVisibilityFilter)
1155                        mViewCellsManager->DeleteLocalMergeTree(viewCell);
1156        }
1157}
1158
1159
1160
1161//-----------------------------------------------------------------------
1162const String VisibilityOctreeSceneManagerFactory::FACTORY_TYPE_NAME = "VisibilityOctreeSceneManager";
1163//-----------------------------------------------------------------------
1164void VisibilityOctreeSceneManagerFactory::initMetaData(void) const
1165{
1166        mMetaData.typeName = FACTORY_TYPE_NAME;
1167        mMetaData.description = "Scene manager organising the scene on the basis of an octree with advanced occlusion culling (TM).";
1168        mMetaData.sceneTypeMask = 0xFFFF; // support all types
1169        mMetaData.worldGeometrySupported = false;
1170}
1171//-----------------------------------------------------------------------
1172SceneManager* VisibilityOctreeSceneManagerFactory::createInstance(
1173        const String& instanceName)
1174{
1175        return new VisibilityOctreeSceneManager(instanceName, visManager);
1176}
1177//-----------------------------------------------------------------------
1178void VisibilityOctreeSceneManagerFactory::destroyInstance(SceneManager* instance)
1179{
1180        delete instance;
1181}
1182
1183}  // namespace Ogre
Note: See TracBrowser for help on using the repository browser.