It does indeed do exactly what you described. Have a close look at how the bvh is constructed, it is a passed a list of concrete shapes that implement hittable
, e.g. xy_rect
, sphere
, etc. The base cases for the recursive bvh construction create leaf nodes that directly reference the concrete shapes that make up the scene.
bvh_node::bvh_node(
const std::vector<shared_ptr<hittable>>& src_objects,
size_t start, size_t end, double time0, double time1
) {
auto objects = src_objects; // Create a modifiable array of the source scene objects
...
size_t object_span = end - start;
// **create leaf nodes, concrete shapes referenced here**
if (object_span == 1) {
left = right = objects[start];
} else if (object_span == 2) {
if (comparator(objects[start], objects[start+1])) {
left = objects[start];
right = objects[start+1];
} else {
left = objects[start+1];
right = objects[start];
}
} else {
// create internal bvh_node
...
}
When bvh_node::hit
is called and the ray/aabb test passes, the left and right child nodes have their hit functions called recursively. Eventually when this recursion bottoms out the concrete shapes referenced by the leaf nodes will have their hit functions called as you would expect.
bool bvh_node::hit(const ray& r, double t_min, double t_max, hit_record& rec) const {
if (!box.hit(r, t_min, t_max))
return false;
bool hit_left = left->hit(r, t_min, t_max, rec);
bool hit_right = right->hit(r, t_min, hit_left ? rec.t : t_max, rec);
return hit_left || hit_right;
}