source: trunk/VUT/OcclusionCullingSceneManager/src/OgreOcclusionCullingSceneTraverser.cpp @ 54

Revision 54, 15.0 KB checked in by mattausch, 19 years ago (diff)

fixed terrainscenemanager bug

RevLine 
[32]1#include "OgreOcclusionCullingSceneTraverser.h"
2#include "OgreMath.h"
3#include "OgreIteratorWrappers.h"
4#include "OgreCamera.h"
5#include "OgreHardwareOcclusionQuery.h"
6#include "OgreSolidHalfBoundingBox.h"
7
[33]8
[32]9#include <windows.h>
10
11namespace Ogre {
12       
13        //-----------------------------------------------------------------------
[33]14        OcclusionCullingSceneTraverser::OcclusionCullingSceneTraverser(SceneManager *sm, RenderSystem *rsys):
[32]15        mFrameId(1), mDistanceQueue(NULL), mVisibilityThreshold(0), mCurrentTestIdx(0),
16        mQueryMode(MODE_RENDER), mNumSceneNodes(0), mCurrentAlgorithm(RENDER_COHERENT),
[41]17        mNumQueries(0), mNumTraversedNodes(0), mNumQueryCulledNodes(0), mNumFrustumCulledNodes(0),
[51]18        mNumRenderedNodes(0),mNumRenderedGeometry(0), mSceneManager(sm), mRenderSystem(rsys), mSceneRoot(NULL)
[32]19        {               
20                mHalfBoundingBox[0] = mHalfBoundingBox[1] = 0;
21        }
22        //-----------------------------------------------------------------------
23        OcclusionCullingSceneTraverser::~OcclusionCullingSceneTraverser()
24        {               
25                if(mHalfBoundingBox[0]) delete mHalfBoundingBox[0];
26                if(mHalfBoundingBox[1]) delete mHalfBoundingBox[1];
27
28                deleteQueries();
[42]29
30                if(mDistanceQueue)
31                        delete mDistanceQueue;
[32]32                //SceneManager::~SceneManager();
33        }
34        //-----------------------------------------------------------------------
[42]35        void OcclusionCullingSceneTraverser::renderScene( Camera *cam )
[32]36        {
37                mNumTraversedNodes = 0;
38                mNumQueryCulledNodes = 0;
39                mNumFrustumCulledNodes = 0;
40                mNumRenderedGeometry = 0;
[51]41                mNumRenderedNodes = 0;
42
[32]43                mCurrentTestIdx = 0;
[34]44
[42]45                initDistanceQueue(cam);
46
[32]47                switch(mCurrentAlgorithm)
48                {
49                        case RENDER_CULL_FRUSTUM:
50                                renderCullFrustum(cam);
51                        break;
52                        case RENDER_STOP_AND_WAIT:
53                                renderStopAndWait(cam);
54                                break;
55                        case RENDER_COHERENT:
[51]56                                renderCoherentWithQueue(cam);
[32]57                                break;
58                        default:
59                                renderCullFrustum(cam);
60                                break;
61                }       
[52]62
[32]63                mFrameId ++;
64        }
65        //-----------------------------------------------------------------------
66        void OcclusionCullingSceneTraverser::renderCoherentWithQueue(Camera *cam)
67        {
68                QueryQueue queryQueue;
69
70                //-- PART 1: process finished occlusion queries
71                while(!mDistanceQueue->empty() || !queryQueue.empty())
72                {
73                        while(!queryQueue.empty() &&
74                                  ((queryQueue.front().second)->resultAvailable() || mDistanceQueue->empty()))
75                        {
76                                SceneNode *node = queryQueue.front().first;
77                                HardwareOcclusionQuery *query = queryQueue.front().second;
78
79                                queryQueue.pop();
80                       
81                                // wait until result available
82                                unsigned int visiblePixels;
83                                query->pullOcclusionQuery(&visiblePixels);
84
85                                if(visiblePixels > mVisibilityThreshold)
86                                {
[52]87                                        pullUpVisibility(node);
[32]88                                        traverseNode(cam, node);
89                                }
90                                else
91                                {
92                                        mNumQueryCulledNodes ++;
93                                }
94                        }       
95
96                        //-- PART 2: hierarchical traversal
97                        if(!mDistanceQueue->empty())
98                        {
99                                SceneNode *node = mDistanceQueue->top();
100                                mDistanceQueue->pop();
[41]101                               
[42]102                                bool intersects = false;
[41]103                                //TODO: Isvisible also checked inside scenenode::findvisibleobjects
[42]104                                if(!cam->isVisible(node->_getWorldAABB(), intersects))
[32]105                                {
[41]106                    mNumFrustumCulledNodes ++;
107                                        continue;
108                                }
109
[42]110                                // if intersects near plane => skip occlusion query because wrong results possible
111                                if(intersects)
112                                {
113                                        // update node's visited flag
114                                        node->setLastVisited(mFrameId);
[52]115                                        pullUpVisibility(node);                 
[42]116                                        traverseNode(cam, node);
117
118                                        continue;
119                                }
120
[41]121                                // identify previously visible nodes
122                                bool wasVisible = node->isNodeVisible() && (node->lastVisited() == mFrameId - 1);
[32]123                                       
[41]124                                // identify nodes that we cannot skip queries for
[52]125                                bool mustQuery= !wasVisible || (node->numAttachedObjects() > 0) || isLeaf(node);
[32]126
[41]127                                // reset node's visibility classification
128                                node->setNodeVisible(false);
[32]129
[41]130                                // update node's visited flag
131                                node->setLastVisited(mFrameId);
[32]132                               
[52]133                                // skip testing previously visible interior nodes without geometry
134                                if(mustQuery)
[41]135                                {
136                                        HardwareOcclusionQuery *query = issueOcclusionQuery(&node->_getWorldAABB(), wasVisible);
137                                        queryQueue.push(QueryPair(node, query));
138                                }
[32]139                                       
[41]140                                // always traverse a node if it was visible
141                                if(wasVisible)
142                                {
143                                        traverseNode(cam, node);
[32]144                                }
145                                else
146                                {
147                                        mNumFrustumCulledNodes ++;
148                                }
149                        }
150                }
151        }
152        //-----------------------------------------------------------------------
153        void OcclusionCullingSceneTraverser::renderCullFrustum(Camera *cam)
154        {
155                while(!mDistanceQueue->empty())
156                {
157                        SceneNode *node = mDistanceQueue->top();
158                        mDistanceQueue->pop();
159       
160                        // interesting for visualization purpose
161                        node->setNodeVisible(false);
[40]162
[41]163                        //TODO: IsVisible also checked inside scenenode::_findvisibleobjects
164                        if(!cam->isVisible(node->_getWorldAABB()))
[32]165                        {                       
166                                mNumFrustumCulledNodes ++;
[41]167                                continue;
[32]168                        }
[41]169
170                        // update node's visited flag
171                        node->setLastVisited(mFrameId);
172                        node->setNodeVisible(true);
173                        traverseNode(cam, node);
[32]174                }
175        }       
176        //-----------------------------------------------------------------------
177        void OcclusionCullingSceneTraverser::renderStopAndWait(Camera *cam)
178        {
179                while(!mDistanceQueue->empty())
180                {
181                        SceneNode *node = mDistanceQueue->top();
182                        mDistanceQueue->pop();
183               
184                        // interesting for the visualization
185                        node->setNodeVisible(false);
186                        node->setLastVisited(mFrameId);
187
[42]188                        bool intersects = false;
[41]189                        //TODO: Isvisible also checked inside scenenode::findvisibleobjects
[42]190                        if(!cam->isVisible(node->_getWorldAABB(), intersects))
[32]191                        {
[41]192                                mNumFrustumCulledNodes ++;
193                                continue;
194                        }
195
[42]196                        // if intersects near plane => skip occlusion query because wrong results possible
197                        if(intersects)
198                        {
199                                node->setNodeVisible(true);
200                                traverseNode(cam, node);
201
202                                continue;
203                        }
204
[41]205                        HardwareOcclusionQuery *query = issueOcclusionQuery(&node->_getWorldAABB(), false);
[32]206                               
[41]207                        unsigned int visiblePixels;
208                        // wait if result not available
209                        query->pullOcclusionQuery(&visiblePixels);
[51]210       
[41]211                        // node visible
212                        if(visiblePixels > mVisibilityThreshold)
213                        {
[42]214                                node->setNodeVisible(true);
[41]215                                traverseNode(cam, node);
[32]216                        }
217                        else
218                        {
[41]219                                mNumQueryCulledNodes ++;
[32]220                        }
221                }
222        }
223        //-----------------------------------------------------------------------
[41]224        HardwareOcclusionQuery *OcclusionCullingSceneTraverser::issueOcclusionQuery(
225                AxisAlignedBox *box, bool wasVisible )
[32]226        {
227                // change state so the bounding box gets not actually rendered on the screen
[41]228                // TODO: in rendervisibleobjects, the rendermode is changed by ogre itself => change this!!
[44]229               
[54]230                //setRenderingMode(MODE_QUERY);
231                //mRenderSystem->_setRasterisationMode(SDL_SOLID); setRenderingMode(MODE_RENDER);
[32]232
233                // get next available test id
[42]234                HardwareOcclusionQuery *query = getNextOcclusionQuery();
[41]235
236                //-- the actual query test
[32]237                query->beginOcclusionQuery();
238                               
[41]239                renderBoundingBox(box);
[32]240
241                query->endOcclusionQuery();
[54]242       
243                /*mRenderSystem->_setRasterisationMode(SDL_WIREFRAME);
[52]244                setRenderingMode(MODE_RENDER);
245                renderBoundingBox(box);
[54]246                mRenderSystem->_setRasterisationMode(SDL_SOLID);*/
[52]247               
[32]248                return query;
249        }
250        //-----------------------------------------------------------------------
251        void OcclusionCullingSceneTraverser::setRenderingMode( int mode )
252        {       
253                // avoid unnecessary state changes
[52]254                if(mode != mQueryMode)
255                {
256                        mQueryMode = mode;
[32]257                        bool enabled = (mode == MODE_RENDER);
[52]258                       
259                        //if(mode == MODE_RENDER) return;
260
261                        /*
262                        mRenderSystem->_setRasterisationMode(SDL_SOLID);
263                        mRenderSystem->_setSurfaceParams(ColourValue(0.9, 0.2, 0.2),
264                        ColourValue(0.2, 0.2, 0.2), ColourValue(0.2, 0.2, 0.2),
265                        ColourValue(0, 0, 0), Real(100));
266                        mRenderSystem->_setDepthBufferCheckEnabled(false);
267                        mRenderSystem->_setAlphaRejectSettings(CMPF_ALWAYS_PASS, 255);
268                        */
269
270                mRenderSystem->_setColourBufferWriteEnabled(enabled, enabled, enabled, enabled);
[32]271                        mRenderSystem->_setDepthBufferWriteEnabled(enabled);
[54]272                        //mRenderSystem->setLightingEnabled(enabled);
[52]273                }
[32]274        }
275        //-----------------------------------------------------------------------
276        void OcclusionCullingSceneTraverser::traverseNode( Camera *cam, SceneNode *node )
277        {
278                mNumTraversedNodes ++;
[34]279               
[32]280                if(node->numAttachedObjects() > 0)
281                {
282                        renderSceneNode(cam, node);
283                }
284
285                // internal node: add children to priority queue for further processing
286                Node::ChildNodeIterator it = node->getChildIterator();
287                                       
288                while (it.hasMoreElements())                   
289                {
290                        SceneNode* sceneChild = static_cast<SceneNode*>(it.getNext());
291                        mDistanceQueue->push(sceneChild);
292                }
293        }
294        //-----------------------------------------------------------------------
295        void OcclusionCullingSceneTraverser::renderSceneNode( Camera *cam, SceneNode *node )
296        {
[41]297                //TODO: does not do any changes
[54]298                //setRenderingMode(MODE_RENDER);
[32]299               
[52]300                if(node->lastRendered() != node->lastVisited())
301                {
302                        node->setLastRendered(node->lastVisited());
303                        mNumRenderedNodes ++;
304
305                        mSceneManager->_renderSceneNode(cam, node);
306                }
[32]307        }
308        //-----------------------------------------------------------------------
[42]309/*      void OcclusionCullingSceneTraverser::preprocess( void )
[32]310        {
311                //-- initialise occlusion queries.
312                deleteQueries();
[37]313
[41]314                for(unsigned int i=0; i < mNumQueries; i++)
[32]315                {
316                        mOcclusionQueries.push_back(mRenderSystem->createHardwareOcclusionQuery());
317                }       
[42]318        }*/
[32]319        //-----------------------------------------------------------------------
320        void OcclusionCullingSceneTraverser::setSceneManager( SceneManager *sm )
321        {
322                mSceneManager = sm;
323        }
324        //-----------------------------------------------------------------------
325        void OcclusionCullingSceneTraverser::setRenderSystem( RenderSystem *rsys )
326        {
327                mRenderSystem = rsys;
328        }
329        //-----------------------------------------------------------------------
330        /*unsigned int OcclusionCullingSceneManager::countSceneNodes(SceneNode *node)
331        {
332                unsigned int result = 1;
333               
334                Node::ChildNodeIterator it = node->getChildIterator();
335               
336                while (it.hasMoreElements())
337                {
338                        SceneNode* sceneChild = static_cast<SceneNode*>(it.getNext());
339                        result += countSceneNodes(sceneChild);
340        }
341
342                return result;
343        }*/
344        //-----------------------------------------------------------------------
345        bool OcclusionCullingSceneTraverser::isLeaf( SceneNode *node )
346        {
347                return (node->numChildren() == 0);
348        }
349        //-----------------------------------------------------------------------
[52]350        void OcclusionCullingSceneTraverser::pullUpVisibility(SceneNode *node )
[32]351        {
352                while(node && !node->isNodeVisible())
353                {
354                        node->setNodeVisible(true);
[42]355                        node = node->getParentSceneNode();
[32]356                }
357        }
358        //-----------------------------------------------------------------------
359        void OcclusionCullingSceneTraverser::deleteQueries( void )
360        {
[51]361                for(unsigned int i=0; i < (unsigned int)mOcclusionQueries.size(); ++i)
[32]362                        delete mOcclusionQueries[i];
363
364                mOcclusionQueries.clear();
365        }
366        //-----------------------------------------------------------------------
[41]367        void OcclusionCullingSceneTraverser::renderBoundingBox( AxisAlignedBox *box )
[32]368        {
369                // Render two halfes of the bounding box (using triangle fans)
370                for(int half = 0; half < 2; half ++)
371                {
[51]372                        static Matrix4 xform[256];
373                        //TODO: this should be full bounding box
[41]374                        SolidHalfBoundingBox *halfbox = getSolidHalfBoundingBox(half);
375                        halfbox->setupBoundingBox(*box);
[51]376                       
[54]377                        /*mRenderSystem->_setWorldMatrix(Matrix4::IDENTITY);
[52]378
[54]379                        halfbox->getWorldTransforms(xform);
[51]380
381                        int numMatrices = halfbox->getNumWorldTransforms();
382                        if (numMatrices > 1)
383                        {
384                                mRenderSystem->_setWorldMatrices(xform, numMatrices);
385                        }
386                        else
387                        {
388                                mRenderSystem->_setWorldMatrix(*xform);
389                        }
[54]390                        mRenderSystem->setClipPlanes(halfbox->getClipPlanes());
[51]391
[32]392                        static RenderOperation ro;
[39]393
[41]394                        mSceneManager->useRenderableViewProjMode(halfbox);
395                        halfbox->getRenderOperation(ro);
396                        ro.srcRenderable = halfbox;
[54]397                        mRenderSystem->_render(ro);*/
398                       
399                        mSceneManager->myrenderSingleObject(getSolidHalfBoundingBox(half),
400                                getSolidHalfBoundingBox(half)->getTechnique()->getPass(0), true);
[32]401                }
402        }
403        //-----------------------------------------------------------------------
404        SolidHalfBoundingBox *OcclusionCullingSceneTraverser::getSolidHalfBoundingBox( int half )
405        {
406                if(!mHalfBoundingBox[half])
407                        mHalfBoundingBox[half] = new SolidHalfBoundingBox(half == 1);
408
409                return mHalfBoundingBox[half]; 
410        }
411        //-----------------------------------------------------------------------
[42]412        void OcclusionCullingSceneTraverser::setNumSceneNodes(int num)
413        {
414                mNumSceneNodes = num;
415        }
416        //-----------------------------------------------------------------------
417        /*void OcclusionCullingSceneTraverser::setNumQueries(int num)
418        {
419                mNumQueries = num;
420        }*/
421        //-----------------------------------------------------------------------
422        void OcclusionCullingSceneTraverser::setSceneRoot(SceneNode *root)
423        {
424                mSceneRoot = root;
425        }
426        //-----------------------------------------------------------------------
427        void OcclusionCullingSceneTraverser::initDistanceQueue(Camera *cam)
428        {
429                mDistanceQueue = new PriorityQueue(myless<SceneNode *>(cam));
430                mDistanceQueue->push(mSceneRoot);
431        }
432        //-----------------------------------------------------------------------
433        HardwareOcclusionQuery *OcclusionCullingSceneTraverser::getNextOcclusionQuery(void)
434        {
435                if(mCurrentTestIdx == mOcclusionQueries.size())
436                {
437                        mOcclusionQueries.push_back(mRenderSystem->createHardwareOcclusionQuery());
438                }
439               
440                return mOcclusionQueries[mCurrentTestIdx ++];
441        }
442        //-----------------------------------------------------------------------
[32]443        bool OcclusionCullingSceneTraverser::setOption( const String & key, const void * val )
444        {
445                if ( key == "Algorithm" )
446                {
447                        mCurrentAlgorithm = * static_cast < const int * > ( val );
448                        return true;
449                }
450                if ( key == "Threshold" )
451                {
452                        mVisibilityThreshold = * static_cast < const int * > ( val );
453                        return true;
454                }
455
456                return false;
457        }
458        //-----------------------------------------------------------------------
459        bool OcclusionCullingSceneTraverser::getOption( const String & key, void *val )
460        {
461                if ( key == "Algorithm" )
462                {
463                        * static_cast < int * > ( val ) = mCurrentAlgorithm;
464                        return true;
465                }
466                if ( key == "Threshold" )
467                {
468                        * static_cast < unsigned int * > ( val ) = mVisibilityThreshold;
469                        return true;
470                }
471                if ( key == "NumSceneNodes" )
472                {
473                        * static_cast < unsigned int * > ( val ) = mNumSceneNodes;
474                        return true;
475                }
476                if ( key == "NumTraversedNodes" )
477                {
478                        * static_cast < unsigned int * > ( val ) = mNumTraversedNodes;
479                        return true;
480                }
481                if ( key == "NumQueryCulledNodes" )
482                {
483                        * static_cast < unsigned int * > ( val ) = mNumQueryCulledNodes;
484                        return true;
485                }
486                if ( key == "NumFrustumCulledNodes" )
487                {
488                        * static_cast < unsigned int * > ( val ) = mNumFrustumCulledNodes;
489                        return true;
490                }
[52]491                if ( key == "NumRenderedNodes" )
492                {
493                        * static_cast < unsigned int * > ( val ) = mNumRenderedNodes;
494                        return true;
495                }
[32]496                return false;
497        }
[33]498        //-----------------------------------------------------------------------
499        bool OcclusionCullingSceneTraverser::getOptionKeys( StringVector & refKeys )
500        {
501                refKeys.push_back( "Algorithm" );
502                refKeys.push_back( "Threshold" );
503                refKeys.push_back( "NumSceneNodes" );
504                refKeys.push_back( "NumTraversedNodes" );
505                refKeys.push_back( "NumQueryCulledNodes" );
506                refKeys.push_back( "NumFrustumCulledNodes" );
[52]507                refKeys.push_back( "mNumRenderedGeometry" );
[33]508
509                return true;
510        }
[32]511}       
Note: See TracBrowser for help on using the repository browser.