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

Revision 59, 14.9 KB checked in by mattausch, 19 years ago (diff)

completely changed file structure plus software design

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