source: trunk/VUT/Ogre/src/OgreVisibilityTerrainSceneManager.cpp @ 137

Revision 137, 19.9 KB checked in by mattausch, 19 years ago (diff)

fixed from camera visibility queries.
deletion of (previously) rendered queue items now before rendering the node (more intuitive)
improved octree implementation (tighter boxes)
added boxes for visibility queries

Line 
1#include "OgreVisibilityTerrainSceneManager.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
12namespace Ogre {
13
14//-----------------------------------------------------------------------
15VisibilityTerrainSceneManager::VisibilityTerrainSceneManager(
16        GtpVisibility::VisibilityManager *visManager):
17mVisibilityManager(visManager),
18mRenderDepthPass(false),
19mShowVisualization(false),
20mRenderNodesForViz(false),
21mRenderNodesContentForViz(false),
22mVisualizeCulledNodes(false),
23mSkipTransparents(false),
24mDelayRenderTransparents(true),
25mUseDepthPass(false),
26mRenderItemBuffer(false),
27mCurrentEntityId(0),
28mEnableDepthWrite(true)
29{
30        mHierarchyInterface = new OctreeHierarchyInterface(this, mDestRenderSystem);
31        mQueryManager = new PlatformQueryManager(mHierarchyInterface, mCurrentViewport);
32
33        mVisibilityManager->SetQueryManager(mQueryManager);
34        //mDisplayNodes = true;
35        //mShowBoundingBoxes = true;
36
37        // TODO: set maxdepth to reasonable value
38        mMaxDepth = 50;
39}
40//-----------------------------------------------------------------------
41void VisibilityTerrainSceneManager::InitDepthPass()
42{
43        MaterialPtr depthMat = MaterialManager::getSingleton().getByName("Visibility/DepthPass");
44
45        if (depthMat.isNull())
46    {
47                // Init
48                depthMat = MaterialManager::getSingleton().create(
49                "Visibility/DepthPass",
50                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
51        mDepthPass = depthMat->getTechnique(0)->getPass(0);
52                mDepthPass->setColourWriteEnabled(false);
53                mDepthPass->setDepthWriteEnabled(true);
54                mDepthPass->setLightingEnabled(false);
55        }
56        else
57        {
58                mDepthPass = depthMat->getTechnique(0)->getPass(0);
59        }
60}
61//-----------------------------------------------------------------------
62void VisibilityTerrainSceneManager::InitItemBufferPass()
63{
64        MaterialPtr itemBufferMat = MaterialManager::getSingleton().
65                getByName("Visibility/ItemBufferPass");
66
67        if (itemBufferMat.isNull())
68    {
69                // Init
70                itemBufferMat = MaterialManager::getSingleton().create("Visibility/ItemBufferPass",
71                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
72
73                mItemBufferPass = itemBufferMat->getTechnique(0)->getPass(0);
74                mItemBufferPass->setColourWriteEnabled(true);
75                mItemBufferPass->setDepthWriteEnabled(true);
76                mItemBufferPass->setLightingEnabled(true);
77        }
78        else
79        {
80                mItemBufferPass = itemBufferMat->getTechnique(0)->getPass(0);
81        }
82        mItemBufferPass->setAmbient(1, 1, 0);
83}
84//-----------------------------------------------------------------------
85VisibilityTerrainSceneManager::~VisibilityTerrainSceneManager()
86{
87        if (mHierarchyInterface)
88        {
89                delete mHierarchyInterface;
90                mHierarchyInterface = NULL;
91        }
92        if (mQueryManager)
93        {
94                delete mQueryManager;
95                mQueryManager = NULL;
96        }
97}
98//-----------------------------------------------------------------------
99void VisibilityTerrainSceneManager::ShowVisualization(Camera *cam)
100{
101        // add player camera for visualization purpose
102        try
103        {
104                Camera *c;
105                if ((c = getCamera("PlayerCam")) != NULL)
106                {
107                        getRenderQueue()->addRenderable(c);
108                }   
109    }
110    catch (...)
111    {
112        // ignore
113    }
114        for (BoxList::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it)
115        {
116                getRenderQueue()->addRenderable(*it);
117        }
118        if (mRenderNodesForViz || mRenderNodesContentForViz)
119        {
120                // change node material so it is better suited for visualization
121                MaterialPtr nodeMat = MaterialManager::getSingleton().getByName("Core/NodeMaterial");
122                nodeMat->setAmbient(1, 1, 0);
123                nodeMat->setLightingEnabled(true);
124                nodeMat->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();
125
126                for (NodeList::iterator it = mVisible.begin(); it != mVisible.end(); ++it)
127                {
128                        if (mRenderNodesForViz)
129                        {
130                                //getRenderQueue()->addRenderable(*it);
131
132                                // addbounding boxes instead of node itself
133                                (*it)->_addBoundingBoxToQueue(getRenderQueue());
134                        }
135                        if (mRenderNodesContentForViz)
136                        {
137                                (*it)->_addToRenderQueue(cam, getRenderQueue(), false);
138                        }
139                }
140        }       
141}
142//-----------------------------------------------------------------------
143Pass *VisibilityTerrainSceneManager::setPass(Pass* pass)
144{
145        //Pass *usedPass = ((mRenderDepthPass && !pass->hasVertexProgram()) ? mDepthPass : pass); // setting vertex program is not efficient
146       
147        // set depth fill pass only if depth write enabled
148        Pass *usedPass = (mRenderDepthPass && !mHierarchyInterface->IsBoundingBoxQuery() ?
149                                          mDepthPass : pass);
150               
151        IlluminationRenderStage savedStage = mIlluminationStage;
152       
153        // set illumination stage to NONE so no shadow material is used
154        // for depth pass or for occlusion query
155        if (mRenderDepthPass || mHierarchyInterface->IsBoundingBoxQuery())
156        {
157                mIlluminationStage = IRS_NONE;
158        }
159       
160        if (mRenderDepthPass)
161        {
162                // --- set vertex program of current pass so z-buffer is updated correctly
163        if (pass->hasVertexProgram())
164                {
165                        mDepthPass->setVertexProgram(pass->getVertexProgramName());
166
167                        if (mDepthPass->hasVertexProgram())
168                        {
169                                const GpuProgramPtr& prg = mDepthPass->getVertexProgram();
170                                // Load this program if not done already
171                                if (!prg->isLoaded())
172                                        prg->load();
173                                // Copy params
174                                mDepthPass->setVertexProgramParameters(pass->getVertexProgramParameters());
175                        }
176                }
177                else if (mDepthPass->hasVertexProgram())
178                {
179                        mDepthPass->setVertexProgram("");
180                }
181        }
182
183        bool IsDepthWrite = usedPass->getDepthWriteEnabled();
184        // global option which enables / disables depth writes
185        if (!mEnableDepthWrite)
186        {
187                usedPass->setDepthWriteEnabled(false);
188        }
189
190        //else if (mIsItemBufferPass) {usedPass = mItemBufferPass;}
191       
192        Pass *result = SceneManager::setPass(usedPass);
193
194        // reset depth write
195        if (!mEnableDepthWrite)
196        {
197                usedPass->setDepthWriteEnabled(IsDepthWrite);
198        }
199
200        // reset illumination stage
201        mIlluminationStage = savedStage;
202
203        return result;
204}
205//-----------------------------------------------------------------------
206void VisibilityTerrainSceneManager::_findVisibleObjects(Camera* cam, bool onlyShadowCasters)
207{
208        // needs full ambient lighting for item colors to be exact
209        /*if (mRenderItemBuffer)
210        {       setAmbientLight(ColourValue(1,1,1,1)); }*/
211       
212        //-- show visible scene nodes and octree bounding boxes from last frame
213        if (mShowVisualization)
214    {
215                ShowVisualization(cam);
216        }
217       
218        //TerrainSceneManager::_findVisibleObjects(cam, onlyShadowCasters);
219       
220        mVisible.clear();
221        mBoxes.clear();
222       
223        // if there is no depth pass =>
224        // we interleave identification and rendering of objects
225        // in _renderVisibibleObjects
226
227        // only shadow casters will be rendered in shadow texture pass
228        mHierarchyInterface->SetOnlyShadowCasters(onlyShadowCasters);
229
230        bool leaveTransparentsInQueue = mDelayRenderTransparents && !mUseDepthPass;
231
232        // possible two cameras (one for culling, one for rendering)
233        mHierarchyInterface->InitFrame(mOctree, cam, //mCameraInProgress,
234                                                mCullCamera ? getCamera("CullCamera") : NULL,
235                                                leaveTransparentsInQueue);
236}
237//-----------------------------------------------------------------------
238void VisibilityTerrainSceneManager::_renderVisibleObjects()
239{
240        // increase terrain renderlevel
241        int renderLevel = TerrainRenderable::getCurrentRenderLevelIndex() + 1;
242
243        if (TerrainRenderable::getCurrentRenderLevelIndex() >= 10)
244        {   // max. 10 different renderlevels
245                renderLevel = 0;
246        }
247
248        // visualization: apply standard rendering
249        if (mShowVisualization)
250        {       
251                TerrainSceneManager::_renderVisibleObjects();
252                TerrainRenderable::setCurrentRenderLevelIndex(renderLevel);
253                return;
254        }
255
256        InitDepthPass();        // create material for depth pass
257        InitItemBufferPass(); // create material for item buffer pass
258
259        //-- hierarchical culling
260        // the objects of different layers (e.g., background, scene,
261        // overlay) must be identified and rendered one after another
262
263        // frame initialisation to reset culling manager stats
264        mVisibilityManager->GetCullingManager()->InitFrame(mVisualizeCulledNodes);
265       
266        mSkipTransparents = false;
267
268        //-- render background, in case there is one
269        clearSpecialCaseRenderQueues();
270        addSpecialCaseRenderQueue(RENDER_QUEUE_BACKGROUND);
271        addSpecialCaseRenderQueue(RENDER_QUEUE_SKIES_EARLY);
272        setSpecialCaseRenderQueueMode(SceneManager::SCRQM_INCLUDE);
273
274        TerrainSceneManager::_renderVisibleObjects();
275
276#ifdef GTP_VISIBILITY_MODIFIED_OGRE
277        _deleteRenderedQueueGroups(false);
278#endif
279
280        //-- render visible objects (i.e., all but overlay and skies late)
281        clearSpecialCaseRenderQueues();
282        addSpecialCaseRenderQueue(RENDER_QUEUE_SKIES_LATE);
283        addSpecialCaseRenderQueue(RENDER_QUEUE_OVERLAY);
284        setSpecialCaseRenderQueueMode(SceneManager::SCRQM_EXCLUDE);
285
286        // transparents are skipped from hierarchical rendering
287        // => they need sorting, thus we render them afterwards
288        mSkipTransparents = mDelayRenderTransparents;
289
290        // set state for depth pass
291    mRenderDepthPass = mUseDepthPass;
292       
293        /**
294          * the hierarchical culling algorithm
295          * for depth pass: will just find objects and update depth buffer
296          * for delayed rendering: will render all but transparents
297        **/
298       
299        mVisibilityManager->ApplyVisibilityCulling();
300
301        // delete remaining renderables from queue (or all but transparents)
302#ifdef GTP_VISIBILITY_MODIFIED_OGRE
303        _deleteRenderedQueueGroups(mSkipTransparents);
304#endif
305
306        // for depth pass: add visible nodes found with the visibility culling
307        if (mUseDepthPass)
308        {
309                for (NodeList::iterator it = mVisible.begin(); it != mVisible.end(); ++it)
310                {
311                        (*it)->_addToRenderQueue(mCameraInProgress, getRenderQueue(), false);
312                }
313                mRenderDepthPass = false;
314        }
315
316        mSkipTransparents = false;
317
318        //-- now we can render all remaining queue objects
319        // for depth pass: all
320        // for delayed rendering: transparents, overlay
321        clearSpecialCaseRenderQueues();
322        TerrainSceneManager::_renderVisibleObjects();
323
324        TerrainRenderable::setCurrentRenderLevelIndex(renderLevel);
325        getRenderQueue()->clear();
326        //WriteLog(); // write out stats
327}
328
329//-----------------------------------------------------------------------
330void VisibilityTerrainSceneManager::_updateSceneGraph(Camera* cam)
331{
332        mVisibilityManager->GetCullingManager()->SetHierarchyInterface(mHierarchyInterface);
333        mHierarchyInterface->SetRenderSystem(mDestRenderSystem);
334
335#ifdef GTP_VISIBILITY_MODIFIED_OGRE
336    mHierarchyInterface->SetNumOctreeNodes(mNumOctreeNodes);
337#endif
338        TerrainSceneManager::_updateSceneGraph(cam);
339}
340//-----------------------------------------------------------------------
341bool VisibilityTerrainSceneManager::setOption(const String & key, const void * val)
342{
343        if (key == "UseDepthPass")
344        {
345                mUseDepthPass = (*static_cast<const bool *>(val));
346                return true;
347        }
348        if (key == "ShowVisualization")
349        {
350                mShowVisualization = (*static_cast<const bool *>(val));
351                return true;
352        }
353        if (key == "RenderNodesForViz")
354        {
355                mRenderNodesForViz = (*static_cast<const bool *>(val));
356                return true;
357        }
358        if (key == "RenderNodesContentForViz")
359        {
360                mRenderNodesContentForViz = (*static_cast<const bool *>(val));
361                return true;
362        }
363        if (key == "SkyBoxEnabled")
364        {
365                mSkyBoxEnabled = (*static_cast<const bool *>(val));
366                return true;
367        }
368        if (key == "SkyPlaneEnabled")
369        {
370                mSkyPlaneEnabled = (*static_cast<const bool *>(val));
371                return true;
372        }
373        if (key == "SkyDomeEnabled")
374        {
375                mSkyDomeEnabled = (*static_cast<const bool *>(val));
376                return true;
377        }
378        if (key == "VisualizeCulledNodes")
379        {
380                mVisualizeCulledNodes = (*static_cast<const bool *>(val));
381                return true;
382        }
383        if (key == "DelayRenderTransparents")
384        {
385                mDelayRenderTransparents = (*static_cast<const bool *>(val));
386                return true;
387        }
388        // notifiy that frame has ended so terrain render level can be reset for correct
389        // terrain rendering
390        if (key == "TerrainLevelIdx")
391        {
392                TerrainRenderable::setCurrentRenderLevelIndex((*static_cast<const int *>(val)));
393                return true;
394        }
395        if (key == "DepthWrite")
396        {
397                mEnableDepthWrite = (*static_cast<const bool *>(val));
398                return true;
399        }
400        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
401                setOption(key, val) || TerrainSceneManager::setOption(key, val);
402}
403//-----------------------------------------------------------------------
404bool VisibilityTerrainSceneManager::getOption(const String & key, void *val)
405{
406        if (key == "NumHierarchyNodes")
407        {
408                * static_cast<unsigned int *>(val) = (unsigned int)mNumOctreeNodes;
409                return true;
410        }
411       
412        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
413                getOption(key, val) && TerrainSceneManager::getOption(key, val);
414}
415//-----------------------------------------------------------------------
416bool VisibilityTerrainSceneManager::getOptionValues(const String & key, StringVector &refValueList)
417{
418        return TerrainSceneManager::getOptionValues( key, refValueList);
419}
420//-----------------------------------------------------------------------
421bool VisibilityTerrainSceneManager::getOptionKeys(StringVector & refKeys)
422{
423        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
424                getOptionKeys(refKeys) || TerrainSceneManager::getOptionKeys(refKeys);
425}
426//-----------------------------------------------------------------------
427void VisibilityTerrainSceneManager::setVisibilityManager(GtpVisibility::VisibilityManager *visManager)
428{
429        mVisibilityManager = visManager;
430}
431//-----------------------------------------------------------------------
432GtpVisibility::VisibilityManager *VisibilityTerrainSceneManager::getVisibilityManager( void )
433{
434        return mVisibilityManager;
435}
436//-----------------------------------------------------------------------
437void VisibilityTerrainSceneManager::WriteLog()
438{
439        std::stringstream d;
440
441        d << "Depth pass: " << StringConverter::toString(mUseDepthPass) << ", "
442          << "Delay transparents: " << StringConverter::toString(mDelayRenderTransparents) << ", "
443          << "Use optimization: " << StringConverter::toString(mHierarchyInterface->GetUseOptimization()) << ", "
444          << "Algorithm type: " << mVisibilityManager->GetCullingManagerType() << ", "
445          << "Hierarchy nodes: " << mNumOctreeNodes << ", "
446          << "Traversed nodes: " << mHierarchyInterface->GetNumTraversedNodes() << ", "
447          << "Rendered nodes: " << mHierarchyInterface->GetNumRenderedNodes() << ", "
448          << "Query culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumQueryCulledNodes() << ", "
449          << "Frustum culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumFrustumCulledNodes() << ", "
450      << "Queries issued: " << mVisibilityManager->GetCullingManager()->GetNumQueriesIssued() << "\n";
451
452        LogManager::getSingleton().logMessage(d.str());
453}
454//-----------------------------------------------------------------------
455void VisibilityTerrainSceneManager::renderObjects(const RenderPriorityGroup::TransparentRenderablePassList& objs,
456            bool doLightIteration, const LightList* manualLightList)
457{
458        // for correct rendering, transparents must be rendered after hierarchical culling
459        if (!mSkipTransparents)
460        {
461                OctreeSceneManager::renderObjects(objs, doLightIteration, manualLightList);
462        }
463}
464//-----------------------------------------------------------------------
465bool VisibilityTerrainSceneManager::validatePassForRendering(Pass* pass)
466{
467        // skip all but first pass if we are doing the depth pass
468        if ((mRenderDepthPass || mRenderItemBuffer) && pass->getIndex() > 0)
469        {
470                return false;
471        }
472        return SceneManager::validatePassForRendering(pass);
473}
474//-----------------------------------------------------------------------
475void VisibilityTerrainSceneManager::renderQueueGroupObjects(RenderQueueGroup* pGroup)
476{
477        if (!mRenderItemBuffer)
478        {
479                TerrainSceneManager::renderQueueGroupObjects(pGroup);
480                return;
481        }
482
483        //--- item buffer
484    // Iterate through priorities
485    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
486
487        while (groupIt.hasMoreElements())
488    {
489                RenderItemBuffer(groupIt.getNext());
490        }
491}
492//-----------------------------------------------------------------------
493void VisibilityTerrainSceneManager::RenderItemBuffer(RenderPriorityGroup* pGroup)
494{
495        // Do solids
496        RenderPriorityGroup::SolidRenderablePassMap solidObjs = pGroup->_getSolidPasses();
497
498        // ----- SOLIDS LOOP -----
499        RenderPriorityGroup::SolidRenderablePassMap::const_iterator ipass, ipassend;
500        ipassend = solidObjs.end();
501
502        for (ipass = solidObjs.begin(); ipass != ipassend; ++ipass)
503        {
504                // Fast bypass if this group is now empty
505                if (ipass->second->empty())
506                        continue;
507
508                // Render only first pass
509                if (ipass->first->getIndex() > 0)
510                        continue;
511
512                RenderPriorityGroup::RenderableList* rendList = ipass->second;
513               
514                RenderPriorityGroup::RenderableList::const_iterator irend, irendend;
515                irendend = rendList->end();
516                       
517                for (irend = rendList->begin(); irend != irendend; ++irend)
518                {
519                        std::stringstream d; d << "itembuffer, pass name: " <<
520                                ipass->first->getParent()->getParent()->getName();
521                                //<< ", renderable name: " << irend->
522
523                        LogManager::getSingleton().logMessage(d.str());
524                       
525                        //if(ipass->first->getParent()->getParent()->getName() == "Examples/Athene")
526                                //<< ", renderable name: " << irend->
527                                RenderSingleObjectForItemBuffer(*irend, ipass->first);
528                                //RenderSingleObjectForOcclusionQuery(
529                }
530        }
531
532        // ----- TRANSPARENT LOOP: must be handled differently
533        // although we don't really     care about transparents for the item buffer
534        // TODO: HOW TO HANDLE OCCLUDED OBJECTS ????
535        RenderPriorityGroup::TransparentRenderablePassList
536                transpObjs = pGroup->_getTransparentPasses();
537        RenderPriorityGroup::TransparentRenderablePassList::const_iterator itrans, itransend;
538
539        itransend = transpObjs.end();
540        for (itrans = transpObjs.begin(); itrans != itransend; ++itrans)
541        {
542                // like for solids, render only first pass
543                if (itrans->pass->getIndex() == 0)
544                {       
545                        RenderSingleObjectForItemBuffer(itrans->renderable, itrans->pass);
546                }
547        }
548}
549//-----------------------------------------------------------------------
550void VisibilityTerrainSceneManager::RenderSingleObjectForItemBuffer(Renderable *rend, Pass *pass)
551{
552        static LightList nullLightList;
553
554        Real col = (Real)rend->getId() / (Real)mCurrentEntityId;
555
556        mItemBufferPass->setAmbient(ColourValue(0, 1, 1));
557        //mItemBufferPass->setDiffuse(ColourValue(0, col, 0));
558//      mItemBufferPass->setSpecular(ColourValue(0, col, 0));
559//      mItemBufferPass->_load();
560
561        // set vertex program of current pass
562        if (pass->hasVertexProgram())
563        {
564                mItemBufferPass->setVertexProgram(pass->getVertexProgramName());
565
566                if (mItemBufferPass->hasVertexProgram())
567                {
568                        const GpuProgramPtr& prg = mItemBufferPass->getVertexProgram();
569                        // Load this program if not done already
570                        if (!prg->isLoaded())
571                                prg->load();
572                        // Copy params
573                        mItemBufferPass->setVertexProgramParameters(pass->getVertexProgramParameters());
574                }
575        }
576        else if (mItemBufferPass->hasVertexProgram())
577        {
578                mItemBufferPass->setVertexProgram("");
579        }
580
581        //LogManager::getSingleton().logMessage("has vertex program");
582        Pass *usedPass = setPass(mItemBufferPass);
583        //Pass *usedPass = setPass(pass);
584        std::stringstream d;
585        d << "item buffer id: " << rend->getId() << ", col: " << col;
586        LogManager::getSingleton().logMessage(d.str());
587
588        // Render a single object, this will set up auto params if required
589        renderSingleObject(rend, usedPass, false, &nullLightList);
590}
591//-----------------------------------------------------------------------
592GtpVisibility::VisibilityManager *VisibilityTerrainSceneManager::GetVisibilityManager()
593{
594        return mVisibilityManager;
595}
596//-----------------------------------------------------------------------
597Entity* VisibilityTerrainSceneManager::createEntity(const String& entityName,
598                                                                                                        const String& meshName)
599{
600        Entity *ent = SceneManager::createEntity(entityName, meshName);
601
602        for (int i = 0; i < (int)ent->getNumSubEntities(); ++i)
603        {
604                ent->getSubEntity(i)->setId(mCurrentEntityId ++);
605        }
606
607        return ent;
608}
609
610} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.