#include "PvsCollectionRenderer.h" #include "ViewCellsTree.h" using namespace std; namespace CHCDemoEngine { PvsCollectionRenderer::PvsCollectionRenderer(): RenderTraverser(), mViewCell(NULL) { } PvsCollectionRenderer::~PvsCollectionRenderer() { } void PvsCollectionRenderer::Traverse() { mPIS.clear(); //////////// //-- part1: do frustum culling + pvs while (!mDistanceQueue.empty()) { BvhNode *node = mDistanceQueue.top(); mDistanceQueue.pop(); if (mBvh->IsWithinViewFrustum(node)) { // for leaves: check if the geometry is already in PVS if (!node->IsVirtualLeaf() || IsNodeGeometryVisible(node, -1)) { TraverseNode(node); } else { mPIS.push_back(node); } } else { ++ mStats.mNumFrustumCulledNodes; } } int pisSize = (int)mPIS.size(); //////////// //-- part2: test the potentially invisible nodes static QueryQueue queries; BvhNodeContainer::const_iterator it, it_end = mPIS.end(); OcclusionQuery *query = mQueryHandler.RequestQuery(); query->Reset(); int querySize = 50; for (it = mPIS.begin(); it != it_end; ++ it) { query->AddNode(*it); if (query->GetSize() == querySize) { // issue multiquery IssueOcclusionQuery(*query); queries.push(query); // get next query query = mQueryHandler.RequestQuery(); query->Reset(); } } // query the rest of the nodes if (!query->IsEmpty()) { IssueOcclusionQuery(*query); queries.push(query); } static BvhNodeContainer probablyVisibleNodes; probablyVisibleNodes.clear(); int qsize = (int)queries.size(); int fqueries = 0; // get query results: collect probably visible nodes while (!queries.empty()) { OcclusionQuery *q = queries.front(); queries.pop(); const int visiblePixels = q->GetQueryResult(); if (visiblePixels > 0) { ++ fqueries; BvhNodeContainer::const_iterator bit, bit_end = q->GetNodes().end(); for (bit= q->GetNodes().begin(); bit != bit_end; ++ bit) { // query failed => render and add to probably visible nodes RenderNode(*bit); probablyVisibleNodes.push_back(*bit); } } } //cout << "probably visible: " << fqueries << " of " << qsize << " (" << (int)probablyVisibleNodes.size() << " of " << pisSize << " nodes)" << endl; ////////////// //-- part4: test probably visible nodes individually, update pvs of current view cell if (!mViewCell) return; // query all nodes individually BvhNodeContainer::const_iterator bit, bit_end = probablyVisibleNodes.end(); for (bit = probablyVisibleNodes.begin(); bit != bit_end; ++ bit) { BvhNode *n = *bit; // node intersects near plane => // add immediately because testing the bb could fail if (mBvh->IntersectsNearPlane(n)) { mViewCell->mPvs.AddEntry(mBvh, n); } else { queries.push(IssueOcclusionQuery(n)); } } // get query results: if visible, add node to pvs while (!queries.empty()) { OcclusionQuery *q = queries.front(); queries.pop(); const int visiblePixels = q->GetQueryResult(); if (visiblePixels > 0) { mViewCell->mPvs.AddEntry(mBvh, q->GetFrontNode()); } } } }