forked from RayTracing/TheNextWeek
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bvh.h
125 lines (112 loc) · 4 KB
/
bvh.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
116
117
118
119
120
121
122
123
124
//==================================================================================================
// Written in 2016 by Peter Shirley <[email protected]>
//
// To the extent possible under law, the author(s) have dedicated all copyright and related and
// neighboring rights to this software to the public domain worldwide. This software is distributed
// without any warranty.
//
// You should have received a copy (see file COPYING.txt) of the CC0 Public Domain Dedication along
// with this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//==================================================================================================
#ifndef BVHH
#define BVHH
#include "hitable.h"
class bvh_node : public hitable {
public:
bvh_node() {}
bvh_node(hitable **l, int n, float time0, float time1);
virtual bool hit(const ray& r, float tmin, float tmax, hit_record& rec) const;
virtual bool bounding_box(float t0, float t1, aabb& box) const;
hitable *left;
hitable *right;
aabb box;
};
bool bvh_node::bounding_box(float t0, float t1, aabb& b) const {
b = box;
return true;
}
bool bvh_node::hit(const ray& r, float t_min, float t_max, hit_record& rec) const {
if (box.hit(r, t_min, t_max)) {
hit_record left_rec, right_rec;
bool hit_left = left->hit(r, t_min, t_max, left_rec);
bool hit_right = right->hit(r, 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;
}
else
return false;
}
else return false;
}
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;
}
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;
}
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*drand48());
if (axis == 0)
qsort(l, n, sizeof(hitable *), box_x_compare);
else if (axis == 1)
qsort(l, n, sizeof(hitable *), box_y_compare);
else
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";
box = surrounding_box(box_left, box_right);
}
#endif