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

Revision 135, 19.9 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(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.