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

Revision 134, 19.7 KB checked in by mattausch, 19 years ago (diff)

fixed some bugs

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
277#ifdef GTP_VISIBILITY_MODIFIED_OGRE
278        _deleteRenderedQueueGroups(false);
279#endif
280
281        //-- render visible objects (i.e., all but overlay and skies late)
282        clearSpecialCaseRenderQueues();
283        addSpecialCaseRenderQueue(RENDER_QUEUE_SKIES_LATE);
284        addSpecialCaseRenderQueue(RENDER_QUEUE_OVERLAY);
285        setSpecialCaseRenderQueueMode(SceneManager::SCRQM_EXCLUDE);
286
287        // transparents are skipped from hierarchical rendering
288        // => they need sorting, thus we render them afterwards
289        mSkipTransparents = mDelayRenderTransparents;
290
291        // set state for depth pass
292    mRenderDepthPass = mUseDepthPass;
293       
294        /**
295          * the hierarchical culling algorithm
296          * for depth pass: will just find objects and update depth buffer
297          * for delayed rendering: will render all but transparents
298        **/
299       
300        mVisibilityManager->ApplyVisibilityCulling();
301
302
303        // for depth pass: add visible nodes found with the visibility culling
304        if (mUseDepthPass)
305        {
306                for (NodeList::iterator it = mVisible.begin(); it != mVisible.end(); ++it)
307                {
308                        (*it)->_addToRenderQueue(mCameraInProgress, getRenderQueue(), false);
309                }
310                mRenderDepthPass = false;
311        }
312
313        mSkipTransparents = false;
314
315        //-- now we can render all remaining queue objects
316        // for depth pass: all
317        // for delayed rendering: transparents, overlay
318        clearSpecialCaseRenderQueues();
319        TerrainSceneManager::_renderVisibleObjects();
320
321        TerrainRenderable::setCurrentRenderLevelIndex(renderLevel);
322        //WriteLog(); // write out stats
323}
324
325//-----------------------------------------------------------------------
326void VisibilityTerrainSceneManager::_updateSceneGraph(Camera* cam)
327{
328        mVisibilityManager->GetCullingManager()->SetHierarchyInterface(mHierarchyInterface);
329        mHierarchyInterface->SetRenderSystem(mDestRenderSystem);
330
331#ifdef GTP_VISIBILITY_MODIFIED_OGRE
332    mHierarchyInterface->SetNumOctreeNodes(mNumOctreeNodes);
333#endif
334        TerrainSceneManager::_updateSceneGraph(cam);
335}
336//-----------------------------------------------------------------------
337bool VisibilityTerrainSceneManager::setOption(const String & key, const void * val)
338{
339        if (key == "UseDepthPass")
340        {
341                mUseDepthPass = (*static_cast<const bool *>(val));
342                return true;
343        }
344        if (key == "ShowVisualization")
345        {
346                mShowVisualization = (*static_cast<const bool *>(val));
347                return true;
348        }
349        if (key == "RenderNodesForViz")
350        {
351                mRenderNodesForViz = (*static_cast<const bool *>(val));
352                return true;
353        }
354        if (key == "RenderNodesContentForViz")
355        {
356                mRenderNodesContentForViz = (*static_cast<const bool *>(val));
357                return true;
358        }
359        if (key == "SkyBoxEnabled")
360        {
361                mSkyBoxEnabled = (*static_cast<const bool *>(val));
362                return true;
363        }
364        if (key == "SkyPlaneEnabled")
365        {
366                mSkyPlaneEnabled = (*static_cast<const bool *>(val));
367                return true;
368        }
369        if (key == "SkyDomeEnabled")
370        {
371                mSkyDomeEnabled = (*static_cast<const bool *>(val));
372                return true;
373        }
374        if (key == "VisualizeCulledNodes")
375        {
376                mVisualizeCulledNodes = (*static_cast<const bool *>(val));
377                return true;
378        }
379        if (key == "DelayRenderTransparents")
380        {
381                mDelayRenderTransparents = (*static_cast<const bool *>(val));
382                return true;
383        }
384        // notifiy that frame has ended so terrain render level can be reset for correct
385        // terrain rendering
386        if (key == "TerrainLevelIdx")
387        {
388                TerrainRenderable::setCurrentRenderLevelIndex((*static_cast<const int *>(val)));
389                return true;
390        }
391        if (key == "DepthWrite")
392        {
393                mEnableDepthWrite = (*static_cast<const bool *>(val));
394                return true;
395        }
396        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
397                setOption(key, val) || TerrainSceneManager::setOption(key, val);
398}
399//-----------------------------------------------------------------------
400bool VisibilityTerrainSceneManager::getOption(const String & key, void *val)
401{
402        if (key == "NumHierarchyNodes")
403        {
404                * static_cast<unsigned int *>(val) = (unsigned int)mNumOctreeNodes;
405                return true;
406        }
407       
408        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
409                getOption(key, val) && TerrainSceneManager::getOption(key, val);
410}
411//-----------------------------------------------------------------------
412bool VisibilityTerrainSceneManager::getOptionValues(const String & key, StringVector &refValueList)
413{
414        return TerrainSceneManager::getOptionValues( key, refValueList);
415}
416//-----------------------------------------------------------------------
417bool VisibilityTerrainSceneManager::getOptionKeys(StringVector & refKeys)
418{
419        return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
420                getOptionKeys(refKeys) || TerrainSceneManager::getOptionKeys(refKeys);
421}
422//-----------------------------------------------------------------------
423void VisibilityTerrainSceneManager::setVisibilityManager(GtpVisibility::VisibilityManager *visManager)
424{
425        mVisibilityManager = visManager;
426}
427//-----------------------------------------------------------------------
428GtpVisibility::VisibilityManager *VisibilityTerrainSceneManager::getVisibilityManager( void )
429{
430        return mVisibilityManager;
431}
432//-----------------------------------------------------------------------
433void VisibilityTerrainSceneManager::WriteLog()
434{
435        std::stringstream d;
436
437        d << "Depth pass: " << StringConverter::toString(mUseDepthPass) << ", "
438          << "Delay transparents: " << StringConverter::toString(mDelayRenderTransparents) << ", "
439          << "Use optimization: " << StringConverter::toString(mHierarchyInterface->GetUseOptimization()) << ", "
440          << "Algorithm type: " << mVisibilityManager->GetCullingManagerType() << ", "
441          << "Hierarchy nodes: " << mNumOctreeNodes << ", "
442          << "Traversed nodes: " << mHierarchyInterface->GetNumTraversedNodes() << ", "
443          << "Rendered nodes: " << mHierarchyInterface->GetNumRenderedNodes() << ", "
444          << "Query culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumQueryCulledNodes() << ", "
445          << "Frustum culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumFrustumCulledNodes() << ", "
446      << "Queries issued: " << mVisibilityManager->GetCullingManager()->GetNumQueriesIssued() << "\n";
447
448        LogManager::getSingleton().logMessage(d.str());
449}
450//-----------------------------------------------------------------------
451void VisibilityTerrainSceneManager::renderObjects(const RenderPriorityGroup::TransparentRenderablePassList& objs,
452            bool doLightIteration, const LightList* manualLightList)
453{
454        // for correct rendering, transparents must be rendered after hierarchical culling
455        if (!mSkipTransparents)
456        {
457                OctreeSceneManager::renderObjects(objs, doLightIteration, manualLightList);
458        }
459}
460//-----------------------------------------------------------------------
461bool VisibilityTerrainSceneManager::validatePassForRendering(Pass* pass)
462{
463        // skip all but first pass if we are doing the depth pass
464        if ((mRenderDepthPass || mRenderItemBuffer) && pass->getIndex() > 0)
465        {
466                return false;
467        }
468        return SceneManager::validatePassForRendering(pass);
469}
470//-----------------------------------------------------------------------
471void VisibilityTerrainSceneManager::renderQueueGroupObjects(RenderQueueGroup* pGroup)
472{
473        if (!mRenderItemBuffer)
474        {
475                TerrainSceneManager::renderQueueGroupObjects(pGroup);
476                return;
477        }
478
479        //--- item buffer
480    // Iterate through priorities
481    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
482
483        while (groupIt.hasMoreElements())
484    {
485                RenderItemBuffer(groupIt.getNext());
486        }
487}
488//-----------------------------------------------------------------------
489void VisibilityTerrainSceneManager::RenderItemBuffer(RenderPriorityGroup* pGroup)
490{
491        // Do solids
492        RenderPriorityGroup::SolidRenderablePassMap solidObjs = pGroup->_getSolidPasses();
493
494        // ----- SOLIDS LOOP -----
495        RenderPriorityGroup::SolidRenderablePassMap::const_iterator ipass, ipassend;
496        ipassend = solidObjs.end();
497
498        for (ipass = solidObjs.begin(); ipass != ipassend; ++ipass)
499        {
500                // Fast bypass if this group is now empty
501                if (ipass->second->empty())
502                        continue;
503
504                // Render only first pass
505                if (ipass->first->getIndex() > 0)
506                        continue;
507
508                RenderPriorityGroup::RenderableList* rendList = ipass->second;
509               
510                RenderPriorityGroup::RenderableList::const_iterator irend, irendend;
511                irendend = rendList->end();
512                       
513                for (irend = rendList->begin(); irend != irendend; ++irend)
514                {
515                        std::stringstream d; d << "itembuffer, pass name: " <<
516                                ipass->first->getParent()->getParent()->getName();
517                                //<< ", renderable name: " << irend->
518
519                        LogManager::getSingleton().logMessage(d.str());
520                       
521                        //if(ipass->first->getParent()->getParent()->getName() == "Examples/Athene")
522                                //<< ", renderable name: " << irend->
523                                RenderSingleObjectForItemBuffer(*irend, ipass->first);
524                                //RenderSingleObjectForOcclusionQuery(
525                }
526        }
527
528        // ----- TRANSPARENT LOOP: must be handled differently
529        // although we don't really     care about transparents for the item buffer
530        // TODO: HOW TO HANDLE OCCLUDED OBJECTS ????
531        RenderPriorityGroup::TransparentRenderablePassList
532                transpObjs = pGroup->_getTransparentPasses();
533        RenderPriorityGroup::TransparentRenderablePassList::const_iterator itrans, itransend;
534
535        itransend = transpObjs.end();
536        for (itrans = transpObjs.begin(); itrans != itransend; ++itrans)
537        {
538                // like for solids, render only first pass
539                if (itrans->pass->getIndex() == 0)
540                {       
541                        RenderSingleObjectForItemBuffer(itrans->renderable, itrans->pass);
542                }
543        }
544}
545//-----------------------------------------------------------------------
546void VisibilityTerrainSceneManager::RenderSingleObjectForItemBuffer(Renderable *rend, Pass *pass)
547{
548        static LightList nullLightList;
549
550        Real col = (Real)rend->getId() / (Real)mCurrentEntityId;
551
552        mItemBufferPass->setAmbient(ColourValue(0, 1, 1));
553        //mItemBufferPass->setDiffuse(ColourValue(0, col, 0));
554//      mItemBufferPass->setSpecular(ColourValue(0, col, 0));
555//      mItemBufferPass->_load();
556
557        // set vertex program of current pass
558        if (pass->hasVertexProgram())
559        {
560                mItemBufferPass->setVertexProgram(pass->getVertexProgramName());
561
562                if (mItemBufferPass->hasVertexProgram())
563                {
564                        const GpuProgramPtr& prg = mItemBufferPass->getVertexProgram();
565                        // Load this program if not done already
566                        if (!prg->isLoaded())
567                                prg->load();
568                        // Copy params
569                        mItemBufferPass->setVertexProgramParameters(pass->getVertexProgramParameters());
570                }
571        }
572        else if (mItemBufferPass->hasVertexProgram())
573        {
574                mItemBufferPass->setVertexProgram("");
575        }
576
577        //LogManager::getSingleton().logMessage("has vertex program");
578        Pass *usedPass = setPass(mItemBufferPass);
579        //Pass *usedPass = setPass(pass);
580        std::stringstream d;
581        d << "item buffer id: " << rend->getId() << ", col: " << col;
582        LogManager::getSingleton().logMessage(d.str());
583
584        // Render a single object, this will set up auto params if required
585        renderSingleObject(rend, usedPass, false, &nullLightList);
586}
587//-----------------------------------------------------------------------
588GtpVisibility::VisibilityManager *VisibilityTerrainSceneManager::GetVisibilityManager()
589{
590        return mVisibilityManager;
591}
592//-----------------------------------------------------------------------
593Entity* VisibilityTerrainSceneManager::createEntity(const String& entityName,
594                                                                                                        const String& meshName)
595{
596        Entity *ent = SceneManager::createEntity(entityName, meshName);
597
598        for (int i = 0; i < (int)ent->getNumSubEntities(); ++i)
599        {
600                ent->getSubEntity(i)->setId(mCurrentEntityId ++);
601        }
602
603        return ent;
604}
605
606} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.