source: trunk/VUT/Ogre/src/OgrePlatformQueryManager.cpp @ 141

Revision 141, 8.0 KB checked in by mattausch, 19 years ago (diff)

fixed visibility queries using occlusion queries
fixed visualization

Line 
1#include "OgrePlatformQueryManager.h"
2#include "OcclusionQuery.h"
3#include <OgreSceneManager.h>
4#include <OgreLogManager.h>
5#include <OgreStringConverter.h>
6#include <vector>
7
8
9namespace Ogre {
10//-----------------------------------------------------------------------
11PlatformQueryManager::PlatformQueryManager(PlatformHierarchyInterface *hierarchyInterface, Viewport *vp):
12QueryManager(hierarchyInterface), mViewport(vp)
13{
14}
15//-----------------------------------------------------------------------
16bool PlatformQueryManager::ShootRay(const Ray &ray, std::vector<Mesh *> *visibleMeshes, bool isGlobalLine)
17{
18    // run OGRE ray shooting query
19    return false;
20}
21//-----------------------------------------------------------------------
22void PlatformQueryManager::ComputeCameraVisibility(const Camera &camera,
23                            InfoContainer<GtpVisibility::NodeInfo> *visibleNodes,
24                            InfoContainer<GtpVisibility::MeshInfo> *visibleGeometry,
25                            bool relativeVisibility)
26{
27        // we need access to the scene manager and the rendersystem
28        PlatformHierarchyInterface *pfHierarchyInterface =
29                dynamic_cast<PlatformHierarchyInterface *>(mHierarchyInterface);
30
31        //-- Render scene to get conservative visibility and fill depth buffer
32
33        // can do const_cast because Camera no changed in renderScene
34        Camera *pCam = const_cast<Camera *>(&camera);
35
36        bool overlayEnabled = mViewport->getOverlaysEnabled();
37        mViewport->setOverlaysEnabled(false);
38        pfHierarchyInterface->GetSceneManager()->_renderScene(pCam, mViewport, false);
39
40        /*
41                Two query lists:
42                We test two to get exact visibility with regard to the current camera and
43                issue all queries at once to avoid starvation & stalls.
44        */
45        GtpVisibility::QueryList queryList[2];
46       
47        // get rendered hierarchy nodes
48        GtpVisibility::HierarchyNodeList *nodeList = mHierarchyInterface->GetRenderedNodes();
49        // vector for storing entities of meshes
50        GtpVisibility::GeometryList geometryList;
51       
52        GtpVisibility::HierarchyNodeList::iterator nodeIt, nodeIt_end = nodeList->end();
53        // geometry list has still do be built
54        GtpVisibility::GeometryList::iterator geometryIt, geometryIt_end;
55
56        // to obtain the correct number of projected pixels, depth write must be disabled
57        bool enableDepthWrite = false;
58
59        // this option must be provided by the scene manager
60        pfHierarchyInterface->GetSceneManager()->setOption("DepthWrite", &enableDepthWrite);
61
62        /* relative visiblity:
63                1) get visible pixels count of objects
64                2) clear frame buffer
65                3) get projected visible pixels count:
66                   test all objects again without depth write (set as option in scene manager)
67                4) calculate ratio between visible vs. projected pixels
68        */
69        // for relative visibility we need 2 rendering passes
70        int n = relativeVisibility ? 2 : 1;
71       
72        for (int i=0; i<n; ++i)
73        {
74                //-- queries for hierarchy nodes
75                for (nodeIt = nodeList->begin(); nodeIt != nodeIt_end; ++nodeIt)               
76                {
77                        // TODO: DELETE QUERIES FROM PREVIOUS RENDER
78                        queryList[i].push_back(mHierarchyInterface->IssueOcclusionQuery(*nodeIt, false));
79                       
80                        // store geometry of the hierarchy node in a geometry list (only once!)
81                        if (i == 0)
82                        {
83                                mHierarchyInterface->GetGeometry(*nodeIt, &geometryList, false);
84                        }
85                }
86
87                geometryIt_end = geometryList.end();
88
89                //-- add queries for geometry
90                for (geometryIt = geometryList.begin(); geometryIt != geometryIt_end; ++geometryIt)
91                {
92                        queryList[i].push_back(mHierarchyInterface->IssueOcclusionQuery(*geometryIt));
93                }
94
95       
96                pfHierarchyInterface->GetRenderSystem()->clearFrameBuffer(FBT_DEPTH);
97        }
98
99        enableDepthWrite = true;
100        // this option must be provided by the scene manager
101        pfHierarchyInterface->GetSceneManager()->setOption("DepthWrite", &enableDepthWrite);
102       
103        mViewport->setOverlaysEnabled(overlayEnabled);
104
105        //---- collect results
106        unsigned int visiblePixels = 0;
107        std::pair<InfoContainer<GtpVisibility::NodeInfo>::iterator, bool> insertNode;
108        std::pair<InfoContainer<GtpVisibility::MeshInfo>::iterator, bool> insertGeom;
109
110        GtpVisibility::QueryList::iterator visQueryIt, projQueryIt;
111
112        visQueryIt = queryList[0].begin();
113        projQueryIt = queryList[1].begin();
114
115       
116        for (nodeIt = nodeList->begin(); nodeIt != nodeIt_end; ++nodeIt)
117        {
118                (*visQueryIt)->GetQueryResult(visiblePixels, true);
119       
120                float vis = (float)visiblePixels;
121                bool isVisible = visiblePixels > 0;
122
123                if (relativeVisibility)
124                {
125                        (*projQueryIt)->GetQueryResult(visiblePixels, true);
126       
127                        if (visiblePixels > 0)
128                        {                               
129                                vis /= (float) visiblePixels;
130                        }
131                        ++projQueryIt;
132                }
133
134                ++visQueryIt;
135               
136                // nodes with visibilty 0 in queue:
137                // happens if node is intersected by near plane
138                if (isVisible)
139                {
140                        insertNode = visibleNodes->insert(GtpVisibility::NodeInfo(*nodeIt, vis));
141
142                        if (!insertNode.second) // element already in list
143                        {
144                                //LogManager::getSingleton().logMessage("element already in list");
145                (*insertNode.first).SetVisibility((*insertNode.first).GetVisibility() + vis);
146
147                                if (relativeVisibility) // relative visibility between zero and one
148                                {
149                                        (*insertNode.first).SetVisibility((*insertNode.first).GetVisibility() * 0.5);
150                                }
151                        }
152                }
153        }
154
155        //---- queries for geometry
156        geometryIt_end = geometryList.end();
157       
158        for (geometryIt = geometryList.begin(); geometryIt != geometryIt_end; ++geometryIt)
159        {
160                (*visQueryIt)->GetQueryResult(visiblePixels, true);
161               
162
163                float vis = (float)visiblePixels;
164                bool isVisible = visiblePixels > 0;
165               
166                if (relativeVisibility)
167                {
168                        (*projQueryIt)->GetQueryResult(visiblePixels, true);
169
170                        if (visiblePixels)
171                        {
172                                vis /= (float) visiblePixels;
173                        }
174                        ++projQueryIt;
175                }
176
177                ++visQueryIt;
178
179                // approximate depth ordering during rendering =>
180                // geometry maybe occluded
181                if (isVisible)
182                {                       
183                        insertGeom = visibleGeometry->insert(GtpVisibility::MeshInfo(*geometryIt, vis));
184                        if (!insertGeom.second) // element already in list
185                        {
186                                //LogManager::getSingleton().logMessage("element already in list");
187                (*insertGeom.first).SetVisibility((*insertGeom.first).GetVisibility() + vis);
188
189                                if (relativeVisibility) // relative visibility between zero and one
190                                {
191                                        (*insertGeom.first).SetVisibility((*insertGeom.first).GetVisibility() * 0.5);
192                                }
193                        }
194                }
195        }
196
197}
198//-----------------------------------------------------------------------
199void PlatformQueryManager::ComputeFromPointVisibility(const Vector3 &point,
200                               InfoContainer<GtpVisibility::NodeInfo> *visibleNodes,
201                               InfoContainer<GtpVisibility::MeshInfo> *visibleGeometry,
202                               bool relativeVisibility)
203{
204        SceneManager *sm = dynamic_cast<PlatformHierarchyInterface *>(mHierarchyInterface)->GetSceneManager();
205        Camera *cam = sm->createCamera("PointQueryCam");       
206
207        //save old camera
208        Camera *savedCam = mViewport->getCamera();
209       
210        // --- initialise new camera
211        mViewport->setCamera(cam);
212        cam->setPosition(point);
213
214        cam->setNearClipDistance(savedCam->getNearClipDistance());
215        cam->setFarClipDistance(savedCam->getFarClipDistance());
216
217        // set frustum to 45 degrees so all the scene can be captured with 6 shots
218        cam->setAspectRatio(1.0);
219        cam->setFOVy(Radian(Math::HALF_PI));
220
221        std::stringstream d;
222        d << "old camera: " + StringConverter::toString(savedCam->getDerivedPosition()) +
223                " " + "O: " + StringConverter::toString(savedCam->getDerivedOrientation());
224        LogManager::getSingleton().logMessage(d.str());
225
226        int sign = -1;
227       
228        // ---- capture visibility from all 6 directions
229        for (int i=0; i < 6; i++)       
230        {
231                sign *= -1;
232               
233                // Print camera details
234        std::stringstream d;
235                d << "Point query camera: " + StringConverter::toString(cam->getDerivedPosition()) +
236                        " " + "O: " + StringConverter::toString(cam->getDerivedOrientation());
237                LogManager::getSingleton().logMessage(d.str());
238
239                ComputeCameraVisibility(*cam, visibleNodes, visibleGeometry, relativeVisibility);
240                           
241                //mViewport->getTarget()->update(); for(int j=0; j<10000000; j++)       printf("HAAHHAHAHAHAH");
242
243                // permute directions
244                Vector3 dir(0,0,0);
245                dir[i/2] = sign;
246
247                cam->setDirection(dir);
248        }
249       
250
251        // reset camera
252        mViewport->setCamera(savedCam);
253}
254//-----------------------------------------------------------------------
255void PlatformQueryManager::SetViewport(Viewport *vp)
256{
257        mViewport = vp;
258}
259} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.