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

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