Skip to content

Commit 11dda74

Browse files
committed
hitvec restLife: hittable_list uses vector
For bvh.h, the original code for TheRestOfYourLife had changes in it plus a final commented-out section. Once that's removed, most of the new code is pointless. In addition, the book makes no mention of BVH changes. In the end, I've decided to make the code identical to match the text.
1 parent 26cc35c commit 11dda74

File tree

5 files changed

+179
-191
lines changed

5 files changed

+179
-191
lines changed

src/TheRestOfYourLife/box.h

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,35 +19,35 @@
1919
class box: public hittable {
2020
public:
2121
box() {}
22-
2322
box(const vec3& p0, const vec3& p1, material *ptr);
2423

2524
virtual bool hit(const ray& r, double t0, double t1, hit_record& rec) const;
2625

2726
virtual bool bounding_box(double t0, double t1, aabb& output_box) const {
28-
output_box = aabb(pmin, pmax);
27+
output_box = aabb(box_min, box_max);
2928
return true;
3029
}
3130

32-
vec3 pmin, pmax;
33-
hittable *list_ptr;
31+
vec3 box_min;
32+
vec3 box_max;
33+
hittable_list sides;
3434
};
3535

3636
box::box(const vec3& p0, const vec3& p1, material *ptr) {
37-
pmin = p0;
38-
pmax = p1;
39-
hittable **list = new hittable*[6];
40-
list[0] = new xy_rect(p0.x(), p1.x(), p0.y(), p1.y(), p1.z(), ptr);
41-
list[1] = new flip_normals(new xy_rect(p0.x(), p1.x(), p0.y(), p1.y(), p0.z(), ptr));
42-
list[2] = new xz_rect(p0.x(), p1.x(), p0.z(), p1.z(), p1.y(), ptr);
43-
list[3] = new flip_normals(new xz_rect(p0.x(), p1.x(), p0.z(), p1.z(), p0.y(), ptr));
44-
list[4] = new yz_rect(p0.y(), p1.y(), p0.z(), p1.z(), p1.x(), ptr);
45-
list[5] = new flip_normals(new yz_rect(p0.y(), p1.y(), p0.z(), p1.z(), p0.x(), ptr));
46-
list_ptr = new hittable_list(list,6);
37+
box_min = p0;
38+
box_max = p1;
39+
40+
sides.add(new xy_rect(p0.x(), p1.x(), p0.y(), p1.y(), p1.z(), ptr));
41+
sides.add(new flip_normals(new xy_rect(p0.x(), p1.x(), p0.y(), p1.y(), p0.z(), ptr)));
42+
sides.add(new xz_rect(p0.x(), p1.x(), p0.z(), p1.z(), p1.y(), ptr));
43+
sides.add(new flip_normals(new xz_rect(p0.x(), p1.x(), p0.z(), p1.z(), p0.y(), ptr)));
44+
sides.add(new yz_rect(p0.y(), p1.y(), p0.z(), p1.z(), p1.x(), ptr));
45+
sides.add(new flip_normals(new yz_rect(p0.y(), p1.y(), p0.z(), p1.z(), p0.x(), ptr)));
4746
}
4847

4948
bool box::hit(const ray& r, double t0, double t1, hit_record& rec) const {
50-
return list_ptr->hit(r, t0, t1, rec);
49+
return sides.hit(r, t0, t1, rec);
5150
}
5251

52+
5353
#endif

src/TheRestOfYourLife/bvh.h

Lines changed: 68 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,20 @@
1313

1414
#include "common/rtweekend.h"
1515
#include "hittable.h"
16+
#include <algorithm>
1617

1718

1819
class bvh_node : public hittable {
1920
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);
2230

2331
virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const;
2432
virtual bool bounding_box(double t0, double t1, aabb& output_box) const;
@@ -28,131 +36,82 @@ class bvh_node : public hittable {
2836
aabb box;
2937
};
3038

31-
bool bvh_node::bounding_box(double t0, double t1, aabb& output_box) const {
32-
output_box = box;
33-
return true;
34-
}
3539

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;
3943

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";
4246

43-
return hit_left || hit_right;
47+
return box_a.min().e[axis] < box_b.min().e[axis];
4448
}
4549

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;
5050

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); }
5354

54-
if (box_left.min().x() - box_right.min().x() < 0.0)
55-
return -1;
56-
else
57-
return 1;
58-
}
5955

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+
}
6563

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);
6883

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+
}
7488

