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

Revision 2561, 7.0 KB checked in by mattausch, 17 years ago (diff)
RevLine 
[59]1#include "CoherentHierarchicalCullingManager.h"
[2287]2#include "CullingLogManager.h"
3
[2280]4#include <time.h>
[2455]5#include <sstream>
[59]6
[2455]7
[59]8namespace GtpVisibility {
9
[2455]10
11
[59]12//-----------------------------------------------------------------------
[2455]13CoherentHierarchicalCullingManager::CoherentHierarchicalCullingManager():
14mAssumedVisibility(0)
[142]15{
16}
17//-----------------------------------------------------------------------
[2258]18CoherentHierarchicalCullingManager::CoherentHierarchicalCullingManager(
[2455]19                                                                                                                const unsigned int assumedVisibility):
20mAssumedVisibility(assumedVisibility)
[155]21{
22}
23//-----------------------------------------------------------------------
[2455]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//-----------------------------------------------------------------------
[59]34void CoherentHierarchicalCullingManager::RenderScene()
35{
[2292]36        if (0) CullingLogManager::GetSingleton()->LogMessage("chc");
[86]37        unsigned int visiblePixels = 0;
[925]38       
[2171]39        /////////////
[59]40        //-- PART 1: process finished occlusion queries
[2171]41
[2555]42        while (!mHierarchyInterface->GetQueue()->empty() || !mQueryQueue.empty())
[59]43        {
[2332]44                //////////
[955]45                //-- only wait for result if there are no nodes to process
[2455]46
[2555]47                while (!mQueryQueue.empty() &&
48                           (NodeInvalid(mQueryQueue.front().first) ||
49                            mQueryQueue.front().second->GetQueryResult(
[2332]50                                             visiblePixels, mHierarchyInterface->GetQueue()->empty())))
[59]51                {
[2555]52                        HierarchyNode *node = mQueryQueue.front().first;
53                        mQueryQueue.pop();
[2332]54
55                        // parent was tested invisible => remove children from queue
[2561]56                        // "invalid nodes" happen for hierarchies where interiors store geometry
57                        if (NodeInvalid(node)) continue;
[2455]58
[2332]59                        // tested visible
[96]60                        if (visiblePixels > mVisibilityThreshold)
[59]61                        {
[2455]62                                // assing the #frames the node is assumed to stay visible
63                                AssignAssumedVisibility(node);
64
[2561]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
[348]70                                if (!mHierarchyInterface->IsNodeVisible(node))
71                                        mHierarchyInterface->TraverseNode(node);
[726]72
[59]73                                mHierarchyInterface->PullUpVisibility(node);
74                        }
75                        else
[142]76                        {       
[348]77                                mHierarchyInterface->SetNodeVisible(node, false);
78
[2332]79                ++ mNumQueryCulledNodes;
[2455]80
[348]81                                if (mVisualizeCulledNodes)
[112]82                                        mHierarchyInterface->VisualizeCulledNode(node, QUERY_CULLED);
[59]83                        }
[2332]84                       
85                        // update node's visited flag
86                        mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId());   
[85]87                }
[87]88               
[2455]89                ////////////////
[59]90                //-- PART 2: hierarchical traversal
[2455]91
[59]92                if (!mHierarchyInterface->GetQueue()->empty())
93                {
94                        HierarchyNode *node = mHierarchyInterface->GetQueue()->top();
95                        mHierarchyInterface->GetQueue()->pop();
96                               
[2332]97                        // parent was tested invisible => remove children from queue
[2561]98                        if (NodeInvalid(node)) continue;
[2332]99
[59]100                        bool intersects = false;
101
[74]102                        if (!mHierarchyInterface->CheckFrustumVisible(node, intersects))
[130]103                        {
[2287]104                                ++ mNumFrustumCulledNodes;
105
[147]106                                if (mVisualizeCulledNodes)
[113]107                                        mHierarchyInterface->VisualizeCulledNode(node, FRUSTUM_CULLED);
[59]108                        }
[1486]109                        //-- if node intersects near plane, skip query because wrong results possible
[155]110                        else if (intersects)
111                        {
112                                SkipQuery(node);
113                        }
[74]114                        else
[59]115                        {
[148]116                                // identify previously visible nodes
117                                bool wasVisible = mHierarchyInterface->IsNodeVisible(node) &&
118                                        (mHierarchyInterface->LastVisited(node) == mHierarchyInterface->GetFrameId() - 1);
[346]119                               
[155]120                                // if we assume node to be visible in this frame => skip query
[2455]121                                const bool skipQuery = wasVisible &&
[2332]122                                                                           DecideVisible(node) &&
123                                                                           mHierarchyInterface->HasGeometry(node);
[348]124
125                                if (skipQuery)
[74]126                                {
[155]127                                        SkipQuery(node);
[74]128                                        continue;
129                                }
[59]130
[148]131                // identify nodes that we cannot skip queries for
[87]132                                // geometry not only in leaves => test for renderable geometry
[348]133                                bool issueQuery = !wasVisible || mHierarchyInterface->HasGeometry(node);
[345]134                                                       
[2455]135                                // set node's visibility classification
136                                // we identify previously visible / invisible nodes in the query queue
[348]137                                mHierarchyInterface->SetNodeVisible(node, wasVisible && issueQuery);
[59]138
[87]139                                if (issueQuery)
[74]140                                {
[147]141                                        ++ mNumQueriesIssued;
[142]142                                       
[2555]143                                        const bool testGeometry =
144                                                wasVisible && mHierarchyInterface->IsLeaf(node) && mTestGeometryForVisibleLeaves;
[2455]145
[2555]146                                        mQueryQueue.push(QueryPair(node, mHierarchyInterface->
[2455]147                                                IssueNodeOcclusionQuery(node, testGeometry)));
[74]148                                }
[2332]149                                else
150                                {
[2455]151                                        // skip testing previously visible nodes without geometry
152                    // just update node's visited flag
[2332]153                                        mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId());
154                                }
155
[74]156                                // always traverse a node if it was visible
157                                if (wasVisible)
158                                {
[158]159                                        mHierarchyInterface->TraverseNode(node);
[74]160                                }
[59]161                        }
162                }
163        }
164}
[142]165//-----------------------------------------------------------------------
[345]166void CoherentHierarchicalCullingManager::SetAssumedVisibility(const unsigned int assumedVisibility)
[142]167{
168        mAssumedVisibility = assumedVisibility;
169}
170//-----------------------------------------------------------------------
[345]171inline bool CoherentHierarchicalCullingManager::DecideVisible(HierarchyNode *node) const
[142]172{
[2455]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;
[142]177}
[155]178//-----------------------------------------------------------------------
[345]179inline void CoherentHierarchicalCullingManager::SkipQuery(HierarchyNode *node) const
[155]180{
[2292]181        //-- set node to be visible in this frame, then traverse it
[155]182        mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId());
[345]183       
[155]184        mHierarchyInterface->PullUpVisibility(node);                   
[158]185        mHierarchyInterface->TraverseNode(node);
[155]186}
[2332]187//-----------------------------------------------------------------------
188bool CoherentHierarchicalCullingManager::NodeInvalid(HierarchyNode *node) const
189{
190        // parent was tested invisible in this frame
[2556]191    const bool nodeInvalid = (
[2555]192                    mHierarchyInterface->GetParent(node) &&
193                    (mHierarchyInterface->LastVisited(node) == mHierarchyInterface->GetFrameId()) &&
194                    !mHierarchyInterface->IsNodeVisible(mHierarchyInterface->GetParent(node))
195           );
[2556]196        return nodeInvalid;
[2332]197}
[2455]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.