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 , list.objects.size(), 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,95 +36,77 @@ 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
-
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 " ;
53
50
54
- if (box_left.min ().x () - box_right.min ().x () < 0.0 )
55
- return -1 ;
56
- else
57
- return 1 ;
58
- }
59
-
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;
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 ); }
65
54
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 " ;
68
55
69
- if (box_left.min ().y () - box_right.min ().y () < 0.0 )
70
- return -1 ;
71
- else
72
- return 1 ;
73
- }
56
+ bvh_node::bvh_node (
57
+ std::vector<hittable*>& objects, size_t start, size_t end, double time0, double time1
58
+ ) {
59
+ int axis = random_int (0 ,2 );
60
+ auto comparator = (axis == 0 ) ? box_x_compare
61
+ : (axis == 1 ) ? box_y_compare
62
+ : box_z_compare;
63
+
64
+ size_t object_span = end - start;
65
+
66
+ if (object_span == 1 ) {
67
+ left = right = objects[start];
68
+ } else if (object_span == 2 ) {
69
+ if (comparator (objects[start], objects[start+1 ])) {
70
+ left = objects[start];
71
+ right = objects[start+1 ];
72
+ } else {
73
+ left = objects[start+1 ];
74
+ right = objects[start];
75
+ }
76
+ } else {
77
+ std::sort (objects.begin () + start, objects.begin () + end, comparator);
78
+
79
+ auto mid = start + object_span/2 ;
80
+ left = new bvh_node (objects, start, mid, time0, time1);
81
+ right = new bvh_node (objects, mid, end, time0, time1);
82
+ }
74
83
75
- int box_z_compare (const void * a, const void * b)
76
- {
77
84
aabb box_left, box_right;
78
- hittable *ah = *(hittable**)a;
79
- hittable *bh = *(hittable**)b;
80
85
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 " ;
86
+ if ( !left->bounding_box (time0, time1, box_left)
87
+ || !right->bounding_box (time0, time1, box_right)
88
+ )
89
+ std::cerr << " No bounding box in bvh_node constructor.\n " ;
83
90
84
- if (box_left.min ().z () - box_right.min ().z () < 0.0 )
85
- return -1 ;
86
- else
87
- return 1 ;
91
+ box = surrounding_box (box_left, box_right);
88
92
}
89
93
90
- bvh_node::bvh_node (hittable **l, int n, double time0, double time1) {
91
- int axis = random_int (0 ,2 );
92
94
93
- if (axis == 0 )
94
- qsort (l, n, sizeof (hittable *), box_x_compare);
95
- else if (axis == 1 )
96
- qsort (l, n, sizeof (hittable *), box_y_compare);
97
- else
98
- qsort (l, n, sizeof (hittable *), box_z_compare);
95
+ bool bvh_node::hit (const ray& r, double t_min, double t_max, hit_record& rec) const {
96
+ if (!box.hit (r, t_min, t_max))
97
+ return false ;
99
98
100
- if (n == 1 ) {
101
- left = right = l[0 ];
102
- }
103
- else if (n == 2 ) {
104
- left = l[0 ];
105
- right = l[1 ];
106
- }
107
- else {
108
- left = new bvh_node (l, n/2 , time0, time1);
109
- right = new bvh_node (l + n/2 , n - n/2 , time0, time1);
110
- }
99
+ bool hit_left = left->hit (r, t_min, t_max, rec);
100
+ bool hit_right = right->hit (r, t_min, hit_left ? rec.t : t_max, rec);
111
101
112
- aabb box_left, box_right;
102
+ return hit_left || hit_right;
103
+ }
113
104
114
- if ( !left->bounding_box (time0, time1, box_left)
115
- || !right->bounding_box (time0, time1, box_right)
116
- )
117
- std::cerr << " no bounding box in bvh_node constructor\n " ;
118
105
119
- box = surrounding_box (box_left, box_right);
106
+ bool bvh_node::bounding_box (double t0, double t1, aabb& output_box) const {
107
+ output_box = box;
108
+ return true ;
120
109
}
121
110
111
+
122
112
#endif
0 commit comments