public int flattenBVHTree(BVHBuildNode node, ref int offset) { LinearBVHNode linearNode = nodes[offset]; linearNode.bounds = node.bounds; int myOffset = (offset)++; if (node.nPrimitives > 0) { //CHECK(!node->children[0] && !node->children[1]); //CHECK_LT(node->nPrimitives, 65536); linearNode.primitivesOffset = node.firstPrimOffset; linearNode.nPrimitives = node.nPrimitives; } else { // Create interior flattened BVH node linearNode.axis = Convert.ToByte(node.splitAxis); linearNode.nPrimitives = 0; flattenBVHTree(node.children[0], ref offset); linearNode.secondChildOffset = flattenBVHTree(node.children[1], ref offset); } return(myOffset); }
/// <inheritdoc /> public override bool IntersectP(Ray ray) { if (nodes == null) { return(false); } //ProfilePhase p(Prof::AccelIntersectP); Vector3D invDir = new Vector3D(1.0 / ray.Direction.X, 1.0 / ray.Direction.Y, 1.0 / ray.Direction.Z); bool[] dirIsNeg = new bool[3] { invDir.X < 0, invDir.Y < 0, invDir.Z < 0 }; int[] nodesToVisit = new int[64]; int toVisitOffset = 0, currentNodeIndex = 0; while (true) { LinearBVHNode node = nodes[currentNodeIndex]; if (node.bounds.IntersectP(ray, invDir, dirIsNeg)) { // Process BVH node _node_ for traversal if (node.nPrimitives > 0) { for (int i = 0; i < node.nPrimitives; ++i) { if (primitives[node.primitivesOffset + i].IntersectP( ray)) { return(true); } } if (toVisitOffset == 0) { break; } currentNodeIndex = nodesToVisit[--toVisitOffset]; } else { if (dirIsNeg[node.axis]) { /// second child first nodesToVisit[toVisitOffset++] = currentNodeIndex + 1; currentNodeIndex = node.secondChildOffset; } else { nodesToVisit[toVisitOffset++] = node.secondChildOffset; currentNodeIndex = currentNodeIndex + 1; } } } else { if (toVisitOffset == 0) { break; } currentNodeIndex = nodesToVisit[--toVisitOffset]; } } return(false); }
/// <inheritdoc /> public override bool Intersect(Ray ray, out SurfaceInteraction isect) { isect = null; if (nodes == null) { return(false); } //ProfilePhase p(Prof::AccelIntersect); bool hit = false; Vector3D invDir = new Vector3D(1.0 / ray.Direction.X, 1.0 / ray.Direction.Y, 1.0 / ray.Direction.Z); bool[] dirIsNeg = new bool[3] { invDir.X < 0, invDir.Y < 0, invDir.Z < 0 }; // Follow ray through BVH nodes to find primitive intersections int toVisitOffset = 0, currentNodeIndex = 0; int[] nodesToVisit = new int[64]; while (true) { LinearBVHNode node = nodes[currentNodeIndex]; // Check ray against BVH node if (node.bounds.IntersectP(ray, invDir, dirIsNeg)) { if (node.nPrimitives > 0) { // Intersect ray with primitives in leaf BVH node for (int i = 0; i < node.nPrimitives; ++i) { if (primitives[node.primitivesOffset + i].Intersect( ray, out isect)) { hit = true; } } if (toVisitOffset == 0) { break; } currentNodeIndex = nodesToVisit[--toVisitOffset]; } else { // Put far BVH node on _nodesToVisit_ stack, advance to near // node if (dirIsNeg[node.axis]) { nodesToVisit[toVisitOffset++] = currentNodeIndex + 1; currentNodeIndex = node.secondChildOffset; } else { nodesToVisit[toVisitOffset++] = node.secondChildOffset; currentNodeIndex = currentNodeIndex + 1; } } } else { if (toVisitOffset == 0) { break; } currentNodeIndex = nodesToVisit[--toVisitOffset]; } } return(hit); }