source: trunk/VUT/Ogre/src/OgreOcclusionQueriesQueryManager.cpp @ 173

Revision 173, 14.7 KB checked in by mattausch, 19 years ago (diff)

did some code cleanup

Line 
1#include "OgreOcclusionQueriesQueryManager.h"
2#include <OgreLogManager.h>
3#include <OgreStringConverter.h>
4#include <vector>
5#include <OgreSubEntity.h>
6
7
8namespace Ogre {
9
10/**
11   These functions necessary to enable sorting of node / mesh / patch info.
12*/
13//-----------------------------------------------------------------------
14inline bool nodeinfo_eq(const GtpVisibility::NodeInfo &info1, const GtpVisibility::NodeInfo &info2)
15{
16        return info1.GetNode() == info2.GetNode();
17}
18//-----------------------------------------------------------------------
19inline bool meshinfo_eq(const GtpVisibility::MeshInfo &info1, const GtpVisibility::MeshInfo &info2)
20{
21        return info1.GetMesh() == info2.GetMesh();
22}
23//-----------------------------------------------------------------------
24inline bool patchinfo_eq(const GtpVisibility::PatchInfo &info1, const GtpVisibility::PatchInfo &info2)
25{
26        return info1.GetPatch() == info2.GetPatch();
27}
28//-----------------------------------------------------------------------
29inline bool nodeinfo_lower(const GtpVisibility::NodeInfo &info1, const GtpVisibility::NodeInfo &info2)
30{
31        return info1.GetNode() < info2.GetNode();
32}
33//-----------------------------------------------------------------------
34inline bool meshinfo_lower(const GtpVisibility::MeshInfo &info1, const GtpVisibility::MeshInfo &info2)
35{
36        return info1.GetMesh() < info2.GetMesh();
37}
38//-----------------------------------------------------------------------
39inline bool patchinfo_lower(const GtpVisibility::PatchInfo &info1, const GtpVisibility::PatchInfo &info2)
40{
41        return info1.GetPatch() < info2.GetPatch();
42}
43
44
45//-----------------------------------------------------------------------
46OcclusionQueriesQueryManager::OcclusionQueriesQueryManager(
47                                                        PlatformHierarchyInterface *hierarchyInterface,
48                                                        Viewport *vp,
49                                                        bool renderPatches,
50                                                        bool useItemBufferForGeometry):
51PlatformQueryManager(hierarchyInterface, vp, renderPatches),
52mUseItemBuffer(useItemBufferForGeometry)
53{
54}
55//-----------------------------------------------------------------------
56void OcclusionQueriesQueryManager::ComputeCameraVisibility(const Camera &camera,
57                            InfoContainer<GtpVisibility::NodeInfo> *visibleNodes,
58                            InfoContainer<GtpVisibility::MeshInfo> *visibleGeometry,
59                                InfoContainer<GtpVisibility::PatchInfo> *visiblePatches,
60                            bool relativeVisibility)
61{
62         // we need access to the scene manager and the rendersystem
63        PlatformHierarchyInterface *pfHierarchyInterface =
64                dynamic_cast<PlatformHierarchyInterface *>(mHierarchyInterface);
65
66        // disable overlays, reset them later
67        bool overlayEnabled = mViewport->getOverlaysEnabled();
68
69        //-- render scene with item buffer (i.e., objects with their id as color codes)
70        if (mUseItemBuffer)
71        {
72                PlatformQueryManager::ComputeCameraVisibility(camera, visibleNodes,
73                            visibleGeometry, visiblePatches, relativeVisibility);
74
75                mViewport->setOverlaysEnabled(false);
76        }
77        else
78        {
79                // const_cast allowed because camera is not changed in renderScene
80                Camera *pCam = const_cast<Camera *>(&camera);
81                mViewport->setOverlaysEnabled(false);
82
83                //-- Render scene to get conservative visibility and fill depth buffer
84                pfHierarchyInterface->GetSceneManager()->_renderScene(pCam, mViewport, false);
85        }
86
87       
88        /*      Two query lists for projected pixels and for visibile pixels:
89                We test queries after a rendering pass
90                to get exact visibility with regard to the current camera.
91                We issue all queries at once to avoid starvation & stalls.
92        */
93        GtpVisibility::QueryList queryList[2];
94       
95        // rendered hierarchy nodes from previous render
96        GtpVisibility::HierarchyNodeList *nodeList = mHierarchyInterface->GetRenderedNodes();
97        GtpVisibility::HierarchyNodeList::iterator nodeIt, nodeIt_end = nodeList->end();
98
99        // vector for storing entities of meshes
100        GtpVisibility::GeometryList geometryList;
101       
102        // store geometry of the hierarchy node in a geometry list (only once!)
103        for (nodeIt = nodeList->begin(); nodeIt != nodeIt_end; ++nodeIt)               
104        {
105                mHierarchyInterface->GetNodeGeometryList(*nodeIt, &geometryList, false);
106        }
107
108        // geometry list iterator
109        GtpVisibility::GeometryList::iterator geometryIt, geometryIt_end = geometryList.end();
110
111        // vector for storing subentities of meshes
112        GtpVisibility::PatchList patchList;
113        GtpVisibility::PatchList::iterator patchIt, patchIt_end = patchList.end();
114
115        // to obtain the correct number of projected pixels, depth write must be disabled
116        bool enableDepthWrite = false;
117        // this option must be provided by the scene manager
118        pfHierarchyInterface->GetSceneManager()->setOption("DepthWrite", &enableDepthWrite);
119
120
121        /* relative visiblity:
122           1) get visible pixels count of objects
123           2) clear frame buffer
124           3) get projected visible pixels count:
125              test all objects again without depth write (set as option in scene manager)
126           4) calculate ratio between visible vs. projected pixels
127        */
128               
129        // for relative visibility we need 2 rendering passes
130        int n = relativeVisibility ? 2 : 1;
131       
132        for (int i = 0; i < n; ++i)
133        {
134                //-- queries for hierarchy nodes
135                for (nodeIt = nodeList->begin(); nodeIt != nodeIt_end; ++nodeIt)               
136                {
137                        // TODO: DELETE QUERIES FROM PREVIOUS RENDER
138                        queryList[i].push_back(mHierarchyInterface->IssueOcclusionQuery(*nodeIt, false));
139                }
140
141                //-- queries for geometry: if item buffer, capture only projected visibility
142                for (geometryIt = geometryList.begin(); geometryIt != geometryIt_end; ++geometryIt)
143                {
144                        queryList[i].push_back(mHierarchyInterface->IssueOcclusionQuery(*geometryIt));
145                }
146               
147                //-- queries for patches: if item buffer, capture only projected visibility
148                if (!(mUseItemBuffer && (i == 0)))
149                {
150                        for (patchIt = patchList.begin(); patchIt != patchIt_end; ++patchIt)
151                        {
152                                queryList[i].push_back(mHierarchyInterface->IssueOcclusionQuery(*patchIt));
153                        }
154                }
155
156                pfHierarchyInterface->GetRenderSystem()->clearFrameBuffer(FBT_DEPTH);
157        }
158
159       
160        //-- collect results
161        GtpVisibility::QueryList::iterator visQueryIt = queryList[0].begin();
162        GtpVisibility::QueryList::iterator projQueryIt = queryList[1].begin();
163       
164        CollectNodeVisibility(visQueryIt, projQueryIt, nodeList, visibleNodes, relativeVisibility);
165
166        if (mUseItemBuffer)
167        {
168                if (relativeVisibility)
169                {
170                        CollectRelativePatchVisibilityForItemBuffer(projQueryIt, &patchList, visiblePatches);
171                }
172    }
173        else
174        {
175                CollectPatchVisibility(visQueryIt, projQueryIt, &patchList, visiblePatches, relativeVisibility);
176        }       
177       
178        CollectGeometryVisibility(visQueryIt, projQueryIt, &geometryList, visibleGeometry, relativeVisibility);
179               
180        //-- reset options
181        enableDepthWrite = true;
182        // this option must be provided by the scene manager
183        pfHierarchyInterface->GetSceneManager()->setOption("DepthWrite", &enableDepthWrite);
184        // reset old overlay status
185        mViewport->setOverlaysEnabled(overlayEnabled);
186
187        mWasInitialised = false;
188}
189//-----------------------------------------------------------------------
190void OcclusionQueriesQueryManager::ComputeFromPointVisibility(const Vector3 &point,
191                               InfoContainer<GtpVisibility::NodeInfo> *visibleNodes,
192                               InfoContainer<GtpVisibility::MeshInfo> *visibleGeometry,
193                                   InfoContainer<GtpVisibility::PatchInfo> *visiblePatches,
194                               bool relativeVisibility)
195{
196        PlatformQueryManager::ComputeFromPointVisibility(point, visibleNodes,
197                visibleGeometry, visiblePatches, relativeVisibility);
198
199        // remove duplicates (duplicates occur if an object is on the edge of the viewport)
200        // before duplicates can be deleted we have to add up their visibility
201        RemoveDuplicateNodes(visibleNodes);
202       
203        if (!mUseItemBuffer)
204        {
205                RemoveDuplicateGeometry(visibleGeometry);
206        }
207}
208//-----------------------------------------------------------------------
209void  OcclusionQueriesQueryManager::CollectNodeVisibility(
210                                                GtpVisibility::QueryList::iterator &visQueryIt,
211                                                GtpVisibility::QueryList::iterator &projQueryIt,
212                                                GtpVisibility::HierarchyNodeList *nodeList, 
213                                                InfoContainer<GtpVisibility::NodeInfo> *visibleNodes,
214                                                bool relativeVisibility)
215{
216        GtpVisibility::HierarchyNodeList::iterator nodeIt;
217
218        //-- queries for nodes
219        for (nodeIt = nodeList->begin(); nodeIt != nodeList->end(); ++nodeIt)
220        {
221                unsigned int visiblePixels = 0;
222                (*visQueryIt)->GetQueryResult(visiblePixels, true);
223       
224                unsigned int projectedPixels = 0;
225
226                if (relativeVisibility)
227                {
228                        (*projQueryIt)->GetQueryResult(projectedPixels, true);
229               
230                        ++projQueryIt;
231                }
232
233                ++visQueryIt;
234               
235                // node with visibilty 0 in queue (e.g., if node is intersected by near plane)
236                if (visiblePixels > 0)
237                {
238                        visibleNodes->push_back(GtpVisibility::NodeInfo(*nodeIt, visiblePixels,
239                                projectedPixels));
240                }
241        }
242}
243//-----------------------------------------------------------------------
244void OcclusionQueriesQueryManager::CollectRelativeGeometryVisibilityForItemBuffer(
245                                                                        GtpVisibility::QueryList::iterator &projQueryIt,
246                                                                        GtpVisibility::GeometryList *geometryList,
247                                                                        InfoContainer<GtpVisibility::MeshInfo> *visibleGeometry)
248{
249        GtpVisibility::GeometryList::iterator geometryIt;
250
251        //-- queries for geometry
252        for (geometryIt = geometryList->begin(); geometryIt != geometryList->end(); ++ geometryIt)
253        {
254                unsigned int projectedPixels = 0;
255
256                (*projQueryIt)->GetQueryResult(projectedPixels, true);
257
258                ++projQueryIt;
259                int id = (*geometryIt)->getSubEntity(0)->getId();
260
261                if ((id > 0) && (id < (int)visibleGeometry->size()))
262                {
263                        (*visibleGeometry)[id].AddVisibility(0, projectedPixels);
264                }
265        }
266}
267//-----------------------------------------------------------------------
268void OcclusionQueriesQueryManager::CollectRelativePatchVisibilityForItemBuffer(
269                                                                        GtpVisibility::QueryList::iterator &projQueryIt,
270                                                                        GtpVisibility::PatchList *patchList,
271                                                                        InfoContainer<GtpVisibility::PatchInfo> *visiblePatches)
272{
273        GtpVisibility::PatchList::iterator patchIt;
274
275        //-- queries for geometry
276        for (patchIt = patchList->begin(); patchIt != patchList->end(); ++ patchIt)
277        {
278                unsigned int projectedPixels = 0;
279
280                (*projQueryIt)->GetQueryResult(projectedPixels, true);
281
282                ++projQueryIt;
283                int id = (*patchIt)->getId();
284
285                if ((id > 0) && (id < (int)visiblePatches->size()))
286                {
287                        (*visiblePatches)[id].AddVisibility(0, projectedPixels);
288                }
289        }
290}
291//-----------------------------------------------------------------------
292void  OcclusionQueriesQueryManager::CollectGeometryVisibility(
293                                                        GtpVisibility::QueryList::iterator &visQueryIt,
294                                                        GtpVisibility::QueryList::iterator &projQueryIt,
295                                                        GtpVisibility::GeometryList *geometryList,
296                                                        InfoContainer<GtpVisibility::MeshInfo> *visibleGeometry,
297                                                        bool relativeVisibility)
298{
299        GtpVisibility::GeometryList::iterator geometryIt;
300
301        //-- queries for geometry
302        for (geometryIt = geometryList->begin(); geometryIt != geometryList->end(); ++ geometryIt)
303        {
304                unsigned int visiblePixels = 0;
305                (*visQueryIt)->GetQueryResult(visiblePixels, true);
306               
307                unsigned int projectedPixels = 0;
308
309                if (relativeVisibility)
310                {
311                        (*projQueryIt)->GetQueryResult(projectedPixels, true);
312                        ++ projQueryIt;
313                }
314
315                ++ visQueryIt;
316
317                // WARNING: approximate depth ordering during rendering =>
318                // geometry maybe occluded
319                if (visiblePixels > 0)
320                {                       
321                        visibleGeometry->push_back(GtpVisibility::MeshInfo(*geometryIt, visiblePixels,
322                                projectedPixels));
323                }
324        }
325}
326//-----------------------------------------------------------------------
327void  OcclusionQueriesQueryManager::CollectPatchVisibility(
328                                                        GtpVisibility::QueryList::iterator &visQueryIt,
329                                                        GtpVisibility::QueryList::iterator &projQueryIt,
330                                                        GtpVisibility::PatchList *patchList,
331                                                        InfoContainer<GtpVisibility::PatchInfo> *visiblePatches,
332                                                        bool relativeVisibility)
333{
334        GtpVisibility::PatchList::iterator patchIt;
335
336        //-- queries for patch
337        for (patchIt = patchList->begin(); patchIt != patchList->end(); ++ patchIt)
338        {
339                unsigned int visiblePixels = 0;
340                (*visQueryIt)->GetQueryResult(visiblePixels, true);
341               
342                unsigned int projectedPixels = 0;
343
344                if (relativeVisibility)
345                {
346                        (*projQueryIt)->GetQueryResult(projectedPixels, true);
347                        ++ projQueryIt;
348                }
349
350                ++ visQueryIt;
351
352                // WARNING: approximate depth ordering during rendering =>
353                // patch maybe occluded
354                if (visiblePixels > 0)
355                {                       
356                        visiblePatches->push_back(GtpVisibility::PatchInfo(*patchIt, visiblePixels,
357                                projectedPixels));
358                }
359        }
360}
361//-----------------------------------------------------------------------
362void  OcclusionQueriesQueryManager::RemoveDuplicateNodes(
363                                        InfoContainer<GtpVisibility::NodeInfo> *visibleNodes)
364{
365        sort(visibleNodes->begin(), visibleNodes->end(), nodeinfo_lower);
366        InfoContainer<GtpVisibility::NodeInfo>::iterator visibleNodesIt,
367                visibleNodesIt_end = visibleNodes->end();
368       
369        GtpVisibility::NodeInfo *nodeInfo = NULL;
370
371        for (visibleNodesIt = visibleNodes->begin(); visibleNodesIt != visibleNodesIt_end;
372                ++visibleNodesIt)
373        {
374                if (!nodeInfo || (nodeInfo->GetNode() != (*visibleNodesIt).GetNode()))
375                {
376                        nodeInfo = &(*visibleNodesIt);
377                }
378                else // add visibility
379                {                       
380                        nodeInfo->AddVisibility(*visibleNodesIt);
381                }
382        }
383       
384        // physically delete duplicates
385        visibleNodes->erase( std::unique(visibleNodes->begin(),
386                visibleNodes->end(), nodeinfo_eq), visibleNodes->end());
387}
388//-----------------------------------------------------------------------
389void  OcclusionQueriesQueryManager::RemoveDuplicateGeometry(
390                                InfoContainer<GtpVisibility::MeshInfo> *visibleGeometry)
391{
392        sort(visibleGeometry->begin(), visibleGeometry->end(), meshinfo_lower);
393       
394        InfoContainer<GtpVisibility::MeshInfo>::iterator visibleGeomIt,
395                        visibleGeomIt_end = visibleGeometry->end();
396
397        GtpVisibility::MeshInfo *geomInfo = NULL;
398
399        for (visibleGeomIt = visibleGeometry->begin(); visibleGeomIt != visibleGeomIt_end;
400                ++visibleGeomIt)
401        {
402                if (!geomInfo || (geomInfo->GetMesh() != (*visibleGeomIt).GetMesh()))
403                {
404                        geomInfo = &(*visibleGeomIt);
405                }
406                else // info points to same mesh, just add visibility
407                {
408                        geomInfo->AddVisibility(*visibleGeomIt);
409                }
410        }
411
412        // physically delete duplicates
413        visibleGeometry->erase(std::unique(visibleGeometry->begin(), visibleGeometry->end(),
414                meshinfo_eq), visibleGeometry->end());
415}
416//-----------------------------------------------------------------------
417void  OcclusionQueriesQueryManager::RemoveDuplicatePatches(
418                                InfoContainer<GtpVisibility::PatchInfo> *visiblePatches)
419{
420        sort(visiblePatches->begin(), visiblePatches->end(), patchinfo_lower);
421       
422        InfoContainer<GtpVisibility::PatchInfo>::iterator visiblePatchIt,
423                        visiblePatchIt_end = visiblePatches->end();
424
425        GtpVisibility::PatchInfo *patchInfo = NULL;
426
427        for (visiblePatchIt = visiblePatches->begin(); visiblePatchIt != visiblePatchIt_end;
428                ++visiblePatchIt)
429        {
430                if (!patchInfo || (patchInfo->GetPatch() != (*visiblePatchIt).GetPatch()))
431                {
432                        patchInfo = &(*visiblePatchIt);
433                }
434                else // info points to same mesh, just add visibility
435                {
436                        patchInfo->AddVisibility(*visiblePatchIt);
437                }
438        }
439
440        // physically delete duplicates
441        visiblePatches->erase(std::unique(visiblePatches->begin(), visiblePatches->end(),
442                patchinfo_eq), visiblePatches->end());
443}
444} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.