source: GTP/trunk/Lib/Vis/OnlineCullingCHC/src/CoherentHierarchicalCullingManager.cpp @ 2561

Revision 2561, 7.0 KB checked in by mattausch, 17 years ago (diff)
Line 
1#include "CoherentHierarchicalCullingManager.h"
2#include "CullingLogManager.h"
3
4#include <time.h>
5#include <sstream>
6
7
8namespace GtpVisibility {
9
10
11
12//-----------------------------------------------------------------------
13CoherentHierarchicalCullingManager::CoherentHierarchicalCullingManager():
14mAssumedVisibility(0)
15{
16}
17//-----------------------------------------------------------------------
18CoherentHierarchicalCullingManager::CoherentHierarchicalCullingManager(
19                                                                                                                const unsigned int assumedVisibility):
20mAssumedVisibility(assumedVisibility)
21{
22}
23//-----------------------------------------------------------------------
24void CoherentHierarchicalCullingManager::AssignAssumedVisibility(GtpVisibility::HierarchyNode *node)
25{
26        if (!mHierarchyInterface->IsNodeVisible(node))
27                // previously invisible nodes: give random offset just for the first test after
28                // becoming visible to avoid that all nodes are tested in the same frame
29                mHierarchyInterface->SetNodeAssumedVisible(node, rand() * mAssumedVisibility / RAND_MAX);
30        else
31                mHierarchyInterface->SetNodeAssumedVisible(node, mAssumedVisibility);
32}
33//-----------------------------------------------------------------------
34void CoherentHierarchicalCullingManager::RenderScene()
35{
36        if (0) CullingLogManager::GetSingleton()->LogMessage("chc");
37        unsigned int visiblePixels = 0;
38       
39        /////////////
40        //-- PART 1: process finished occlusion queries
41
42        while (!mHierarchyInterface->GetQueue()->empty() || !mQueryQueue.empty())
43        {
44                //////////
45                //-- only wait for result if there are no nodes to process
46
47                while (!mQueryQueue.empty() &&
48                           (NodeInvalid(mQueryQueue.front().first) ||
49                            mQueryQueue.front().second->GetQueryResult(
50                                             visiblePixels, mHierarchyInterface->GetQueue()->empty())))
51                {
52                        HierarchyNode *node = mQueryQueue.front().first;
53                        mQueryQueue.pop();
54
55                        // parent was tested invisible => remove children from queue
56                        // "invalid nodes" happen for hierarchies where interiors store geometry
57                        if (NodeInvalid(node)) continue;
58
59                        // tested visible
60                        if (visiblePixels > mVisibilityThreshold)
61                        {
62                                // assing the #frames the node is assumed to stay visible
63                                AssignAssumedVisibility(node);
64
65                                // traverse node if not already traversed in this frame
66                                // (i.e., the visible flag is not set)
67                                // note: it is necessary to do this test because we query
68                                // previously visible interior node containing geometry
69                                // without waiting for the result
70                                if (!mHierarchyInterface->IsNodeVisible(node))
71                                        mHierarchyInterface->TraverseNode(node);
72
73                                mHierarchyInterface->PullUpVisibility(node);
74                        }
75                        else
76                        {       
77                                mHierarchyInterface->SetNodeVisible(node, false);
78
79                ++ mNumQueryCulledNodes;
80
81                                if (mVisualizeCulledNodes)
82                                        mHierarchyInterface->VisualizeCulledNode(node, QUERY_CULLED);
83                        }
84                       
85                        // update node's visited flag
86                        mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId());   
87                }
88               
89                ////////////////
90                //-- PART 2: hierarchical traversal
91
92                if (!mHierarchyInterface->GetQueue()->empty())
93                {
94                        HierarchyNode *node = mHierarchyInterface->GetQueue()->top();
95                        mHierarchyInterface->GetQueue()->pop();
96                               
97                        // parent was tested invisible => remove children from queue
98                        if (NodeInvalid(node)) continue;
99
100                        bool intersects = false;
101
102                        if (!mHierarchyInterface->CheckFrustumVisible(node, intersects))
103                        {
104                                ++ mNumFrustumCulledNodes;
105
106                                if (mVisualizeCulledNodes)
107                                        mHierarchyInterface->VisualizeCulledNode(node, FRUSTUM_CULLED);
108                        }
109                        //-- if node intersects near plane, skip query because wrong results possible
110                        else if (intersects)
111                        {
112                                SkipQuery(node);
113                        }
114                        else
115                        {
116                                // identify previously visible nodes
117                                bool wasVisible = mHierarchyInterface->IsNodeVisible(node) &&
118                                        (mHierarchyInterface->LastVisited(node) == mHierarchyInterface->GetFrameId() - 1);
119                               
120                                // if we assume node to be visible in this frame => skip query
121                                const bool skipQuery = wasVisible &&
122                                                                           DecideVisible(node) &&
123                                                                           mHierarchyInterface->HasGeometry(node);
124
125                                if (skipQuery)
126                                {
127                                        SkipQuery(node);
128                                        continue;
129                                }
130
131                // identify nodes that we cannot skip queries for
132                                // geometry not only in leaves => test for renderable geometry
133                                bool issueQuery = !wasVisible || mHierarchyInterface->HasGeometry(node);
134                                                       
135                                // set node's visibility classification
136                                // we identify previously visible / invisible nodes in the query queue
137                                mHierarchyInterface->SetNodeVisible(node, wasVisible && issueQuery);
138
139                                if (issueQuery)
140                                {
141                                        ++ mNumQueriesIssued;
142                                       
143                                        const bool testGeometry =
144                                                wasVisible && mHierarchyInterface->IsLeaf(node) && mTestGeometryForVisibleLeaves;
145
146                                        mQueryQueue.push(QueryPair(node, mHierarchyInterface->
147                                                IssueNodeOcclusionQuery(node, testGeometry)));
148                                }
149                                else
150                                {
151                                        // skip testing previously visible nodes without geometry
152                    // just update node's visited flag
153                                        mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId());
154                                }
155
156                                // always traverse a node if it was visible
157                                if (wasVisible)
158                                {
159                                        mHierarchyInterface->TraverseNode(node);
160                                }
161                        }
162                }
163        }
164}
165//-----------------------------------------------------------------------
166void CoherentHierarchicalCullingManager::SetAssumedVisibility(const unsigned int assumedVisibility)
167{
168        mAssumedVisibility = assumedVisibility;
169}
170//-----------------------------------------------------------------------
171inline bool CoherentHierarchicalCullingManager::DecideVisible(HierarchyNode *node) const
172{
173        mHierarchyInterface->DecNodeAssumedVisible(node);
174        //std::stringstream d; d << "node visible: " << mHierarchyInterface->GetNodeAssumedVisible(node);
175        //CullingLogManager::GetSingleton()->LogMessage(d.str());
176        return mHierarchyInterface->GetNodeAssumedVisible(node) > 0;
177}
178//-----------------------------------------------------------------------
179inline void CoherentHierarchicalCullingManager::SkipQuery(HierarchyNode *node) const
180{
181        //-- set node to be visible in this frame, then traverse it
182        mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId());
183       
184        mHierarchyInterface->PullUpVisibility(node);                   
185        mHierarchyInterface->TraverseNode(node);
186}
187//-----------------------------------------------------------------------
188bool CoherentHierarchicalCullingManager::NodeInvalid(HierarchyNode *node) const
189{
190        // parent was tested invisible in this frame
191    const bool nodeInvalid = (
192                    mHierarchyInterface->GetParent(node) &&
193                    (mHierarchyInterface->LastVisited(node) == mHierarchyInterface->GetFrameId()) &&
194                    !mHierarchyInterface->IsNodeVisible(mHierarchyInterface->GetParent(node))
195           );
196        return nodeInvalid;
197}
198//-----------------------------------------------------------------------
199void CoherentHierarchicalCullingManager::SetTestGeometryForVisibleLeaves(const bool testGeometry)
200{
201        mTestGeometryForVisibleLeaves = testGeometry;
202}
203//-----------------------------------------------------------------------
204bool CoherentHierarchicalCullingManager::GetTestGeometryForVisibleLeaves()
205{
206        return mTestGeometryForVisibleLeaves;
207}
208
209}
Note: See TracBrowser for help on using the repository browser.