68 lines
2.0 KiB
C++
68 lines
2.0 KiB
C++
#include "bvh.h"
|
|
|
|
#include <algorithm>
|
|
#include <functional>
|
|
|
|
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<Hittable> a, const std::shared_ptr<Hittable> 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<std::shared_ptr<Hittable>>& 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<Bvh_node>(objects, start, mid, time0, time1);
|
|
right = std::make_shared<Bvh_node>(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);
|
|
}
|