Skip to content

Commit 2a90c89

Browse files
committed
Update inOneWeekend book with new hittable_list
1 parent 11dda74 commit 2a90c89

File tree

1 file changed

+76
-53
lines changed

1 file changed

+76
-53
lines changed

books/RayTracingInOneWeekend.html

Lines changed: 76 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -617,8 +617,7 @@
617617
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
618618
if (discriminant < 0) {
619619
return -1.0;
620-
}
621-
else {
620+
} else {
622621
return (-b - sqrt(discriminant) ) / (2.0*a);
623622
}
624623
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
@@ -683,8 +682,7 @@
683682

684683
if (discriminant < 0) {
685684
return -1.0;
686-
}
687-
else {
685+
} else {
688686
return (-half_b - sqrt(discriminant) ) / a;
689687
}
690688
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -792,27 +790,35 @@
792790
#define HITTABLE_LIST_H
793791

794792
#include "hittable.h"
793+
#include <vector>
795794

796795
class hittable_list: public hittable {
797796
public:
798797
hittable_list() {}
799-
hittable_list(hittable **l, int n) {list = l; list_size = n; }
798+
hittable_list(hittable* object) { add(object); }
799+
800+
void clear() { objects.clear(); }
801+
void add(hittable* object) { objects.push_back(object); }
802+
800803
virtual bool hit(const ray& r, double tmin, double tmax, hit_record& rec) const;
801-
hittable **list;
802-
int list_size;
804+
805+
public:
806+
std::vector<hittable*> objects;
803807
};
804808

