#include "CHCTraverser.h" #include "SceneEntity.h" namespace CHCDemoEngine { CHCTraverser::CHCTraverser() {} OcclusionQuery *CHCTraverser::IssueOcclusionQueryWithGeometry(BvhNode *node) { // render out what is left in the qeue if (mUseRenderQueue) ApplyRenderQueue(); OcclusionQuery *query = mQueryHandler.RequestQuery(); query->AddNode(node); ++ mStats.mNumIssuedQueries; query->BeginQuery(); RenderNode(node); if (mUseRenderQueue) ApplyRenderQueue(); query->EndQuery(); return query; } void CHCTraverser::Traverse() { //-- PART 1: process finished occlusion queries while (!mDistanceQueue.empty() || !mQueryQueue.empty()) { while (!mQueryQueue.empty() && (mQueryQueue.front()->ResultAvailable() || mDistanceQueue.empty())) { OcclusionQuery *query = mQueryQueue.front(); mQueryQueue.pop(); // wait until result available int visiblePixels = query->GetQueryResult(); if (visiblePixels > mVisibilityThreshold) { BvhNode *node = query->GetFrontNode(); node->SetAssumedVisibleFrameId(mFrameId + mAssumedVisibleFrames); node->SetVisible(true); mBvh->MakeParentsVisible(node); TraverseNode(node); } else { ++ mStats.mNumQueryCulledNodes; } } //-- PART 2: hierarchical traversal if (!mDistanceQueue.empty()) { BvhNode *node = mDistanceQueue.top(); mDistanceQueue.pop(); if (mBvh->IsWithinViewFrustum(node)) { // for near plane intersecting bounding box possible // wrong results => skip occlusion query if (IntersectsNearPlane(node)) { // update node's visited flag node->SetLastVisitedFrame(mFrameId); node->SetVisible(true); mBvh->MakeParentsVisible(node); TraverseNode(node); } else { // identify previously visible nodes const bool wasVisible = node->IsVisible() && (node->GetLastVisitedFrame() == mFrameId - 1); // identify nodes that we cannot skip queries for const bool queryFeasible = (!wasVisible || (node->IsVirtualLeaf() && (node->GetAssumedVisibleFrameId() <= mFrameId))); // update node's visited flag node->SetLastVisitedFrame(mFrameId); // skip testing previously visible interior nodes if (queryFeasible) { OcclusionQuery *query; // if this node is a previous visible leaf: // leaves will be rendered anyway => we can directly query the real geometry if (wasVisible && mUseOptimization) query = IssueOcclusionQueryWithGeometry(node); else query = IssueOcclusionQuery(node); mQueryQueue.push(query); } else { if (node->IsVirtualLeaf()) { node->SetVisible(true); mBvh->MakeParentsVisible(node); } else // reset visibility classification { node->SetVisible(false); } } // always traverse a node if it was visible if (wasVisible) TraverseNode(node); } } else { // for stats ++ mStats.mNumFrustumCulledNodes; } } } } }