[243] | 1 | void NV_PureKdTreeRenderAction::TraverseNode(KdTreeNode *pCurrNode) |
---|
| 2 | { |
---|
| 3 | if (pCurrNode->m_bLeaf) |
---|
| 4 | { |
---|
| 5 | // this has a frame counter to prevent double rendering |
---|
| 6 | pCurrNode->RenderGeometry(); |
---|
| 7 | } |
---|
| 8 | else |
---|
| 9 | { |
---|
| 10 | Point3f ptViewpoint = GetState()->GetCamera()->GetPosition(); |
---|
| 11 | |
---|
| 12 | //---- insert the children in the reverse order as they shall be dealt with |
---|
| 13 | if (ptViewpoint[pCurrNode->m_iSplitAxis] > pCurrNode->m_fSplitValue) |
---|
| 14 | { |
---|
| 15 | m_TraverseStack.Push(pCurrNode->m_pLeftChild); |
---|
| 16 | m_TraverseStack.Push(pCurrNode->m_pRightChild); |
---|
| 17 | } |
---|
| 18 | else |
---|
| 19 | { |
---|
| 20 | m_TraverseStack.Push(pCurrNode->m_pRightChild); |
---|
| 21 | m_TraverseStack.Push(pCurrNode->m_pLeftChild); |
---|
| 22 | } |
---|
| 23 | } // no leaf |
---|
| 24 | } |
---|
| 25 | |
---|
| 26 | |
---|
| 27 | //---- the actual render algorithm |
---|
| 28 | void NV_PureKdTreeRenderAction::RenderSorted() |
---|
| 29 | { |
---|
| 30 | KdTreeNode * pCurrNode; |
---|
| 31 | int iTestCounter = 0; |
---|
| 32 | |
---|
| 33 | //---- clear the two needed datastructures |
---|
| 34 | m_TraverseStack.Clear(); |
---|
| 35 | m_NVTestQueue.Clear(); |
---|
| 36 | |
---|
| 37 | //---- generate the occlusion queries |
---|
| 38 | glGenOcclusionQueriesNV(m_nNumNodes, m_pOcclusionQueries); |
---|
| 39 | |
---|
| 40 | //---- take the root as a start |
---|
| 41 | m_pKdTree->m_iPlaneMask = 0x3f; // = 0011 1111 which means that at the beginning, all six planes have to frustum culled |
---|
| 42 | m_TraverseStack.Push(m_pKdTree); |
---|
| 43 | |
---|
| 44 | //---- the loop |
---|
| 45 | while ((!m_TraverseStack.Empty()) || (!m_NVTestQueue.Empty())) |
---|
| 46 | { |
---|
| 47 | bool result_available; |
---|
| 48 | |
---|
| 49 | while (!m_NVTestQueue.Empty() && |
---|
| 50 | (m_TraverseStack.Empty() || |
---|
| 51 | (result_available = ResultAvailable(m_NVTestQueue.GetFirst()->m_nTest)) |
---|
| 52 | ) |
---|
| 53 | ) |
---|
| 54 | { |
---|
| 55 | pCurrNode = m_NVTestQueue.GetFirst(); m_NVTestQueue.RemoveFirst(); |
---|
| 56 | |
---|
| 57 | // the next line is only interesting if we want to avoid double rendering already here: |
---|
| 58 | //bool was_visible = pCurrNode->m_bVisible && (m_nLastVisitedId == (GetCurrentFrame() - 1)); |
---|
| 59 | |
---|
| 60 | // update visibility classification (this is the wait variety!) |
---|
| 61 | pCurrNode->m_bVisible = GetVisiblePixels(pCurrNode->m_nTest) > Settings::Global()->get_nvocc_pixel_treshold(); |
---|
| 62 | pCurrNode->m_nLastVisitedId = GetCurrentFrame(); |
---|
| 63 | |
---|
| 64 | if (pCurrNode->m_bVisible) // && !was_visible) // note: could prevent double rendering already here! |
---|
| 65 | { |
---|
| 66 | pCurrNode->MakeParentsVisible(); |
---|
| 67 | TraverseNode(pCurrNode); |
---|
| 68 | } // visible |
---|
| 69 | } |
---|
| 70 | |
---|
| 71 | //---- the second part manages the distance heap |
---|
| 72 | if (!m_TraverseStack.Empty()) |
---|
| 73 | { |
---|
| 74 | //---- get the element with the lowest distance |
---|
| 75 | pCurrNode = m_TraverseStack.Pop(); |
---|
| 76 | |
---|
| 77 | // question: what is the difference if we do frustum culling only after setting visibility? |
---|
| 78 | if (pCurrNode->IsWithinViewFrustum()) |
---|
| 79 | { |
---|
| 80 | bool was_visible = pCurrNode->m_bVisible && (pCurrNode->m_nLastVisitedId == (GetCurrentFrame() - 1)); |
---|
| 81 | |
---|
| 82 | // note: this is actually only done for internal nodes and could be skipped for leaf nodes |
---|
| 83 | // in which case leaf node double rendering could be prevented here (see above) |
---|
| 84 | pCurrNode->m_bVisible = FALSE; |
---|
| 85 | pCurrNode->m_nLastVisitedId = GetCurrentFrame(); |
---|
| 86 | |
---|
| 87 | if (pCurrNode->m_bLeaf || !was_visible) |
---|
| 88 | { |
---|
| 89 | if (pCurrNode->m_pSuccessor->IssueNVTest(m_pOcclusionQueries[iTestCounter])) ++iTestCounter; |
---|
| 90 | m_NVTestQueue.Append(pCurrNode); |
---|
| 91 | } |
---|
| 92 | |
---|
| 93 | if (was_visible) |
---|
| 94 | { |
---|
| 95 | TraverseNode(pCurrNode); |
---|
| 96 | } |
---|
| 97 | } |
---|
| 98 | } |
---|
| 99 | } |
---|
| 100 | |
---|
| 101 | //---- tell the driver that the occlusion queries won't be needed any more |
---|
| 102 | glDeleteOcclusionQueriesNV(m_nNumNodes, m_pOcclusionQueries); |
---|
| 103 | |
---|
| 104 | } |
---|