805809
bool hittable_list::hit(const ray& r, double t_min, double t_max, hit_record& rec) const {
806810
hit_record temp_rec;
807811
bool hit_anything = false;
808-
double closest_so_far = t_max;
809-
for (int i = 0; i < list_size; i++) {
810-
if (list[i]->hit(r, t_min, closest_so_far, temp_rec)) {
812+
auto closest_so_far = t_max;
813+
814+
for (auto object : objects) {
815+
if (object->hit(r, t_min, closest_so_far, temp_rec)) {
811816
hit_anything = true;
812817
closest_so_far = temp_rec.t;
813818
rec = temp_rec;
814819
}
815820
}
821+
816822
return hit_anything;
817823
}
818824

@@ -821,6 +827,11 @@
821827
[Listing [hittable-list-initial]: <kbd>[hittable_list.h]</kbd> The hittable_list class]
822828
</div>
823829

830+
If you're unfamiliar with C++'s `std::vector`, this is a generic array-like collection of an
831+
arbitrary type. Above, we use a collection of pointers to `hittable`. `std::vector` automatically
832+
grows as more values are added: `objects.push_back(object)` adds a value to the end of the
833+
`std::vector` member variable `objects`.
834+
824835
<div class='together'></div>
825836
We need some math constants that we conveniently define in their own header file. For now we only
826837
need infinity, but we will also throw our own definition of pi in there, which we will need later.
@@ -876,10 +887,10 @@
876887
#include <iostream>
877888

878889
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
879-
vec3 ray_color(const ray& r, hittable *world) {
890+
vec3 ray_color(const ray& r, hittable& world) {
880891
hit_record rec;
881-
if (world->hit(r, 0.0, infinity, rec)) {
882-
return 0.5*vec3(rec.normal.x()+1, rec.normal.y()+1, rec.normal.z()+1);
892+
if (world.hit(r, 0.0, infinity, rec)) {
893+
return 0.5 * (rec.normal + vec3(1,1,1));
883894
}
884895

885896
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
@@ -893,18 +904,19 @@
893904
int main() {
894905
int nx = 200;
895906
int ny = 100;
907+
896908
std::cout << "P3\n" << nx << ' ' << ny << "\n255\n";
909+
897910
vec3 lower_left_corner(-2.0, -1.0, -1.0);
898911
vec3 horizontal(4.0, 0.0, 0.0);
899912
vec3 vertical(0.0, 2.0, 0.0);
900913
vec3 origin(0.0, 0.0, 0.0);
901914

902915

903916
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
904-
hittable *list[2];
905-
list[0] = new sphere(vec3(0,0,-1), 0.5);
906-
list[1] = new sphere(vec3(0,-100.5,-1), 100);
907-
hittable *world = new hittable_list(list,2);
917+
hittable_list world;
918+
world.add(new sphere(vec3(0,0,-1), 0.5));
919+
world.add(new sphere(vec3(0,-100.5,-1), 100));
908920
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
909921

910922
for (int j = ny-1; j >= 0; --j) {
@@ -1077,12 +1089,12 @@
10771089
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
10781090
int num_samples = 100;
10791091
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
1092+
10801093
std::cout << "P3\n" << nx << " " << ny << "\n255\n";
10811094

1082-
hittable *list[2];
1083-
list[0] = new sphere(vec3(0,0,-1), 0.5);
1084-
list[1] = new sphere(vec3(0,-100.5,-1), 100);
1085-
hittable *world = new hittable_list(list,2);
1095+
hittable_list world;
1096+
world.add(new sphere(vec3(0,0,-1), 0.5));
1097+
world.add(new sphere(vec3(0,-100.5,-1), 100));
10861098

10871099
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
10881100
camera cam;
@@ -1196,9 +1208,9 @@
11961208
Then update the `ray_color()` function to use the new random direction generator:
11971209

11981210
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
1199-
vec3 ray_color(const ray& r, hittable *world) {
1211+
vec3 ray_color(const ray& r, hittable& world) {
12001212
hit_record rec;
1201-
if (world->hit(r, 0.0, infinity, rec)) {
1213+
if (world.hit(r, 0.0, infinity, rec)) {
12021214
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
12031215
vec3 target = rec.p + rec.normal + random_in_unit_sphere();
12041216
return 0.5 * ray_color(ray(rec.p, target - rec.p), world);
@@ -1220,9 +1232,10 @@
12201232
depth, returning no light contribution at the maximum depth:
12211233

12221234
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
1223-
vec3 ray_color(const ray& r, hittable *world, int depth) {
1235+
vec3 ray_color(const ray& r, hittable& world, int depth) {
12241236
hit_record rec;
1225-
if (world->hit(r, 0.0, infinity, rec)) {
1237+
if (world.hit(r, 0.0, infinity, rec)) {
1238+
// If we've exceeded the ray bounce limit, no more light is gathered.
12261239
if (depth <= 0)
12271240
return vec3(0,0,0);
12281241
vec3 target = rec.p + rec.normal + random_in_unit_sphere();
@@ -1242,6 +1255,7 @@
12421255
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
12431256
int max_depth = 50;
12441257
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
1258+
12451259
...
12461260
for (int j = ny-1; j >= 0; --j) {
12471261
std::cerr << "\rScanlines remaining: " << j << ' ' << std::flush;
@@ -1316,7 +1330,7 @@
13161330
point approximation the sphere intersector gives us. So we need to ignore hits very near zero:
13171331

13181332
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
1319-
if (world->hit(r, 0.001, infinity, rec)) {
1333+
if (world.hit(r, 0.001, infinity, rec)) {
13201334
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13211335
[Listing [reflect-tolerance]: <kbd>[main.cc]</kbd> Calculating reflected ray origins with tolerance]
13221336

@@ -1357,9 +1371,10 @@
13571371
function.
13581372

13591373
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
1360-
vec3 ray_color(const ray& r, hittable *world, int depth) {
1374+
vec3 ray_color(const ray& r, hittable& world, int depth) {
13611375
hit_record rec;
1362-
if (world->hit(r, 0.0, infinity, rec)) {
1376+
if (world.hit(r, 0.0, infinity, rec)) {
1377+
// If we've exceeded the ray bounce limit, no more light is gathered.
13631378
if (depth <= 0)
13641379
return vec3(0,0,0);
13651380
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
@@ -1432,9 +1447,10 @@
14321447
Plugging the new formula into the `ray_color()` function:
14331448

14341449
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
1435-
vec3 ray_color(const ray& r, hittable *world, int depth) {
1450+
vec3 ray_color(const ray& r, hittable& world, int depth) {
14361451
hit_record rec;
1437-
if (world->hit(r, 0.0, infinity, rec)) {
1452+
if (world.hit(r, 0.0, infinity, rec)) {
1453+
// If we've exceeded the ray bounce limit, no more light is gathered.
14381454
if (depth <= 0)
14391455
return vec3(0,0,0);
14401456
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
@@ -1660,10 +1676,11 @@
16601676
We need to modify the color function to use this:
16611677

16621678
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
1663-
vec3 ray_color(const ray& r, hittable *world, int depth) {
1679+
vec3 ray_color(const ray& r, hittable& world, int depth) {
16641680
hit_record rec;
16651681
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
1666-
if (world->hit(r, 0.001, infinity, rec)) {
1682+
if (world.hit(r, 0.001, infinity, rec)) {
1683+
// If we've exceeded the ray bounce limit, no more light is gathered.
16671684
if (depth <= 0)
16681685
return vec3(0,0,0);
16691686
ray scattered;
@@ -1696,12 +1713,11 @@
16961713

16971714

16981715
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
1699-
hittable *list[4];
1700-
list[0] = new sphere(vec3(0,0,-1), 0.5, new lambertian(vec3(0.7, 0.3, 0.3)));
1701-
list[1] = new sphere(vec3(0,-100.5,-1), 100, new lambertian(vec3(0.8, 0.8, 0.0)));
1702-
list[2] = new sphere(vec3(1,0,-1), 0.5, new metal(vec3(0.8, 0.6, 0.2)));
1703-
list[3] = new sphere(vec3(-1,0,-1), 0.5, new metal(vec3(0.8, 0.8, 0.8)));
1704-
hittable *world = new hittable_list(list,4);
1716+
hittable_list world;
1717+
world.add(new sphere(vec3(0,0,-1), 0.5, new lambertian(vec3(0.7, 0.3, 0.3))));
1718+
world.add(new sphere(vec3(0,-100.5,-1), 100, new lambertian(vec3(0.8, 0.8, 0.0))));
1719+
world.add(new sphere(vec3(1,0,-1), 0.5, new metal(vec3(0.8, 0.6, 0.2))));
1720+
world.add(new sphere(vec3(-1,0,-1), 0.5, new metal(vec3(0.8, 0.8, 0.8))));
17051721
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
17061722

17071723
camera cam;
@@ -2068,9 +2084,9 @@
20682084

20692085
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
20702086
auto R = cos(pi/4);
2071-
list[0] = new sphere(vec3(-R,0,-1), R, new lambertian(vec3(0, 0, 1)));
2072-
list[1] = new sphere(vec3( R,0,-1), R, new lambertian(vec3(1, 0, 0)));
2073-
hittable *world = new hittable_list(list,2);
2087+
hittable_list world;
2088+
world.add(new sphere(vec3(-R,0,-1), R, new lambertian(vec3(0, 0, 1))));
2089+
world.add(new sphere(vec3( R,0,-1), R, new lambertian(vec3(1, 0, 0))));
20742090
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20752091
[Listing [scene-wide-angle]: <kbd>[main.cc]</kbd> Scene with wide-angle camera]
20762092

@@ -2307,38 +2323,45 @@
23072323
First let’s make the image on the cover of this book -- lots of random spheres:
23082324

23092325
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
2310-
hittable *random_scene() {
2311-
int n = 500;
2312-
hittable **list = new hittable*[n+1];
2313-
list[0] = new sphere(vec3(0,-1000,0), 1000, new lambertian(vec3(0.5, 0.5, 0.5)));
2326+
hittable_list random_scene() {
2327+
hittable_list objects;
2328+
2329+
objects.add(new sphere(vec3(0,-1000,0), 1000, new lambertian(vec3(0.5, 0.5, 0.5))));
2330+
23142331
int i = 1;
23152332
for (int a = -11; a < 11; a++) {
23162333
for (int b = -11; b < 11; b++) {
23172334
auto choose_mat = random_double();
23182335
vec3 center(a + 0.9*random_double(), 0.2, b + 0.9*random_double());
2319-
if ((center-vec3(4,0.2,0)).length() > 0.9) {
2336+
if ((center - vec3(4, .2, 0)).length() > 0.9) {
23202337
if (choose_mat < 0.8) {
23212338
// diffuse
23222339
auto albedo = vec3::random() * vec3::random();
2323-
list[i++] = new sphere(center, 0.2, new lambertian(albedo));
2340+
objects.add(new sphere(center, 0.2, new lambertian(albedo)));
23242341
} else if (choose_mat < 0.95) {
23252342
// metal
23262343
auto albedo = vec3::random(.5, 1);
23272344
auto fuzz = random_double(0, .5);
2328-
list[i++] = new sphere(center, 0.2, new metal(albedo, fuzz));
2345+
objects.add(new sphere(center, 0.2, new metal(albedo, fuzz)));
23292346
} else {
23302347
// glass
2331-
list[i++] = new sphere(center, 0.2, new dielectric(1.5));
2348+
objects.add(new sphere(center, 0.2, new dielectric(1.5)));
23322349
}
23332350
}
23342351
}
23352352
}
23362353

2337-
list[i++] = new sphere(vec3(0, 1, 0), 1.0, new dielectric(1.5));
2338-
list[i++] = new sphere(vec3(-4, 1, 0), 1.0, new lambertian(vec3(0.4, 0.2, 0.1)));
2339-
list[i++] = new sphere(vec3(4, 1, 0), 1.0, new metal(vec3(0.7, 0.6, 0.5), 0.0));
2354+
objects.add(new sphere(vec3(0, 1, 0), 1.0, new dielectric(1.5)));
2355+
objects.add(new sphere(vec3(-4, 1, 0), 1.0, new lambertian(vec3(0.4, 0.2, 0.1))));
2356+
objects.add(new sphere(vec3(4, 1, 0), 1.0, new metal(vec3(0.7, 0.6, 0.5), 0.0)));
23402357

2341-
return new hittable_list(list,i);
2358+
return objects;
2359+
}
2360+
2361+
int main() {
2362+
...
2363+
auto world = random_scene();
2364+
...
23422365
}
23432366
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23442367
[Listing [scene-final]: <kbd>[main.cc]</kbd> Final scene]

0 commit comments

Comments
 (0)