source: trunk/VUT/OcclusionCullingSceneManager/src/OgreOcclusionCullingTerrainSceneTraverser.cpp @ 42

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