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

Revision 52, 8.6 KB checked in by mattausch, 19 years ago (diff)
Line 
1#include "OgreOcclusionCullingOctreeSceneTraverser.h"
2#include "OgreOcclusionCullingOctreeSceneManager.h"
3#include "OgreHardwareOcclusionQuery.h"
4
5#include <windows.h>
6
7namespace Ogre {
8        //-----------------------------------------------------------------------
9        OcclusionCullingOctreeSceneTraverser::OcclusionCullingOctreeSceneTraverser(SceneManager *sm, RenderSystem *rsys):
10        OcclusionCullingSceneTraverser(sm, rsys), mOctreeSceneRoot(0), mOctreeDistanceQueue(0)
11        {
12        }
13        //-----------------------------------------------------------------------
14        OcclusionCullingOctreeSceneTraverser::~OcclusionCullingOctreeSceneTraverser()
15        {               
16                if(mOctreeDistanceQueue)
17                        delete mOctreeDistanceQueue;
18        }
19        //-----------------------------------------------------------------------
20        void OcclusionCullingOctreeSceneTraverser::traverseOctant(Camera *cam, Octree *octant)
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];
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
35                        if(nextChild)
36                        {
37                                mOctreeDistanceQueue->push(nextChild);
38                        }
39                }
40        }
41        //-----------------------------------------------------------------------
42        void OcclusionCullingOctreeSceneTraverser::renderCullFrustum(Camera *cam)
43        {
44                AxisAlignedBox box;
45
46                while(!mOctreeDistanceQueue->empty())
47                {
48                        Octree *octant = mOctreeDistanceQueue->top();
49                        mOctreeDistanceQueue->pop();
50       
51                        // interesting for visualization purpose
52                        octant->setOctreeVisible(false);
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. */
70        void OcclusionCullingOctreeSceneTraverser::renderStopAndWait( Camera *cam )
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
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
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);
104                        //      char msg[100]; sprintf(msg, "intersecting\n");
105                        //      OutputDebugString(msg);
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);
115
116                        char msg[100]; sprintf(msg, "visible pixels: %d\n", visiblePixels, intersects);
117                        OutputDebugString(msg);
118
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. */
132        void OcclusionCullingOctreeSceneTraverser::renderCoherentWithQueue( Camera *cam )
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);
151
152                                if(visiblePixels > mVisibilityThreshold)
153                                {
154                                        pullUpVisibility(octant);
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                                {
182                                        // update octant's visited flag
183                                        octant->setLastVisited(mFrameId);
184
185                                        pullUpVisibility(octant);                       
186                                        traverseOctant(cam, octant);
187
188                                        continue;
189                                }
190
191                                // identify previously visible nodes
192                                bool wasVisible = octant->isOctreeVisible() && (octant->lastVisited() == mFrameId - 1);
193                               
194                                /*
195                                char msg[100];
196                                if(wasVisible) sprintf(msg, "yes, was visible, %d\n", mFrameId);
197                                else sprintf(msg, "no was invisible, %d\n", mFrameId);
198                                OutputDebugString(msg);
199                                */
200
201                                // identify nodes that we cannot skip queries for
202                                bool mustQuery = !wasVisible || (octant->numNodes() > 0) || isLeaf(octant);
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
211                                if(mustQuery)
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        //-----------------------------------------------------------------------
226        void OcclusionCullingOctreeSceneTraverser::pullUpVisibility( Octree *octant )
227        {
228                while(octant && !octant->isOctreeVisible())
229                {
230                        octant->setOctreeVisible(true);
231                        octant = octant->getParent();
232                }
233        }
234        //-----------------------------------------------------------------------
235        void OcclusionCullingOctreeSceneTraverser::renderOctant( Camera *cam, Octree *octant )
236        {
237                if(octant->lastRendered() != mFrameId)
238                {
239                        octant->setLastRendered(mFrameId);
240
241                        if(octant->numNodes() == 0) return;
242
243                        //TODO: does nothing useful
244                        setRenderingMode(MODE_RENDER);
245
246                        ((OctreeSceneManager *)mSceneManager)->_renderOctant(cam, octant);
247
248                        mNumRenderedNodes ++;
249                }
250        }
251        //-----------------------------------------------------------------------
252        void OcclusionCullingOctreeSceneTraverser::setSceneRoot( Octree *root )
253        {
254                mOctreeSceneRoot = root;
255        }
256        //-----------------------------------------------------------------------
257        void OcclusionCullingOctreeSceneTraverser::initDistanceQueue( Camera *cam )
258        {
259                if(mOctreeDistanceQueue)
260                        delete mOctreeDistanceQueue;
261
262                mOctreeDistanceQueue = new OctreePriorityQueue(octreeless<Octree *>(cam));
263                mOctreeDistanceQueue->push(mOctreeSceneRoot);
264        }
265        //-----------------------------------------------------------------------
266        bool OcclusionCullingOctreeSceneTraverser::isLeaf(Octree *octant)
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        //-----------------------------------------------------------------------
277        void OcclusionCullingOctreeSceneTraverser::setNumOctreeNodes(unsigned int num)
278        {
279                mNumOctreeNodes = num;
280        }
281        //-----------------------------------------------------------------------
282        bool OcclusionCullingOctreeSceneTraverser::getOption( const String & key, void *val )
283        {
284                if (key == "NumOctreeNodes")
285                {
286                        * static_cast < unsigned int * > ( val ) = mNumOctreeNodes;
287                        return true;
288                }
289
290                return OcclusionCullingSceneTraverser::getOption(key, val);
291        }
292        //-----------------------------------------------------------------------
293        bool OcclusionCullingOctreeSceneTraverser::getOptionKeys( StringVector & refKeys )
294        {
295                refKeys.push_back("NumOctreeNodes");
296               
297                return OcclusionCullingSceneTraverser::getOptionKeys(refKeys);         
298        }
299}       
Note: See TracBrowser for help on using the repository browser.