Skip to content

Commit 391e3ce

Browse files
committed
Update book1 to shared_ptr
1 parent 9b156c5 commit 391e3ce

File tree

2 files changed

+100
-37
lines changed

2 files changed

+100
-37
lines changed

books/RayTracingInOneWeekend.html

Lines changed: 97 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -920,15 +920,15 @@
920920
class hittable_list: public hittable {
921921
public:
922922
hittable_list() {}
923-
hittable_list(hittable* object) { add(object); }
923+
hittable_list(shared_ptr<hittable> object) { add(object); }
924924

925-
void clear() { objects.clear(); }
926-
void add(hittable* object) { objects.push_back(object); }
925+
void clear() { objects.clear(); }
926+
void add(shared_ptr<hittable> object) { objects.push_back(object); }
927927

928928
virtual bool hit(const ray& r, double tmin, double tmax, hit_record& rec) const;
929929

930930
public:
931-
std::vector<hittable*> objects;
931+
std::vector<shared_ptr<hittable>> objects;
932932
};
933933

934934
bool hittable_list::hit(const ray& r, double t_min, double t_max, hit_record& rec) const {
@@ -952,10 +952,41 @@
952952
[Listing [hittable-list-initial]: <kbd>[hittable_list.h]</kbd> The hittable_list class]
953953
</div>
954954

955-
If you're unfamiliar with C++'s `std::vector`, this is a generic array-like collection of an
956-
arbitrary type. Above, we use a collection of pointers to `hittable`. `std::vector` automatically
957-
grows as more values are added: `objects.push_back(object)` adds a value to the end of the
958-
`std::vector` member variable `objects`.
955+
## Some New C++ Features
956+
957+
This code uses two C++ features that may trip you up if you're not normally a C++ programmer:
958+
`vector` and `shared_ptr`.
959+
960+
`shared_ptr<type>` is a pointer to some allocated type, with reference-counting semantics.
961+
Every time you assign its value to another shared pointer (usually with a simple assignment), the
962+
reference count is incremented. As shared pointers go out of scope (like at the end of a block or
963+
function), the reference count is decremented. Once the count goes to zero, the object is deleted.
964+
965+
<div class='together'>
966+
Typically, a shared pointer is first initialized with a newly-allocated object, something like this:
967+
968+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
969+
shared_ptr<thing> thing_ptr = make_shared<thing>(1, true);
970+
auto thing2_ptr = make_shared<thing2>(2, false);
971+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
972+
[Listing [shared-ptr]: An example allocation using `shared_ptr`]
973+
974+
`make_shared<thing>(1, true)` allocates a new instance of type `thing`, using the constructor
975+
arguments `(1, true)`. It returns a `shared_ptr<thing>`. This can be simplified as in the second
976+
line with the `auto` type declaration, because the type is sufficiently defined by the return type
977+
of `make_shared<thing2>`.
978+
979+
We'll use shared pointers in our code, because it allows multiple objects to use a common object
980+
(for example, a bunch of spheres that all use the same material), and because it makes memory
981+
management automatic and easier to reason about.
982+
</div>
983+
984+
The second C++ feature you may be unfamiliar with is `std::vector`. This is a generic array-like
985+
collection of an arbitrary type. Above, we use a collection of pointers to `hittable`. `std::vector`
986+
automatically grows as more values are added: `objects.push_back(object)` adds a value to the end of
987+
the `std::vector` member variable `objects`.
988+
989+
## Common Constants and Utility Functions
959990

960991
<div class='together'></div>
961992
We need some math constants that we conveniently define in their own header file. For now we only
@@ -1040,8 +1071,8 @@
10401071

10411072
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
10421073
hittable_list world;
1043-
world.add(new sphere(vec3(0,0,-1), 0.5));
1044-
world.add(new sphere(vec3(0,-100.5,-1), 100));
1074+
world.add(make_shared<sphere>(vec3(0,0,-1), 0.5));
1075+
world.add(make_shared<sphere>(vec3(0,-100.5,-1), 100));
10451076
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
10461077

10471078
for (int j = ny-1; j >= 0; --j) {
@@ -1218,8 +1249,8 @@
12181249
std::cout << "P3\n" << nx << " " << ny << "\n255\n";
12191250

12201251
hittable_list world;
1221-
world.add(new sphere(vec3(0,0,-1), 0.5));
1222-
world.add(new sphere(vec3(0,-100.5,-1), 100));
1252+
world.add(make_shared<sphere>(vec3(0,0,-1), 0.5));
1253+
world.add(make_shared<sphere>(vec3(0,-100.5,-1), 100));
12231254

12241255
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
12251256
camera cam;
@@ -1650,7 +1681,7 @@
16501681
vec3 p;
16511682
vec3 normal;
16521683
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
1653-
material *mat_ptr;
1684+
shared_ptr<material> mat_ptr;
16541685
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
16551686
double t;
16561687
bool front_face;
@@ -1687,12 +1718,17 @@
16871718
class sphere: public hittable {
16881719
public:
16891720
sphere() {}
1690-
sphere(vec3 cen, double r, material *m) : center(cen), radius(r), mat_ptr(m) {};
1721+
1722+
sphere(vec3 cen, double r, shared_ptr<material> m)
1723+
: center(cen), radius(r), mat_ptr(m) {};
1724+
16911725
virtual bool hit(const ray& r, double tmin, double tmax, hit_record& rec) const;
1726+
1727+
public:
16921728
vec3 center;
16931729
double radius;
16941730
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
1695-
material *mat_ptr;
1731+
shared_ptr<material> mat_ptr;
16961732
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
16971733
};
16981734
bool sphere::hit(const ray& r, double t_min, double t_max, hit_record& rec) const {
@@ -1752,6 +1788,7 @@
17521788
return true;
17531789
}
17541790

1791+
public:
17551792
vec3 albedo;
17561793
};
17571794
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1799,6 +1836,8 @@
17991836
attenuation = albedo;
18001837
return (dot(scattered.direction(), rec.normal) > 0);
18011838
}
1839+
1840+
public:
18021841
vec3 albedo;
18031842
};
18041843
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1847,10 +1886,15 @@
18471886

