#include "CoherentHierarchicalCullingManager.h" namespace GtpVisibility { //----------------------------------------------------------------------- CoherentHierarchicalCullingManager::CoherentHierarchicalCullingManager(HierarchyInterface *hierarchyInterface): CullingManager(hierarchyInterface) { } //----------------------------------------------------------------------- void CoherentHierarchicalCullingManager::RenderScene() { QueryQueue queryQueue; mNumFrustumCulledNodes = mNumQueryCulledNodes = 0; //-- PART 1: process finished occlusion queries while (!mHierarchyInterface->GetQueue()->empty() || !queryQueue.empty()) { while (!queryQueue.empty() && (queryQueue.front().second->ResultAvailable() || mHierarchyInterface->GetQueue()->empty())) { HierarchyNode *node = queryQueue.front().first; // wait until result available unsigned int visiblePixels = queryQueue.front().second->GetQueryResult(); queryQueue.pop(); if (visiblePixels > mVisibilityThreshold) { mHierarchyInterface->PullUpVisibility(node); mHierarchyInterface->TraverseNode(node); } else { mNumQueryCulledNodes ++; } } //-- 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 ++; continue; } // if intersects near plane => skip occlusion query because wrong results possible if (intersects) { // update octant's visited flag mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId()); mHierarchyInterface->PullUpVisibility(node); mHierarchyInterface->TraverseNode(node); continue; } // identify previously visible nodes bool wasVisible = mHierarchyInterface->IsNodeVisible(node) && (mHierarchyInterface->LastVisited(node) == mHierarchyInterface->GetFrameId() - 1); // identify nodes that we cannot skip queries for bool mustQuery = !wasVisible || mHierarchyInterface->HasGeometry(node) || mHierarchyInterface->IsLeaf(node); // reset node's visibility classification mHierarchyInterface->SetNodeVisible(node, false); // update node's visited flag mHierarchyInterface->SetLastVisited(node, mHierarchyInterface->GetFrameId()); // skip testing previously visible interior nodes if (mustQuery) { queryQueue.push(QueryPair(node, mHierarchyInterface->IssueOcclusionQuery(node))); } // always traverse a node if it was visible if (wasVisible) { mHierarchyInterface->TraverseNode(node); } } } } } // namespace GtpVisibility