bool BVHAccel::IntersectP(const Ray &ray) const { if (!nodes) return false; PBRT_BVH_INTERSECTIONP_STARTED(const_cast<BVHAccel *>(this), const_cast<Ray *>(&ray)); Vector invDir(1.f / ray.d.x, 1.f / ray.d.y, 1.f / ray.d.z); uint32_t dirIsNeg[3] = { invDir.x < 0, invDir.y < 0, invDir.z < 0 }; uint32_t todo[64]; uint32_t todoOffset = 0, nodeNum = 0; while (true) { const LinearBVHNode *node = &nodes[nodeNum]; if (::IntersectP(node->bounds, ray, invDir, dirIsNeg)) { // Process BVH node _node_ for traversal if (node->nPrimitives > 0) { PBRT_BVH_INTERSECTIONP_TRAVERSED_LEAF_NODE(const_cast<LinearBVHNode *>(node)); for (uint32_t i = 0; i < node->nPrimitives; ++i) { PBRT_BVH_INTERSECTIONP_PRIMITIVE_TEST(const_cast<Primitive *>(primitives[node->primitivesOffset + i].GetPtr())); if (primitives[node->primitivesOffset+i]->IntersectP(ray)) { PBRT_BVH_INTERSECTIONP_PRIMITIVE_HIT(const_cast<Primitive *>(primitives[node->primitivesOffset+i].GetPtr())); // printf("\t BVH Intersect P: thit=%f\n", ray.maxt); return true; } else { PBRT_BVH_INTERSECTIONP_PRIMITIVE_MISSED(const_cast<Primitive *>(primitives[node->primitivesOffset + i].GetPtr())); } } if (todoOffset == 0) break; nodeNum = todo[--todoOffset]; } else { PBRT_BVH_INTERSECTIONP_TRAVERSED_INTERIOR_NODE(const_cast<LinearBVHNode *>(node)); if (dirIsNeg[node->axis]) { /// 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]; } } PBRT_BVH_INTERSECTIONP_FINISHED(); return false; }
bool EBVHAccel::IntersectP(const Ray &ray) const { if (!nodes) return false; PBRT_BVH_INTERSECTIONP_STARTED(const_cast<EBVHAccel *>(this), const_cast<Ray *>(&ray)); Vector invDir(1.f / ray.d.x, 1.f / ray.d.y, 1.f / ray.d.z); uint32_t dirIsNeg[3] = { invDir.x < 0, invDir.y < 0, invDir.z < 0 }; uint32_t todo[64]; uint32_t todoOffset = 0, nodeNum = 0; std::stack<BBox> stackOfBoxes; stackOfBoxes.push(this->sceneBoundingBox); while (true) { const LinearEBVHNode *node = &nodes[nodeNum]; BBox myBBox = uncompressBBox(BBox(Point(node->bounds_x0, node->bounds_y0, node->bounds_z0), Point(node->bounds_x1, node->bounds_y1, node->bounds_z1)), stackOfBoxes.top()); if (::IntersectP(myBBox, ray, invDir, dirIsNeg)) { // Process EBVH node _node_ for traversal if (node->nPrimitives > 0) { PBRT_BVH_INTERSECTIONP_TRAVERSED_LEAF_NODE(const_cast<LinearEBVHNode *>(node)); for (uint32_t i = 0; i < node->nPrimitives; ++i) { PBRT_BVH_INTERSECTIONP_PRIMITIVE_TEST(const_cast<Primitive *>(primitives[node->primitivesOffset + i].GetPtr())); if (primitives[node->primitivesOffset+i]->IntersectP(ray)) { PBRT_BVH_INTERSECTIONP_PRIMITIVE_HIT(const_cast<Primitive *>(primitives[node->primitivesOffset+i].GetPtr())); return true; } else { PBRT_BVH_INTERSECTIONP_PRIMITIVE_MISSED(const_cast<Primitive *>(primitives[node->primitivesOffset + i].GetPtr())); } } if (todoOffset == 0) break; todoOffset--; nodeNum = todo[todoOffset]; stackOfBoxes.pop(); } else { PBRT_BVH_INTERSECTIONP_TRAVERSED_INTERIOR_NODE(const_cast<LinearEBVHNode *>(node)); if (dirIsNeg[node->axis]) { /// second child first todo[todoOffset] = nodeNum + 1; nodeNum = node->secondChildOffset; todoOffset++; stackOfBoxes.pop(); stackOfBoxes.push(myBBox); stackOfBoxes.push(myBBox); } else { todo[todoOffset] = node->secondChildOffset; nodeNum = nodeNum + 1; todoOffset++; stackOfBoxes.pop(); stackOfBoxes.push(myBBox); stackOfBoxes.push(myBBox); } } } else { if (todoOffset == 0) break; todoOffset--; nodeNum = todo[todoOffset]; stackOfBoxes.pop(); } } PBRT_BVH_INTERSECTIONP_FINISHED(); return false; }