18481887
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
18491888
hittable_list world;
1850-
world.add(new sphere(vec3(0,0,-1), 0.5, new lambertian(vec3(0.7, 0.3, 0.3))));
1851-
world.add(new sphere(vec3(0,-100.5,-1), 100, new lambertian(vec3(0.8, 0.8, 0.0))));
1852-
world.add(new sphere(vec3(1,0,-1), 0.5, new metal(vec3(0.8, 0.6, 0.2))));
1853-
world.add(new sphere(vec3(-1,0,-1), 0.5, new metal(vec3(0.8, 0.8, 0.8))));
1889+
1890+
world.add(make_shared<sphere>(
1891+
vec3(0,0,-1), 0.5, make_shared<lambertian>(vec3(0.7, 0.3, 0.3))));
1892+
1893+
world.add(make_shared<sphere>(
1894+
vec3(0,-100.5,-1), 100, make_shared<lambertian>(vec3(0.8, 0.8, 0.0))));
1895+
1896+
world.add(make_shared<sphere>(vec3(1,0,-1), 0.5, make_shared<metal>(vec3(0.8, 0.6, 0.2))));
1897+
world.add(make_shared<sphere>(vec3(-1,0,-1), 0.5, make_shared<metal>(vec3(0.8, 0.8, 0.8))));
18541898
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
18551899

18561900
camera cam;
@@ -1912,6 +1956,8 @@
19121956
attenuation = albedo;
19131957
return (dot(scattered.direction(), rec.normal) > 0);
19141958
}
1959+
1960+
public:
19151961
vec3 albedo;
19161962
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
19171963
double fuzz;
@@ -2134,6 +2180,7 @@
21342180
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
21352181
}
21362182

2183+
public:
21372184
double ref_idx;
21382185
};
21392186
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2144,10 +2191,14 @@
21442191
Attenuation is always 1 -- the glass surface absorbs nothing. If we try that out with these parameters:
21452192

