diff --git a/CHANGELOG.md b/CHANGELOG.md
index eb4f0d4c..9cffc92a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,8 @@ Change Log -- Ray Tracing in One Weekend
# v4.0.0 (pending, targeted for 2020-12-25)
### Common
+ - Change: Introduce new `interval` class used throughout codebase (#777)
+ - Change: `hittable:hit()` methods use new interval class for ray t parameter
### In One Weekend
diff --git a/books/RayTracingInOneWeekend.html b/books/RayTracingInOneWeekend.html
index 6c1d4b14..6c3ce6ce 100644
--- a/books/RayTracingInOneWeekend.html
+++ b/books/RayTracingInOneWeekend.html
@@ -1278,6 +1278,128 @@
+An Interval Class
+------------------
+Before we continue, we'll implement an interval class to manage real-valued intervals with a minimum
+and a maximum. We'll end up using this class quite often as we proceed.
+
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
+ #ifndef INTERVAL_H
+ #define INTERVAL_H
+
+ class interval {
+ public:
+ double min, max;
+
+ interval(double _min, double _max) : min(_min), max(_max) {}
+ interval() : min(+infinity), max(-infinity) {} // Default interval is empty
+
+ bool contains(double x) const {
+ return min <= x && x <= max;
+ }
+ };
+
+ const static interval empty (+infinity, -infinity);
+ const static interval universe(-infinity, +infinity);
+
+
+ #endif
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [interval-initial]: [interval.h] Introducing the new interval class]
+
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
+ class hittable {
+ public:
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const = 0;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
+ };
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [hittable-with-interval]: [hittable.h] hittable::hit() using interval]
+
+
+
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
+ class hittable_list : public hittable {
+ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
+ ...
+ };
+
+
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
+ bool hittable_list::hit(const ray& r, interval ray_t, hit_record& rec) const {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
+ hit_record temp_rec;
+ bool hit_anything = false;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
+ auto closest_so_far = ray_t.max;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
+
+ for (const auto& object : objects) {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
+ if (object->hit(r, interval(ray_t.min, closest_so_far), temp_rec)) {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
+ hit_anything = true;
+ closest_so_far = temp_rec.t;
+ rec = temp_rec;
+ }
+ }
+
+ return hit_anything;
+ }
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [hittable-list-with-interval]: [hittable.h]
+ hittable_list::hit() using interval]
+
+
+
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
+ class sphere : public hittable {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
+ ...
+ };
+
+
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
+ bool sphere::hit(const ray& r, interval ray_t, hit_record& rec) const {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
+ ...
+
+ // Find the nearest root that lies in the acceptable range.
+ auto root = (-half_b - sqrtd) / a;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
+ if (!ray_t.contains(root)) {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
+ root = (-half_b + sqrtd) / a;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
+ if (!ray_t.contains(root))
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
+ return false;
+ }
+ ...
+ }
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [sphere-with-interval]: [sphere.h] sphere using interval]
+
+
+
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
+ ...
+ color ray_color(const ray& r, const hittable& world) {
+ hit_record rec;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
+ if (world.hit(r, interval(0, infinity), rec)) {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
+ return 0.5 * (rec.normal + color(1,1,1));
+ }
+ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ [Listing [main-with-interval]: [main.cc] The new main using interval]
Antialiasing
@@ -1570,7 +1692,7 @@
color ray_color(const ray& r, const hittable& world) {
hit_record rec;
- if (world.hit(r, 0, infinity, rec)) {
+ if (world.hit(r, interval(0, infinity), rec)) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
point3 target = rec.p + rec.normal + random_in_unit_sphere();
return 0.5 * ray_color(ray(rec.p, target - rec.p), world);
@@ -1606,7 +1728,7 @@
return color(0,0,0);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- if (world.hit(r, 0, infinity, rec)) {
+ if (world.hit(r, interval(0, infinity), rec)) {
point3 target = rec.p + rec.normal + random_in_unit_sphere();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
return 0.5 * ray_color(ray(rec.p, target - rec.p), world, depth-1);
@@ -1721,7 +1843,7 @@
point approximation the sphere intersector gives us. So we need to ignore hits very near zero:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- if (world.hit(r, 0.001, infinity, rec)) {
+ if (world.hit(r, interval(0.001, infinity), rec)) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[Listing [reflect-tolerance]: [main.cc] Calculating reflected ray origins with tolerance]
@@ -1772,7 +1894,7 @@
if (depth <= 0)
return color(0,0,0);
- if (world.hit(r, 0.001, infinity, rec)) {
+ if (world.hit(r, interval(0.001, infinity), rec)) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
point3 target = rec.p + rec.normal + random_unit_vector();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
@@ -1854,7 +1976,7 @@
if (depth <= 0)
return color(0,0,0);
- if (world.hit(r, 0.001, infinity, rec)) {
+ if (world.hit(r, interval(0.001, infinity), rec)) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
point3 target = rec.p + random_in_hemisphere(rec.normal);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
@@ -1976,8 +2098,7 @@
: center(ctr), radius(r), mat_ptr(m) {};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
public:
point3 center;
@@ -1987,7 +2108,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
};
- bool sphere::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+ bool sphere::hit(const ray& r, interval ray_t, hit_record& rec) const {
...
rec.t = root;
@@ -2146,7 +2267,7 @@
if (depth <= 0)
return color(0,0,0);
- if (world.hit(r, 0.001, infinity, rec)) {
+ if (world.hit(r, interval(0.001, infinity), rec)) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
ray scattered;
color attenuation;
diff --git a/books/RayTracingTheNextWeek.html b/books/RayTracingTheNextWeek.html
index 984594c8..6aa2e9a3 100644
--- a/books/RayTracingTheNextWeek.html
+++ b/books/RayTracingTheNextWeek.html
@@ -197,8 +197,7 @@
time0(time_start), time1(time_end)
{};
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
point3 center(double time) const;
@@ -226,7 +225,7 @@
just needs to become a function `center(time)`:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- bool moving_sphere::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+ bool moving_sphere::hit(const ray& r, interval ray_t, hit_record& rec) const {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
vec3 oc = r.origin() - center(r.time());
@@ -241,9 +240,9 @@
// Find the nearest root that lies in the acceptable range.
auto root = (-half_b - sqrtd) / a;
- if (root < ray_tmin || ray_tmax < root) {
+ if (!ray_t.contains(root)) {
root = (-half_b + sqrtd) / a;
- if (root < ray_tmin || ray_tmax < root)
+ if (!ray_t.contains(root))
return false;
}
@@ -662,14 +661,14 @@
point3 min() const {return minimum; }
point3 max() const {return maximum; }
- bool hit(const ray& r, double ray_tmin, double ray_tmax) const {
+ bool hit(const ray& r, interval ray_t) const {
for (int a = 0; a < 3; a++) {
auto t0 = fmin((minimum[a] - r.origin()[a]) / r.direction()[a],
(maximum[a] - r.origin()[a]) / r.direction()[a]);
auto t1 = fmax((minimum[a] - r.origin()[a]) / r.direction()[a],
(maximum[a] - r.origin()[a]) / r.direction()[a]);
- ray_tmin = fmax(t0, ray_tmin);
- ray_tmax = fmin(t1, ray_tmax);
+ auto ray_tmin = fmax(t0, ray_t.min);
+ auto ray_tmax = fmin(t1, ray_t.max);
if (ray_tmax <= ray_tmin)
return false;
}
@@ -694,15 +693,15 @@
as my go-to method:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- inline bool aabb::hit(const ray& r, double ray_tmin, double ray_tmax) const {
+ inline bool aabb::hit(const ray& r, interval ray_t) const {
for (int a = 0; a < 3; a++) {
auto invD = 1.0f / r.direction()[a];
auto t0 = (min()[a] - r.origin()[a]) * invD;
auto t1 = (max()[a] - r.origin()[a]) * invD;
if (invD < 0.0f)
std::swap(t0, t1);
- ray_tmin = t0 > ray_tmin ? t0 : ray_tmin;
- ray_tmax = t1 < ray_tmax ? t1 : ray_tmax;
+ auto ray_tmin = t0 > ray_t.min ? t0 : ray_t.min;
+ auto ray_tmax = t1 < ray_t.max ? t1 : ray_t.max;
if (ray_tmax <= ray_tmin)
return false;
}
@@ -730,8 +729,7 @@
class hittable {
public:
...
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const = 0;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const = 0;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
@@ -751,8 +749,7 @@
class sphere : public hittable {
public:
...
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
@@ -788,8 +785,7 @@
class moving_sphere : public hittable {
public:
...
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
@@ -833,8 +829,7 @@
class hittable_list : public hittable {
public:
...
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
@@ -917,8 +912,7 @@
const std::vector>& src_objects,
size_t start, size_t end, double time_start, double time_end);
- virtual bool hit(
- const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override;
@@ -947,12 +941,12 @@
check the children and sort out any details:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- bool bvh_node::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
- if (!box.hit(r, ray_tmin, ray_tmax))
+ bool bvh_node::hit(const ray& r, interval ray_t, hit_record& rec) const {
+ if (!box.hit(r, ray_t))
return false;
- bool hit_left = left->hit(r, ray_tmin, ray_tmax, rec);
- bool hit_right = right->hit(r, ray_tmin, hit_left ? rec.t : ray_tmax, rec);
+ bool hit_left = left->hit(r, ray_t, rec);
+ bool hit_right = right->hit(r, interval(ray_t.min, hit_left ? rec.t : ray_t.max), rec);
return hit_left || hit_right;
}
@@ -2313,7 +2307,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
// If the ray hits nothing, return the background color.
- if (!world.hit(r, 0.001, infinity, rec))
+ if (!world.hit(r, interval(0.001, infinity), rec))
return background;
ray scattered;
@@ -2469,8 +2463,7 @@
shared_ptr mat)
: x0(_x0), x1(_x1), y0(_y0), y1(_y1), k(_k), mp(mat) {};
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override {
@@ -2494,9 +2487,9 @@
And the hit function is:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- bool xy_rect::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+ bool xy_rect::hit(const ray& r, interval ray_t, hit_record& rec) const {
auto t = (k-r.origin().z()) / r.direction().z();
- if (t < ray_tmin || t > ray_tmax)
+ if (!ray_t.contains(t))
return false;
auto x = r.origin().x() + t*r.direction().x();
auto y = r.origin().y() + t*r.direction().y();
@@ -2612,8 +2605,7 @@
shared_ptr mat)
: x0(_x0), x1(_x1), z0(_z0), z1(_z1), k(_k), mp(mat) {};
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override {
@@ -2636,8 +2628,7 @@
shared_ptr mat)
: y0(_y0), y1(_y1), z0(_z0), z1(_z1), k(_k), mp(mat) {};
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override {
@@ -2659,9 +2650,9 @@
With unsurprising hit functions:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- bool xz_rect::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+ bool xz_rect::hit(const ray& r, interval ray_t, hit_record& rec) const {
auto t = (k-r.origin().y()) / r.direction().y();
- if (t < ray_tmin || t > ray_tmax)
+ if (!ray_t.contains(t))
return false;
auto x = r.origin().x() + t*r.direction().x();
auto z = r.origin().z() + t*r.direction().z();
@@ -2677,9 +2668,9 @@
return true;
}
- bool yz_rect::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+ bool yz_rect::hit(const ray& r, interval ray_t, hit_record& rec) const {
auto t = (k-r.origin().x()) / r.direction().x();
- if (t < ray_tmin || t > ray_tmax)
+ if (!ray_t.contains(t))
return false;
auto y = r.origin().y() + t*r.direction().y();
auto z = r.origin().z() + t*r.direction().z();
@@ -2795,8 +2786,7 @@
box() {}
box(const point3& p0, const point3& p1, shared_ptr ptr);
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override {
@@ -2824,8 +2814,8 @@
sides.add(make_shared(p0.y(), p1.y(), p0.z(), p1.z(), p0.x(), ptr));
}
- bool box::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
- return sides.hit(r, ray_tmin, ray_tmax, rec);
+ bool box::hit(const ray& r, interval ray_t, hit_record& rec) const {
+ return sides.hit(r, ray_t, rec);
}
#endif
@@ -2878,8 +2868,7 @@
translate(shared_ptr p, const vec3& displacement)
: ptr(p), offset(displacement) {}
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override;
@@ -2889,9 +2878,9 @@
vec3 offset;
};
- bool translate::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+ bool translate::hit(const ray& r, interval ray_t, hit_record& rec) const {
ray moved_r(r.origin() - offset, r.direction(), r.time());
- if (!ptr->hit(moved_r, ray_tmin, ray_tmax, rec))
+ if (!ptr->hit(moved_r, ray_t, rec))
return false;
rec.p += offset;
@@ -2966,8 +2955,7 @@
public:
rotate_y(shared_ptr p, double angle);
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override {
@@ -3029,7 +3017,7 @@
And the hit function:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- bool rotate_y::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+ bool rotate_y::hit(const ray& r, interval ray_t, hit_record& rec) const {
auto origin = r.origin();
auto direction = r.direction();
@@ -3041,7 +3029,7 @@
ray rotated_r(origin, direction, r.time());
- if (!ptr->hit(rotated_r, ray_tmin, ray_tmax, rec))
+ if (!ptr->hit(rotated_r, ray_t, rec))
return false;
auto p = rec.p;
@@ -3146,8 +3134,7 @@
phase_function(make_shared(c))
{}
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override {
@@ -3193,25 +3180,23 @@
And the hit function is:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
- bool constant_medium::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const {
-
+ bool constant_medium::hit(const ray& r, interval ray_t, hit_record& rec) const {
// Print occasional samples when debugging. To enable, set enableDebug true.
const bool enableDebug = false;
const bool debugging = enableDebug && random_double() < 0.00001;
hit_record rec1, rec2;
- if (!boundary->hit(r, -infinity, infinity, rec1))
+ if (!boundary->hit(r, universe, rec1))
return false;
- if (!boundary->hit(r, rec1.t+0.0001, infinity, rec2))
+ if (!boundary->hit(r, interval(rec1.t+0.0001, infinity), rec2))
return false;
if (debugging) std::cerr << "\nray_tmin=" << rec1.t << ", ray_tmax=" << rec2.t << '\n';
- if (rec1.t < ray_tmin) rec1.t = ray_tmin;
- if (rec2.t > ray_tmax) rec2.t = ray_tmax;
+ if (rec1.t < ray_t.min) rec1.t = ray_t.min;
+ if (rec2.t > ray_t.max) rec2.t = ray_t.max;
if (rec1.t >= rec2.t)
return false;
diff --git a/books/RayTracingTheRestOfYourLife.html b/books/RayTracingTheRestOfYourLife.html
index 13f38bce..bbfeb870 100644
--- a/books/RayTracingTheRestOfYourLife.html
+++ b/books/RayTracingTheRestOfYourLife.html
@@ -913,7 +913,7 @@
return color(0,0,0);
// If the ray hits nothing, return the background color.
- if (!world.hit(r, 0.001, infinity, rec))
+ if (!world.hit(r, interval(0.001, infinity), rec))
return background;
ray scattered;
@@ -1409,7 +1409,7 @@
return color(0,0,0);
// If the ray hits nothing, return the background color.
- if (!world.hit(r, 0.001, infinity, rec))
+ if (!world.hit(r, interval(0.001, infinity), rec))
return background;
ray scattered;
@@ -1486,10 +1486,8 @@
public:
flip_face(shared_ptr p) : ptr(p) {}
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override {
-
- if (!ptr->hit(r, ray_tmin, ray_tmax, rec))
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override {
+ if (!ptr->hit(r, ray_t, rec))
return false;
rec.front_face = !rec.front_face;
@@ -1659,7 +1657,7 @@
return color(0,0,0);
// If the ray hits nothing, return the background color.
- if (!world.hit(r, 0.001, infinity, rec))
+ if (!world.hit(r, interval(0.001, infinity), rec))
return background;
ray scattered;
@@ -1727,8 +1725,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
class hittable {
public:
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const = 0;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const = 0;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const = 0;
@@ -1758,7 +1755,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
virtual double pdf_value(const point3& origin, const vec3& v) const override {
hit_record rec;
- if (!this->hit(ray(origin, v), 0.001, infinity, rec))
+ if (!this->hit(ray(origin, v), interval(0.001, infinity), rec))
return 0;
auto area = (x1-x0)*(z1-z0);
@@ -2083,7 +2080,7 @@
return color(0,0,0);
// If the ray hits nothing, return the background color.
- if (!world.hit(r, 0.001, infinity, rec))
+ if (!world.hit(r, interval(0.001, infinity), rec))
return background;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
@@ -2339,7 +2336,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
double sphere::pdf_value(const point3& o, const vec3& v) const {
hit_record rec;
- if (!this->hit(ray(o, v), 0.001, infinity, rec))
+ if (!this->hit(ray(o, v), interval(0.001, infinity), rec))
return 0;
auto cos_theta_max = sqrt(1 - radius*radius/(center-o).length_squared());
diff --git a/src/InOneWeekend/hittable.h b/src/InOneWeekend/hittable.h
index 75073e84..1070fc3c 100644
--- a/src/InOneWeekend/hittable.h
+++ b/src/InOneWeekend/hittable.h
@@ -32,8 +32,7 @@ struct hit_record {
class hittable {
public:
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const = 0;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const = 0;
};
diff --git a/src/InOneWeekend/hittable_list.h b/src/InOneWeekend/hittable_list.h
index 721ded14..84eeaf16 100644
--- a/src/InOneWeekend/hittable_list.h
+++ b/src/InOneWeekend/hittable_list.h
@@ -27,21 +27,20 @@ class hittable_list : public hittable {
void clear() { objects.clear(); }
void add(shared_ptr object) { objects.push_back(object); }
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
public:
std::vector> objects;
};
-bool hittable_list::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+bool hittable_list::hit(const ray& r, interval ray_t, hit_record& rec) const {
hit_record temp_rec;
auto hit_anything = false;
- auto closest_so_far = ray_tmax;
+ auto closest_so_far = ray_t.max;
for (const auto& object : objects) {
- if (object->hit(r, ray_tmin, closest_so_far, temp_rec)) {
+ if (object->hit(r, interval(ray_t.min, closest_so_far), temp_rec)) {
hit_anything = true;
closest_so_far = temp_rec.t;
rec = temp_rec;
diff --git a/src/InOneWeekend/main.cc b/src/InOneWeekend/main.cc
index 86576d34..02b423b7 100644
--- a/src/InOneWeekend/main.cc
+++ b/src/InOneWeekend/main.cc
@@ -27,7 +27,7 @@ color ray_color(const ray& r, const hittable& world, int depth) {
if (depth <= 0)
return color(0,0,0);
- if (world.hit(r, 0.001, infinity, rec)) {
+ if (world.hit(r, interval(0.001, infinity), rec)) {
ray scattered;
color attenuation;
if (rec.mat_ptr->scatter(r, rec, attenuation, scattered))
diff --git a/src/InOneWeekend/sphere.h b/src/InOneWeekend/sphere.h
index af8686eb..423460b1 100644
--- a/src/InOneWeekend/sphere.h
+++ b/src/InOneWeekend/sphere.h
@@ -22,8 +22,7 @@ class sphere : public hittable {
sphere(point3 ctr, double r, shared_ptr m)
: center(ctr), radius(r), mat_ptr(m) {};
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
public:
point3 center;
@@ -32,7 +31,7 @@ class sphere : public hittable {
};
-bool sphere::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+bool sphere::hit(const ray& r, interval ray_t, hit_record& rec) const {
vec3 oc = r.origin() - center;
auto a = r.direction().length_squared();
auto half_b = dot(oc, r.direction());
@@ -44,9 +43,9 @@ bool sphere::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec
// Find the nearest root that lies in the acceptable range.
auto root = (-half_b - sqrtd) / a;
- if (root < ray_tmin || ray_tmax < root) {
+ if (!ray_t.contains(root)) {
root = (-half_b + sqrtd) / a;
- if (root < ray_tmin || ray_tmax < root)
+ if (!ray_t.contains(root))
return false;
}
diff --git a/src/TheNextWeek/aarect.h b/src/TheNextWeek/aarect.h
index a60d0113..7e844e5c 100644
--- a/src/TheNextWeek/aarect.h
+++ b/src/TheNextWeek/aarect.h
@@ -24,8 +24,7 @@ class xy_rect : public hittable {
double _x0, double _x1, double _y0, double _y1, double _k, shared_ptr mat
) : x0(_x0), x1(_x1), y0(_y0), y1(_y1), k(_k), mp(mat) {};
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override
@@ -50,8 +49,7 @@ class xz_rect : public hittable {
double _x0, double _x1, double _z0, double _z1, double _k, shared_ptr mat
) : x0(_x0), x1(_x1), z0(_z0), z1(_z1), k(_k), mp(mat) {};
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override
@@ -76,8 +74,7 @@ class yz_rect : public hittable {
double _y0, double _y1, double _z0, double _z1, double _k, shared_ptr mat
) : y0(_y0), y1(_y1), z0(_z0), z1(_z1), k(_k), mp(mat) {};
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override
@@ -94,9 +91,9 @@ class yz_rect : public hittable {
};
-bool xy_rect::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+bool xy_rect::hit(const ray& r, interval ray_t, hit_record& rec) const {
auto t = (k-r.origin().z()) / r.direction().z();
- if (t < ray_tmin || t > ray_tmax)
+ if (!ray_t.contains(t))
return false;
auto x = r.origin().x() + t*r.direction().x();
@@ -116,9 +113,9 @@ bool xy_rect::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& re
}
-bool xz_rect::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+bool xz_rect::hit(const ray& r, interval ray_t, hit_record& rec) const {
auto t = (k-r.origin().y()) / r.direction().y();
- if (t < ray_tmin || ray_tmax < t)
+ if (!ray_t.contains(t))
return false;
auto x = r.origin().x() + t*r.direction().x();
@@ -138,9 +135,9 @@ bool xz_rect::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& re
}
-bool yz_rect::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+bool yz_rect::hit(const ray& r, interval ray_t, hit_record& rec) const {
auto t = (k-r.origin().x()) / r.direction().x();
- if (t < ray_tmin || t > ray_tmax)
+ if (!ray_t.contains(t))
return false;
auto y = r.origin().y() + t*r.direction().y();
diff --git a/src/TheNextWeek/box.h b/src/TheNextWeek/box.h
index 6fa2fabd..31347354 100644
--- a/src/TheNextWeek/box.h
+++ b/src/TheNextWeek/box.h
@@ -22,8 +22,7 @@ class box : public hittable {
box() {}
box(const point3& p0, const point3& p1, shared_ptr ptr);
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override
@@ -54,8 +53,8 @@ box::box(const point3& p0, const point3& p1, shared_ptr ptr) {
}
-bool box::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
- return sides.hit(r, ray_tmin, ray_tmax, rec);
+bool box::hit(const ray& r, interval ray_t, hit_record& rec) const {
+ return sides.hit(r, ray_t, rec);
}
diff --git a/src/TheNextWeek/bvh.h b/src/TheNextWeek/bvh.h
index 159d4d90..c7df5bc5 100644
--- a/src/TheNextWeek/bvh.h
+++ b/src/TheNextWeek/bvh.h
@@ -31,8 +31,7 @@ class bvh_node : public hittable {
const std::vector>& src_objects,
size_t start, size_t end, double time0, double time1);
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time0, double time1, aabb& output_box) const override;
@@ -109,12 +108,12 @@ bvh_node::bvh_node(
}
-bool bvh_node::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
- if (!box.hit(r, ray_tmin, ray_tmax))
+bool bvh_node::hit(const ray& r, interval ray_t, hit_record& rec) const {
+ if (!box.hit(r, ray_t))
return false;
- bool hit_left = left->hit(r, ray_tmin, ray_tmax, rec);
- bool hit_right = right->hit(r, ray_tmin, hit_left ? rec.t : ray_tmax, rec);
+ bool hit_left = left->hit(r, ray_t, rec);
+ bool hit_right = right->hit(r, interval(ray_t.min, hit_left ? rec.t : ray_t.max), rec);
return hit_left || hit_right;
}
diff --git a/src/TheNextWeek/constant_medium.h b/src/TheNextWeek/constant_medium.h
index c22dd866..430d0e20 100644
--- a/src/TheNextWeek/constant_medium.h
+++ b/src/TheNextWeek/constant_medium.h
@@ -32,8 +32,7 @@ class constant_medium : public hittable {
phase_function(make_shared(c))
{}
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override {
@@ -48,25 +47,23 @@ class constant_medium : public hittable {
};
-bool constant_medium::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const {
-
+bool constant_medium::hit(const ray& r, interval ray_t, hit_record& rec) const {
// Print occasional samples when debugging. To enable, set enableDebug true.
const bool enableDebug = false;
const bool debugging = enableDebug && random_double() < 0.00001;
hit_record rec1, rec2;
- if (!boundary->hit(r, -infinity, infinity, rec1))
+ if (!boundary->hit(r, universe, rec1))
return false;
- if (!boundary->hit(r, rec1.t+0.0001, infinity, rec2))
+ if (!boundary->hit(r, interval(rec1.t+0.0001, infinity), rec2))
return false;
if (debugging) std::cerr << "\nt_min=" << rec1.t << ", t_max=" << rec2.t << '\n';
- if (rec1.t < ray_tmin) rec1.t = ray_tmin;
- if (rec2.t > ray_tmax) rec2.t = ray_tmax;
+ if (rec1.t < ray_t.min) rec1.t = ray_t.min;
+ if (rec2.t > ray_t.max) rec2.t = ray_t.max;
if (rec1.t >= rec2.t)
return false;
diff --git a/src/TheNextWeek/hittable.h b/src/TheNextWeek/hittable.h
index d0b8d645..431bba93 100644
--- a/src/TheNextWeek/hittable.h
+++ b/src/TheNextWeek/hittable.h
@@ -37,8 +37,7 @@ struct hit_record {
class hittable {
public:
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const = 0;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const = 0;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const = 0;
@@ -49,8 +48,7 @@ class translate : public hittable {
translate(shared_ptr p, const vec3& displacement)
: ptr(p), offset(displacement) {}
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override;
@@ -61,9 +59,9 @@ class translate : public hittable {
};
-bool translate::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+bool translate::hit(const ray& r, interval ray_t, hit_record& rec) const {
ray moved_r(r.origin() - offset, r.direction(), r.time());
- if (!ptr->hit(moved_r, ray_tmin, ray_tmax, rec))
+ if (!ptr->hit(moved_r, ray_t, rec))
return false;
rec.p += offset;
@@ -89,8 +87,7 @@ class rotate_y : public hittable {
public:
rotate_y(shared_ptr p, double angle);
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override
@@ -141,7 +138,7 @@ rotate_y::rotate_y(shared_ptr p, double angle) : ptr(p) {
}
-bool rotate_y::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+bool rotate_y::hit(const ray& r, interval ray_t, hit_record& rec) const {
auto origin = r.origin();
auto direction = r.direction();
@@ -153,7 +150,7 @@ bool rotate_y::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& r
ray rotated_r(origin, direction, r.time());
- if (!ptr->hit(rotated_r, ray_tmin, ray_tmax, rec))
+ if (!ptr->hit(rotated_r, ray_t, rec))
return false;
auto p = rec.p;
diff --git a/src/TheNextWeek/hittable_list.h b/src/TheNextWeek/hittable_list.h
index 54249880..9f4d522a 100644
--- a/src/TheNextWeek/hittable_list.h
+++ b/src/TheNextWeek/hittable_list.h
@@ -27,8 +27,7 @@ class hittable_list : public hittable {
void clear() { objects.clear(); }
void add(shared_ptr object) { objects.push_back(object); }
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override;
@@ -38,13 +37,13 @@ class hittable_list : public hittable {
};
-bool hittable_list::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+bool hittable_list::hit(const ray& r, interval ray_t, hit_record& rec) const {
hit_record temp_rec;
auto hit_anything = false;
- auto closest_so_far = ray_tmax;
+ auto closest_so_far = ray_t.max;
for (const auto& object : objects) {
- if (object->hit(r, ray_tmin, closest_so_far, temp_rec)) {
+ if (object->hit(r, interval(ray_t.min, closest_so_far), temp_rec)) {
hit_anything = true;
closest_so_far = temp_rec.t;
rec = temp_rec;
diff --git a/src/TheNextWeek/main.cc b/src/TheNextWeek/main.cc
index a370339e..dd431676 100644
--- a/src/TheNextWeek/main.cc
+++ b/src/TheNextWeek/main.cc
@@ -33,7 +33,7 @@ color ray_color(const ray& r, const color& background, const hittable& world, in
return color(0,0,0);
// If the ray hits nothing, return the background color.
- if (!world.hit(r, 0.001, infinity, rec))
+ if (!world.hit(r, interval(0.001, infinity), rec))
return background;
ray scattered;
diff --git a/src/TheNextWeek/moving_sphere.h b/src/TheNextWeek/moving_sphere.h
index 135196dc..a56fef52 100644
--- a/src/TheNextWeek/moving_sphere.h
+++ b/src/TheNextWeek/moving_sphere.h
@@ -27,8 +27,7 @@ class moving_sphere : public hittable {
time0(time_start), time1(time_end)
{};
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override;
@@ -60,7 +59,7 @@ bool moving_sphere::bounding_box(double time_start, double time_end, aabb& outpu
}
-bool moving_sphere::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+bool moving_sphere::hit(const ray& r, interval ray_t, hit_record& rec) const {
vec3 oc = r.origin() - center(r.time());
auto a = r.direction().length_squared();
auto half_b = dot(oc, r.direction());
@@ -72,9 +71,9 @@ bool moving_sphere::hit(const ray& r, double ray_tmin, double ray_tmax, hit_reco
// Find the nearest root that lies in the acceptable range.
auto root = (-half_b - sqrtd) / a;
- if (root < ray_tmin || ray_tmax < root) {
+ if (!ray_t.contains(root)) {
root = (-half_b + sqrtd) / a;
- if (root < ray_tmin || ray_tmax < root)
+ if (!ray_t.contains(root))
return false;
}
diff --git a/src/TheNextWeek/sphere.h b/src/TheNextWeek/sphere.h
index 47f442b2..a724dbe8 100644
--- a/src/TheNextWeek/sphere.h
+++ b/src/TheNextWeek/sphere.h
@@ -22,8 +22,7 @@ class sphere : public hittable {
sphere(point3 ctr, double r, shared_ptr m)
: center(ctr), radius(r), mat_ptr(m) {};
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override;
@@ -59,7 +58,7 @@ bool sphere::bounding_box(double time_start, double time_end, aabb& output_box)
}
-bool sphere::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+bool sphere::hit(const ray& r, interval ray_t, hit_record& rec) const {
vec3 oc = r.origin() - center;
auto a = r.direction().length_squared();
auto half_b = dot(oc, r.direction());
@@ -71,9 +70,9 @@ bool sphere::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec
// Find the nearest root that lies in the acceptable range.
auto root = (-half_b - sqrtd) / a;
- if (root < ray_tmin || ray_tmax < root) {
+ if (!ray_t.contains(root)) {
root = (-half_b + sqrtd) / a;
- if (root < ray_tmin || ray_tmax < root)
+ if (!ray_t.contains(root))
return false;
}
diff --git a/src/TheRestOfYourLife/aarect.h b/src/TheRestOfYourLife/aarect.h
index eaf1cd8d..fdba358a 100644
--- a/src/TheRestOfYourLife/aarect.h
+++ b/src/TheRestOfYourLife/aarect.h
@@ -24,8 +24,7 @@ class xy_rect : public hittable {
double _x0, double _x1, double _y0, double _y1, double _k, shared_ptr mat
) : x0(_x0), x1(_x1), y0(_y0), y1(_y1), k(_k), mp(mat) {};
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override
@@ -50,8 +49,7 @@ class xz_rect : public hittable {
double _x0, double _x1, double _z0, double _z1, double _k, shared_ptr mat
) : x0(_x0), x1(_x1), z0(_z0), z1(_z1), k(_k), mp(mat) {};
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override
@@ -64,7 +62,7 @@ class xz_rect : public hittable {
virtual double pdf_value(const point3& origin, const vec3& v) const override {
hit_record rec;
- if (!this->hit(ray(origin, v), 0.001, infinity, rec))
+ if (!this->hit(ray(origin, v), interval(0.001, infinity), rec))
return 0;
auto area = (x1-x0)*(z1-z0);
@@ -93,8 +91,7 @@ class yz_rect : public hittable {
double _y0, double _y1, double _z0, double _z1, double _k, shared_ptr mat
) : y0(_y0), y1(_y1), z0(_z0), z1(_z1), k(_k), mp(mat) {};
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override
@@ -111,9 +108,9 @@ class yz_rect : public hittable {
};
-bool xy_rect::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+bool xy_rect::hit(const ray& r, interval ray_t, hit_record& rec) const {
auto t = (k-r.origin().z()) / r.direction().z();
- if (t < ray_tmin || t > ray_tmax)
+ if (!ray_t.contains(t))
return false;
auto x = r.origin().x() + t*r.direction().x();
@@ -133,9 +130,9 @@ bool xy_rect::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& re
}
-bool xz_rect::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+bool xz_rect::hit(const ray& r, interval ray_t, hit_record& rec) const {
auto t = (k-r.origin().y()) / r.direction().y();
- if (t < ray_tmin || ray_tmax < t)
+ if (!ray_t.contains(t))
return false;
auto x = r.origin().x() + t*r.direction().x();
@@ -155,9 +152,9 @@ bool xz_rect::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& re
}
-bool yz_rect::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+bool yz_rect::hit(const ray& r, interval ray_t, hit_record& rec) const {
auto t = (k-r.origin().x()) / r.direction().x();
- if (t < ray_tmin || t > ray_tmax)
+ if (!ray_t.contains(t))
return false;
auto y = r.origin().y() + t*r.direction().y();
diff --git a/src/TheRestOfYourLife/box.h b/src/TheRestOfYourLife/box.h
index 6fa2fabd..31347354 100644
--- a/src/TheRestOfYourLife/box.h
+++ b/src/TheRestOfYourLife/box.h
@@ -22,8 +22,7 @@ class box : public hittable {
box() {}
box(const point3& p0, const point3& p1, shared_ptr ptr);
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override
@@ -54,8 +53,8 @@ box::box(const point3& p0, const point3& p1, shared_ptr ptr) {
}
-bool box::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
- return sides.hit(r, ray_tmin, ray_tmax, rec);
+bool box::hit(const ray& r, interval ray_t, hit_record& rec) const {
+ return sides.hit(r, ray_t, rec);
}
diff --git a/src/TheRestOfYourLife/bvh.h b/src/TheRestOfYourLife/bvh.h
index 159d4d90..8254ee09 100644
--- a/src/TheRestOfYourLife/bvh.h
+++ b/src/TheRestOfYourLife/bvh.h
@@ -31,8 +31,7 @@ class bvh_node : public hittable {
const std::vector>& src_objects,
size_t start, size_t end, double time0, double time1);
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time0, double time1, aabb& output_box) const override;
@@ -109,12 +108,12 @@ bvh_node::bvh_node(
}
-bool bvh_node::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
- if (!box.hit(r, ray_tmin, ray_tmax))
+bool bvh_node::hit(const ray& r, interval ray_t, hit_record& rec) const {
+ if (!box.hit(r, ray_t))
return false;
- bool hit_left = left->hit(r, ray_tmin, ray_tmax, rec);
- bool hit_right = right->hit(r, ray_tmin, hit_left ? rec.t : ray_tmax, rec);
+ bool hit_left = left->hit(r, ray_t, rec);
+ bool hit_right = right->hit(r, interval(ray_tmin, hit_left ? rec.t : ray_tmax), rec);
return hit_left || hit_right;
}
diff --git a/src/TheRestOfYourLife/hittable.h b/src/TheRestOfYourLife/hittable.h
index 43f848fc..efd2e229 100644
--- a/src/TheRestOfYourLife/hittable.h
+++ b/src/TheRestOfYourLife/hittable.h
@@ -37,8 +37,7 @@ struct hit_record {
class hittable {
public:
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const = 0;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const = 0;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const = 0;
@@ -57,10 +56,8 @@ class flip_face : public hittable {
public:
flip_face(shared_ptr p) : ptr(p) {}
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override {
-
- if (!ptr->hit(r, ray_tmin, ray_tmax, rec))
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override {
+ if (!ptr->hit(r, ray_t, rec))
return false;
rec.front_face = !rec.front_face;
@@ -83,8 +80,7 @@ class translate : public hittable {
translate(shared_ptr p, const vec3& displacement)
: ptr(p), offset(displacement) {}
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override;
@@ -95,9 +91,9 @@ class translate : public hittable {
};
-bool translate::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+bool translate::hit(const ray& r, interval ray_t, hit_record& rec) const {
ray moved_r(r.origin() - offset, r.direction(), r.time());
- if (!ptr->hit(moved_r, ray_tmin, ray_tmax, rec))
+ if (!ptr->hit(moved_r, ray_t, rec))
return false;
rec.p += offset;
@@ -123,8 +119,7 @@ class rotate_y : public hittable {
public:
rotate_y(shared_ptr p, double angle);
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override
@@ -175,7 +170,7 @@ rotate_y::rotate_y(shared_ptr p, double angle) : ptr(p) {
}
-bool rotate_y::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+bool rotate_y::hit(const ray& r, interval ray_t, hit_record& rec) const {
auto origin = r.origin();
auto direction = r.direction();
@@ -187,7 +182,7 @@ bool rotate_y::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& r
ray rotated_r(origin, direction, r.time());
- if (!ptr->hit(rotated_r, ray_tmin, ray_tmax, rec))
+ if (!ptr->hit(rotated_r, ray_t, rec))
return false;
auto p = rec.p;
diff --git a/src/TheRestOfYourLife/hittable_list.h b/src/TheRestOfYourLife/hittable_list.h
index bc5116c9..33fbad50 100644
--- a/src/TheRestOfYourLife/hittable_list.h
+++ b/src/TheRestOfYourLife/hittable_list.h
@@ -27,8 +27,7 @@ class hittable_list : public hittable {
void clear() { objects.clear(); }
void add(shared_ptr object) { objects.push_back(object); }
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override;
@@ -41,13 +40,13 @@ class hittable_list : public hittable {
};
-bool hittable_list::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+bool hittable_list::hit(const ray& r, interval ray_t, hit_record& rec) const {
hit_record temp_rec;
auto hit_anything = false;
- auto closest_so_far = ray_tmax;
+ auto closest_so_far = ray_t.max;
for (const auto& object : objects) {
- if (object->hit(r, ray_tmin, closest_so_far, temp_rec)) {
+ if (object->hit(r, interval(ray_t.min, closest_so_far), temp_rec)) {
hit_anything = true;
closest_so_far = temp_rec.t;
rec = temp_rec;
diff --git a/src/TheRestOfYourLife/main.cc b/src/TheRestOfYourLife/main.cc
index b5ffbbcd..82ada93f 100644
--- a/src/TheRestOfYourLife/main.cc
+++ b/src/TheRestOfYourLife/main.cc
@@ -36,7 +36,7 @@ color ray_color(
return color(0,0,0);
// If the ray hits nothing, return the background color.
- if (!world.hit(r, 0.001, infinity, rec))
+ if (!world.hit(r, interval(0.001, infinity), rec))
return background;
scatter_record srec;
diff --git a/src/TheRestOfYourLife/sphere.h b/src/TheRestOfYourLife/sphere.h
index 6069b731..ed8e0fa6 100644
--- a/src/TheRestOfYourLife/sphere.h
+++ b/src/TheRestOfYourLife/sphere.h
@@ -23,8 +23,7 @@ class sphere : public hittable {
sphere(point3 ctr, double r, shared_ptr m)
: center(ctr), radius(r), mat_ptr(m) {};
- virtual bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec)
- const override;
+ virtual bool hit(const ray& r, interval ray_t, hit_record& rec) const override;
virtual bool bounding_box(double time_start, double time_end, aabb& output_box)
const override;
@@ -57,7 +56,7 @@ class sphere : public hittable {
double sphere::pdf_value(const point3& o, const vec3& v) const {
hit_record rec;
- if (!this->hit(ray(o, v), 0.001, infinity, rec))
+ if (!this->hit(ray(o, v), interval(0.001, infinity), rec))
return 0;
auto cos_theta_max = sqrt(1 - radius*radius/(center-o).length_squared());
@@ -84,7 +83,7 @@ bool sphere::bounding_box(double time_start, double time_end, aabb& output_box)
}
-bool sphere::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const {
+bool sphere::hit(const ray& r, interval ray_t, hit_record& rec) const {
vec3 oc = r.origin() - center;
auto a = r.direction().length_squared();
auto half_b = dot(oc, r.direction());
@@ -96,9 +95,9 @@ bool sphere::hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec
// Find the nearest root that lies in the acceptable range.
auto root = (-half_b - sqrtd) / a;
- if (root < ray_tmin || ray_tmax < root) {
+ if (!ray_t.contains(root)) {
root = (-half_b + sqrtd) / a;
- if (root < ray_tmin || ray_tmax < root)
+ if (!ray_t.contains(root))
return false;
}
diff --git a/src/common/aabb.h b/src/common/aabb.h
index ea2b7fdc..6fc9dbe1 100644
--- a/src/common/aabb.h
+++ b/src/common/aabb.h
@@ -22,15 +22,15 @@ class aabb {
point3 min() const {return minimum; }
point3 max() const {return maximum; }
- bool hit(const ray& r, double ray_tmin, double ray_tmax) const {
+ bool hit(const ray& r, interval ray_t) const {
for (int a = 0; a < 3; a++) {
auto t0 = fmin((minimum[a] - r.origin()[a]) / r.direction()[a],
(maximum[a] - r.origin()[a]) / r.direction()[a]);
auto t1 = fmax((minimum[a] - r.origin()[a]) / r.direction()[a],
(maximum[a] - r.origin()[a]) / r.direction()[a]);
- ray_tmin = fmax(t0, ray_tmin);
- ray_tmax = fmin(t1, ray_tmax);
- if (ray_tmax <= ray_tmin)
+ ray_t.min = fmax(t0, ray_t.min);
+ ray_t.max = fmin(t1, ray_t.max);
+ if (ray_t.max <= ray_t.min)
return false;
}
return true;
diff --git a/src/common/interval.h b/src/common/interval.h
new file mode 100644
index 00000000..c03a0d71
--- /dev/null
+++ b/src/common/interval.h
@@ -0,0 +1,28 @@
+#ifndef INTERVAL_H
+#define INTERVAL_H
+//==============================================================================================
+// To the extent possible under law, the author(s) have dedicated all copyright and related and
+// neighboring rights to this software to the public domain worldwide. This software is
+// distributed without any warranty.
+//
+// You should have received a copy (see file COPYING.txt) of the CC0 Public Domain Dedication
+// along with this software. If not, see .
+//==============================================================================================
+
+class interval {
+ public:
+ double min, max;
+
+ interval(double _min, double _max) : min(_min), max(_max) {}
+ interval() : min(+infinity), max(-infinity) {} // Default interval is empty
+
+ bool contains(double x) const {
+ return min <= x && x <= max;
+ }
+};
+
+const static interval empty (+infinity, -infinity);
+const static interval universe(-infinity, +infinity);
+
+
+#endif
diff --git a/src/common/rtweekend.h b/src/common/rtweekend.h
index 797a9e13..c4fdbbcd 100644
--- a/src/common/rtweekend.h
+++ b/src/common/rtweekend.h
@@ -55,6 +55,7 @@ inline int random_int(int min, int max) {
// Common Headers
+#include "interval.h"
#include "ray.h"
#include "vec3.h"