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

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

implemented part of chc++

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                        // "invalid nodes" happen for hierarchies that have geometry
56                        // not neccessarily in the leaves:
57                        // parent was tested invisible => remove children from queue
58
59                        if (1 && NodeInvalid(node))
60                                continue;
61
62                        // tested visible
63                        if (visiblePixels > mVisibilityThreshold)
64                        {
65                                // assing the #frames the node is assumed to stay visible
66                                AssignAssumedVisibility(node);
67
68                                // for previously visible interior node which contains geometry:
69                                // ensure that we did not already traverse this node
70                                // (which means that the visibility flag is set)
71                                if (!mHierarchyInterface->IsNodeVisible(node))
72                                        mHierarchyInterface->TraverseNode(node);
73
74                                mHierarchyInterface->PullUpVisibility(node);
75                        }
76                        else
77                        {       
78                                mHierarchyInterface->SetNodeVisible(node, false);
79
80                ++ mNumQueryCulledNodes;
81
82                                if (mVisualizeCulledNodes)
83                                        mHierarchyInterface->VisualizeCulledNode(node, QUERY_CULLED);
84                        }
85                       
86                        // update node's visited flag
87                        mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId());   
88                }
89               
90                ////////////////
91                //-- PART 2: hierarchical traversal
92
93                if (!mHierarchyInterface->GetQueue()->empty())
94                {
95                        HierarchyNode *node = mHierarchyInterface->GetQueue()->top();
96                        mHierarchyInterface->GetQueue()->pop();
97                               
98                        // parent was tested invisible => remove children from queue
99                        if (1 && NodeInvalid(node))
100                                continue;
101
102                        bool intersects = false;
103
104                        if (!mHierarchyInterface->CheckFrustumVisible(node, intersects))
105                        {
106                                ++ mNumFrustumCulledNodes;
107
108                                if (mVisualizeCulledNodes)
109                                        mHierarchyInterface->VisualizeCulledNode(node, FRUSTUM_CULLED);
110                        }
111                        //-- if node intersects near plane, skip query because wrong results possible
112                        else if (intersects)
113                        {
114                                SkipQuery(node);
115                        }
116                        else
117                        {
118                                // identify previously visible nodes
119                                bool wasVisible = mHierarchyInterface->IsNodeVisible(node) &&
120                                        (mHierarchyInterface->LastVisited(node) == mHierarchyInterface->GetFrameId() - 1);
121                               
122                                // if we assume node to be visible in this frame => skip query
123                                const bool skipQuery = wasVisible &&
124                                                                           DecideVisible(node) &&
125                                                                           mHierarchyInterface->HasGeometry(node);
126
127                                if (skipQuery)
128                                {
129                                        SkipQuery(node);
130                                        continue;
131                                }
132
133                // identify nodes that we cannot skip queries for
134                                // geometry not only in leaves => test for renderable geometry
135                                bool issueQuery = !wasVisible || mHierarchyInterface->HasGeometry(node);
136                                                       
137                                // set node's visibility classification
138                                // we identify previously visible / invisible nodes in the query queue
139                                mHierarchyInterface->SetNodeVisible(node, wasVisible && issueQuery);
140
141                                if (issueQuery)
142                                {
143                                        ++ mNumQueriesIssued;
144                                       
145                                        const bool testGeometry =
146                                                wasVisible && mHierarchyInterface->IsLeaf(node) && mTestGeometryForVisibleLeaves;
147
148                                        mQueryQueue.push(QueryPair(node, mHierarchyInterface->
149                                                IssueNodeOcclusionQuery(node, testGeometry)));
150                                }
151                                else
152                                {
153                                        // skip testing previously visible nodes without geometry
154                    // just update node's visited flag
155                                        mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId());
156                                }
157
158                                // always traverse a node if it was visible
159                                if (wasVisible)
160                                {
161                                        mHierarchyInterface->TraverseNode(node);
162                                }
163                        }
164                }
165        }
166}
167//-----------------------------------------------------------------------
168void CoherentHierarchicalCullingManager::SetAssumedVisibility(const unsigned int assumedVisibility)
169{
170        mAssumedVisibility = assumedVisibility;
171}
172//-----------------------------------------------------------------------
173inline bool CoherentHierarchicalCullingManager::DecideVisible(HierarchyNode *node) const
174{
175        mHierarchyInterface->DecNodeAssumedVisible(node);
176        //std::stringstream d; d << "node visible: " << mHierarchyInterface->GetNodeAssumedVisible(node);
177        //CullingLogManager::GetSingleton()->LogMessage(d.str());
178        return mHierarchyInterface->GetNodeAssumedVisible(node) > 0;
179}
180//-----------------------------------------------------------------------
181inline void CoherentHierarchicalCullingManager::SkipQuery(HierarchyNode *node) const
182{
183        //-- set node to be visible in this frame, then traverse it
184        mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId());
185       
186        mHierarchyInterface->PullUpVisibility(node);                   
187        mHierarchyInterface->TraverseNode(node);
188}
189//-----------------------------------------------------------------------
190bool CoherentHierarchicalCullingManager::NodeInvalid(HierarchyNode *node) const
191{
192        // parent was tested invisible in this frame
193    const bool nodeInvalid = (
194                    mHierarchyInterface->GetParent(node) &&
195                    (mHierarchyInterface->LastVisited(node) == mHierarchyInterface->GetFrameId()) &&
196                    !mHierarchyInterface->IsNodeVisible(mHierarchyInterface->GetParent(node))
197           );
198
199       
200        if (nodeInvalid)
201        {
202                CullingLogManager::GetSingleton()->LogMessage("node invalid");
203        }
204
205        return nodeInvalid;
206}
207//-----------------------------------------------------------------------
208void CoherentHierarchicalCullingManager::SetTestGeometryForVisibleLeaves(const bool testGeometry)
209{
210        mTestGeometryForVisibleLeaves = testGeometry;
211}
212//-----------------------------------------------------------------------
213bool CoherentHierarchicalCullingManager::GetTestGeometryForVisibleLeaves()
214{
215        return mTestGeometryForVisibleLeaves;
216}
217
218}
Note: See TracBrowser for help on using the repository browser.