21462193
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
2147-
list[0] = new sphere(vec3(0,0,-1), 0.5, new lambertian(vec3(0.1, 0.2, 0.5)));
2148-
list[1] = new sphere(vec3(0,-100.5,-1), 100, new lambertian(vec3(0.8, 0.8, 0.0)));
2149-
list[2] = new sphere(vec3(1,0,-1), 0.5, new metal(vec3(0.8, 0.6, 0.2), 0.0));
2150-
list[3] = new sphere(vec3(-1,0,-1), 0.5, new dielectric(1.5));
2194+
world.add(make_shared<sphere>(
2195+
vec3(0,0,-1), 0.5, make_shared<lambertian>(vec3(0.1, 0.2, 0.5)));
2196+
2197+
world.add(make_shared<sphere>(
2198+
vec3(0,-100.5,-1), 100, make_shared<lambertian>(vec3(0.8, 0.8, 0.0)));
2199+
2200+
world.add(make_shared<sphere>(vec3(1,0,-1), 0.5, make_shared<metal>(vec3(0.8, 0.6, 0.2), 0.0));
2201+
world.add(make_shared<sphere>(vec3(-1,0,-1), 0.5, make_shared<dielectric>(1.5));
21512202
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21522203
[Listing [scene-dielectric]: <kbd>[main.cc]</kbd> Scene with dielectric sphere]
21532204

@@ -2206,6 +2257,7 @@
22062257
return true;
22072258
}
22082259

2260+
public:
22092261
double ref_idx;
22102262
};
22112263
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2218,11 +2270,12 @@
22182270
to make a hollow glass sphere:
22192271

22202272
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
2221-
list[0] = new sphere(vec3(0,0,-1), 0.5, new lambertian(vec3(0.1, 0.2, 0.5)));
2222-
list[1] = new sphere(vec3(0,-100.5,-1), 100, new lambertian(vec3(0.8, 0.8, 0.0)));
2223-
list[2] = new sphere(vec3(1,0,-1), 0.5, new metal(vec3(0.8, 0.6, 0.2), 0.3));
2224-
list[3] = new sphere(vec3(-1,0,-1), 0.5, new dielectric(1.5));
2225-
list[4] = new sphere(vec3(-1,0,-1), -0.45, new dielectric(1.5));
2273+
world.add(make_shared<sphere>(vec3(0,0,-1), 0.5, make_shared<lambertian>(vec3(0.1, 0.2, 0.5)));
2274+
world.add(make_shared<sphere>(
2275+
vec3(0,-100.5,-1), 100, make_shared<lambertian>(vec3(0.8, 0.8, 0.0)));
2276+
world.add(make_shared<sphere>(vec3(1,0,-1), 0.5, make_shared<metal>(vec3(0.8, 0.6, 0.2), 0.3));
2277+
world.add(make_shared<sphere>(vec3(-1,0,-1), 0.5, make_shared<dielectric>(1.5));
2278+
world.add(make_shared<sphere>(vec3(-1,0,-1), -0.45, make_shared<dielectric>(1.5));
22262279
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22272280
[Listing [scene-hollow-glass]: <kbd>[main.cc]</kbd> Scene with hollow glass sphere]
22282281
</div>
@@ -2295,8 +2348,8 @@
22952348
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
22962349
auto R = cos(pi/4);
22972350
hittable_list world;
2298-
world.add(new sphere(vec3(-R,0,-1), R, new lambertian(vec3(0, 0, 1))));
2299-
world.add(new sphere(vec3( R,0,-1), R, new lambertian(vec3(1, 0, 0))));
2351+
world.add(make_shared<sphere>(vec3(-R,0,-1), R, make_shared<lambertian>(vec3(0, 0, 1))));
2352+
world.add(make_shared<sphere(>vec3( R,0,-1), R, make_shared<lambertian>(vec3(1, 0, 0))));
23002353
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23012354
[Listing [scene-wide-angle]: <kbd>[main.cc]</kbd> Scene with wide-angle camera]
23022355

@@ -2536,7 +2589,8 @@
25362589
hittable_list random_scene() {
25372590
hittable_list objects;
25382591

2539-
objects.add(new sphere(vec3(0,-1000,0), 1000, new lambertian(vec3(0.5, 0.5, 0.5))));
2592+
objects.add(make_shared<sphere>(
2593+
vec3(0,-1000,0), 1000, make_shared<lambertian>(vec3(0.5, 0.5, 0.5))));
25402594

25412595
int i = 1;
25422596
for (int a = -11; a < 11; a++) {
@@ -2547,23 +2601,29 @@
25472601
if (choose_mat < 0.8) {
25482602
// diffuse
25492603
auto albedo = vec3::random() * vec3::random();
2550-
objects.add(new sphere(center, 0.2, new lambertian(albedo)));
2604+
objects.add(
2605+
make_shared<sphere>(center, 0.2, make_shared<lambertian>(albedo)));
25512606
} else if (choose_mat < 0.95) {
25522607
// metal
25532608
auto albedo = vec3::random(.5, 1);
25542609
auto fuzz = random_double(0, .5);
2555-
objects.add(new sphere(center, 0.2, new metal(albedo, fuzz)));
2610+
objects.add(
2611+
make_shared<sphere>(center, 0.2, make_shared<metal>(albedo, fuzz)));
25562612
} else {
25572613
// glass
2558-
objects.add(new sphere(center, 0.2, new dielectric(1.5)));
2614+
objects.add(make_shared<sphere>(center, 0.2, make_shared<dielectric>(1.5)));
25592615
}
25602616
}
25612617
}
25622618
}
25632619

2564-
objects.add(new sphere(vec3(0, 1, 0), 1.0, new dielectric(1.5)));
2565-
objects.add(new sphere(vec3(-4, 1, 0), 1.0, new lambertian(vec3(0.4, 0.2, 0.1))));
2566-
objects.add(new sphere(vec3(4, 1, 0), 1.0, new metal(vec3(0.7, 0.6, 0.5), 0.0)));
2620+
objects.add(make_shared<sphere>(vec3(0, 1, 0), 1.0, make_shared<dielectric>(1.5)));
2621+
2622+
objects.add(
2623+
make_shared<sphere>(vec3(-4, 1, 0), 1.0, make_shared<lambertian>(vec3(0.4, 0.2, 0.1))));
2624+
2625+
objects.add(
2626+
make_shared<sphere>(vec3(4, 1, 0), 1.0, make_shared<metal>(vec3(0.7, 0.6, 0.5), 0.0)));
25672627

25682628
return objects;
25692629
}

src/InOneWeekend/material.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class dielectric : public material {
6464
return true;
6565
}
6666

67+
public:
6768
double ref_idx;
6869
};
6970

@@ -81,6 +82,7 @@ class lambertian : public material {
8182
return true;
8283
}
8384

85+
public:
8486
vec3 albedo;
8587
};
8688

@@ -98,6 +100,7 @@ class metal : public material {
98100
return (dot(scattered.direction(), rec.normal) > 0);
99101
}
100102

103+
public:
101104
vec3 albedo;
102105
double fuzz;
103106
};

0 commit comments

Comments
 (0)