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

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

added node traversal interface

Line 
1#include "OgreOcclusionQueriesQueryManager.h"
2#include <OgreLogManager.h>
3#include <OgreStringConverter.h>
4#include <vector>
5
6
7namespace Ogre {
8//-----------------------------------------------------------------------
9OcclusionQueriesQueryManager::OcclusionQueriesQueryManager(PlatformHierarchyInterface *hierarchyInterface, Viewport *vp):
10PlatformQueryManager(hierarchyInterface, vp)
11{
12}
13//-----------------------------------------------------------------------
14bool OcclusionQueriesQueryManager::ShootRay(const Ray &ray, std::vector<Mesh *> *visibleMeshes, bool isGlobalLine)
15{
16    // run OGRE ray shooting query
17    return false;
18}
19//-----------------------------------------------------------------------
20void OcclusionQueriesQueryManager::ComputeCameraVisibility(const Camera &camera,
21                            InfoContainer<GtpVisibility::NodeInfo> *visibleNodes,
22                            InfoContainer<GtpVisibility::MeshInfo> *visibleGeometry,
23                            bool relativeVisibility)
24{
25        // we need access to the scene manager and the rendersystem
26        PlatformHierarchyInterface *pfHierarchyInterface =
27                dynamic_cast<PlatformHierarchyInterface *>(mHierarchyInterface);
28
29        //-- Render scene to get conservative visibility and fill depth buffer
30
31        // const_cast allowed because camera is not changed in renderScene
32        Camera *pCam = const_cast<Camera *>(&camera);
33
34        // disable overlays, reset them later
35        bool overlayEnabled = mViewport->getOverlaysEnabled();
36        mViewport->setOverlaysEnabled(false);
37
38        //-- render the scene once to update depth buffer
39        pfHierarchyInterface->GetSceneManager()->_renderScene(pCam, mViewport, false);
40
41        /*
42                Two query lists for projected pixels and for visibile pixels:
43                We test queries after a rendering pass
44                to get exact visibility with regard to the current camera.
45                We issue all queries at once to avoid starvation & stalls.
46        */
47        GtpVisibility::QueryList queryList[2];
48       
49        // get rendered hierarchy nodes
50        GtpVisibility::HierarchyNodeList *nodeList = mHierarchyInterface->GetRenderedNodes();
51        // vector for storing entities of meshes
52        GtpVisibility::GeometryList geometryList;
53       
54        GtpVisibility::HierarchyNodeList::iterator nodeIt, nodeIt_end = nodeList->end();
55        // geometry list has still do be built
56        GtpVisibility::GeometryList::iterator geometryIt, geometryIt_end;
57
58        // to obtain the correct number of projected pixels, depth write must be disabled
59        bool enableDepthWrite = false;
60
61        // this option must be provided by the scene manager
62        pfHierarchyInterface->GetSceneManager()->setOption("DepthWrite", &enableDepthWrite);
63
64        /* relative visiblity:
65                1) get visible pixels count of objects
66                2) clear frame buffer
67                3) get projected visible pixels count:
68                   test all objects again without depth write (set as option in scene manager)
69                4) calculate ratio between visible vs. projected pixels
70        */
71        // for relative visibility we need 2 rendering passes
72        int n = relativeVisibility ? 2 : 1;
73       
74        for (int i=0; i<n; ++i)
75        {
76                //-- queries for hierarchy nodes
77                for (nodeIt = nodeList->begin(); nodeIt != nodeIt_end; ++nodeIt)               
78                {
79                        // TODO: DELETE QUERIES FROM PREVIOUS RENDER
80                        queryList[i].push_back(mHierarchyInterface->IssueOcclusionQuery(*nodeIt, false));
81                       
82                        // store geometry of the hierarchy node in a geometry list (only once!)
83                        if (i == 0)
84                        {
85                                mHierarchyInterface->GetNodeGeometryList(*nodeIt, &geometryList, false);
86                        }
87                }
88
89                geometryIt_end = geometryList.end();
90
91                //-- add queries for geometry
92                for (geometryIt = geometryList.begin(); geometryIt != geometryIt_end; ++geometryIt)
93                {
94                        queryList[i].push_back(mHierarchyInterface->IssueOcclusionQuery(*geometryIt));
95                }
96
97       
98                pfHierarchyInterface->GetRenderSystem()->clearFrameBuffer(FBT_DEPTH);
99        }
100
101        enableDepthWrite = true;
102        // this option must be provided by the scene manager
103        pfHierarchyInterface->GetSceneManager()->setOption("DepthWrite", &enableDepthWrite);
104        // reset old overlay status
105        mViewport->setOverlaysEnabled(overlayEnabled);
106
107        // ---- collect results
108        GtpVisibility::QueryList::iterator visQueryIt, projQueryIt;
109
110        visQueryIt = queryList[0].begin();
111        projQueryIt = queryList[1].begin();
112
113       
114        for (nodeIt = nodeList->begin(); nodeIt != nodeIt_end; ++nodeIt)
115        {
116                unsigned int visiblePixels = 0;
117                (*visQueryIt)->GetQueryResult(visiblePixels, true);
118       
119                unsigned int projectedPixels = 0;
120
121                if (relativeVisibility)
122                {
123                        (*projQueryIt)->GetQueryResult(projectedPixels, true);
124               
125                        ++projQueryIt;
126                }
127
128                ++visQueryIt;
129               
130                // node with visibilty 0 in queue (e.g., if node is intersected by near plane)
131                if (visiblePixels > 0)
132                {
133                        visibleNodes->push_back(GtpVisibility::NodeInfo(*nodeIt, visiblePixels, projectedPixels));
134                }
135        }
136
137        // ---- queries for geometry
138        geometryIt_end = geometryList.end();
139       
140        for (geometryIt = geometryList.begin(); geometryIt != geometryIt_end; ++geometryIt)
141        {
142                unsigned int visiblePixels = 0;
143                (*visQueryIt)->GetQueryResult(visiblePixels, true);
144               
145                unsigned int projectedPixels = 0;
146
147                if (relativeVisibility)
148                {
149                        (*projQueryIt)->GetQueryResult(projectedPixels, true);
150
151                        ++projQueryIt;
152                }
153
154                ++visQueryIt;
155
156                // WARNING: approximate depth ordering during rendering =>
157                // geometry maybe occluded
158                if (visiblePixels > 0)
159                {                       
160                        visibleGeometry->push_back(GtpVisibility::MeshInfo(*geometryIt, visiblePixels,
161                                projectedPixels));
162                }
163        }
164
165}
166//-----------------------------------------------------------------------
167inline bool nodeinfo_eq(const GtpVisibility::NodeInfo &info1, const GtpVisibility::NodeInfo &info2)
168{
169        return info1.GetNode() == info2.GetNode();
170}
171//-----------------------------------------------------------------------
172inline bool meshinfo_eq(const GtpVisibility::MeshInfo &info1, const GtpVisibility::MeshInfo &info2)
173{
174        return info1.GetMesh() == info2.GetMesh();
175}
176//-----------------------------------------------------------------------
177inline bool nodeinfo_lower(const GtpVisibility::NodeInfo &info1, const GtpVisibility::NodeInfo &info2)
178{
179        return info1.GetNode() < info2.GetNode();
180}
181//-----------------------------------------------------------------------
182inline bool meshinfo_lower(const GtpVisibility::MeshInfo &info1, const GtpVisibility::MeshInfo &info2)
183{
184        return info1.GetMesh() < info2.GetMesh();
185}
186//-----------------------------------------------------------------------
187void OcclusionQueriesQueryManager::ComputeFromPointVisibility(const Vector3 &point,
188                               InfoContainer<GtpVisibility::NodeInfo> *visibleNodes,
189                               InfoContainer<GtpVisibility::MeshInfo> *visibleGeometry,
190                               bool relativeVisibility)
191{
192        PlatformQueryManager::ComputeFromPointVisibility(point, visibleNodes, visibleGeometry, relativeVisibility);
193
194        // --- remove duplicates (duplicates occur if an object is on the edge of the viewport)
195
196        // before duplicates can be deleted we have to add up their visibility
197
198        // --- visible nodes
199        sort(visibleNodes->begin(), visibleNodes->end(), nodeinfo_lower);
200        InfoContainer<GtpVisibility::NodeInfo>::iterator visibleNodesIt,
201                visibleNodesIt_end = visibleNodes->end();
202       
203        GtpVisibility::NodeInfo *nodeInfo = NULL;
204
205        for (visibleNodesIt = visibleNodes->begin(); visibleNodesIt != visibleNodesIt_end;
206                ++visibleNodesIt)
207        {
208                if (!nodeInfo || (nodeInfo->GetNode() != (*visibleNodesIt).GetNode()))
209                {
210                        nodeInfo = &(*visibleNodesIt);
211                }
212                else // add visibility
213                {                       
214                        nodeInfo->AddVisibility(*visibleNodesIt);
215                }
216
217        }
218       
219        // physically delete duplicates
220        visibleNodes->erase( std::unique(visibleNodes->begin(),
221                visibleNodes->end(), nodeinfo_eq), visibleNodes->end());
222
223        // --- visible geometry
224        sort(visibleGeometry->begin(), visibleGeometry->end(), meshinfo_lower);
225        InfoContainer<GtpVisibility::MeshInfo>::iterator visibleGeomIt,
226                visibleGeomIt_end = visibleGeometry->end();
227
228        GtpVisibility::MeshInfo *geomInfo = NULL;
229
230        int i=0;
231        for (visibleGeomIt = visibleGeometry->begin(); visibleGeomIt != visibleGeomIt_end;
232                ++visibleGeomIt)
233        {
234                if (!geomInfo || (geomInfo->GetMesh() != (*visibleGeomIt).GetMesh()))
235                {
236                        geomInfo = &(*visibleGeomIt);
237                }
238                else // info points to same mesh, just add visibility
239                {
240                        geomInfo->AddVisibility(*visibleGeomIt);
241                }
242        }
243
244        // physically delete duplicates
245        visibleGeometry->erase(std::unique(visibleGeometry->begin(), visibleGeometry->end(),
246                meshinfo_eq), visibleGeometry->end());
247}
248
249} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.