int flattenBVHTree(BVHBuildNode node, ref int offset) { LinearBVHNode linearNode = nodes[offset]; linearNode.bounds = node.bounds; int myOffset = offset++; if (node.nShapes > 0) { Debug.Assert(node.childLeft != null && node.childRight != null); linearNode.ShapesOffset = node.firstPrimOffset; linearNode.nShapes = (byte)node.nShapes; } else { // Creater interior flattened BVH node linearNode.axis = (byte)node.splitAxis; linearNode.nShapes = 0; flattenBVHTree(node.childLeft, ref offset); linearNode.secondChildOffset = flattenBVHTree(node.childRight, ref offset); } return(myOffset); }
bool Intersect(Ray ray, ref LFloat isect) { if (nodes == null || nodes.Count == 0) { return(false); } bool hit = false; LVector3 invDir = new LVector3(1 / ray.d.x, 1 / ray.d.y, 1 / ray.d.z); int[] dirIsNeg = new int[3] { invDir.x < 0 ? 1 : 0, invDir.y < 0 ? 1 : 0, invDir.z < 0 ? 1 : 0 }; // Follow ray through BVH nodes to find Shape intersections int todoOffset = 0, nodeNum = 0; int[] todo = new int[64]; LFloat tmin = LFloat.zero; LFloat tmax = LFloat.zero; while (true) { LinearBVHNode node = nodes[nodeNum]; // Check ray against BVH node if (IntersectP(node.bounds, ray, invDir, dirIsNeg, tmin, tmax)) { if (node.nShapes > 0) { // Intersect ray with Shapes in leaf BVH node for (int i = 0; i < node.nShapes; ++i) { if (Shapes[node.ShapesOffset + i].TestWith(ray, ref isect)) { hit = true; } } if (todoOffset == 0) { break; } nodeNum = todo[--todoOffset]; } else { // Put far BVH node on _todo_ stack, advance to near node if (dirIsNeg[node.axis] != 0) { todo[todoOffset++] = nodeNum + 1; nodeNum = node.secondChildOffset; } else { todo[todoOffset++] = node.secondChildOffset; nodeNum = nodeNum + 1; } } } else { if (todoOffset == 0) { break; } nodeNum = todo[--todoOffset]; } } return(hit); }
bool IntersectP(Ray ray, LFloat tmin, LFloat tmax) { if (nodes == null || nodes.Count == 0) { return(false); } LVector3 invDir = new LVector3(1 / ray.d.x, 1 / ray.d.y, 1 / ray.d.z); int[] dirIsNeg = new int[3] { invDir.x < 0 ? 1 : 0, invDir.y < 0 ? 1 : 0, invDir.z < 0 ? 1 : 0 }; int[] todo = new int[64]; //最大堆栈数 int todoOffset = 0, nodeNum = 0; while (true) { LinearBVHNode node = nodes[nodeNum]; if (IntersectP(node.bounds, ray, invDir, dirIsNeg, tmin, tmax)) { // Process BVH node _node_ for traversal if (node.nShapes > 0) { for (int i = 0; i < node.nShapes; ++i) { if (Shapes[node.ShapesOffset + i].TestWith(ray)) { return(true); } } if (todoOffset == 0) { break; } nodeNum = todo[--todoOffset]; } else { if (dirIsNeg[node.axis] != 0) { /// second child first todo[todoOffset++] = nodeNum + 1; nodeNum = node.secondChildOffset; } else { todo[todoOffset++] = node.secondChildOffset; nodeNum = nodeNum + 1; } } } else { if (todoOffset == 0) { break; } nodeNum = todo[--todoOffset]; } } return(false); }