Skip to content

Commit c4177a7

Browse files
committed
Revise random in unit disk/sphere, random unit vec
1 parent e1f97c5 commit c4177a7

File tree

4 files changed

+37
-45
lines changed

4 files changed

+37
-45
lines changed

books/RayTracingInOneWeekend.html

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,8 +1161,7 @@
11611161
<div class='together'>
11621162
We need a way to pick a random point in a unit radius sphere. We’ll use what is usually the easiest
11631163
algorithm: a rejection method. First, pick a random point in the unit cube where x, y, and z all
1164-
range from -1 to +1. Reject this point and try again if the point is outside the sphere. A
1165-
do-while construct is perfect for that:
1164+
range from -1 to +1. Reject this point and try again if the point is outside the sphere.
11661165

11671166
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
11681167
class vec3 {
@@ -1180,11 +1179,11 @@
11801179

11811180
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
11821181
vec3 random_in_unit_sphere() {
1183-
vec3 p;
1184-
do {
1185-
p = vec3::random(-1,1);
1186-
} while (p.length_squared() >= 1.0);
1187-
return p;
1182+
while (true) {
1183+
auto p = vec3::random(-1,1);
1184+
if (p.length_squared() >= 1) continue;
1185+
return p;
1186+
}
11881187
}
11891188
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11901189
[Listing [random-in-unit-sphere]: <kbd>[material.h]</kbd> The random_in_unit_sphere() function]
@@ -1337,7 +1336,10 @@
13371336

13381337
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
13391338
vec3 random_unit_vector() {
1340-
return unit_vector(random_in_unit_sphere());
1339+
auto a = random_double(0, 2*pi);
1340+
auto z = random_double(-1, 1);
1341+
auto r = sqrt(1 - z*z);
1342+
return vec3(r*cos(a), r*sin(a), z);
13411343
}
13421344
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13431345
[Listing [random-unit-vector]: <kbd>[vec3.h]</kbd> The random_unit_vector() function]
@@ -1585,15 +1587,6 @@
15851587
it could be a mixture of those strategies. For Lambertian materials we get this simple class:
15861588

15871589
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
1588-
vec3 random_unit_vector() {
1589-
auto a = random_double(0, 2*pi);
1590-
auto z = random_double(-1, 1);
1591-
auto r = sqrt(1 - z*z);
1592-
return vec3(r*cos(a), r*sin(a), z);
1593-
}
1594-
1595-
...
1596-
15971590
class lambertian : public material {
15981591
public:
15991592
lambertian(const vec3& a) : albedo(a) {}
@@ -1775,10 +1768,6 @@
17751768
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17761769
[Listing [metal-fuzz]: <kbd>[material.h]</kbd> Metal spheres with fuzziness]
17771770

1778-
In order to generate a random point inside a unit sphere (`random_in_unit_sphere()`), we used one of
1779-
the easiest algorithms: a rejection method. First, pick a random point in the unit cube where x, y,
1780-
and z all range from -1 to +1. If the generated point is outside the unit sphere, repeat until we
1781-
get one on the inside. A do/while construct is perfect for that.
17821771
</div>
17831772

17841773
<div class='together'>
@@ -2222,11 +2211,11 @@
22222211

22232212
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
22242213
vec3 random_in_unit_disk() {
2225-
vec3 p;
2226-
do {
2227-
p = vec3(random_double(-1,1), random_double(-1,1), 0);
2228-
} while (dot(p,p) >= 1.0);
2229-
return p;
2214+
while (true) {
2215+
auto p = vec3(random_double(-1,1), random_double(-1,1), 0);
2216+
if (p.length_squared() >= 1) continue;
2217+
return p;
2218+
}
22302219
}
22312220
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22322221
[Listing [rand-in-unit-disk]: <kbd>[vec3.h]</kbd> Generate random point inside unit disk]
@@ -2265,7 +2254,7 @@
22652254

22662255
ray get_ray(double s, double t) {
22672256
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
2268-
vec3 rd = lens_radius*random_in_unit_disk();
2257+
vec3 rd = lens_radius * random_in_unit_disk();
22692258
vec3 offset = u * rd.x() + v * rd.y();
22702259

22712260
return ray(

books/RayTracingTheNextWeek.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@
132132
}
133133

134134
ray get_ray(double s, double t) {
135-
vec3 rd = lens_radius*random_in_unit_disk();
135+
vec3 rd = lens_radius * random_in_unit_disk();
136136
vec3 offset = u * rd.x() + v * rd.y();
137137
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
138138
return ray(

books/RayTracingTheRestOfYourLife.html

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -537,19 +537,22 @@
537537
is direction in that context? We could make it based on polar coordinates, so $p$ would be in terms
538538
of $(\theta, \phi)$. However you do it, remember that a PDF has to integrate to 1 and represent the
539539
relative probability of that direction being sampled. We have a method from the last books to take
540-
uniform random samples on a unit sphere:
540+
uniform random samples in or on a unit sphere:
541541

542542
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
543543
vec3 random_in_unit_sphere() {
544-
vec3 p;
545-
do {
546-
p = vec3(random_double(-1,1), random_double(-1,1), random_double(-1,1));
547-
} while (p.length_squared() >= 1);
548-
return p;
544+
while (true) {
545+
auto p = vec3::random(-1,1);
546+
if (p.length_squared() >= 1) continue;
547+
return p;
548+
}
549549
}
550550

551551
vec3 random_unit_vector() {
552-
return unit_vector(random_in_unit_sphere());
552+
auto a = random_double(0, 2*pi);
553+
auto z = random_double(-1, 1);
554+
auto r = sqrt(1 - z*z);
555+
return vec3(r*cos(a), r*sin(a), z);
553556
}
554557
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
555558
[Listing [random-unit-vector]: <kbd>[vec3.h]</kbd> Random vector of unit length]

src/common/vec3.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,11 @@ inline vec3 unit_vector(vec3 v) {
132132
}
133133

134134
vec3 random_in_unit_disk() {
135-
vec3 p;
136-
do {
137-
p = vec3(random_double(-1,1), random_double(-1,1), 0);
138-
} while (p.length_squared() >= 1.0);
139-
return p;
135+
while (true) {
136+
auto p = vec3(random_double(-1,1), random_double(-1,1), 0);
137+
if (p.length_squared() >= 1) continue;
138+
return p;
139+
}
140140
}
141141

142142
vec3 random_unit_vector() {
@@ -147,11 +147,11 @@ vec3 random_unit_vector() {
147147
}
148148

149149
vec3 random_in_unit_sphere() {
150-
vec3 p;
151-
do {
152-
p = vec3::random(-1,1);
153-
} while (p.length_squared() >= 1.0);
154-
return p;
150+
while (true) {
151+
auto p = vec3::random(-1,1);
152+
if (p.length_squared() >= 1) continue;
153+
return p;
154+
}
155155
}
156156

157157
vec3 random_in_hemisphere(const vec3& normal) {

0 commit comments

Comments
 (0)