bool Mesh::intersectKD(KDTree& node, const BBox& box, const FastRay& ray, IntersectionInfo& info) const { if (node.axis == AXIS_NONE) { vector<int>& trios = *node.data.triangles; double foundlambda2 = 0, foundlambda3 = 0, dist = INF; int foundIdx = -1; for (int i = 0; i < (int) trios.size(); i++) { const Triangle& t = triangles[trios[i]]; double l2, l3; if (intersectTriangleFast(ray, vertices[t.v[0]], t, l2, l3, dist)) { foundIdx = trios[i]; foundlambda2 = l2; foundlambda3 = l3; } } if (foundIdx != -1) { Vector ip = ray.start + ray.dir * dist; if (box.inside(ip)) { fillInfo(ray, info, foundIdx, foundlambda2, foundlambda3, dist); return true; } } return false; } else { BBox boxChild[2]; box.split(node.axis, node.sp, boxChild[0], boxChild[1]); int order[2] = { 0, 1 }; if (ray.start[node.axis] > node.sp) swap(order[0], order[1]); // if the ray intersects the common wall between the two sub-boxes, then it invariably // intersects both boxes (we can skip the testIntersect() checks): // (see http://raytracing-bg.net/?q=node/68 ) if (box.intersectWall(node.axis, node.sp, ray)) { if (intersectKD(node.data.children[order[0]], boxChild[order[0]], ray, info)) return true; return intersectKD(node.data.children[order[1]], boxChild[order[1]], ray, info); } else { // if the wall isn't hit, then we intersect exclusively one of the sub-boxes; // test one, if the test fails, then it's in the other: if (boxChild[order[0]].testIntersect(ray)) return intersectKD(node.data.children[order[0]], boxChild[order[0]], ray, info); else return intersectKD(node.data.children[order[1]], boxChild[order[1]], ray, info); } } return false; }
bool Mesh::intersectKD(KDTreeNode& node, const BBox& bbox, const Ray& ray, IntersectionData& data) { if (node.axis == AXIS_NONE) { // leaf node; try intersecting with the triangle list: bool found = false; for (size_t i = 0; i < node.triangles->size(); i++) { int triIdx = (*node.triangles)[i]; if (intersectTriangle(ray, data, triangles[triIdx])) { found = true; } } // the found intersection has to be inside "our" BBox, otherwise we can miss a triangle, // as explained in the presentations: if (found && bbox.inside(data.p)) return true; return false; } else { // a in-node; intersect with the two children, starting with the closer one first: int childOrder[2] = { 0, 1 }; if (ray.start[node.axis] > node.splitPos) swap(childOrder[0], childOrder[1]); // BBox childBB[2]; bbox.split(node.axis, node.splitPos, childBB[0], childBB[1]); // name the children bboxen: BBox& firstBB = childBB[childOrder[0]]; BBox& secondBB = childBB[childOrder[1]]; KDTreeNode& firstChild = node.children[childOrder[0]]; KDTreeNode& secondChild = node.children[childOrder[1]]; // if the ray intersects the common wall between the two sub-boxes, then it invariably // intersects both boxes (we can skip the testIntersect() checks): // (see http://raytracing-bg.net/?q=node/68 ) if (bbox.intersectWall(node.axis, node.splitPos, ray)) { if (intersectKD(firstChild, firstBB, ray, data)) return true; return intersectKD(secondChild, secondBB, ray, data); } else { // if the wall isn't hit, then we intersect exclusively one of the sub-boxes; // test one, if the test fails, then it's in the other: if (firstBB.testIntersect(ray)) return intersectKD(firstChild, firstBB, ray, data); else return intersectKD(secondChild, secondBB, ray, data); } } }