#include "bvh.h" #include #include bool Bvh_node::bounding_box(double t0, double t1, Aabb& output_box) const { output_box = box; return true; } 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; } bool box_compare(const std::shared_ptr a, const std::shared_ptr b, int axis, double t0, double t1) { Aabb box_a; Aabb box_b; if (!a->bounding_box(t0, t1, box_a) || !b->bounding_box(t0, t1, box_b)) { std::cerr << "No bounding box in Bvh_node constructor.\n"; std::exit(1); } return box_a.min()[axis] < box_b.min()[axis]; } Bvh_node::Bvh_node(std::vector>& objects, int start, int end, double time0, double time1) { using namespace std::placeholders; int axis = random_int(0, 2); auto comparator = std::bind(box_compare, _1, _2, axis, time0, time1); int object_span = end - start; 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 { std::sort(objects.begin() + start, objects.begin() + end, comparator); auto mid = start + object_span/2; left = std::make_shared(objects, start, mid, time0, time1); right = std::make_shared(objects, mid, end, time0, time1); } Aabb box_left, box_right; if (!left->bounding_box(time0, time1, box_left) || !right->bounding_box(time0, time1, box_right)) { std::cerr << "No bounding box in Bvh_node constructor.\n"; std::exit(1); } box = surrounding_box(box_left, box_right); }