13
13
14
14
#include " common/rtweekend.h"
15
15
#include " hittable.h"
16
+ #include < algorithm>
16
17
17
18
18
19
class bvh_node : public hittable {
19
20
public:
20
- bvh_node () {}
21
- bvh_node (hittable **l, int n, double time0, double time1);
21
+ bvh_node () = delete ;
22
+
23
+ bvh_node::bvh_node (hittable_list &list, double time0, double time1)
24
+ : bvh_node(list.objects, 0 , 0 , time0, time1)
25
+ {}
26
+
27
+ bvh_node (
28
+ std::vector<hittable*> &objects,
29
+ size_t start, size_t end, double time0, double time1);
22
30
23
31
virtual bool hit (const ray& r, double t_min, double t_max, hit_record& rec) const ;
24
32
virtual bool bounding_box (double t0, double t1, aabb& output_box) const ;
@@ -28,131 +36,82 @@ class bvh_node : public hittable {
28
36
aabb box;
29
37
};
30
38
31
- bool bvh_node::bounding_box (double t0, double t1, aabb& output_box) const {
32
- output_box = box;
33
- return true ;
34
- }
35
39
36
- bool bvh_node::hit (const ray& r, double t_min, double t_max, hit_record& rec) const {
37
- if (!box. hit (r, t_min, t_max))
38
- return false ;
40
+ bool box_compare (const hittable *a, const hittable *b, int axis) {
41
+ aabb box_a;
42
+ aabb box_b ;
39
43
40
- bool hit_left = left-> hit (r, t_min, t_max, rec);
41
- bool hit_right = right-> hit (r, t_min, hit_left ? rec. t : t_max, rec) ;
44
+ if (!a-> bounding_box ( 0 , 0 , box_a) || !b-> bounding_box ( 0 , 0 , box_b))
45
+ std::cerr << " No bounding box in bvh_node constructor. \n " ;
42
46
43
- return hit_left || hit_right ;
47
+ return box_a. min (). e [axis] < box_b. min (). e [axis] ;
44
48
}
45
49
46
- int box_x_compare (const void * a, const void * b) {
47
- aabb box_left, box_right;
48
- hittable *ah = *(hittable**)a;
49
- hittable *bh = *(hittable**)b;
50
50
51
- if (!ah->bounding_box (0 ,0 , box_left) || !bh->bounding_box (0 ,0 , box_right))
52
- std::cerr << " no bounding box in bvh_node constructor\n " ;
51
+ bool box_x_compare (const hittable *a, const hittable *b) { return box_compare (a, b, 0 ); }
52
+ bool box_y_compare (const hittable *a, const hittable *b) { return box_compare (a, b, 1 ); }
53
+ bool box_z_compare (const hittable *a, const hittable *b) { return box_compare (a, b, 2 ); }
53
54
54
- if (box_left.min ().x () - box_right.min ().x () < 0.0 )
55
- return -1 ;
56
- else
57
- return 1 ;
58
- }
59
55
60
- int box_y_compare (const void * a, const void * b)
61
- {
62
- aabb box_left, box_right;
63
- hittable *ah = *(hittable**)a;
64
- hittable *bh = *(hittable**)b;
56
+ bvh_node::bvh_node (
57
+ std::vector<hittable*> &objects, size_t start, size_t end, double time0, double time1
58
+ ) {
59
+ if (end <= start) {
60
+ start = 0 ;
61
+ end = objects.size ();
62
+ }
65
63
66
- if (!ah->bounding_box (0 ,0 , box_left) || !bh->bounding_box (0 ,0 , box_right))
67
- std::cerr << " no bounding box in bvh_node constructor\n " ;
64
+ size_t object_span = end - start;
65
+
66
+ int axis = random_int (0 ,2 );
67
+ auto comparator = (axis == 0 ) ? box_x_compare
68
+ : (axis == 1 ) ? box_y_compare
69
+ : box_z_compare;
70
+
71
+ if (object_span == 1 ) {
72
+ left = right = objects[start];
73
+ } else if (object_span == 2 ) {
74
+ if (comparator (objects[start], objects[start+1 ])) {
75
+ left = objects[start];
76
+ right = objects[start+1 ];
77
+ } else {
78
+ left = objects[start+1 ];
79
+ right = objects[start];
80
+ }
81
+ } else {
82
+ std::sort (objects.begin () + start, objects.begin () + end, comparator);
68
83
69
- if (box_left.min ().y () - box_right.min ().y () < 0.0 )
70
- return -1 ;
71
- else
72
- return 1 ;
73
- }
84
+ auto mid = start + object_span/2 ;
85
+ left = new bvh_node (objects, start, mid, time0, time1);
86
+ right = new bvh_node (objects, mid, end, time0, time1);
87
+ }
74
88
75
- int box_z_compare (const void * a, const void * b)
76
- {
77
89
aabb box_left, box_right;
78
- hittable *ah = *(hittable**)a;
79
- hittable *bh = *(hittable**)b;
80
90
81
- if (!ah->bounding_box (0 ,0 , box_left) || !bh->bounding_box (0 ,0 , box_right))
82
- std::cerr << " no bounding box in bvh_node constructor\n " ;
91
+ if ( !left->bounding_box (time0, time1, box_left)
92
+ || !right->bounding_box (time0, time1, box_right)
93
+ )
94
+ std::cerr << " No bounding box in bvh_node constructor.\n " ;
83
95
84
- if (box_left.min ().z () - box_right.min ().z () < 0.0 )
85
- return -1 ;
86
- else
87
- return 1 ;
96
+ box = surrounding_box (box_left, box_right);
88
97
}
89
98
90
- bvh_node::bvh_node (hittable **l, int n, double time0, double time1) {
91
- aabb *boxes = new aabb[n];
92
- auto *left_area = new double [n];
93
- auto *right_area = new double [n];
94
- aabb main_box;
95
- bool dummy = l[0 ]->bounding_box (time0, time1, main_box);
96
- for (int i = 1 ; i < n; i++) {
97
- aabb new_box;
98
- bool dummy = l[i]->bounding_box (time0, time1, new_box);
99
- main_box = surrounding_box (new_box, main_box);
100
- }
101
- int axis = main_box.longest_axis ();
102
- if (axis == 0 )
103
- qsort (l, n, sizeof (hittable *), box_x_compare);
104
- else if (axis == 1 )
105
- qsort (l, n, sizeof (hittable *), box_y_compare);
106
- else
107
- qsort (l, n, sizeof (hittable *), box_z_compare);
108
- for (int i = 0 ; i < n; i++)
109
- bool dummy = l[i]->bounding_box (time0, time1, boxes[i]);
110
- left_area[0 ] = boxes[0 ].area ();
111
- aabb left_box = boxes[0 ];
112
- for (int i = 1 ; i < n-1 ; i++) {
113
- left_box = surrounding_box (left_box, boxes[i]);
114
- left_area[i] = left_box.area ();
115
- }
116
- right_area[n-1 ] = boxes[n-1 ].area ();
117
- aabb right_box = boxes[n-1 ];
118
- for (int i = n-2 ; i > 0 ; i--) {
119
- right_box = surrounding_box (right_box, boxes[i]);
120
- right_area[i] = right_box.area ();
121
- }
122
- auto min_SAH = infinity;
123
- int min_SAH_idx;
124
- for (int i = 0 ; i < n-1 ; i++) {
125
- auto SAH = i*left_area[i] + (n-i-1 )*right_area[i+1 ];
126
- if (SAH < min_SAH) {
127
- min_SAH_idx = i;
128
- min_SAH = SAH;
129
- }
130
- }
131
99
132
- /*
133
- if (min_SAH_idx == 0)
134
- left = l[0];
135
- else
136
- left = new bvh_node(l, min_SAH_idx+1, time0, time1);
137
- if (min_SAH_idx == n-2)
138
- right = l[min_SAH_idx+1];
139
- else
140
- right = new bvh_node(l + min_SAH_idx+1, n - min_SAH_idx -1, time0, time1);
141
- */
142
-
143
- if (n == 1 ) {
144
- left = right = l[0 ];
145
- }
146
- else if (n == 2 ) {
147
- left = l[0 ];
148
- right = l[1 ];
149
- }
150
- else {
151
- left = new bvh_node (l, n/2 , time0, time1);
152
- right = new bvh_node (l + n/2 , n - n/2 , time0, time1);
153
- }
100
+ bool bvh_node::hit (const ray& r, double t_min, double t_max, hit_record& rec) const {
101
+ if (!box.hit (r, t_min, t_max))
102
+ return false ;
103
+
104
+ bool hit_left = left->hit (r, t_min, t_max, rec);
105
+ bool hit_right = right->hit (r, t_min, hit_left ? rec.t : t_max, rec);
106
+
107
+ return hit_left || hit_right;
108
+ }
154
109
155
- box = main_box;
110
+
111
+ bool bvh_node::bounding_box (double t0, double t1, aabb& output_box) const {
112
+ output_box = box;
113
+ return true ;
156
114
}
157
115
116
+
158
117
#endif
0 commit comments