#include "CoherentHierarchicalCullingManager2.h" #include "CullingLogManager.h" #include #include namespace GtpVisibility { //----------------------------------------------------------------------- CoherentHierarchicalCullingManager2::CoherentHierarchicalCullingManager2() { SetAssumedVisibility(0); // initialise random generator in case we use assumed visibility //srand(time(NULL)); } //----------------------------------------------------------------------- CoherentHierarchicalCullingManager2::CoherentHierarchicalCullingManager2( const unsigned int assumedVisibility) { SetAssumedVisibility(assumedVisibility); // initialise random generator in case we use assumed visibility //srand(time(NULL)); } //----------------------------------------------------------------------- #if 1 void CoherentHierarchicalCullingManager2::RenderScene() { //CullingLogManager::GetSingleton()->LogMessage("chc"); QueryQueue queryQueue; unsigned int visiblePixels = 0; ///////////// //-- PART 1: process finished occlusion queries while (!mHierarchyInterface->GetQueue()->empty() || !queryQueue.empty()) { bool resultAvailable = false; const bool nodeQueueEmpty = mHierarchyInterface->GetQueue()->empty(); const int queryQueueSize = (int)queryQueue.size(); bool queryAvailable = true; //-- only wait for result if there are no nodes to process while (!queryQueue.empty() && (queryAvailable = queryQueue.front().second->GetQueryResult(visiblePixels, false))) { HierarchyNode *node = queryQueue.front().first; queryQueue.pop(); // render nodes if queue is still idle ... if (1&&nodeQueueEmpty) { std::stringstream d; d << "qu: " << queryQueueSize; CullingLogManager::GetSingleton()->LogMessage(d.str()); } if (visiblePixels > mVisibilityThreshold) { // check visibility to ensure that we traverse node only once // (important for interior nodes with geometry if (!mHierarchyInterface->IsNodeVisible(node)) { mHierarchyInterface->TraverseNode(node); } mHierarchyInterface->PullUpVisibility(node); } else { mHierarchyInterface->SetNodeVisible(node, false); ++ mNumQueryCulledNodes; if (mVisualizeCulledNodes) { mHierarchyInterface->VisualizeCulledNode(node, QUERY_CULLED); } } } if (!queryAvailable) { // query not yet available => render some geometry HierarchyNode *node = queryQueue.front().first; // check visibility to ensure that we traverse node only once // (important for interior nodes with geometry if (!mHierarchyInterface->IsNodeVisible(node)) { mHierarchyInterface->SetNodeVisible(node, true); mHierarchyInterface->TraverseNode(node); } } //-- PART 2: hierarchical traversal if (!mHierarchyInterface->GetQueue()->empty()) { HierarchyNode *node = mHierarchyInterface->GetQueue()->top(); mHierarchyInterface->GetQueue()->pop(); bool intersects = false; if (!mHierarchyInterface->CheckFrustumVisible(node, intersects)) { ++ mNumFrustumCulledNodes; if (mVisualizeCulledNodes) { mHierarchyInterface->VisualizeCulledNode(node, FRUSTUM_CULLED); } } //-- if node intersects near plane, skip query because wrong results possible else if (intersects) { SkipQuery(node); } else { // identify previously visible nodes bool wasVisible = mHierarchyInterface->IsNodeVisible(node) && (mHierarchyInterface->LastVisited(node) == mHierarchyInterface->GetFrameId() - 1); // if we assume node to be visible in this frame => skip query bool skipQuery = wasVisible && (mAssumedVisibility > 0) && DecideVisible(node) && mHierarchyInterface->HasGeometry(node); if (skipQuery) { SkipQuery(node); continue; } // identify nodes that we cannot skip queries for // geometry not only in leaves => test for renderable geometry bool issueQuery = !wasVisible || mHierarchyInterface->HasGeometry(node); // reset node's visibility classification // set visibe if geometry in node so we only traverse once mHierarchyInterface->SetNodeVisible(node, wasVisible && issueQuery); // update node's visited flag mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId()); // skip testing previously visible nodes without geometry if (issueQuery) { ++ mNumQueriesIssued; queryQueue.push(QueryPair(node, mHierarchyInterface-> IssueNodeOcclusionQuery(node, wasVisible))); } // always traverse a node if it was visible if (wasVisible) { mHierarchyInterface->TraverseNode(node); } } } } } #else void CoherentHierarchicalCullingManager2::RenderScene() { //CullingLogManager::GetSingleton()->LogMessage("chc"); QueryQueue queryQueue; unsigned int visiblePixels = 0; ///////////// //-- PART 1: process finished occlusion queries while (!mHierarchyInterface->GetQueue()->empty() || !queryQueue.empty()) { bool resultAvailable = false; const bool nodeQueueEmpty = mHierarchyInterface->GetQueue()->empty(); const int queryQueueSize = (int)queryQueue.size(); //-- only wait for result if there are no nodes to process while (!queryQueue.empty() && queryQueue.front().second->GetQueryResult(visiblePixels, nodeQueueEmpty)) { HierarchyNode *node = queryQueue.front().first; queryQueue.pop(); // render nodes if queue is still idle ... if (1&&nodeQueueEmpty) { std::stringstream d; d << "qu: " << queryQueueSize; CullingLogManager::GetSingleton()->LogMessage(d.str()); } if (visiblePixels > mVisibilityThreshold) { // in case geometry is in omterior node: ensure that we only traverse once if (!mHierarchyInterface->IsNodeVisible(node)) { mHierarchyInterface->TraverseNode(node); } mHierarchyInterface->PullUpVisibility(node); } else { mHierarchyInterface->SetNodeVisible(node, false); ++ mNumQueryCulledNodes; if (mVisualizeCulledNodes) { mHierarchyInterface->VisualizeCulledNode(node, QUERY_CULLED); } } } //-- PART 2: hierarchical traversal if (!mHierarchyInterface->GetQueue()->empty()) { HierarchyNode *node = mHierarchyInterface->GetQueue()->top(); mHierarchyInterface->GetQueue()->pop(); bool intersects = false; if (!mHierarchyInterface->CheckFrustumVisible(node, intersects)) { ++ mNumFrustumCulledNodes; if (mVisualizeCulledNodes) { mHierarchyInterface->VisualizeCulledNode(node, FRUSTUM_CULLED); } } //-- if node intersects near plane, skip query because wrong results possible else if (intersects) { SkipQuery(node); } else { // identify previously visible nodes bool wasVisible = mHierarchyInterface->IsNodeVisible(node) && (mHierarchyInterface->LastVisited(node) == mHierarchyInterface->GetFrameId() - 1); // if we assume node to be visible in this frame => skip query bool skipQuery = wasVisible && (mAssumedVisibility > 0) && DecideVisible(node) && mHierarchyInterface->HasGeometry(node); if (skipQuery) { SkipQuery(node); continue; } // identify nodes that we cannot skip queries for // geometry not only in leaves => test for renderable geometry bool issueQuery = !wasVisible || mHierarchyInterface->HasGeometry(node); // reset node's visibility classification // set visibe if geometry in node so we only traverse once mHierarchyInterface->SetNodeVisible(node, wasVisible && issueQuery); // update node's visited flag mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId()); // skip testing previously visible nodes without geometry if (issueQuery) { ++ mNumQueriesIssued; queryQueue.push(QueryPair(node, mHierarchyInterface-> IssueNodeOcclusionQuery(node, wasVisible))); } // always traverse a node if it was visible if (wasVisible) { mHierarchyInterface->TraverseNode(node); } } } } } #endif //----------------------------------------------------------------------- void CoherentHierarchicalCullingManager2::SetAssumedVisibility(const unsigned int assumedVisibility) { mAssumedVisibility = assumedVisibility; mThreshold = 0; if (mAssumedVisibility > 0) { mThreshold = RAND_MAX - RAND_MAX / mAssumedVisibility; // fix visibility if (mAssumedVisibility > 100) mThreshold = RAND_MAX; } } //----------------------------------------------------------------------- inline bool CoherentHierarchicalCullingManager2::DecideVisible(HierarchyNode *node) const { return rand() < mThreshold; } //----------------------------------------------------------------------- inline void CoherentHierarchicalCullingManager2::SkipQuery(HierarchyNode *node) const { // -- set node to be visible in this frame, then traverse it mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId()); mHierarchyInterface->PullUpVisibility(node); mHierarchyInterface->TraverseNode(node); } } // namespace GtpVisibility