Skip to content

Commit 4f4144c

Browse files
committed
Simplify the ONB class
The `onb` class implemented several unused methods, so I've removed them in the interest of simplicity. These include the operator[] methods to retrieve the basis axes, as well as a transform function that took three individual double values. Finally, instead of having an uninitialized form with a `build_from_w()` function, the class now requires a vector at construction time, consistent with our use of the class. I've renamed `local()` to `transform()` for a bit more clarity, without trying to name either the input space or the result space, as "local" means different things at different times, and to different people. Resolves #1088
1 parent b98d19a commit 4f4144c

File tree

5 files changed

+34
-59
lines changed

5 files changed

+34
-59
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Change Log -- Ray Tracing in One Weekend
1414
### The Next Week
1515

1616
### The Rest of Your Life
17-
17+
- Change -- Simplified the `onb` class, and renamed or deleted methods (#1080)
1818

1919

2020

books/RayTracingTheRestOfYourLife.html

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2257,31 +2257,20 @@
22572257

22582258
class onb {
22592259
public:
2260-
onb() {}
2261-
2262-
vec3 operator[](int i) const { return axis[i]; }
2263-
vec3& operator[](int i) { return axis[i]; }
2264-
2265-
vec3 u() const { return axis[0]; }
2266-
vec3 v() const { return axis[1]; }
2267-
vec3 w() const { return axis[2]; }
2268-
2269-
vec3 local(double a, double b, double c) const {
2270-
return a*u() + b*v() + c*w();
2260+
onb(const vec3& n) {
2261+
axis[2] = unit_vector(n);
2262+
vec3 a = (std::fabs(axis[2].x()) > 0.9) ? vec3(0,1,0) : vec3(1,0,0);
2263+
axis[1] = unit_vector(cross(axis[2], a));
2264+
axis[0] = cross(axis[2], axis[1]);
22712265
}
22722266

2273-
vec3 local(const vec3& a) const {
2274-
return a.x()*u() + a.y()*v() + a.z()*w();
2275-
}
2267+
const vec3& u() const { return axis[0]; }
2268+
const vec3& v() const { return axis[1]; }
2269+
const vec3& w() const { return axis[2]; }
22762270

2277-
void build_from_w(const vec3& w) {
2278-
vec3 unit_w = unit_vector(w);
2279-
vec3 a = (std::fabs(unit_w.x()) > 0.9) ? vec3(0,1,0) : vec3(1,0,0);
2280-
vec3 v = unit_vector(cross(unit_w, a));
2281-
vec3 u = cross(unit_w, v);
2282-
axis[0] = u;
2283-
axis[1] = v;
2284-
axis[2] = unit_w;
2271+
vec3 transform(const vec3& v) const {
2272+
// Transform from basis coordinates to local space.
2273+
return (v[0] * axis[0]) + (v[1] * axis[1]) + (v[2] * axis[2]);
22852274
}
22862275

22872276
private:
@@ -2332,9 +2321,8 @@
23322321
bool scatter(
23332322
const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered, double& pdf
23342323
) const override {
2335-
onb uvw;
2336-
uvw.build_from_w(rec.normal);
2337-
auto scatter_direction = uvw.local(random_cosine_direction());
2324+
onb uvw(rec.normal);
2325+
auto scatter_direction = uvw.transform(random_cosine_direction());
23382326

23392327
scattered = ray(rec.p, unit_vector(scatter_direction), r_in.time());
23402328
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
@@ -2428,7 +2416,7 @@
24282416
...
24292417
};
24302418
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2431-
[Listing [scatter-onb-ray-color]: <kbd>[camera.h]</kbd>
2419+
[Listing [scatter-ray-color]: <kbd>[camera.h]</kbd>
24322420
Updated ray_color function with returned PDF value
24332421
]
24342422

@@ -2769,15 +2757,15 @@
27692757
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
27702758
class cosine_pdf : public pdf {
27712759
public:
2772-
cosine_pdf(const vec3& w) { uvw.build_from_w(w); }
2760+
cosine_pdf(const vec3& w) : uvw(w) {}
27732761

27742762
double value(const vec3& direction) const override {
27752763
auto cosine_theta = dot(unit_vector(direction), uvw.w());
27762764
return std::fmax(0, cosine_theta/pi);
27772765
}
27782766

27792767
vec3 generate() const override {
2780-
return uvw.local(random_cosine_direction());
2768+
return uvw.transform(random_cosine_direction());
27812769
}
27822770

27832771
private:
@@ -3756,9 +3744,8 @@
37563744
vec3 random(const point3& origin) const override {
37573745
vec3 direction = center1 - origin;
37583746
auto distance_squared = direction.length_squared();
3759-
onb uvw;
3760-
uvw.build_from_w(direction);
3761-
return uvw.local(random_to_sphere(radius, distance_squared));
3747+
onb uvw(direction);
3748+
return uvw.transform(random_to_sphere(radius, distance_squared));
37623749
}
37633750
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
37643751

src/TheRestOfYourLife/onb.h

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,20 @@
1616

1717
class onb {
1818
public:
19-
onb() {}
20-
21-
vec3 operator[](int i) const { return axis[i]; }
22-
vec3& operator[](int i) { return axis[i]; }
23-
24-
vec3 u() const { return axis[0]; }
25-
vec3 v() const { return axis[1]; }
26-
vec3 w() const { return axis[2]; }
27-
28-
vec3 local(double a, double b, double c) const {
29-
return a*u() + b*v() + c*w();
19+
onb(const vec3& n) {
20+
axis[2] = unit_vector(n);
21+
vec3 a = (std::fabs(axis[2].x()) > 0.9) ? vec3(0,1,0) : vec3(1,0,0);
22+
axis[1] = unit_vector(cross(axis[2], a));
23+
axis[0] = cross(axis[2], axis[1]);
3024
}
3125

32-
vec3 local(const vec3& a) const {
33-
return a.x()*u() + a.y()*v() + a.z()*w();
34-
}
26+
const vec3& u() const { return axis[0]; }
27+
const vec3& v() const { return axis[1]; }
28+
const vec3& w() const { return axis[2]; }
3529

36-
void build_from_w(const vec3& w) {
37-
vec3 unit_w = unit_vector(w);
38-
vec3 a = (std::fabs(unit_w.x()) > 0.9) ? vec3(0,1,0) : vec3(1,0,0);
39-
vec3 v = unit_vector(cross(unit_w, a));
40-
vec3 u = cross(unit_w, v);
41-
axis[0] = u;
42-
axis[1] = v;
43-
axis[2] = unit_w;
30+
vec3 transform(const vec3& v) const {
31+
// Transform from basis coordinates to local space.
32+
return (v[0] * axis[0]) + (v[1] * axis[1]) + (v[2] * axis[2]);
4433
}
4534

4635
private:

src/TheRestOfYourLife/pdf.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,15 @@ class sphere_pdf : public pdf {
4242

4343
class cosine_pdf : public pdf {
4444
public:
45-
cosine_pdf(const vec3& w) { uvw.build_from_w(w); }
45+
cosine_pdf(const vec3& w) : uvw(w) {}
4646

4747
double value(const vec3& direction) const override {
4848
auto cosine_theta = dot(unit_vector(direction), uvw.w());
4949
return std::fmax(0, cosine_theta/pi);
5050
}
5151

5252
vec3 generate() const override {
53-
return uvw.local(random_cosine_direction());
53+
return uvw.transform(random_cosine_direction());
5454
}
5555

5656
private:

src/TheRestOfYourLife/sphere.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,8 @@ class sphere : public hittable {
8787
vec3 random(const point3& origin) const override {
8888
vec3 direction = center1 - origin;
8989
auto distance_squared = direction.length_squared();
90-
onb uvw;
91-
uvw.build_from_w(direction);
92-
return uvw.local(random_to_sphere(radius, distance_squared));
90+
onb uvw(direction);
91+
return uvw.transform(random_to_sphere(radius, distance_squared));
9392
}
9493

9594
private:

0 commit comments

Comments
 (0)