source: trunk/VUT/obsolete/OcclusionCullingSceneManager/src/OgreOcclusionCullingOctreeSceneTraverser.cpp @ 55

Revision 55, 8.1 KB checked in by mattausch, 19 years ago (diff)

added TerrainContentGenerator?

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                                mNumQueryCulledNodes ++;
117                        }
118                }
119        }
120        //-----------------------------------------------------------------------
121        /** Renders the scene with the coherent hierarchical algorithm and the query queye. */
122        void OcclusionCullingOctreeSceneTraverser::renderCoherentWithQueue( Camera *cam )
123        {
124                OctreeQueryQueue queryQueue;
125                AxisAlignedBox box;
126
127                //-- PART 1: process finished occlusion queries
128                while(!mOctreeDistanceQueue->empty() || !queryQueue.empty())
129                {
130                        while(!queryQueue.empty() &&
131                                  ((queryQueue.front().second)->resultAvailable() || mOctreeDistanceQueue->empty()))
132                        {
133                                Octree *octant = queryQueue.front().first;
134                                HardwareOcclusionQuery *query = queryQueue.front().second;
135
136                                queryQueue.pop();
137                       
138                                // wait until result available
139                                unsigned int visiblePixels;
140                                query->pullOcclusionQuery(&visiblePixels);
141
142                                if(visiblePixels > mVisibilityThreshold)
143                                {
144                                        pullUpVisibility(octant);
145                                        traverseOctant(cam, octant);
146                                }
147                                else
148                                {
149                                        mNumQueryCulledNodes ++;
150                                }
151                        }       
152
153                        //-- PART 2: hierarchical traversal
154                        if(!mOctreeDistanceQueue->empty())
155                        {
156                                Octree *octant = mOctreeDistanceQueue->top();
157                                mOctreeDistanceQueue->pop();
158                                       
159                                octant->_getCullBounds(&box);
160
161                                bool intersects = false;
162                                //TODO: Isvisible also checked inside scenenode::findvisibleobjects
163                                if(!cam->isVisible(box, intersects))
164                                {
165                    mNumFrustumCulledNodes ++;
166                                        continue;
167                                }
168
169                                // if intersects near plane => skip occlusion query because wrong results possible
170                                if(intersects)
171                                {
172                                        // update octant's visited flag
173                                        octant->setLastVisited(mFrameId);
174
175                                        pullUpVisibility(octant);                       
176                                        traverseOctant(cam, octant);
177
178                                        continue;
179                                }
180
181                                // identify previously visible nodes
182                                bool wasVisible = octant->isOctreeVisible() && (octant->lastVisited() == mFrameId - 1);
183                               
184                                // identify nodes that we cannot skip queries for
185                                bool mustQuery = !wasVisible || (octant->numNodes() > 0) || isLeaf(octant);
186
187                                // reset node's visibility classification
188                                octant->setOctreeVisible(false);
189
190                                // update node's visited flag
191                                octant->setLastVisited(mFrameId);
192                       
193                                // skip testing previously visible interior nodes
194                                if(mustQuery)
195                                {
196                                        HardwareOcclusionQuery *query = issueOcclusionQuery(&box, wasVisible);
197                                        queryQueue.push(OctreeQueryPair(octant, query));
198                                }
199                                       
200                                // always traverse a node if it was visible
201                                if(wasVisible)
202                                {
203                                        traverseOctant(cam, octant);
204                                }
205                        }
206                }
207        }
208        //-----------------------------------------------------------------------
209        void OcclusionCullingOctreeSceneTraverser::pullUpVisibility( Octree *octant )
210        {
211                while(octant && !octant->isOctreeVisible())
212                {
213                        octant->setOctreeVisible(true);
214                        octant = octant->getParent();
215                }
216        }
217        //-----------------------------------------------------------------------
218        void OcclusionCullingOctreeSceneTraverser::renderOctant( Camera *cam, Octree *octant )
219        {
220                if(octant->lastRendered() != mFrameId)
221                {
222                        octant->setLastRendered(mFrameId);
223
224                        if(octant->numNodes() == 0) return;
225
226                        //TODO: does nothing useful
227                        //setRenderingMode(MODE_RENDER);
228
229                        ((OctreeSceneManager *)mSceneManager)->_renderOctant(cam, octant);
230
231                        mNumRenderedNodes ++;
232                }
233        }
234        //-----------------------------------------------------------------------
235        void OcclusionCullingOctreeSceneTraverser::setSceneRoot( Octree *root )
236        {
237                mOctreeSceneRoot = root;
238        }
239        //-----------------------------------------------------------------------
240        void OcclusionCullingOctreeSceneTraverser::initDistanceQueue( Camera *cam )
241        {
242                if(mOctreeDistanceQueue)
243                        delete mOctreeDistanceQueue;
244
245                mOctreeDistanceQueue = new OctreePriorityQueue(octreeless<Octree *>(cam));
246                mOctreeDistanceQueue->push(mOctreeSceneRoot);
247        }
248        //-----------------------------------------------------------------------
249        bool OcclusionCullingOctreeSceneTraverser::isLeaf(Octree *octant)
250        {
251                for(int i=0; i<8; i++)
252                {
253                        if(octant->mChildren[(i & 4) >> 2][(i & 2) >> 1][i & 1])
254                                return false;
255                }
256
257                return true;
258        }
259        //-----------------------------------------------------------------------
260        void OcclusionCullingOctreeSceneTraverser::setNumOctreeNodes(unsigned int num)
261        {
262                mNumOctreeNodes = num;
263        }
264        //-----------------------------------------------------------------------
265        bool OcclusionCullingOctreeSceneTraverser::getOption( const String & key, void *val )
266        {
267                if (key == "NumOctreeNodes")
268                {
269                        * static_cast < unsigned int * > ( val ) = mNumOctreeNodes;
270                        return true;
271                }
272
273                return OcclusionCullingSceneTraverser::getOption(key, val);
274        }
275        //-----------------------------------------------------------------------
276        bool OcclusionCullingOctreeSceneTraverser::getOptionKeys( StringVector & refKeys )
277        {
278                refKeys.push_back("NumOctreeNodes");
279               
280                return OcclusionCullingSceneTraverser::getOptionKeys(refKeys);         
281        }
282}       
Note: See TracBrowser for help on using the repository browser.