75-
int box_z_compare (const void * a, const void * b)
76-
{
7789
aabb box_left, box_right;
78-
hittable *ah = *(hittable**)a;
79-
hittable *bh = *(hittable**)b;
8090

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";
8395

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);
8897
}
8998

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-
}
13199

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+
}
154109

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;
156114
}
157115

116+
158117
#endif

src/TheRestOfYourLife/hittable_list.h

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,50 +11,58 @@
1111
// along with this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
1212
//==============================================================================================
1313

14-
#include "common/rtweekend.h"
1514
#include "hittable.h"
15+
#include <vector>
1616

1717

1818
class hittable_list: public hittable {
1919
public:
2020
hittable_list() {}
21-
hittable_list(hittable **l, int n) {list = l; list_size = n; }
21+
hittable_list(hittable* object) { add(object); }
22+
23+
void clear() { objects.clear(); }
24+
void add(hittable* object) { objects.push_back(object); }
25+
2226
virtual bool hit(const ray& r, double tmin, double tmax, hit_record& rec) const;
2327
virtual bool bounding_box(double t0, double t1, aabb& output_box) const;
24-
virtual double pdf_value(const vec3& o, const vec3& v) const;
25-
virtual vec3 random(const vec3& o) const;
28+
virtual double pdf_value(const vec3 &o, const vec3 &v) const;
29+
virtual vec3 random(const vec3 &o) const;
2630

27-
hittable **list;
28-
int list_size;
31+
public:
32+
std::vector<hittable*> objects;
2933
};
3034

31-
double hittable_list::pdf_value(const vec3& o, const vec3& v) const {
32-
auto weight = 1.0/list_size;
33-
auto sum = 0.0;
34-
for (int i = 0; i < list_size; i++)
35-
sum += weight*list[i]->pdf_value(o, v);
36-
return sum;
37-
}
3835

39-
vec3 hittable_list::random(const vec3& o) const {
40-
int index = random_int(0, list_size-1);
41-
return list[ index ]->random(o);
36+
bool hittable_list::hit(const ray& r, double t_min, double t_max, hit_record& rec) const {
37+
hit_record temp_rec;
38+
auto hit_anything = false;
39+
auto closest_so_far = t_max;
40+
41+
for (auto object : objects) {
42+
if (object->hit(r, t_min, closest_so_far, temp_rec)) {
43+
hit_anything = true;
44+
closest_so_far = temp_rec.t;
45+
rec = temp_rec;
46+
}
47+
}
48+
49+
return hit_anything;
4250
}
4351

4452

4553
bool hittable_list::bounding_box(double t0, double t1, aabb& output_box) const {
46-
if (list_size < 1) return false;
54+
if (objects.empty()) return false;
4755

4856
aabb temp_box;
49-
bool first_true = list[0]->bounding_box(t0, t1, temp_box);
57+
bool first_true = objects[0]->bounding_box(t0, t1, temp_box);
5058

5159
if (!first_true)
5260
return false;
5361
else
5462
output_box = temp_box;
5563

56-
for (int i = 1; i < list_size; i++) {
57-
if (list[i]->bounding_box(t0, t1, temp_box))
64+
for (auto object : objects) {
65+
if (object->bounding_box(t0, t1, temp_box))
5866
output_box = surrounding_box(output_box, temp_box);
5967
else
6068
return false;
@@ -63,19 +71,23 @@ bool hittable_list::bounding_box(double t0, double t1, aabb& output_box) const {
6371
return true;
6472
}
6573

66-
bool hittable_list::hit(const ray& r, double t_min, double t_max, hit_record& rec) const {
67-
hit_record temp_rec;
68-
bool hit_anything = false;
69-
double closest_so_far = t_max;
7074

71-
for (int i = 0; i < list_size; i++) {
72-
if (list[i]->hit(r, t_min, closest_so_far, temp_rec)) {
73-
hit_anything = true;
74-
closest_so_far = temp_rec.t;
75-
rec = temp_rec;
76-
}
77-
}
78-
return hit_anything;
75+
double hittable_list::pdf_value(const vec3& o, const vec3& v) const {
76+
auto weight = 1.0/objects.size();
77+
auto sum = 0.0;
78+
79+
for (auto object : objects)
80+
sum += weight * object->pdf_value(o, v);
81+
82+
return sum;
7983
}
8084

85+
86+
vec3 hittable_list::random(const vec3 &o) const {
87+
auto int_size = static_cast<int>(objects.size());
88+
auto index = static_cast<size_t>(random_int(0, int_size-1));
89+
return objects[index]->random(o);
90+
}
91+
92+
8193
#endif

0 commit comments

Comments
 (0)