source: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreOcclusionCullingSceneManager.cpp @ 897

Revision 897, 30.9 KB checked in by mattausch, 18 years ago (diff)

updated to ogre 1.2

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