in libraries/hvvr/raycaster/traverse_ref_bvh.cpp [134:217]
uint32_t traverseTiles(
uint32_t* triIndices, uint32_t maxTriCount,
TileFrame& frame, uint32_t top, const Frustum& frustum)
{
(void)maxTriCount;
if (frustum.degenerate)
return 0;
uint32_t triCount = 0;
while (top > 0) {
// pop the node stack
top--;
// grab a node to test the children of
const BVHNode* node = frame.stack[top].node;
// tile frustum vs 4x AABB of children, corresponding bit is set if AABB is hit
uint32_t mask = frustum.testBVHNodeChildren(*node);
// no children hit? Move onto the next node
if (!mask)
continue;
// were any of the hit children leaf nodes? If so, add the children to the output list.
uint32_t leaf = mask & node->boxData.leafMask;
if (leaf) {
// spend some additional time to refine the test results
// this is a tradeoff between extra traversal time, vs extra intersection time/memory
// if we don't do this, we'll end up with more triangles to test later on
mask = frustum.testBVHNodeChildrenRefine(*node, mask);
leaf = mask & node->boxData.leafMask;
if (leaf) {
for (int c = 0; c < childCount; c++) {
if ((leaf & (1 << c)) == 0)
continue; // this child was culled
uint32_t triIndexStart = node->boxData.leaf.triIndex[c];
uint32_t triIndexEnd = node->boxData.leaf.triIndex[c + 1];
for (uint32_t triIndex = triIndexStart; triIndex < triIndexEnd; triIndex++) {
assert(triCount < maxTriCount);
triIndices[triCount++] = triIndex;
}
}
}
}
// strip leaf nodes from the hit mask, now we only care about the remaining hit internal nodes
mask &= ~node->boxData.leafMask;
// if there's nothing left, move onto the next stack entry
if (!mask)
continue;
// This is needed because block cull inserts nodes that contain a child mix of hit leaf nodes and hit internal
// nodes up to 4 times into the stack. Leaf node children are grouped into a single entry w/ hit mask, internal node
// children each get their own entry. This test prevents the leaf entry from spawning duplicate copies of the
// prepopulated sibling internal nodes.
// mask will be 0 for internal nodes, or the leaf hit mask for nodes which contain leaf children
if (frame.stack[top].mask)
continue;
// conservative min ray bundle distance to children along the primary traversal axis
float childDist[childCount];
for (int c = 0; c < childCount; c++) {
childDist[c] = -((float*)((uintptr_t)node + frustum.distanceEstimateOffset))[c];
}
// insert each surviving internal child into the stack, closest node goes at top of stack
for (int c = 0; c < childCount; c++) {
if ((mask & (1 << c)) == 0)
continue; // this child was culled
uint32_t slot = top++;
for (; slot > 0; slot--) {
if (frame.stack[slot - 1].tMin >= childDist[c])
break;
frame.stack[slot] = frame.stack[slot - 1];
}
frame.stack[slot].node = node + node->boxData.children.offset[c];
frame.stack[slot].tMin = childDist[c];
frame.stack[slot].mask = 0;
}
}
return triCount;
}