diff --git a/books/RayTracingInOneWeekend.html b/books/RayTracingInOneWeekend.html index c9498a24..0ba61dc2 100644 --- a/books/RayTracingInOneWeekend.html +++ b/books/RayTracingInOneWeekend.html @@ -940,8 +940,7 @@ class sphere : public hittable { public: - sphere() {} - sphere(point3 ctr, double r) : center(ctr), radius(r) {}; + sphere(point3 _center, double _radius) : center(_center), radius(_radius) {} bool hit(const ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const override { vec3 oc = r.origin() - center; @@ -2184,8 +2183,8 @@ class sphere : public hittable { public: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight - sphere(point3 ctr, double r, shared_ptr m) - : center(ctr), radius(r), mat(m) {}; + sphere(point3 _center, double _radius, shared_ptr _material) + : center(_center), radius(_radius), mat(_material) {} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ bool hit(const ray& r, interval ray_t, hit_record& rec) const override { diff --git a/books/RayTracingTheNextWeek.html b/books/RayTracingTheNextWeek.html index c641ee0a..da07c895 100644 --- a/books/RayTracingTheNextWeek.html +++ b/books/RayTracingTheNextWeek.html @@ -165,91 +165,77 @@ Adding Moving Spheres ---------------------- -Now to create a moving object. I’ll create a sphere class that has its center move linearly from -`center0` at time=0 to `center1` at time=1. (It continues on indefinitely outside that time -interval, so it really can be sampled at any time.) +Now to create a moving object. +I’ll update the sphere class so that its center moves linearly from `center1` at time=0 to `center2` +at time=1. +(It continues on indefinitely outside that time interval, so it really can be sampled at any time.) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ - #ifndef MOVING_SPHERE_H - #define MOVING_SPHERE_H - - #include "rtweekend.h" - - #include "hittable.h" - - class moving_sphere : public hittable { + class sphere : public hittable { public: - moving_sphere(point3 c0, point3 c1, double r, shared_ptr m) - : center0(c0), center1(c1), center_vec(c1 - c0), radius(r), mat(m) - { }; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight + // Stationary Sphere + sphere(point3 _center, double _radius, shared_ptr _material) + : center1(_center), radius(_radius), mat(_material), is_moving(false) {} - bool hit(const ray& r, interval ray_t, hit_record& rec) const override { - // Implementation below. + // Moving Sphere + sphere(point3 _center1, point3 _center2, double _radius, shared_ptr _material) + : center1(_center1), radius(_radius), mat(_material), is_moving(true) + { + center_vec = _center2 - _center1; } + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ - point3 center(double time) const { - // Linearly interpolate from center0 to center1 according to time, where t=0 yields - // center0, and t=1 yields center1. - return center0 + time * center_vec; - } + ... private: - point3 center0, center1; - vec3 center_vec; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight + point3 center1; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ double radius; shared_ptr mat; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight + bool is_moving; + vec3 center_vec; + + point3 center(double time) const { + // Linearly interpolate from center1 to center2 according to time, where t=0 yields + // center1, and t=1 yields center2. + return center0 + time*center_vec; + } + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ }; #endif ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - [Listing [moving-sphere]: [moving_sphere.h] A moving sphere] + [Listing [moving-sphere]: [sphere.h] A moving sphere]
-An alternative to making a new moving sphere class is to just make them all move, while stationary -spheres have the same begin and end position. I’m on the fence about that trade-off between fewer -classes and more efficient stationary spheres, so let your design taste guide you. +An alternative to making special stationary spheres is to just make them all move, but stationary +spheres have the same begin and end position. I’m on the fence about that trade-off between simpler +code and more efficient stationary spheres, so let your design taste guide you. -The `moving_sphere::hit()` function is almost identical to the `sphere::hit()` function: `center` -just needs to become a function `center(time)`: +The updated `sphere::hit()` function is almost identical to the old `sphere::hit()` function: +`center` just needs to query a function `sphere_center(time)`: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ - class moving_sphere : public hittable { + class sphere : public hittable { public: ... bool hit(const ray& r, interval ray_t, hit_record& rec) const override { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight - vec3 oc = r.origin() - center(r.time()); + point3 center = is_moving ? sphere_center(r.time()) : center1; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ + vec3 oc = r.origin() - center; auto a = r.direction().length_squared(); auto half_b = dot(oc, r.direction()); auto c = oc.length_squared() - radius*radius; - - auto discriminant = half_b*half_b - a*c; - if (discriminant < 0) return false; - auto sqrtd = sqrt(discriminant); - - // Find the nearest root that lies in the acceptable range. - auto root = (-half_b - sqrtd) / a; - if (!ray_t.surrounds(root)) { - root = (-half_b + sqrtd) / a; - if (!ray_t.surrounds(root)) - return false; - } - - rec.t = root; - rec.p = r.at(rec.t); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight - auto outward_normal = (rec.p - center(r.time())) / radius; - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ - rec.set_face_normal(r, outward_normal); - rec.mat = mat; - - return true; + ... } ... }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - [Listing [moving-sphere-hit]: [moving_sphere.h] Moving sphere hit function] + [Listing [moving-sphere-hit]: [sphere.h] Moving sphere hit function]
We need to implement the new `interval::contains()` method mentioned above: @@ -747,16 +733,19 @@
-For a sphere, the `bounding_box` function is easy: +For a stationary sphere, the `bounding_box` function is easy: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ class sphere : public hittable { public: + // Stationary Sphere ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight - sphere(point3 ctr, double r, shared_ptr m) : center(ctr), radius(r), mat(m) { + sphere(point3 _center, double _radius, shared_ptr _material) + : center1(_center), radius(_radius), mat(_material), is_moving(false) + { auto rvec = vec3(radius, radius, radius); - bbox = aabb(center - rvec, center + rvec); - }; + bbox = aabb(center1 - rvec, center1 + rvec); + } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ ... ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight @@ -764,57 +753,42 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ private: - point3 center; + point3 center1; double radius; shared_ptr mat; + bool is_moving; + vec3 center_vec; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight aabb bbox; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ + ... }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Listing [sphere-bbox]: [sphere.h] Sphere with bounding box]
-For `moving sphere`, we want the bounds of its entire range of motion. To do this, we can take the +For a moving sphere, we want the bounds of its entire range of motion. To do this, we can take the box of the sphere at time=0, and the box of the sphere at time=1, and compute the box around those two boxes. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ - ... - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight - #include "aabb.h" - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ - ... - - class moving_sphere : public hittable { + class sphere : public hittable { public: ... - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight - moving_sphere(point3 c0, point3 c1, double r, shared_ptr m) - : center0(c0), center1(c1), center_vec(c1 - c0), radius(r), mat(m) + // Moving Sphere + sphere(point3 _center1, point3 _center2, double _radius, shared_ptr _material) + : center1(_center1), radius(_radius), mat(_material), is_moving(true) { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight auto rvec = vec3(radius, radius, radius); - aabb box0(center0 - rvec, center0 + rvec); - aabb box1(center1 - rvec, center1 + rvec); - bbox = aabb(box0, box1); - }; + aabb box1(_center1 - rvec, _center1 + rvec); + aabb box2(_center2 - rvec, _center2 + rvec); + bbox = aabb(box1, box2); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ - ... - - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight - aabb bounding_box() const override { return bbox; } - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ + center_vec = _center2 - _center1; + } ... - - private: - point3 center0, center1; - vec3 center_vec; - double radius; - shared_ptr mat; - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight - aabb bbox; - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Listing [moving-sphere-bbox]: [moving_sphere.h] Moving sphere with bounding box] diff --git a/books/RayTracingTheRestOfYourLife.html b/books/RayTracingTheRestOfYourLife.html index 63ff1856..9ea8311f 100644 --- a/books/RayTracingTheRestOfYourLife.html +++ b/books/RayTracingTheRestOfYourLife.html @@ -3451,25 +3451,26 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight double pdf_value(const point3& o, const vec3& v) const override { + // This method only works for stationary spheres. + hit_record 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()); + auto cos_theta_max = sqrt(1 - radius*radius/(center1 - o).length_squared()); auto solid_angle = 2*pi*(1-cos_theta_max); return 1 / solid_angle; } vec3 random(const point3& o) const override { - vec3 direction = center - o; + vec3 direction = center1 - o; auto distance_squared = direction.length_squared(); onb uvw; uvw.build_from_w(direction); return uvw.local(random_to_sphere(radius, distance_squared)); } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ - ... private: ...