-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbvh_node.h
115 lines (108 loc) · 2.94 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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#pragma once
#include "hitable.h"
#include "rand.h"
class bvh_node : public hitable
{
public:
bvh_node() {}
bvh_node(hitable **l, int n, float time0, float time1);
virtual bool hit(const ray &ray, float t_min, float t_max, hit_record &rec) const override;
virtual bool bounding_box(float t0, float t1, aabb &bbox) const;
hitable *left, *right;
aabb bbox;
};
bool bvh_node::hit(const ray &_ray, float t_min, float t_max, hit_record &rec) const
{
if (bbox.hit(_ray, t_min, t_max))
{
hit_record left_rec, right_rec;
bool hit_left = left->hit(_ray, t_min, t_max, left_rec);
bool hit_right = right->hit(_ray, t_min, t_max, right_rec);
if (hit_left && hit_right)
{
if (left_rec.t < right_rec.t)
rec = left_rec;
else
rec = right_rec;
return true;
}
else if (hit_left)
{
rec = left_rec;
return true;
}
else if (hit_right)
{
rec = right_rec;
return true;
}
}
return false;
}
bool bvh_node::bounding_box(float t0, float t1, aabb &box) const
{
box = bbox;
return true;
}
inline int box_x_compare(const void *a, const void *b)
{
aabb box_left, box_right;
hitable *ah = *(hitable **)a;
hitable *bh = *(hitable **)b;
if (!ah->bounding_box(0, 0, box_left) || !bh->bounding_box(0, 0, box_right))
std::cerr << "no bounding box in bvh_node constructor\n";
if (box_left.min().x() - box_right.min().x() < 0.0)
return -1;
else
return 1;
}
inline int box_y_compare(const void *a, const void *b)
{
aabb box_left, box_right;
hitable *ah = *(hitable **)a;
hitable *bh = *(hitable **)b;
if (!ah->bounding_box(0, 0, box_left) || !bh->bounding_box(0, 0, box_right))
std::cerr << "no bounding box in bvh_node constructor\n";
if (box_left.min().y() - box_right.min().y() < 0.0)
return -1;
else
return 1;
}
inline int box_z_compare(const void *a, const void *b)
{
aabb box_left, box_right;
hitable *ah = *(hitable **)a;
hitable *bh = *(hitable **)b;
if (!ah->bounding_box(0, 0, box_left) || !bh->bounding_box(0, 0, box_right))
std::cerr << "no bounding box in bvh_node constructor\n";
if (box_left.min().z() - box_right.min().z() < 0.0)
return -1;
else
return 1;
}
bvh_node::bvh_node(hitable **l, int n, float time0, float time1)
{
int axis = int(3 * rand_float());
if (axis == 0)
qsort(l, n, sizeof(hitable *), box_x_compare);
else if (axis == 1)
qsort(l, n, sizeof(hitable *), box_y_compare);
else if (axis == 2)
qsort(l, n, sizeof(hitable *), box_z_compare);
if (n == 1)
left = right = l[0];
else if (n == 2)
{
left = l[0];
right = l[1];
}
else
{
left = new bvh_node(l, n / 2, time0, time1);
right = new bvh_node(l + n / 2, n - n / 2, 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";
bbox = surrounding_box(box_left, box_right);
}