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

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

fixed terrainscenemanager bug

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