[2755] | 1 | #include "CHCTraverser.h"
|
---|
[2764] | 2 | #include "SceneEntity.h"
|
---|
[2755] | 3 |
|
---|
[2764] | 4 |
|
---|
[2776] | 5 | namespace CHCDemoEngine
|
---|
[2755] | 6 | {
|
---|
| 7 |
|
---|
[2767] | 8 | CHCTraverser::CHCTraverser()
|
---|
| 9 | {}
|
---|
[2755] | 10 |
|
---|
| 11 |
|
---|
[2792] | 12 | OcclusionQuery *CHCTraverser::IssueOcclusionQueryWithGeometry(BvhNode *node)
|
---|
| 13 | {
|
---|
[2795] | 14 | // render out what is left in the qeue
|
---|
| 15 | if (mUseRenderQueue) ApplyRenderQueue();
|
---|
| 16 |
|
---|
[2792] | 17 | OcclusionQuery *query = mQueryHandler.RequestQuery();
|
---|
| 18 | query->AddNode(node);
|
---|
| 19 |
|
---|
| 20 | ++ mStats.mNumIssuedQueries;
|
---|
| 21 |
|
---|
| 22 | query->BeginQuery();
|
---|
| 23 |
|
---|
| 24 | RenderNode(node);
|
---|
[2795] | 25 | if (mUseRenderQueue) ApplyRenderQueue();
|
---|
[2792] | 26 |
|
---|
| 27 | query->EndQuery();
|
---|
| 28 |
|
---|
| 29 | return query;
|
---|
| 30 | }
|
---|
| 31 |
|
---|
| 32 |
|
---|
[2767] | 33 | void CHCTraverser::Traverse()
|
---|
[2755] | 34 | {
|
---|
| 35 | //-- PART 1: process finished occlusion queries
|
---|
[2767] | 36 | while (!mDistanceQueue.empty() || !mQueryQueue.empty())
|
---|
[2755] | 37 | {
|
---|
[2767] | 38 | while (!mQueryQueue.empty() &&
|
---|
| 39 | (mQueryQueue.front()->ResultAvailable() || mDistanceQueue.empty()))
|
---|
[2755] | 40 | {
|
---|
[2767] | 41 | OcclusionQuery *query = mQueryQueue.front();
|
---|
| 42 | mQueryQueue.pop();
|
---|
[2755] | 43 |
|
---|
| 44 | // wait until result available
|
---|
[2764] | 45 | int visiblePixels = query->GetQueryResult();
|
---|
[2755] | 46 |
|
---|
[2764] | 47 | if (visiblePixels > mVisibilityThreshold)
|
---|
[2755] | 48 | {
|
---|
[2764] | 49 | BvhNode *node = query->GetFrontNode();
|
---|
[2776] | 50 | node->SetAssumedVisibleFrameId(mFrameId + mAssumedVisibleFrames);
|
---|
[2764] | 51 |
|
---|
[2770] | 52 | node->SetVisible(true);
|
---|
[2764] | 53 | mBvh->MakeParentsVisible(node);
|
---|
[2755] | 54 | TraverseNode(node);
|
---|
| 55 | }
|
---|
| 56 | else
|
---|
| 57 | {
|
---|
[2776] | 58 |
|
---|
[2764] | 59 | ++ mStats.mNumQueryCulledNodes;
|
---|
[2755] | 60 | }
|
---|
| 61 | }
|
---|
| 62 |
|
---|
| 63 | //-- PART 2: hierarchical traversal
|
---|
| 64 | if (!mDistanceQueue.empty())
|
---|
| 65 | {
|
---|
[2764] | 66 | BvhNode *node = mDistanceQueue.top();
|
---|
[2755] | 67 | mDistanceQueue.pop();
|
---|
| 68 |
|
---|
[2764] | 69 | if (mBvh->IsWithinViewFrustum(node))
|
---|
[2755] | 70 | {
|
---|
| 71 | // for near plane intersecting bounding box possible
|
---|
| 72 | // wrong results => skip occlusion query
|
---|
[2764] | 73 | if (IntersectsNearPlane(node))
|
---|
[2755] | 74 | {
|
---|
| 75 | // update node's visited flag
|
---|
[2765] | 76 | node->SetLastVisitedFrame(mFrameId);
|
---|
[2755] | 77 | node->SetVisible(true);
|
---|
[2764] | 78 | mBvh->MakeParentsVisible(node);
|
---|
| 79 |
|
---|
[2755] | 80 | TraverseNode(node);
|
---|
| 81 | }
|
---|
| 82 | else
|
---|
| 83 | {
|
---|
| 84 | // identify previously visible nodes
|
---|
[2765] | 85 | const bool wasVisible = node->IsVisible() && (node->GetLastVisitedFrame() == mFrameId - 1);
|
---|
[2755] | 86 |
|
---|
| 87 | // identify nodes that we cannot skip queries for
|
---|
[2792] | 88 | const bool queryFeasible = (!wasVisible ||
|
---|
[2776] | 89 | (node->IsVirtualLeaf() && (node->GetAssumedVisibleFrameId() <= mFrameId)));
|
---|
[2755] | 90 |
|
---|
| 91 | // update node's visited flag
|
---|
[2765] | 92 | node->SetLastVisitedFrame(mFrameId);
|
---|
[2755] | 93 |
|
---|
| 94 | // skip testing previously visible interior nodes
|
---|
[2792] | 95 | if (queryFeasible)
|
---|
[2755] | 96 | {
|
---|
[2792] | 97 | OcclusionQuery *query;
|
---|
| 98 |
|
---|
| 99 | // if this node is a previous visible leaf:
|
---|
| 100 | // leaves will be rendered anyway => we can directly query the real geometry
|
---|
| 101 | if (wasVisible && mUseOptimization)
|
---|
| 102 | query = IssueOcclusionQueryWithGeometry(node);
|
---|
| 103 | else
|
---|
| 104 | query = IssueOcclusionQuery(node);
|
---|
| 105 |
|
---|
[2767] | 106 | mQueryQueue.push(query);
|
---|
[2755] | 107 | }
|
---|
[2776] | 108 | else
|
---|
| 109 | {
|
---|
| 110 | if (node->IsVirtualLeaf())
|
---|
| 111 | {
|
---|
| 112 | node->SetVisible(true);
|
---|
| 113 | mBvh->MakeParentsVisible(node);
|
---|
| 114 | }
|
---|
| 115 | else // reset visibility classification
|
---|
| 116 | {
|
---|
| 117 | node->SetVisible(false);
|
---|
| 118 | }
|
---|
| 119 | }
|
---|
| 120 |
|
---|
[2755] | 121 | // always traverse a node if it was visible
|
---|
[2764] | 122 | if (wasVisible)
|
---|
[2755] | 123 | TraverseNode(node);
|
---|
| 124 | }
|
---|
| 125 | }
|
---|
| 126 | else
|
---|
| 127 | {
|
---|
| 128 | // for stats
|
---|
[2764] | 129 | ++ mStats.mNumFrustumCulledNodes;
|
---|
[2755] | 130 | }
|
---|
| 131 | }
|
---|
| 132 | }
|
---|
| 133 | }
|
---|
| 134 |
|
---|
| 135 | } |
---|