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

Revision 880, 34.8 KB checked in by mattausch, 18 years ago (diff)

added filter to online stuff (not fully working, too slow
)

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