source: trunk/VUT/OcclusionCullingSceneManager/src/OgreOcclusionCullingOctreeSceneTraverser.cpp @ 52

Revision 52, 8.6 KB checked in by mattausch, 19 years ago (diff)
RevLine 
[45]1#include "OgreOcclusionCullingOctreeSceneTraverser.h"
[48]2#include "OgreOcclusionCullingOctreeSceneManager.h"
[45]3#include "OgreHardwareOcclusionQuery.h"
4
5#include <windows.h>
6
7namespace Ogre {
8        //-----------------------------------------------------------------------
[48]9        OcclusionCullingOctreeSceneTraverser::OcclusionCullingOctreeSceneTraverser(SceneManager *sm, RenderSystem *rsys):
[45]10        OcclusionCullingSceneTraverser(sm, rsys), mOctreeSceneRoot(0), mOctreeDistanceQueue(0)
11        {
12        }
13        //-----------------------------------------------------------------------
[48]14        OcclusionCullingOctreeSceneTraverser::~OcclusionCullingOctreeSceneTraverser()
[45]15        {               
16                if(mOctreeDistanceQueue)
17                        delete mOctreeDistanceQueue;
18        }
19        //-----------------------------------------------------------------------
[52]20        void OcclusionCullingOctreeSceneTraverser::traverseOctant(Camera *cam, Octree *octant)
[45]21        {
22                mNumTraversedNodes ++;
23       
24                // if we come across some renderable geometry => render it
25                renderOctant(cam, octant);
26               
27                for(int i=0; i<8; i++)
28                {
29                        Octree *nextChild = octant->mChildren[(i & 4) >> 2][(i & 2) >> 1][i & 1];
[51]30
31                        /*char msg[100];
32                        sprintf(msg, "node number: %d %d %d\n", (i & 4) >> 2, (i & 2) >> 1, i & 1);
33                        OutputDebugString(msg);*/
34
[45]35                        if(nextChild)
[52]36                        {
[45]37                                mOctreeDistanceQueue->push(nextChild);
[52]38                        }
[45]39                }
40        }
41        //-----------------------------------------------------------------------
[48]42        void OcclusionCullingOctreeSceneTraverser::renderCullFrustum(Camera *cam)
[45]43        {
44                AxisAlignedBox box;
45
46                while(!mOctreeDistanceQueue->empty())
47                {
48                        Octree *octant = mOctreeDistanceQueue->top();
49                        mOctreeDistanceQueue->pop();
50       
51                        // interesting for visualization purpose
[51]52                        octant->setOctreeVisible(false);
[45]53                        octant->_getCullBounds(&box);
54                       
55                        if(!cam->isVisible(box))
56                        {
57                                mNumFrustumCulledNodes ++;
58                                continue;
59                        }
60
61                        // update node's visited flag
62                        octant->setLastVisited(mFrameId);
63                        octant->setOctreeVisible(true);
64               
65                        traverseOctant(cam, octant);
66                }
67        }       
68        //-----------------------------------------------------------------------
69        /** Renders the scene with the hierarchical stop and wait algorithm. */
[48]70        void OcclusionCullingOctreeSceneTraverser::renderStopAndWait( Camera *cam )
[45]71        {
72                AxisAlignedBox box;
73
74                while(!mOctreeDistanceQueue->empty())
75                {
76                        Octree *octant = mOctreeDistanceQueue->top();
77                        mOctreeDistanceQueue->pop();
78               
79                        // interesting for visualization purpose
80                        octant->setOctreeVisible(false);
81                        octant->setLastVisited(mFrameId);
82
83                        //TODO: Isvisible also checked inside scenenode::findvisibleobjects
84                        octant->_getCullBounds(&box);
85
86                        bool intersects = false;
87
[52]88                        /*char msg2[100];
89                        Vector3 min = box.getMinimum();
90                        Vector3 max = box.getMaximum();
91
92                        sprintf(msg2, "culling box: %3.3f %3.3f %3.3f %3.3f %3.3f %3.3f\n", min.x, min.y, min.z, max.x, max.y, max.z);
93                        OutputDebugString(msg2);*/
94
[45]95                        if(!cam->isVisible(box, intersects))
96                        {
97                                mNumFrustumCulledNodes ++;
98                                continue;
99                        }
100                        //if intersects near plane => skip occlusion query because wrong results possible
101                        if(intersects)
102                        {
103                                octant->setOctreeVisible(true);
[52]104                        //      char msg[100]; sprintf(msg, "intersecting\n");
105                        //      OutputDebugString(msg);
[45]106                                traverseOctant(cam, octant);
107                                continue;
108                        }
109
110                        HardwareOcclusionQuery *query = issueOcclusionQuery(&box, false);
111                               
112                        unsigned int visiblePixels;
113                        // wait if result not available
114                        query->pullOcclusionQuery(&visiblePixels);
[52]115
116                        char msg[100]; sprintf(msg, "visible pixels: %d\n", visiblePixels, intersects);
117                        OutputDebugString(msg);
118
[45]119                        // node visible
120                        if(visiblePixels > mVisibilityThreshold)
121                        {
122                                traverseOctant(cam, octant);
123                        }
124                        else
125                        {
126                                mNumQueryCulledNodes ++;
127                        }
128                }
129        }
130        //-----------------------------------------------------------------------
131        /** Renders the scene with the coherent hierarchical algorithm and the query queye. */
[48]132        void OcclusionCullingOctreeSceneTraverser::renderCoherentWithQueue( Camera *cam )
[45]133        {
134                OctreeQueryQueue queryQueue;
135                AxisAlignedBox box;
136
137                //-- PART 1: process finished occlusion queries
138                while(!mOctreeDistanceQueue->empty() || !queryQueue.empty())
139                {
140                        while(!queryQueue.empty() &&
141                                  ((queryQueue.front().second)->resultAvailable() || mOctreeDistanceQueue->empty()))
142                        {
143                                Octree *octant = queryQueue.front().first;
144                                HardwareOcclusionQuery *query = queryQueue.front().second;
145
146                                queryQueue.pop();
147                       
148                                // wait until result available
149                                unsigned int visiblePixels;
150                                query->pullOcclusionQuery(&visiblePixels);
[52]151
[45]152                                if(visiblePixels > mVisibilityThreshold)
153                                {
[52]154                                        pullUpVisibility(octant);
[45]155                                        traverseOctant(cam, octant);
156                                }
157                                else
158                                {
159                                        mNumQueryCulledNodes ++;
160                                }
161                        }       
162
163                        //-- PART 2: hierarchical traversal
164                        if(!mOctreeDistanceQueue->empty())
165                        {
166                                Octree *octant = mOctreeDistanceQueue->top();
167                                mOctreeDistanceQueue->pop();
168                                       
169                                octant->_getCullBounds(&box);
170
171                                bool intersects = false;
172                                //TODO: Isvisible also checked inside scenenode::findvisibleobjects
173                                if(!cam->isVisible(box, intersects))
174                                {
175                    mNumFrustumCulledNodes ++;
176                                        continue;
177                                }
178
179                                // if intersects near plane => skip occlusion query because wrong results possible
180                                if(intersects)
181                                {
[51]182                                        // update octant's visited flag
[45]183                                        octant->setLastVisited(mFrameId);
[52]184
185                                        pullUpVisibility(octant);                       
[45]186                                        traverseOctant(cam, octant);
187
188                                        continue;
189                                }
190
191                                // identify previously visible nodes
192                                bool wasVisible = octant->isOctreeVisible() && (octant->lastVisited() == mFrameId - 1);
[51]193                               
[52]194                                /*
195                                char msg[100];
[51]196                                if(wasVisible) sprintf(msg, "yes, was visible, %d\n", mFrameId);
197                                else sprintf(msg, "no was invisible, %d\n", mFrameId);
[52]198                                OutputDebugString(msg);
199                                */
[51]200
[45]201                                // identify nodes that we cannot skip queries for
[52]202                                bool mustQuery = !wasVisible || (octant->numNodes() > 0) || isLeaf(octant);
[45]203
204                                // reset node's visibility classification
205                                octant->setOctreeVisible(false);
206
207                                // update node's visited flag
208                                octant->setLastVisited(mFrameId);
209                       
210                                // skip testing previously visible interior nodes
[52]211                                if(mustQuery)
[45]212                                {
213                                        HardwareOcclusionQuery *query = issueOcclusionQuery(&box, wasVisible);
214                                        queryQueue.push(OctreeQueryPair(octant, query));
215                                }
216                                       
217                                // always traverse a node if it was visible
218                                if(wasVisible)
219                                {
220                                        traverseOctant(cam, octant);
221                                }
222                        }
223                }
224        }
225        //-----------------------------------------------------------------------
[52]226        void OcclusionCullingOctreeSceneTraverser::pullUpVisibility( Octree *octant )
[45]227        {
228                while(octant && !octant->isOctreeVisible())
229                {
230                        octant->setOctreeVisible(true);
231                        octant = octant->getParent();
232                }
233        }
234        //-----------------------------------------------------------------------
[48]235        void OcclusionCullingOctreeSceneTraverser::renderOctant( Camera *cam, Octree *octant )
[45]236        {
[52]237                if(octant->lastRendered() != mFrameId)
[45]238                {
[52]239                        octant->setLastRendered(mFrameId);
240
241                        if(octant->numNodes() == 0) return;
242
[51]243                        //TODO: does nothing useful
244                        setRenderingMode(MODE_RENDER);
[45]245
[51]246                        ((OctreeSceneManager *)mSceneManager)->_renderOctant(cam, octant);
[52]247
248                        mNumRenderedNodes ++;
[45]249                }
250        }
251        //-----------------------------------------------------------------------
[52]252        void OcclusionCullingOctreeSceneTraverser::setSceneRoot( Octree *root )
[45]253        {
254                mOctreeSceneRoot = root;
255        }
256        //-----------------------------------------------------------------------
[52]257        void OcclusionCullingOctreeSceneTraverser::initDistanceQueue( Camera *cam )
[45]258        {
259                if(mOctreeDistanceQueue)
260                        delete mOctreeDistanceQueue;
261
262                mOctreeDistanceQueue = new OctreePriorityQueue(octreeless<Octree *>(cam));
263                mOctreeDistanceQueue->push(mOctreeSceneRoot);
264        }
265        //-----------------------------------------------------------------------
[48]266        bool OcclusionCullingOctreeSceneTraverser::isLeaf(Octree *octant)
[45]267        {
268                for(int i=0; i<8; i++)
269                {
270                        if(octant->mChildren[(i & 4) >> 2][(i & 2) >> 1][i & 1])
271                                return false;
272                }
273
274                return true;
275        }
276        //-----------------------------------------------------------------------
[48]277        void OcclusionCullingOctreeSceneTraverser::setNumOctreeNodes(unsigned int num)
[45]278        {
279                mNumOctreeNodes = num;
280        }
281        //-----------------------------------------------------------------------
[48]282        bool OcclusionCullingOctreeSceneTraverser::getOption( const String & key, void *val )
[45]283        {
[52]284                if (key == "NumOctreeNodes")
[45]285                {
286                        * static_cast < unsigned int * > ( val ) = mNumOctreeNodes;
287                        return true;
288                }
289
290                return OcclusionCullingSceneTraverser::getOption(key, val);
291        }
292        //-----------------------------------------------------------------------
[48]293        bool OcclusionCullingOctreeSceneTraverser::getOptionKeys( StringVector & refKeys )
[45]294        {
[52]295                refKeys.push_back("NumOctreeNodes");
[45]296               
297                return OcclusionCullingSceneTraverser::getOptionKeys(refKeys);         
298        }
299}       
Note: See TracBrowser for help on using the repository browser.