#include "CoherentHierarchicalCullingManager.h" #include namespace GtpVisibility { //----------------------------------------------------------------------- CoherentHierarchicalCullingManager:: CoherentHierarchicalCullingManager(): mAssumedVisibility(0), mThreshold(0) { // initialise random generator because of assumed visibility srand(time(NULL)); } //----------------------------------------------------------------------- void CoherentHierarchicalCullingManager::RenderScene() { QueryQueue queryQueue; unsigned int visiblePixels = 0; bool isAvailable = false; //-- PART 1: process finished occlusion queries while (!mHierarchyInterface->GetQueue()->empty() || !queryQueue.empty()) { while (!queryQueue.empty() && queryQueue.front().second->GetQueryResult(visiblePixels, mHierarchyInterface->GetQueue()->empty())) { HierarchyNode *node = queryQueue.front().first; queryQueue.pop(); if (visiblePixels > mVisibilityThreshold) { mHierarchyInterface->PullUpVisibility(node); mHierarchyInterface->TraverseNode(node); } else { 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); } } else { // 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); // if visibility is assumed to be true in this frame bool assumeVisible = wasVisible && (mAssumedVisibility > 0) && DecideVisible(node); // identify nodes that we cannot skip queries for // geometry not only in leaves => test for renderable geometry bool issueQuery = !wasVisible || (mHierarchyInterface->HasGeometry(node) && !assumeVisible); // reset node's visibility classification mHierarchyInterface->SetNodeVisible(node, !issueQuery && assumeVisible); // 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-> IssueOcclusionQuery(node, wasVisible))); } // always traverse a node if it was visible if (wasVisible) { mHierarchyInterface->TraverseNode(node); } } } } } //----------------------------------------------------------------------- void CoherentHierarchicalCullingManager::SetAssumedVisibility(unsigned int assumedVisibility) { mAssumedVisibility = assumedVisibility; mThreshold = 0; if (mAssumedVisibility > 0) { mThreshold = RAND_MAX - RAND_MAX / mAssumedVisibility; } //std::stringstream d; d << "*** setting assumed vis: " << mAssumedVisibility; Ogre::LogManager::getSingleton().logMessage(d.str()); } //----------------------------------------------------------------------- bool CoherentHierarchicalCullingManager::DecideVisible(HierarchyNode *node) const { /*bool result = rand() < mThreshold; std::stringstream d; d << "Assumed vis: " << mAssumedVisibility << ", result: " << result; Ogre::LogManager::getSingleton().logMessage(d.str()); return result;*/ return rand() < mThreshold; } } // namespace GtpVisibility