-
Notifications
You must be signed in to change notification settings - Fork 0
/
bvh_node.h
96 lines (72 loc) · 3.36 KB
/
bvh_node.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#ifndef RAYTRACINGINONEWEEKEND_BVH_NODE_H
#define RAYTRACINGINONEWEEKEND_BVH_NODE_H
#include <algorithm>
#include "rtweekend.h"
#include "hittable.h"
#include "hittable_list.h"
inline bool box_compare(const shared_ptr<hittable> &a, const shared_ptr<hittable> &b, int axis);
inline bool box_x_comparator(const shared_ptr<hittable> &a, const shared_ptr<hittable> &b) { return box_compare(a, b, 0); }
inline bool box_y_comparator(const shared_ptr<hittable> &a, const shared_ptr<hittable> &b) { return box_compare(a, b, 1); }
inline bool box_z_comparator(const shared_ptr<hittable> &a, const shared_ptr<hittable> &b) { return box_compare(a, b, 2); }
class bvh_node : public hittable {
public:
shared_ptr<hittable> left;
shared_ptr<hittable> right;
aabb box;
bvh_node() = default;
bvh_node(const hittable_list &list, double time0, double time1) : bvh_node(list.objects, 0, list.objects.size(),
time0, time1) {};
bvh_node(const std::vector<shared_ptr<hittable>> &src_objects, size_t start, size_t end, double time0,
double time1);
bool bounding_box(double time0, double time1, aabb &output_box) const override;
bool hit(const ray &r, double t_min, double t_max, hit_record &rec) const override;
};
bool bvh_node::bounding_box(double time0, double time1, aabb &output_box) const {
output_box = box;
return true;
}
bvh_node::bvh_node(const std::vector<shared_ptr<hittable>> &src_objects, size_t start, size_t end, double time0,
double time1) {
// Todo: it seems redundant in memory.
auto objects(src_objects);
int axis = random_int(0, 2);
auto comparator = axis == 0 ? box_x_comparator :
axis == 1 ? box_y_comparator :
box_z_comparator;
size_t num = end - start;
if (num == 1) {
left = right = objects[start];
} else if (num == 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);
size_t mid = start + num / 2;
left = make_shared<bvh_node>(objects, start, mid, time0, time1);
right = make_shared<bvh_node>(objects, mid, end, time0, time1);
}
aabb box_left;
aabb box_right;
if (!left->bounding_box(time0, time1, box_left) || !right->bounding_box(time0, time1, box_right))
std::cerr << "No bounding box in BVH constructor!" << std::endl;
box = surrounding_box(box_left, box_right);
}
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 && left->hit(r, t_min, t_max, rec);
bool hit_right = right && right->hit(r, t_min, hit_left ? rec.t : t_max, rec);
return hit_left || hit_right;
}
bool box_compare(const shared_ptr<hittable> &a, const shared_ptr<hittable> &b, int axis) {
aabb box_a;
aabb box_b;
if (!a->bounding_box(0, 0, box_a) || !b->bounding_box(0, 0, box_b))
std::cerr << "No bounding box in BVH constructor!" << std::endl;
return box_a.min()[axis] < box_b.min()[axis];
}
#endif //RAYTRACINGINONEWEEKEND_BVH_NODE_H