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

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