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

Revision 2556, 11.1 KB checked in by mattausch, 17 years ago (diff)

implemented part of chc++

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