source: GTP/trunk/Lib/Vis/OnlineCullingCHC/src/CoherentHierarchicalCullingPlusPlusManager.cpp @ 2555

Revision 2555, 9.6 KB checked in by mattausch, 17 years ago (diff)

added partial implementation of chc++. problem: bounding box rendering in Ogre is VERY slow

Line 
1#include "CoherentHierarchicalCullingPlusPlusManager.h"
2#include "CullingLogManager.h"
3
4#include <time.h>
5#include <sstream>
6
7
8
9namespace GtpVisibility {
10
11
12static const bool CULL_INVALID_NODES = false;
13
14//-----------------------------------------------------------------------
15CoherentHierarchicalCullingPlusPlusManager::CoherentHierarchicalCullingPlusPlusManager():
16mAssumedVisibility(0), mMaxInvisibleNodesSize(50)
17{
18}
19//-----------------------------------------------------------------------
20CoherentHierarchicalCullingPlusPlusManager::CoherentHierarchicalCullingPlusPlusManager(
21                                                                                                                const unsigned int assumedVisibility):
22mAssumedVisibility(assumedVisibility), mMaxInvisibleNodesSize(50)
23{
24}
25//-----------------------------------------------------------------------
26void CoherentHierarchicalCullingPlusPlusManager::AssignAssumedVisibility(GtpVisibility::HierarchyNode *node)
27{
28        if (!mHierarchyInterface->IsNodeVisible(node))
29                // previously invisible nodes: give random offset just for the first test after
30                // becoming visible to avoid that all nodes are tested in the same frame
31                mHierarchyInterface->SetNodeAssumedVisible(node, rand() * mAssumedVisibility / RAND_MAX);
32        else
33                mHierarchyInterface->SetNodeAssumedVisible(node, mAssumedVisibility);
34}
35//-----------------------------------------------------------------------
36void CoherentHierarchicalCullingPlusPlusManager::RenderScene()
37{
38        if (0) CullingLogManager::GetSingleton()->LogMessage("chc++");
39       
40        unsigned int visiblePixels = 0;
41
42        /////////////
43        //-- PART 1: process finished occlusion queries
44
45        while (!mHierarchyInterface->GetQueue()->empty() || !mQueryQueue.empty() ||
46                   !mInvisibleNodes.empty() || !mVisibleNodes.empty())
47        {
48                //////////
49                //-- only wait for result if there are no nodes to process
50
51                bool resultAvailable = false;
52                while (
53                           !mQueryQueue.empty() &&
54                           (NodeInvalid(mQueryQueue.front().first) ||
55                           mHierarchyInterface->GetQueue()->empty() ||
56                           (resultAvailable = mQueryQueue.front().second->GetQueryResult(visiblePixels, false)))
57                           )
58                {
59                        HierarchyNode *node = mQueryQueue.front().first;
60
61                        // "invalid nodes" happen for hierarchies that store geometry in the interiors
62                        // parent was tested invisible => remove children from queue
63                        if (NodeInvalid(node)) {mQueryQueue.pop(); continue;}
64
65                        // during the wait time issue nodes from visible queue
66                        while (!mVisibleNodes.empty() && !resultAvailable)
67                        {
68                                HierarchyNode *vn = mVisibleNodes.front();
69                                mVisibleNodes.pop();
70                                IssueQuery(vn, false);
71
72                                // check if result is already availalbe
73                                resultAvailable = mQueryQueue.front().second->GetQueryResult(visiblePixels, false);
74                        }
75
76                        if (!resultAvailable)
77                                mQueryQueue.front().second->GetQueryResult(visiblePixels, true);
78
79                        resultAvailable = false;
80                mQueryQueue.pop();
81
82                        // tested visible
83                        if (visiblePixels > mVisibilityThreshold)
84                        {
85                                // assing the #frames the node is assumed to stay visible
86                                AssignAssumedVisibility(node);
87
88                                // for previously visible interior node which contains geometry:
89                                // ensure that we did not already traverse this node
90                                // (which means that the visibility flag is set)
91                                if (!mHierarchyInterface->IsNodeVisible(node))
92                                        mHierarchyInterface->TraverseNode2(node);
93
94                                mHierarchyInterface->PullUpVisibility(node);
95                        }
96                        else
97                        {       
98                                mHierarchyInterface->SetNodeVisible(node, false);
99
100                                ++ mNumQueryCulledNodes;
101                               
102                                if (mVisualizeCulledNodes)
103                                        mHierarchyInterface->VisualizeCulledNode(node, QUERY_CULLED);
104                                }
105                       
106                        // update node's visited flag
107                        mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId());   
108                }
109               
110                ////////////////
111                //-- PART 2: hierarchical traversal
112
113                if (!mHierarchyInterface->GetQueue()->empty())
114                {
115                        HierarchyNode *node = mHierarchyInterface->GetQueue()->top();
116                        mHierarchyInterface->GetQueue()->pop();
117                               
118                        // parent was tested invisible => remove children from queue
119                        if (NodeInvalid(node)) continue;
120
121                        bool intersects = false;
122
123                        if (!mHierarchyInterface->CheckFrustumVisible(node, intersects))
124                        {
125                                ++ mNumFrustumCulledNodes;
126                               
127                                if (mVisualizeCulledNodes)
128                                        mHierarchyInterface->VisualizeCulledNode(node, FRUSTUM_CULLED);
129                        }
130                        else if (intersects)
131                        {
132                                //-- if node intersects near plane, skip query because wrong results possible
133                                SkipQuery(node);
134                        }
135                        else
136                        {
137                                // identify previously visible nodes
138                                bool wasVisible = mHierarchyInterface->IsNodeVisible(node) &&
139                                        (mHierarchyInterface->LastVisited(node) == mHierarchyInterface->GetFrameId() - 1);
140                               
141                                // if we assume node to be visible in this frame => skip query
142                                const bool skipQuery = wasVisible &&
143                                                                           DecideVisible(node) &&
144                                                                           mHierarchyInterface->HasGeometry(node);
145
146                                if (skipQuery)
147                                {
148                                        SkipQuery(node);
149                                        continue;
150                                }
151
152                // identify nodes that we cannot skip queries for
153                                // geometry not only in leaves => test for renderable geometry
154                                const bool issueQuery = !wasVisible || mHierarchyInterface->HasGeometry(node);
155                                                       
156                                // set node's visibility classification
157                                // we identify previously visible / invisible nodes in the query queue
158                                mHierarchyInterface->SetNodeVisible(node, wasVisible && issueQuery);
159
160                                if (issueQuery)
161                                {
162                                        ++ mNumQueriesIssued;
163
164                                        if (!wasVisible)
165                                        {
166                                                mInvisibleNodes.push_back(node);
167
168                                                if ((int)mInvisibleNodes.size() >= mMaxInvisibleNodesSize)
169                                                {
170                                                        mHierarchyInterface->RenderQueue();
171                                                        // issue the batched queries
172                                                        IssueBatchedQuery(mInvisibleNodes);
173                                                }
174                                        }
175                                        else
176                                        {
177                                                mVisibleNodes.push(node);
178                                                //IssueQuery(node, false);
179                                        }
180                                }
181                                else
182                                {
183                                        // skip testing previously visible nodes without geometry
184                    // just update node's visited flag
185                                        mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId());
186                                }
187                               
188                                // always traverse a node if it was visible
189                                if (wasVisible)
190                                {
191                                        mHierarchyInterface->TraverseNode2(node);
192                                }
193                        }
194                }
195
196               
197                if (mHierarchyInterface->GetQueue()->empty() && !mInvisibleNodes.empty())
198                {
199                        if (0)
200                        {
201                                std::stringstream d;
202                                d << "inv nodes: " << (int)mInvisibleNodes.size();
203                                CullingLogManager::GetSingleton()->LogMessage(d.str());
204                        }
205                       
206                        mHierarchyInterface->RenderQueue();
207                        IssueBatchedQuery(mInvisibleNodes);
208                }
209
210        // issue rest of nodes from nodes from visible queue
211                if (mHierarchyInterface->GetQueue()->empty() && mQueryQueue.empty() && !mVisibleNodes.empty())
212                {
213                        if (0)
214                        {
215                                std::stringstream d;
216                                d << "vis nodes: " << (int)mVisibleNodes.size();
217                                CullingLogManager::GetSingleton()->LogMessage(d.str());
218                        }
219
220                        while (!mVisibleNodes.empty())
221                        {
222                                IssueQuery(mVisibleNodes.front(), false);
223                                mVisibleNodes.pop();
224                        }
225                }
226        }
227
228
229        if (0)
230        {
231                std::stringstream d;
232                d << "queries: " << (int)mQueryQueue.size() << " vis: " << (int)mVisibleNodes.size() << " inv: " << (int)mInvisibleNodes.size();
233                CullingLogManager::GetSingleton()->LogMessage(d.str());
234        }
235       
236        // render rest
237        mHierarchyInterface->RenderQueue();
238}
239//-----------------------------------------------------------------------
240void CoherentHierarchicalCullingPlusPlusManager::SetAssumedVisibility(const unsigned int assumedVisibility)
241{
242        mAssumedVisibility = assumedVisibility;
243}
244//-----------------------------------------------------------------------
245inline bool CoherentHierarchicalCullingPlusPlusManager::DecideVisible(HierarchyNode *node) const
246{
247        mHierarchyInterface->DecNodeAssumedVisible(node);
248        //std::stringstream d; d << "node visible: " << mHierarchyInterface->GetNodeAssumedVisible(node);
249        //CullingLogManager::GetSingleton()->LogMessage(d.str());
250        return mHierarchyInterface->GetNodeAssumedVisible(node) > 0;
251}
252//-----------------------------------------------------------------------
253inline void CoherentHierarchicalCullingPlusPlusManager::SkipQuery(HierarchyNode *node) const
254{
255        //-- set node to be visible in this frame, then traverse it
256        mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId());
257
258        mHierarchyInterface->PullUpVisibility(node);                   
259        mHierarchyInterface->TraverseNode2(node);
260}
261//-----------------------------------------------------------------------
262inline bool CoherentHierarchicalCullingPlusPlusManager::NodeInvalid(HierarchyNode *node) const
263{
264        if (!CULL_INVALID_NODES) return false;
265
266        // parent was tested invisible in this frame
267    return (
268                    mHierarchyInterface->GetParent(node) &&
269                    (mHierarchyInterface->LastVisited(node) == mHierarchyInterface->GetFrameId()) &&
270                    !mHierarchyInterface->IsNodeVisible(mHierarchyInterface->GetParent(node))
271           );
272}
273//-----------------------------------------------------------------------
274void CoherentHierarchicalCullingPlusPlusManager::SetTestGeometryForVisibleLeaves(const bool testGeometry)
275{
276        mTestGeometryForVisibleLeaves = testGeometry;
277}
278//-----------------------------------------------------------------------
279bool CoherentHierarchicalCullingPlusPlusManager::GetTestGeometryForVisibleLeaves()
280{
281        return mTestGeometryForVisibleLeaves;
282}
283//-----------------------------------------------------------------------
284inline void CoherentHierarchicalCullingPlusPlusManager::IssueQuery(HierarchyNode *node,
285                                                                                                                                   const bool queryGeometry)
286{
287        mQueryQueue.push(QueryPair(node, mHierarchyInterface->
288                IssueNodeOcclusionQuery(node, queryGeometry)));
289}
290//-----------------------------------------------------------------------
291void CoherentHierarchicalCullingPlusPlusManager::IssueBatchedQuery(HierarchyNodeContainer &nodes)
292{
293        HierarchyNodeContainer::const_iterator nit, nit_end = nodes.end();
294
295        for (nit = nodes.begin(); nit != nit_end; ++ nit)
296                IssueQuery(*nit, false);
297
298        nodes.clear();
299}
300               
301}
Note: See TracBrowser for help on using the repository browser.