From 22152d947c3b2b60a05ee7f8cd157de0536debcf Mon Sep 17 00:00:00 2001 From: Kaan ERASLAN Date: Sun, 21 Jun 2020 20:26:57 +0200 Subject: [PATCH] Override keyword added to all books and code "override" qualifier is added to all derived classes. The qualifier is also added to the text of the book. All the code compiles and no runtime error during the execution. I have only tested the three main executables: inOneWeekend theNextWeek theRestOfYourLife Fixes #639 --- books/RayTracingInOneWeekend.html | 33 ++-- books/RayTracingTheNextWeek.html | 101 ++++++---- books/RayTracingTheRestOfYourLife.html | 41 ++-- src/InOneWeekend/hittable_list.h | 59 +++--- src/InOneWeekend/material.h | 142 +++++++------ src/InOneWeekend/sphere.h | 89 +++++---- src/TheNextWeek/aarect.h | 223 ++++++++++----------- src/TheNextWeek/box.h | 69 +++---- src/TheNextWeek/bvh.h | 150 +++++++------- src/TheNextWeek/constant_medium.h | 119 +++++------ src/TheNextWeek/hittable.h | 245 ++++++++++++----------- src/TheNextWeek/hittable_list.h | 84 ++++---- src/TheNextWeek/material.h | 210 ++++++++++---------- src/TheNextWeek/moving_sphere.h | 132 ++++++------- src/TheNextWeek/sphere.h | 126 ++++++------ src/TheRestOfYourLife/aarect.h | 249 +++++++++++------------ src/TheRestOfYourLife/box.h | 69 +++---- src/TheRestOfYourLife/bvh.h | 150 +++++++------- src/TheRestOfYourLife/hittable.h | 263 ++++++++++++------------- src/TheRestOfYourLife/hittable_list.h | 111 +++++------ src/TheRestOfYourLife/main.cc | 207 +++++++++---------- src/TheRestOfYourLife/material.h | 255 +++++++++++------------- src/TheRestOfYourLife/pdf.h | 138 +++++++------ src/TheRestOfYourLife/sphere.h | 147 +++++++------- src/common/texture.h | 185 +++++++++-------- 25 files changed, 1797 insertions(+), 1800 deletions(-) diff --git a/books/RayTracingInOneWeekend.html b/books/RayTracingInOneWeekend.html index 6044b6c8..c7516281 100644 --- a/books/RayTracingInOneWeekend.html +++ b/books/RayTracingInOneWeekend.html @@ -888,7 +888,8 @@ sphere() {} sphere(point3 cen, double r) : center(cen), radius(r) {}; - virtual bool hit(const ray& r, double tmin, double tmax, hit_record& rec) const; + bool hit(const ray& r, double tmin, double tmax, hit_record& rec) + const override; public: point3 center; @@ -1098,7 +1099,8 @@ void clear() { objects.clear(); } void add(shared_ptr object) { objects.push_back(object); } - virtual bool hit(const ray& r, double tmin, double tmax, hit_record& rec) const; + bool hit(const ray& r, double tmin, double tmax, hit_record& rec) + const override; public: std::vector> objects; @@ -2017,7 +2019,8 @@ : center(cen), radius(r), mat_ptr(m) {}; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ - virtual bool hit(const ray& r, double tmin, double tmax, hit_record& rec) const; + bool hit(const ray& r, double tmin, double tmax, hit_record& rec) + const override; public: point3 center; @@ -2078,9 +2081,9 @@ public: lambertian(const color& a) : albedo(a) {} - virtual bool scatter( + bool scatter( const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const { + ) const override{ vec3 scatter_direction = rec.normal + random_unit_vector(); scattered = ray(rec.p, scatter_direction); attenuation = albedo; @@ -2129,9 +2132,9 @@ public: metal(const color& a) : albedo(a) {} - virtual bool scatter( + bool scatter( const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const { + ) const override{ vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal); scattered = ray(rec.p, reflected); attenuation = albedo; @@ -2276,9 +2279,9 @@ metal(const color& a, double f) : albedo(a), fuzz(f < 1 ? f : 1) {} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ - virtual bool scatter( + bool scatter( const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const { + ) const override { vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight scattered = ray(rec.p, reflected + fuzz*random_in_unit_sphere()); @@ -2414,9 +2417,9 @@ public: dielectric(double ri) : ref_idx(ri) {} - virtual bool scatter( + bool scatter( const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const { + ) const override { attenuation = color(1.0, 1.0, 1.0); double etai_over_etat = rec.front_face ? (1.0 / ref_idx) : ref_idx; @@ -2524,9 +2527,9 @@ public: dielectric(double ri) : ref_idx(ri) {} - virtual bool scatter( + bool scatter( const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const { + ) const override { attenuation = color(1.0, 1.0, 1.0); double etai_over_etat = rec.front_face ? (1.0 / ref_idx) : ref_idx; @@ -2599,9 +2602,9 @@ public: dielectric(double ri) : ref_idx(ri) {} - virtual bool scatter( + bool scatter( const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const { + ) const override { attenuation = color(1.0, 1.0, 1.0); double etai_over_etat = rec.front_face ? (1.0 / ref_idx) : ref_idx; diff --git a/books/RayTracingTheNextWeek.html b/books/RayTracingTheNextWeek.html index e2e8ccf9..82cbde22 100644 --- a/books/RayTracingTheNextWeek.html +++ b/books/RayTracingTheNextWeek.html @@ -190,7 +190,8 @@ : center0(cen0), center1(cen1), time0(t0), time1(t1), radius(r), mat_ptr(m) {}; - virtual bool hit(const ray& r, double tmin, double tmax, hit_record& rec) const; + bool hit(const ray& r, double tmin, double tmax, hit_record& rec) + const override; point3 center(double time) const; @@ -272,9 +273,9 @@ public: lambertian(const color& a) : albedo(a) {} - virtual bool scatter( + bool scatter( const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const { + ) const override{ vec3 scatter_direction = rec.normal + random_unit_vector(); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight scattered = ray(rec.p, scatter_direction, r_in.time()); @@ -706,9 +707,11 @@ class sphere : public hittable { public: ... - virtual bool hit(const ray& r, double tmin, double tmax, hit_record& rec) const; + bool hit(const ray& r, double tmin, double tmax, hit_record& rec) + const override; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight - virtual bool sphere::bounding_box(double t0, double t1, aabb& output_box) const; + bool sphere::bounding_box(double t0, double t1, aabb& output_box) + const override; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ ... }; @@ -739,9 +742,11 @@ class moving_sphere : public hittable { public: ... - virtual bool hit(const ray& r, double tmin, double tmax, hit_record& rec) const; + bool hit(const ray& r, double tmin, double tmax, hit_record& rec) + const override; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight - virtual bool bounding_box(double t0, double t1, aabb& output_box) const; + bool bounding_box(double t0, double t1, aabb& output_box) const + override; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ ... }; @@ -780,9 +785,11 @@ class hittable_list : public hittable { public: ... - virtual bool hit(const ray& r, double tmin, double tmax, hit_record& rec) const; + bool hit(const ray& r, double tmin, double tmax, hit_record& rec) + const override; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight - virtual bool bounding_box(double t0, double t1, aabb& output_box) const; + bool bounding_box(double t0, double t1, aabb& output_box) const + override; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ ... }; @@ -855,8 +862,10 @@ std::vector>& objects, size_t start, size_t end, double time0, double time1); - virtual bool hit(const ray& r, double tmin, double tmax, hit_record& rec) const; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const; + bool hit(const ray& r, double tmin, double tmax, hit_record& rec) + const override; + bool bounding_box(double t0, double t1, aabb& output_box) const + override; public: shared_ptr left; @@ -1045,7 +1054,7 @@ solid_color(double red, double green, double blue) : solid_color(color(red,green,blue)) {} - virtual color value(double u, double v, const vec3& p) const { + color value(double u, double v, const vec3& p) const override{ return color_value; } @@ -1186,9 +1195,9 @@ lambertian(shared_ptr a) : albedo(a) {} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ - virtual bool scatter( + bool scatter( const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const { + ) const override { vec3 scatter_direction = rec.normal + random_unit_vector(); scattered = ray(rec.p, scatter_direction, r_in.time()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight @@ -1225,7 +1234,7 @@ checker_texture(color c1, color c2) : even(make_shared(c1)) , odd(make_shared(c2)) {} - virtual color value(double u, double v, const point3& p) const { + color value(double u, double v, const point3& p) const override{ auto sines = sin(10*p.x())*sin(10*p.y())*sin(10*p.z()); if (sines < 0) return odd->value(u, v, p); @@ -1464,7 +1473,7 @@ public: noise_texture() {} - virtual color value(double u, double v, const point3& p) const { + color value(double u, double v, const point3& p) const override{ return color(1,1,1) * noise.noise(p); } @@ -1636,7 +1645,7 @@ noise_texture() {} noise_texture(double sc) : scale(sc) {} - virtual color value(double u, double v, const point3& p) const { + color value(double u, double v, const point3& p) const override{ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight return color(1,1,1) * noise.noise(scale * p); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ @@ -1774,7 +1783,7 @@ noise_texture() {} noise_texture(double sc) : scale(sc) {} - virtual color value(double u, double v, const point3& p) const { + color value(double u, double v, const point3& p) const override{ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight return color(1,1,1) * 0.5 * (1.0 + noise.noise(scale * p)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ @@ -1851,7 +1860,7 @@ noise_texture() {} noise_texture(double sc) : scale(sc) {} - virtual color value(double u, double v, const point3& p) const { + color value(double u, double v, const point3& p) const override{ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight return color(1,1,1) * 0.5 * (1 + sin(scale*p.z() + 10*noise.turb(p))); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ @@ -1932,7 +1941,7 @@ delete data; } - virtual color value(double u, double v, const vec3& p) const { + color value(double u, double v, const vec3& p) const override{ // If we have no texture data, then return solid cyan as a debugging aid. if (data == nullptr) return color(0,1,1); @@ -2033,13 +2042,13 @@ diffuse_light(shared_ptr a) : emit(a) {} diffuse_light(color c) : emit(make_shared(c)) {} - virtual bool scatter( + bool scatter( const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const { + ) const override { return false; } - virtual color emitted(double u, double v, const point3& p) const { + color emitted(double u, double v, const point3& p) const override{ return emit->value(u, v, p); } @@ -2168,9 +2177,11 @@ xy_rect(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 t0, double t1, hit_record& rec) const; + bool hit(const ray& r, double t0, double t1, hit_record& rec) + const override; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const { + bool bounding_box(double t0, double t1, aabb& output_box) const + override{ // The bounding box must have non-zero width in each dimension, so pad the Z // dimension a small amount. output_box = aabb(point3(x0,y0, k-0.0001), point3(x1, y1, k+0.0001)); @@ -2267,9 +2278,11 @@ xz_rect(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 t0, double t1, hit_record& rec) const; + bool hit(const ray& r, double t0, double t1, hit_record& rec) + const override; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const { + bool bounding_box(double t0, double t1, aabb& output_box) const + override{ // The bounding box must have non-zero width in each dimension, so pad the Y // dimension a small amount. output_box = aabb(point3(x0,k-0.0001,z0), point3(x1, k+0.0001, z1)); @@ -2288,9 +2301,11 @@ yz_rect(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 t0, double t1, hit_record& rec) const; + bool hit(const ray& r, double t0, double t1, hit_record& rec) + const override; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const { + bool bounding_box(double t0, double t1, aabb& output_box) const + override{ // The bounding box must have non-zero width in each dimension, so pad the X // dimension a small amount. output_box = aabb(point3(k-0.0001, y0, z0), point3(k+0.0001, y1, z1)); @@ -2417,9 +2432,11 @@ box() {} box(const point3& p0, const point3& p1, shared_ptr ptr); - virtual bool hit(const ray& r, double t0, double t1, hit_record& rec) const; + bool hit(const ray& r, double t0, double t1, hit_record& rec) + const override; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const { + bool bounding_box(double t0, double t1, aabb& output_box) const + override{ output_box = aabb(box_min, box_max); return true; } @@ -2498,8 +2515,10 @@ translate(shared_ptr p, const vec3& displacement) : ptr(p), offset(displacement) {} - virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const; + bool hit(const ray& r, double t_min, double t_max, hit_record& + rec) const override; + bool bounding_box(double t0, double t1, aabb& output_box) const + override; public: shared_ptr ptr; @@ -2583,8 +2602,10 @@ public: rotate_y(shared_ptr p, double angle); - virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const { + bool hit(const ray& r, double t_min, double t_max, hit_record& + rec) const override; + bool bounding_box(double t0, double t1, aabb& output_box) const + override{ output_box = bbox; return hasbox; } @@ -2751,9 +2772,11 @@ phase_function(make_shared(color(c))) {} - virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const; + bool hit(const ray& r, double t_min, double t_max, hit_record& + rec) const override; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const { + bool bounding_box(double t0, double t1, aabb& output_box) const + override{ return boundary->bounding_box(t0, t1, output_box); } @@ -2774,9 +2797,9 @@ public: isotropic(shared_ptr a) : albedo(a) {} - virtual bool scatter( + bool scatter( const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const { + ) const override{ scattered = ray(rec.p, random_in_unit_sphere(), r_in.time()); attenuation = albedo->value(rec.u, rec.v, rec.p); return true; diff --git a/books/RayTracingTheRestOfYourLife.html b/books/RayTracingTheRestOfYourLife.html index f182ad90..41ed7835 100644 --- a/books/RayTracingTheRestOfYourLife.html +++ b/books/RayTracingTheRestOfYourLife.html @@ -856,9 +856,9 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight - virtual bool scatter( + bool scatter( const ray& r_in, const hit_record& rec, color& alb, ray& scattered, double& pdf - ) const { + ) const override{ auto direction = rec.normal + random_unit_vector(); scattered = ray(rec.p, unit_vector(direction), r_in.time()); alb = albedo->value(rec.u, rec.v, rec.p); @@ -930,9 +930,9 @@ randomly from the hemisphere above the surface. This would be $p(direction) = \frac{1}{2\pi}$. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ - virtual bool scatter( + bool scatter( const ray& r_in, const hit_record& rec, color& alb, ray& scattered, double& pdf - ) const { + ) const override { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight auto direction = random_in_hemisphere(rec.normal); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ @@ -1298,9 +1298,9 @@ We can rewrite our Lambertian material using this to get: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ - virtual bool scatter( + bool scatter( const ray& r_in, const hit_record& rec, color& alb, ray& scattered, double& pdf - ) const { + ) const override { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight onb uvw; uvw.build_from_w(rec.normal); @@ -1444,8 +1444,8 @@ down. We can do that by letting the emitted member function of hittable take extra information: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ - virtual color emitted(const ray& r_in, const hit_record& rec, double u, double v, - const point3& p) const { + color emitted(const ray& r_in, const hit_record& rec, double u, double v, + const point3& p) const override{ if (rec.front_face) return emit->value(u, v, p); @@ -1550,12 +1550,12 @@ public: cosine_pdf(const vec3& w) { uvw.build_from_w(w); } - virtual double value(const vec3& direction) const { + double value(const vec3& direction) const override{ auto cosine = dot(unit_vector(direction), uvw.w()); return (cosine <= 0) ? 0 : cosine/pi; } - virtual vec3 generate() const { + vec3 generate() const override{ return uvw.local(random_cosine_direction()); } @@ -1625,11 +1625,11 @@ public: hittable_pdf(shared_ptr p, const point3& origin) : ptr(p), o(origin) {} - virtual double value(const vec3& direction) const { + double value(const vec3& direction) const override{ return ptr->pdf_value(o, direction); } - virtual vec3 generate() const { + vec3 generate() const override{ return ptr->random(o); } @@ -1674,7 +1674,8 @@ ... ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight - virtual double pdf_value(const point3& origin, const vec3& v) const { + double pdf_value(const point3& origin, const vec3& v) const + override{ hit_record rec; if (!this->hit(ray(origin, v), 0.001, infinity, rec)) return 0; @@ -1686,7 +1687,7 @@ return distance_squared / (cosine * area); } - virtual vec3 random(const point3& origin) const { + vec3 random(const point3& origin) const override{ auto random_point = point3(random_double(x0,x1), k, random_double(z0,z1)); return random_point - origin; } @@ -1759,11 +1760,11 @@ p[1] = p1; } - virtual double value(const vec3& direction) const { + double value(const vec3& direction) const override{ return 0.5 * p[0]->value(direction) + 0.5 *p[1]->value(direction); } - virtual vec3 generate() const { + vec3 generate() const override{ if (random_double() < 0.5) return p[0]->generate(); else @@ -1958,9 +1959,9 @@ lambertian(shared_ptr a) : albedo(a) {} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight - virtual bool scatter( + bool scatter( const ray& r_in, const hit_record& rec, scatter_record& srec - ) const { + ) const override{ srec.is_specular = false; srec.attenuation = albedo->value(rec.u, rec.v, rec.p); srec.pdf_ptr = new cosine_pdf(rec.normal); @@ -2038,9 +2039,9 @@ public: metal(const color& a, double f) : albedo(a), fuzz(f < 1 ? f : 1) {} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight - virtual bool scatter( + bool scatter( const ray& r_in, const hit_record& rec, scatter_record& srec - ) const { + ) const override { vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal); srec.specular_ray = ray(rec.p, reflected+fuzz*random_in_unit_sphere()); srec.attenuation = albedo; diff --git a/src/InOneWeekend/hittable_list.h b/src/InOneWeekend/hittable_list.h index 26a840f3..c7d6e360 100644 --- a/src/InOneWeekend/hittable_list.h +++ b/src/InOneWeekend/hittable_list.h @@ -3,12 +3,16 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" @@ -18,37 +22,36 @@ #include #include +class hittable_list : public hittable { +public: + hittable_list() {} + hittable_list(shared_ptr object) { add(object); } -class hittable_list: public hittable { - public: - hittable_list() {} - hittable_list(shared_ptr object) { add(object); } + void clear() { objects.clear(); } + void add(shared_ptr object) { objects.push_back(object); } - void clear() { objects.clear(); } - void add(shared_ptr object) { objects.push_back(object); } + bool hit(const ray &r, double tmin, double tmax, + hit_record &rec) const override; - virtual bool hit(const ray& r, double tmin, double tmax, hit_record& rec) const; - - public: - std::vector> objects; +public: + std::vector> objects; }; - -bool hittable_list::hit(const ray& r, double t_min, double t_max, hit_record& rec) const { - hit_record temp_rec; - auto hit_anything = false; - auto closest_so_far = t_max; - - for (const auto& object : objects) { - if (object->hit(r, t_min, closest_so_far, temp_rec)) { - hit_anything = true; - closest_so_far = temp_rec.t; - rec = temp_rec; - } +bool hittable_list::hit(const ray &r, double t_min, double t_max, + hit_record &rec) const { + hit_record temp_rec; + auto hit_anything = false; + auto closest_so_far = t_max; + + for (const auto &object : objects) { + if (object->hit(r, t_min, closest_so_far, temp_rec)) { + hit_anything = true; + closest_so_far = temp_rec.t; + rec = temp_rec; } + } - return hit_anything; + return hit_anything; } - #endif diff --git a/src/InOneWeekend/material.h b/src/InOneWeekend/material.h index 418bc85b..6233eaef 100644 --- a/src/InOneWeekend/material.h +++ b/src/InOneWeekend/material.h @@ -3,102 +3,94 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" - struct hit_record; - double schlick(double cosine, double ref_idx) { - auto r0 = (1-ref_idx) / (1+ref_idx); - r0 = r0*r0; - return r0 + (1-r0)*pow((1 - cosine),5); + auto r0 = (1 - ref_idx) / (1 + ref_idx); + r0 = r0 * r0; + return r0 + (1 - r0) * pow((1 - cosine), 5); } - class material { - public: - virtual bool scatter( - const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const = 0; +public: + virtual bool scatter(const ray &r_in, const hit_record &rec, + color &attenuation, ray &scattered) const = 0; }; - class lambertian : public material { - public: - lambertian(const color& a) : albedo(a) {} - - virtual bool scatter( - const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const { - vec3 scatter_direction = rec.normal + random_unit_vector(); - scattered = ray(rec.p, scatter_direction); - attenuation = albedo; - return true; - } - - public: - color albedo; +public: + lambertian(const color &a) : albedo(a) {} + + bool scatter(const ray &r_in, const hit_record &rec, color &attenuation, + ray &scattered) const override { + vec3 scatter_direction = rec.normal + random_unit_vector(); + scattered = ray(rec.p, scatter_direction); + attenuation = albedo; + return true; + } + +public: + color albedo; }; - class metal : public material { - public: - metal(const color& a, double f) : albedo(a), fuzz(f < 1 ? f : 1) {} - - virtual bool scatter( - const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const { - vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal); - scattered = ray(rec.p, reflected + fuzz*random_in_unit_sphere()); - attenuation = albedo; - return (dot(scattered.direction(), rec.normal) > 0); - } - - public: - color albedo; - double fuzz; +public: + metal(const color &a, double f) : albedo(a), fuzz(f < 1 ? f : 1) {} + + bool scatter(const ray &r_in, const hit_record &rec, color &attenuation, + ray &scattered) const override { + vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal); + scattered = ray(rec.p, reflected + fuzz * random_in_unit_sphere()); + attenuation = albedo; + return (dot(scattered.direction(), rec.normal) > 0); + } + +public: + color albedo; + double fuzz; }; - class dielectric : public material { - public: - dielectric(double ri) : ref_idx(ri) {} - - virtual bool scatter( - const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const { - attenuation = color(1.0, 1.0, 1.0); - double etai_over_etat = rec.front_face ? (1.0 / ref_idx) : ref_idx; - - vec3 unit_direction = unit_vector(r_in.direction()); - double cos_theta = fmin(dot(-unit_direction, rec.normal), 1.0); - double sin_theta = sqrt(1.0 - cos_theta*cos_theta); - - if ( (etai_over_etat * sin_theta > 1.0) - || (random_double() < schlick(cos_theta, etai_over_etat)) - ) { - vec3 reflected = reflect(unit_direction, rec.normal); - scattered = ray(rec.p, reflected); - return true; - } - - vec3 refracted = refract(unit_direction, rec.normal, etai_over_etat); - scattered = ray(rec.p, refracted); - return true; - } - - public: - double ref_idx; +public: + dielectric(double ri) : ref_idx(ri) {} + + bool scatter(const ray &r_in, const hit_record &rec, color &attenuation, + ray &scattered) const override { + attenuation = color(1.0, 1.0, 1.0); + double etai_over_etat = rec.front_face ? (1.0 / ref_idx) : ref_idx; + + vec3 unit_direction = unit_vector(r_in.direction()); + double cos_theta = fmin(dot(-unit_direction, rec.normal), 1.0); + double sin_theta = sqrt(1.0 - cos_theta * cos_theta); + + if ((etai_over_etat * sin_theta > 1.0) || + (random_double() < schlick(cos_theta, etai_over_etat))) { + vec3 reflected = reflect(unit_direction, rec.normal); + scattered = ray(rec.p, reflected); + return true; + } + + vec3 refracted = refract(unit_direction, rec.normal, etai_over_etat); + scattered = ray(rec.p, refracted); + return true; + } + +public: + double ref_idx; }; - #endif diff --git a/src/InOneWeekend/sphere.h b/src/InOneWeekend/sphere.h index 299c8362..f9ad4ae0 100644 --- a/src/InOneWeekend/sphere.h +++ b/src/InOneWeekend/sphere.h @@ -3,68 +3,71 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" #include "hittable.h" - class sphere : public hittable { - public: - sphere() {} +public: + sphere() {} - sphere(point3 cen, double r, shared_ptr m) - : center(cen), radius(r), mat_ptr(m) {}; + sphere(point3 cen, double r, shared_ptr m) + : center(cen), radius(r), mat_ptr(m){}; - virtual bool hit(const ray& r, double tmin, double tmax, hit_record& rec) const; + bool hit(const ray &r, double tmin, double tmax, + hit_record &rec) const override; - public: - point3 center; - double radius; - shared_ptr mat_ptr; +public: + point3 center; + double radius; + shared_ptr mat_ptr; }; +bool sphere::hit(const ray &r, double t_min, double t_max, + hit_record &rec) const { + 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; -bool sphere::hit(const ray& r, double t_min, double t_max, hit_record& rec) const { - 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) { - auto root = sqrt(discriminant); + if (discriminant > 0) { + auto root = sqrt(discriminant); - auto temp = (-half_b - root) / a; - if (temp < t_max && temp > t_min) { - rec.t = temp; - rec.p = r.at(rec.t); - vec3 outward_normal = (rec.p - center) / radius; - rec.set_face_normal(r, outward_normal); - rec.mat_ptr = mat_ptr; - return true; - } + auto temp = (-half_b - root) / a; + if (temp < t_max && temp > t_min) { + rec.t = temp; + rec.p = r.at(rec.t); + vec3 outward_normal = (rec.p - center) / radius; + rec.set_face_normal(r, outward_normal); + rec.mat_ptr = mat_ptr; + return true; + } - temp = (-half_b + root) / a; - if (temp < t_max && temp > t_min) { - rec.t = temp; - rec.p = r.at(rec.t); - vec3 outward_normal = (rec.p - center) / radius; - rec.set_face_normal(r, outward_normal); - rec.mat_ptr = mat_ptr; - return true; - } + temp = (-half_b + root) / a; + if (temp < t_max && temp > t_min) { + rec.t = temp; + rec.p = r.at(rec.t); + vec3 outward_normal = (rec.p - center) / radius; + rec.set_face_normal(r, outward_normal); + rec.mat_ptr = mat_ptr; + return true; } + } - return false; + return false; } - #endif diff --git a/src/TheNextWeek/aarect.h b/src/TheNextWeek/aarect.h index ed4d7145..06d522ec 100644 --- a/src/TheNextWeek/aarect.h +++ b/src/TheNextWeek/aarect.h @@ -3,146 +3,149 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" #include "hittable.h" +class xy_rect : public hittable { +public: + xy_rect() {} -class xy_rect: public hittable { - public: - xy_rect() {} + xy_rect(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){}; - xy_rect( - 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) {}; + bool hit(const ray &r, double t0, double t1, hit_record &rec) const override; - virtual bool hit(const ray& r, double t0, double t1, hit_record& rec) const; - - virtual bool bounding_box(double t0, double t1, aabb& output_box) const { - // The bounding box must have non-zero width in each dimension, so pad the Z - // dimension a small amount. - output_box = aabb(point3(x0,y0, k-0.0001), point3(x1, y1, k+0.0001)); - return true; - } + bool bounding_box(double t0, double t1, aabb &output_box) const override { + // The bounding box must have non-zero width in each dimension, so pad the Z + // dimension a small amount. + output_box = aabb(point3(x0, y0, k - 0.0001), point3(x1, y1, k + 0.0001)); + return true; + } - public: - shared_ptr mp; - double x0, x1, y0, y1, k; +public: + shared_ptr mp; + double x0, x1, y0, y1, k; }; -class xz_rect: public hittable { - public: - xz_rect() {} +class xz_rect : public hittable { +public: + xz_rect() {} - xz_rect( - 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) {}; + xz_rect(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 t0, double t1, hit_record& rec) const; + bool hit(const ray &r, double t0, double t1, hit_record &rec) const override; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const { - // The bounding box must have non-zero width in each dimension, so pad the Y - // dimension a small amount. - output_box = aabb(point3(x0,k-0.0001,z0), point3(x1, k+0.0001, z1)); - return true; - } + bool bounding_box(double t0, double t1, aabb &output_box) const override { + // The bounding box must have non-zero width in each dimension, so pad the Y + // dimension a small amount. + output_box = aabb(point3(x0, k - 0.0001, z0), point3(x1, k + 0.0001, z1)); + return true; + } - public: - shared_ptr mp; - double x0, x1, z0, z1, k; +public: + shared_ptr mp; + double x0, x1, z0, z1, k; }; -class yz_rect: public hittable { - public: - yz_rect() {} +class yz_rect : public hittable { +public: + yz_rect() {} - yz_rect( - 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) {}; + yz_rect(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 t0, double t1, hit_record& rec) const; + bool hit(const ray &r, double t0, double t1, hit_record &rec) const override; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const { - // The bounding box must have non-zero width in each dimension, so pad the X - // dimension a small amount. - output_box = aabb(point3(k-0.0001, y0, z0), point3(k+0.0001, y1, z1)); - return true; - } + bool bounding_box(double t0, double t1, aabb &output_box) const override { + // The bounding box must have non-zero width in each dimension, so pad the X + // dimension a small amount. + output_box = aabb(point3(k - 0.0001, y0, z0), point3(k + 0.0001, y1, z1)); + return true; + } - public: - shared_ptr mp; - double y0, y1, z0, z1, k; +public: + shared_ptr mp; + double y0, y1, z0, z1, k; }; -bool xy_rect::hit(const ray& r, double t0, double t1, hit_record& rec) const { - auto t = (k-r.origin().z()) / r.direction().z(); - if (t < t0 || t > t1) - return false; - - auto x = r.origin().x() + t*r.direction().x(); - auto y = r.origin().y() + t*r.direction().y(); - if (x < x0 || x > x1 || y < y0 || y > y1) - return false; - - rec.u = (x-x0)/(x1-x0); - rec.v = (y-y0)/(y1-y0); - rec.t = t; - auto outward_normal = vec3(0, 0, 1); - rec.set_face_normal(r, outward_normal); - rec.mat_ptr = mp; - rec.p = r.at(t); - - return true; +bool xy_rect::hit(const ray &r, double t0, double t1, hit_record &rec) const { + auto t = (k - r.origin().z()) / r.direction().z(); + if (t < t0 || t > t1) + return false; + + auto x = r.origin().x() + t * r.direction().x(); + auto y = r.origin().y() + t * r.direction().y(); + if (x < x0 || x > x1 || y < y0 || y > y1) + return false; + + rec.u = (x - x0) / (x1 - x0); + rec.v = (y - y0) / (y1 - y0); + rec.t = t; + auto outward_normal = vec3(0, 0, 1); + rec.set_face_normal(r, outward_normal); + rec.mat_ptr = mp; + rec.p = r.at(t); + + return true; } -bool xz_rect::hit(const ray& r, double t0, double t1, hit_record& rec) const { - auto t = (k-r.origin().y()) / r.direction().y(); - if (t < t0 || t > t1) - return false; - - auto x = r.origin().x() + t*r.direction().x(); - auto z = r.origin().z() + t*r.direction().z(); - if (x < x0 || x > x1 || z < z0 || z > z1) - return false; - - rec.u = (x-x0)/(x1-x0); - rec.v = (z-z0)/(z1-z0); - rec.t = t; - auto outward_normal = vec3(0, 1, 0); - rec.set_face_normal(r, outward_normal); - rec.mat_ptr = mp; - rec.p = r.at(t); - - return true; +bool xz_rect::hit(const ray &r, double t0, double t1, hit_record &rec) const { + auto t = (k - r.origin().y()) / r.direction().y(); + if (t < t0 || t > t1) + return false; + + auto x = r.origin().x() + t * r.direction().x(); + auto z = r.origin().z() + t * r.direction().z(); + if (x < x0 || x > x1 || z < z0 || z > z1) + return false; + + rec.u = (x - x0) / (x1 - x0); + rec.v = (z - z0) / (z1 - z0); + rec.t = t; + auto outward_normal = vec3(0, 1, 0); + rec.set_face_normal(r, outward_normal); + rec.mat_ptr = mp; + rec.p = r.at(t); + + return true; } -bool yz_rect::hit(const ray& r, double t0, double t1, hit_record& rec) const { - auto t = (k-r.origin().x()) / r.direction().x(); - if (t < t0 || t > t1) - return false; - - auto y = r.origin().y() + t*r.direction().y(); - auto z = r.origin().z() + t*r.direction().z(); - if (y < y0 || y > y1 || z < z0 || z > z1) - return false; - - rec.u = (y-y0)/(y1-y0); - rec.v = (z-z0)/(z1-z0); - rec.t = t; - auto outward_normal = vec3(1, 0, 0); - rec.set_face_normal(r, outward_normal); - rec.mat_ptr = mp; - rec.p = r.at(t); - - return true; +bool yz_rect::hit(const ray &r, double t0, double t1, hit_record &rec) const { + auto t = (k - r.origin().x()) / r.direction().x(); + if (t < t0 || t > t1) + return false; + + auto y = r.origin().y() + t * r.direction().y(); + auto z = r.origin().z() + t * r.direction().z(); + if (y < y0 || y > y1 || z < z0 || z > z1) + return false; + + rec.u = (y - y0) / (y1 - y0); + rec.v = (z - z0) / (z1 - z0); + rec.t = t; + auto outward_normal = vec3(1, 0, 0); + rec.set_face_normal(r, outward_normal); + rec.mat_ptr = mp; + rec.p = r.at(t); + + return true; } #endif diff --git a/src/TheNextWeek/box.h b/src/TheNextWeek/box.h index 4f57c10f..4bf6be02 100644 --- a/src/TheNextWeek/box.h +++ b/src/TheNextWeek/box.h @@ -3,12 +3,16 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" @@ -16,46 +20,43 @@ #include "aarect.h" #include "hittable_list.h" +class box : public hittable { +public: + box() {} + box(const point3 &p0, const point3 &p1, shared_ptr ptr); -class box: public hittable { - public: - box() {} - box(const point3& p0, const point3& p1, shared_ptr ptr); + bool hit(const ray &r, double t0, double t1, hit_record &rec) const override; - virtual bool hit(const ray& r, double t0, double t1, hit_record& rec) const; + virtual bool bounding_box(double t0, double t1, aabb &output_box) const { + output_box = aabb(box_min, box_max); + return true; + } - virtual bool bounding_box(double t0, double t1, aabb& output_box) const { - output_box = aabb(box_min, box_max); - return true; - } - - public: - point3 box_min; - point3 box_max; - hittable_list sides; +public: + point3 box_min; + point3 box_max; + hittable_list sides; }; +box::box(const point3 &p0, const point3 &p1, shared_ptr ptr) { + box_min = p0; + box_max = p1; -box::box(const point3& p0, const point3& p1, shared_ptr ptr) { - box_min = p0; - box_max = p1; - - sides.add(make_shared(p0.x(), p1.x(), p0.y(), p1.y(), p1.z(), ptr)); - sides.add(make_shared( - make_shared(p0.x(), p1.x(), p0.y(), p1.y(), p0.z(), ptr))); + sides.add(make_shared(p0.x(), p1.x(), p0.y(), p1.y(), p1.z(), ptr)); + sides.add(make_shared( + make_shared(p0.x(), p1.x(), p0.y(), p1.y(), p0.z(), ptr))); - sides.add(make_shared(p0.x(), p1.x(), p0.z(), p1.z(), p1.y(), ptr)); - sides.add(make_shared( - make_shared(p0.x(), p1.x(), p0.z(), p1.z(), p0.y(), ptr))); + sides.add(make_shared(p0.x(), p1.x(), p0.z(), p1.z(), p1.y(), ptr)); + sides.add(make_shared( + make_shared(p0.x(), p1.x(), p0.z(), p1.z(), p0.y(), ptr))); - sides.add(make_shared(p0.y(), p1.y(), p0.z(), p1.z(), p1.x(), ptr)); - sides.add(make_shared( - make_shared(p0.y(), p1.y(), p0.z(), p1.z(), p0.x(), ptr))); + sides.add(make_shared(p0.y(), p1.y(), p0.z(), p1.z(), p1.x(), ptr)); + sides.add(make_shared( + make_shared(p0.y(), p1.y(), p0.z(), p1.z(), p0.x(), ptr))); } -bool box::hit(const ray& r, double t0, double t1, hit_record& rec) const { - return sides.hit(r, t0, t1, rec); +bool box::hit(const ray &r, double t0, double t1, hit_record &rec) const { + return sides.hit(r, t0, t1, rec); } - #endif diff --git a/src/TheNextWeek/bvh.h b/src/TheNextWeek/bvh.h index 84455457..96247aa9 100644 --- a/src/TheNextWeek/bvh.h +++ b/src/TheNextWeek/bvh.h @@ -3,12 +3,16 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" @@ -17,108 +21,98 @@ #include +class bvh_node : public hittable { +public: + bvh_node(); -class bvh_node : public hittable { - public: - bvh_node(); + bvh_node(hittable_list &list, double time0, double time1) + : bvh_node(list.objects, 0, list.objects.size(), time0, time1) {} - bvh_node(hittable_list& list, double time0, double time1) - : bvh_node(list.objects, 0, list.objects.size(), time0, time1) - {} + bvh_node(std::vector> &objects, size_t start, size_t end, + double time0, double time1); - bvh_node( - std::vector>& objects, - size_t start, size_t end, double time0, double time1); + bool hit(const ray &r, double t_min, double t_max, + hit_record &rec) const override; + bool bounding_box(double t0, double t1, aabb &output_box) const override; - virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const; - - public: - shared_ptr left; - shared_ptr right; - aabb box; +public: + shared_ptr left; + shared_ptr right; + aabb box; }; +inline bool box_compare(const shared_ptr a, + const shared_ptr b, int axis) { + aabb box_a; + aabb box_b; -inline bool box_compare(const shared_ptr a, const shared_ptr b, int axis) { - aabb box_a; - aabb box_b; - - if (!a->bounding_box(0,0, box_a) || !b->bounding_box(0,0, box_b)) - std::cerr << "No bounding box in bvh_node constructor.\n"; + if (!a->bounding_box(0, 0, box_a) || !b->bounding_box(0, 0, box_b)) + std::cerr << "No bounding box in bvh_node constructor.\n"; - return box_a.min().e[axis] < box_b.min().e[axis]; + return box_a.min().e[axis] < box_b.min().e[axis]; } - -bool box_x_compare (const shared_ptr a, const shared_ptr b) { - return box_compare(a, b, 0); +bool box_x_compare(const shared_ptr a, const shared_ptr b) { + return box_compare(a, b, 0); } -bool box_y_compare (const shared_ptr a, const shared_ptr b) { - return box_compare(a, b, 1); +bool box_y_compare(const shared_ptr a, const shared_ptr b) { + return box_compare(a, b, 1); } -bool box_z_compare (const shared_ptr a, const shared_ptr b) { - return box_compare(a, b, 2); +bool box_z_compare(const shared_ptr a, const shared_ptr b) { + return box_compare(a, b, 2); } +bvh_node::bvh_node(std::vector> &objects, size_t start, + size_t end, double time0, double time1) { + int axis = random_int(0, 2); + auto comparator = + (axis == 0) ? box_x_compare : (axis == 1) ? box_y_compare : box_z_compare; -bvh_node::bvh_node( - std::vector>& objects, - size_t start, size_t end, double time0, double time1 -) { - int axis = random_int(0,2); - auto comparator = (axis == 0) ? box_x_compare - : (axis == 1) ? box_y_compare - : box_z_compare; - - size_t object_span = end - start; - - if (object_span == 1) { - left = right = objects[start]; - } else if (object_span == 2) { - if (comparator(objects[start], objects[start+1])) { - left = objects[start]; - right = objects[start+1]; - } else { - left = objects[start+1]; - right = objects[start]; - } - } else { - std::sort(objects.begin() + start, objects.begin() + end, comparator); + size_t object_span = end - start; - auto mid = start + object_span/2; - left = make_shared(objects, start, mid, time0, time1); - right = make_shared(objects, mid, end, time0, time1); + if (object_span == 1) { + left = right = objects[start]; + } else if (object_span == 2) { + if (comparator(objects[start], objects[start + 1])) { + left = objects[start]; + right = objects[start + 1]; + } else { + left = objects[start + 1]; + right = objects[start]; } + } else { + std::sort(objects.begin() + start, objects.begin() + end, comparator); - aabb box_left, box_right; + auto mid = start + object_span / 2; + left = make_shared(objects, start, mid, time0, time1); + right = make_shared(objects, mid, end, time0, time1); + } - if ( !left->bounding_box (time0, time1, box_left) - || !right->bounding_box(time0, time1, box_right) - ) - std::cerr << "No bounding box in bvh_node constructor.\n"; + aabb box_left, box_right; - box = surrounding_box(box_left, box_right); -} + if (!left->bounding_box(time0, time1, box_left) || + !right->bounding_box(time0, time1, box_right)) + std::cerr << "No bounding box in bvh_node constructor.\n"; + box = surrounding_box(box_left, box_right); +} -bool bvh_node::hit(const ray& r, double t_min, double t_max, hit_record& rec) const { - if (!box.hit(r, t_min, t_max)) - return false; +bool bvh_node::hit(const ray &r, double t_min, double t_max, + hit_record &rec) const { + if (!box.hit(r, t_min, t_max)) + return false; - bool hit_left = left->hit(r, t_min, t_max, rec); - bool hit_right = right->hit(r, t_min, hit_left ? rec.t : t_max, rec); + bool hit_left = left->hit(r, t_min, t_max, rec); + bool hit_right = right->hit(r, t_min, hit_left ? rec.t : t_max, rec); - return hit_left || hit_right; + return hit_left || hit_right; } - -bool bvh_node::bounding_box(double t0, double t1, aabb& output_box) const { - output_box = box; - return true; +bool bvh_node::bounding_box(double t0, double t1, aabb &output_box) const { + output_box = box; + return true; } - #endif diff --git a/src/TheNextWeek/constant_medium.h b/src/TheNextWeek/constant_medium.h index a6f119c5..1e83f274 100644 --- a/src/TheNextWeek/constant_medium.h +++ b/src/TheNextWeek/constant_medium.h @@ -3,12 +3,16 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" @@ -17,79 +21,78 @@ #include "material.h" #include "texture.h" +class constant_medium : public hittable { +public: + constant_medium(shared_ptr b, double d, shared_ptr a) + : boundary(b), neg_inv_density(-1 / d), + phase_function(make_shared(a)) {} -class constant_medium : public hittable { - public: - constant_medium(shared_ptr b, double d, shared_ptr a) - : boundary(b), - neg_inv_density(-1/d), - phase_function(make_shared(a)) - {} + constant_medium(shared_ptr b, double d, color c) + : boundary(b), neg_inv_density(-1 / d), + phase_function(make_shared(make_shared(c))) {} - constant_medium(shared_ptr b, double d, color c) - : boundary(b), - neg_inv_density(-1/d), - phase_function(make_shared(make_shared(c))) - {} + bool hit(const ray &r, double t_min, double t_max, + hit_record &rec) const override; - virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const; + bool bounding_box(double t0, double t1, aabb &output_box) const override { + return boundary->bounding_box(t0, t1, output_box); + } - virtual bool bounding_box(double t0, double t1, aabb& output_box) const { - return boundary->bounding_box(t0, t1, output_box); - } - - public: - shared_ptr boundary; - shared_ptr phase_function; - double neg_inv_density; +public: + shared_ptr boundary; + shared_ptr phase_function; + double neg_inv_density; }; +bool constant_medium::hit(const ray &r, double t_min, double t_max, + 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; -bool constant_medium::hit(const ray& r, double t_min, double t_max, 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; + hit_record rec1, rec2; - if (!boundary->hit(r, -infinity, infinity, rec1)) - return false; + if (!boundary->hit(r, -infinity, infinity, rec1)) + return false; - if (!boundary->hit(r, rec1.t+0.0001, infinity, rec2)) - return false; + if (!boundary->hit(r, rec1.t + 0.0001, infinity, rec2)) + return false; - if (debugging) std::cerr << "\nt0=" << rec1.t << ", t1=" << rec2.t << '\n'; + if (debugging) + std::cerr << "\nt0=" << rec1.t << ", t1=" << rec2.t << '\n'; - if (rec1.t < t_min) rec1.t = t_min; - if (rec2.t > t_max) rec2.t = t_max; + if (rec1.t < t_min) + rec1.t = t_min; + if (rec2.t > t_max) + rec2.t = t_max; - if (rec1.t >= rec2.t) - return false; + if (rec1.t >= rec2.t) + return false; - if (rec1.t < 0) - rec1.t = 0; + if (rec1.t < 0) + rec1.t = 0; - const auto ray_length = r.direction().length(); - const auto distance_inside_boundary = (rec2.t - rec1.t) * ray_length; - const auto hit_distance = neg_inv_density * log(random_double()); + const auto ray_length = r.direction().length(); + const auto distance_inside_boundary = (rec2.t - rec1.t) * ray_length; + const auto hit_distance = neg_inv_density * log(random_double()); - if (hit_distance > distance_inside_boundary) - return false; + if (hit_distance > distance_inside_boundary) + return false; - rec.t = rec1.t + hit_distance / ray_length; - rec.p = r.at(rec.t); + rec.t = rec1.t + hit_distance / ray_length; + rec.p = r.at(rec.t); - if (debugging) { - std::cerr << "hit_distance = " << hit_distance << '\n' - << "rec.t = " << rec.t << '\n' - << "rec.p = " << rec.p << '\n'; - } + if (debugging) { + std::cerr << "hit_distance = " << hit_distance << '\n' + << "rec.t = " << rec.t << '\n' + << "rec.p = " << rec.p << '\n'; + } - rec.normal = vec3(1,0,0); // arbitrary - rec.front_face = true; // also arbitrary - rec.mat_ptr = phase_function; + rec.normal = vec3(1, 0, 0); // arbitrary + rec.front_face = true; // also arbitrary + rec.mat_ptr = phase_function; - return true; + return true; } #endif diff --git a/src/TheNextWeek/hittable.h b/src/TheNextWeek/hittable.h index 1f575a9f..61b66538 100644 --- a/src/TheNextWeek/hittable.h +++ b/src/TheNextWeek/hittable.h @@ -3,184 +3,183 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" #include "aabb.h" - class material; struct hit_record { - point3 p; - vec3 normal; - shared_ptr mat_ptr; - double t; - double u; - double v; - bool front_face; - - inline void set_face_normal(const ray& r, const vec3& outward_normal) { - front_face = dot(r.direction(), outward_normal) < 0; - normal = front_face ? outward_normal :-outward_normal; - } + point3 p; + vec3 normal; + shared_ptr mat_ptr; + double t; + double u; + double v; + bool front_face; + + inline void set_face_normal(const ray &r, const vec3 &outward_normal) { + front_face = dot(r.direction(), outward_normal) < 0; + normal = front_face ? outward_normal : -outward_normal; + } }; - class hittable { - public: - virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const = 0; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const = 0; +public: + virtual bool hit(const ray &r, double t_min, double t_max, + hit_record &rec) const = 0; + virtual bool bounding_box(double t0, double t1, aabb &output_box) const = 0; }; - class flip_face : public hittable { - public: - flip_face(shared_ptr p) : ptr(p) {} +public: + flip_face(shared_ptr p) : ptr(p) {} - virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const { - if (!ptr->hit(r, t_min, t_max, rec)) - return false; + bool hit(const ray &r, double t_min, double t_max, + hit_record &rec) const override { + if (!ptr->hit(r, t_min, t_max, rec)) + return false; - rec.front_face = !rec.front_face; - return true; - } + rec.front_face = !rec.front_face; + return true; + } - virtual bool bounding_box(double t0, double t1, aabb& output_box) const { - return ptr->bounding_box(t0, t1, output_box); - } + bool bounding_box(double t0, double t1, aabb &output_box) const override { + return ptr->bounding_box(t0, t1, output_box); + } - public: - shared_ptr ptr; +public: + shared_ptr ptr; }; - class translate : public hittable { - public: - translate(shared_ptr p, const vec3& displacement) - : ptr(p), offset(displacement) {} +public: + translate(shared_ptr p, const vec3 &displacement) + : ptr(p), offset(displacement) {} - virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const; + bool hit(const ray &r, double t_min, double t_max, + hit_record &rec) const override; + bool bounding_box(double t0, double t1, aabb &output_box) const override; - public: - shared_ptr ptr; - vec3 offset; +public: + shared_ptr ptr; + vec3 offset; }; +bool translate::hit(const ray &r, double t_min, double t_max, + hit_record &rec) const { + ray moved_r(r.origin() - offset, r.direction(), r.time()); + if (!ptr->hit(moved_r, t_min, t_max, rec)) + return false; -bool translate::hit(const ray& r, double t_min, double t_max, hit_record& rec) const { - ray moved_r(r.origin() - offset, r.direction(), r.time()); - if (!ptr->hit(moved_r, t_min, t_max, rec)) - return false; - - rec.p += offset; - rec.set_face_normal(moved_r, rec.normal); + rec.p += offset; + rec.set_face_normal(moved_r, rec.normal); - return true; + return true; } +bool translate::bounding_box(double t0, double t1, aabb &output_box) const { + if (!ptr->bounding_box(t0, t1, output_box)) + return false; -bool translate::bounding_box(double t0, double t1, aabb& output_box) const { - if (!ptr->bounding_box(t0, t1, output_box)) - return false; - - output_box = aabb( - output_box.min() + offset, - output_box.max() + offset); + output_box = aabb(output_box.min() + offset, output_box.max() + offset); - return true; + return true; } - class rotate_y : public hittable { - public: - rotate_y(shared_ptr p, double angle); +public: + rotate_y(shared_ptr p, double angle); + + bool hit(const ray &r, double t_min, double t_max, + hit_record &rec) const override; + virtual bool bounding_box(double t0, double t1, + aabb &output_box) const override { + output_box = bbox; + return hasbox; + } + +public: + shared_ptr ptr; + double sin_theta; + double cos_theta; + bool hasbox; + aabb bbox; +}; - virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const { - output_box = bbox; - return hasbox; - } +rotate_y::rotate_y(shared_ptr p, double angle) : ptr(p) { + auto radians = degrees_to_radians(angle); + sin_theta = sin(radians); + cos_theta = cos(radians); + hasbox = ptr->bounding_box(0, 1, bbox); - public: - shared_ptr ptr; - double sin_theta; - double cos_theta; - bool hasbox; - aabb bbox; -}; + point3 min(infinity, infinity, infinity); + point3 max(-infinity, -infinity, -infinity); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { + auto x = i * bbox.max().x() + (1 - i) * bbox.min().x(); + auto y = j * bbox.max().y() + (1 - j) * bbox.min().y(); + auto z = k * bbox.max().z() + (1 - k) * bbox.min().z(); -rotate_y::rotate_y(shared_ptr p, double angle) : ptr(p) { - auto radians = degrees_to_radians(angle); - sin_theta = sin(radians); - cos_theta = cos(radians); - hasbox = ptr->bounding_box(0, 1, bbox); - - point3 min( infinity, infinity, infinity); - point3 max(-infinity, -infinity, -infinity); - - for (int i = 0; i < 2; i++) { - for (int j = 0; j < 2; j++) { - for (int k = 0; k < 2; k++) { - auto x = i*bbox.max().x() + (1-i)*bbox.min().x(); - auto y = j*bbox.max().y() + (1-j)*bbox.min().y(); - auto z = k*bbox.max().z() + (1-k)*bbox.min().z(); - - auto newx = cos_theta*x + sin_theta*z; - auto newz = -sin_theta*x + cos_theta*z; - - vec3 tester(newx, y, newz); - - for (int c = 0; c < 3; c++) { - min[c] = fmin(min[c], tester[c]); - max[c] = fmax(max[c], tester[c]); - } - } + auto newx = cos_theta * x + sin_theta * z; + auto newz = -sin_theta * x + cos_theta * z; + + vec3 tester(newx, y, newz); + + for (int c = 0; c < 3; c++) { + min[c] = fmin(min[c], tester[c]); + max[c] = fmax(max[c], tester[c]); } + } } + } - bbox = aabb(min, max); + bbox = aabb(min, max); } +bool rotate_y::hit(const ray &r, double t_min, double t_max, + hit_record &rec) const { + point3 origin = r.origin(); + vec3 direction = r.direction(); -bool rotate_y::hit(const ray& r, double t_min, double t_max, hit_record& rec) const { - point3 origin = r.origin(); - vec3 direction = r.direction(); - - origin[0] = cos_theta*r.origin()[0] - sin_theta*r.origin()[2]; - origin[2] = sin_theta*r.origin()[0] + cos_theta*r.origin()[2]; + origin[0] = cos_theta * r.origin()[0] - sin_theta * r.origin()[2]; + origin[2] = sin_theta * r.origin()[0] + cos_theta * r.origin()[2]; - direction[0] = cos_theta*r.direction()[0] - sin_theta*r.direction()[2]; - direction[2] = sin_theta*r.direction()[0] + cos_theta*r.direction()[2]; + direction[0] = cos_theta * r.direction()[0] - sin_theta * r.direction()[2]; + direction[2] = sin_theta * r.direction()[0] + cos_theta * r.direction()[2]; - ray rotated_r(origin, direction, r.time()); + ray rotated_r(origin, direction, r.time()); - if (!ptr->hit(rotated_r, t_min, t_max, rec)) - return false; + if (!ptr->hit(rotated_r, t_min, t_max, rec)) + return false; - point3 p = rec.p; - vec3 normal = rec.normal; + point3 p = rec.p; + vec3 normal = rec.normal; - p[0] = cos_theta*rec.p[0] + sin_theta*rec.p[2]; - p[2] = -sin_theta*rec.p[0] + cos_theta*rec.p[2]; + p[0] = cos_theta * rec.p[0] + sin_theta * rec.p[2]; + p[2] = -sin_theta * rec.p[0] + cos_theta * rec.p[2]; - normal[0] = cos_theta*rec.normal[0] + sin_theta*rec.normal[2]; - normal[2] = -sin_theta*rec.normal[0] + cos_theta*rec.normal[2]; + normal[0] = cos_theta * rec.normal[0] + sin_theta * rec.normal[2]; + normal[2] = -sin_theta * rec.normal[0] + cos_theta * rec.normal[2]; - rec.p = p; - rec.set_face_normal(rotated_r, normal); + rec.p = p; + rec.set_face_normal(rotated_r, normal); - return true; + return true; } - #endif diff --git a/src/TheNextWeek/hittable_list.h b/src/TheNextWeek/hittable_list.h index 325c2535..d28dfc09 100644 --- a/src/TheNextWeek/hittable_list.h +++ b/src/TheNextWeek/hittable_list.h @@ -3,12 +3,16 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" @@ -17,54 +21,54 @@ #include +class hittable_list : public hittable { +public: + hittable_list() {} + hittable_list(shared_ptr object) { add(object); } -class hittable_list: public hittable { - public: - hittable_list() {} - hittable_list(shared_ptr object) { add(object); } + void clear() { objects.clear(); } + void add(shared_ptr object) { objects.push_back(object); } - void clear() { objects.clear(); } - void add(shared_ptr object) { objects.push_back(object); } + bool hit(const ray &r, double tmin, double tmax, + hit_record &rec) const override; + bool bounding_box(double t0, double t1, aabb &output_box) const override; - virtual bool hit(const ray& r, double tmin, double tmax, hit_record& rec) const; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const; - - public: - std::vector> objects; +public: + std::vector> objects; }; - -bool hittable_list::hit(const ray& r, double t_min, double t_max, hit_record& rec) const { - hit_record temp_rec; - auto hit_anything = false; - auto closest_so_far = t_max; - - for (const auto& object : objects) { - if (object->hit(r, t_min, closest_so_far, temp_rec)) { - hit_anything = true; - closest_so_far = temp_rec.t; - rec = temp_rec; - } +bool hittable_list::hit(const ray &r, double t_min, double t_max, + hit_record &rec) const { + hit_record temp_rec; + auto hit_anything = false; + auto closest_so_far = t_max; + + for (const auto &object : objects) { + if (object->hit(r, t_min, closest_so_far, temp_rec)) { + hit_anything = true; + closest_so_far = temp_rec.t; + rec = temp_rec; } + } - return hit_anything; + return hit_anything; } +bool hittable_list::bounding_box(double t0, double t1, aabb &output_box) const { + if (objects.empty()) + return false; -bool hittable_list::bounding_box(double t0, double t1, aabb& output_box) const { - if (objects.empty()) return false; + aabb temp_box; + bool first_box = true; - aabb temp_box; - bool first_box = true; + for (const auto &object : objects) { + if (!object->bounding_box(t0, t1, temp_box)) + return false; + output_box = first_box ? temp_box : surrounding_box(output_box, temp_box); + first_box = false; + } - for (const auto& object : objects) { - if (!object->bounding_box(t0, t1, temp_box)) return false; - output_box = first_box ? temp_box : surrounding_box(output_box, temp_box); - first_box = false; - } - - return true; + return true; } - #endif diff --git a/src/TheNextWeek/material.h b/src/TheNextWeek/material.h index 5c497e63..516bc026 100644 --- a/src/TheNextWeek/material.h +++ b/src/TheNextWeek/material.h @@ -3,12 +3,16 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" @@ -16,131 +20,117 @@ #include "hittable.h" #include "texture.h" - double schlick(double cosine, double ref_idx) { - auto r0 = (1-ref_idx) / (1+ref_idx); - r0 = r0*r0; - return r0 + (1-r0)*pow((1 - cosine),5); + auto r0 = (1 - ref_idx) / (1 + ref_idx); + r0 = r0 * r0; + return r0 + (1 - r0) * pow((1 - cosine), 5); } +class material { +public: + virtual color emitted(double u, double v, const point3 &p) const { + return color(0, 0, 0); + } -class material { - public: - virtual color emitted(double u, double v, const point3& p) const { - return color(0,0,0); - } - - virtual bool scatter( - const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const = 0; + virtual bool scatter(const ray &r_in, const hit_record &rec, + color &attenuation, ray &scattered) const = 0; }; - class lambertian : public material { - public: - lambertian(const color& a) : albedo(make_shared(a)) {} - lambertian(shared_ptr a) : albedo(a) {} - - virtual bool scatter( - const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const { - vec3 scatter_direction = rec.normal + random_unit_vector(); - scattered = ray(rec.p, scatter_direction, r_in.time()); - attenuation = albedo->value(rec.u, rec.v, rec.p); - return true; - } - - public: - shared_ptr albedo; +public: + lambertian(const color &a) : albedo(make_shared(a)) {} + lambertian(shared_ptr a) : albedo(a) {} + + bool scatter(const ray &r_in, const hit_record &rec, color &attenuation, + ray &scattered) const override { + vec3 scatter_direction = rec.normal + random_unit_vector(); + scattered = ray(rec.p, scatter_direction, r_in.time()); + attenuation = albedo->value(rec.u, rec.v, rec.p); + return true; + } + +public: + shared_ptr albedo; }; - class metal : public material { - public: - metal(const color& a, double f) : albedo(a), fuzz(f < 1 ? f : 1) {} - - virtual bool scatter( - const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const { - vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal); - scattered = ray(rec.p, reflected + fuzz*random_in_unit_sphere(), r_in.time()); - attenuation = albedo; - return (dot(scattered.direction(), rec.normal) > 0); - } - - public: - color albedo; - double fuzz; +public: + metal(const color &a, double f) : albedo(a), fuzz(f < 1 ? f : 1) {} + + bool scatter(const ray &r_in, const hit_record &rec, color &attenuation, + ray &scattered) const override { + vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal); + scattered = + ray(rec.p, reflected + fuzz * random_in_unit_sphere(), r_in.time()); + attenuation = albedo; + return (dot(scattered.direction(), rec.normal) > 0); + } + +public: + color albedo; + double fuzz; }; - class dielectric : public material { - public: - dielectric(double ri) : ref_idx(ri) {} - - virtual bool scatter( - const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const { - attenuation = color(1.0, 1.0, 1.0); - double etai_over_etat = (rec.front_face) ? (1.0 / ref_idx) : ref_idx; - - vec3 unit_direction = unit_vector(r_in.direction()); - double cos_theta = fmin(dot(-unit_direction, rec.normal), 1.0); - double sin_theta = sqrt(1.0 - cos_theta*cos_theta); - - if ( (etai_over_etat * sin_theta > 1.0) - || (random_double() < schlick(cos_theta, etai_over_etat)) - ) { - vec3 reflected = reflect(unit_direction, rec.normal); - scattered = ray(rec.p, reflected, r_in.time()); - return true; - } - - vec3 refracted = refract(unit_direction, rec.normal, etai_over_etat); - scattered = ray(rec.p, refracted, r_in.time()); - return true; - } - - public: - double ref_idx; +public: + dielectric(double ri) : ref_idx(ri) {} + + bool scatter(const ray &r_in, const hit_record &rec, color &attenuation, + ray &scattered) const override { + attenuation = color(1.0, 1.0, 1.0); + double etai_over_etat = (rec.front_face) ? (1.0 / ref_idx) : ref_idx; + + vec3 unit_direction = unit_vector(r_in.direction()); + double cos_theta = fmin(dot(-unit_direction, rec.normal), 1.0); + double sin_theta = sqrt(1.0 - cos_theta * cos_theta); + + if ((etai_over_etat * sin_theta > 1.0) || + (random_double() < schlick(cos_theta, etai_over_etat))) { + vec3 reflected = reflect(unit_direction, rec.normal); + scattered = ray(rec.p, reflected, r_in.time()); + return true; + } + + vec3 refracted = refract(unit_direction, rec.normal, etai_over_etat); + scattered = ray(rec.p, refracted, r_in.time()); + return true; + } + +public: + double ref_idx; }; - class diffuse_light : public material { - public: - diffuse_light(shared_ptr a) : emit(a) {} - diffuse_light(color c) : emit(make_shared(c)) {} - - virtual bool scatter( - const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const { - return false; - } - - virtual color emitted(double u, double v, const point3& p) const { - return emit->value(u, v, p); - } - - public: - shared_ptr emit; -}; +public: + diffuse_light(shared_ptr a) : emit(a) {} + diffuse_light(color c) : emit(make_shared(c)) {} + bool scatter(const ray &r_in, const hit_record &rec, color &attenuation, + ray &scattered) const override { + return false; + } -class isotropic : public material { - public: - isotropic(shared_ptr a) : albedo(a) {} - - virtual bool scatter( - const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const { - scattered = ray(rec.p, random_in_unit_sphere(), r_in.time()); - attenuation = albedo->value(rec.u, rec.v, rec.p); - return true; - } - - public: - shared_ptr albedo; + color emitted(double u, double v, const point3 &p) const override { + return emit->value(u, v, p); + } + +public: + shared_ptr emit; }; +class isotropic : public material { +public: + isotropic(shared_ptr a) : albedo(a) {} + + bool scatter(const ray &r_in, const hit_record &rec, color &attenuation, + ray &scattered) const override { + scattered = ray(rec.p, random_in_unit_sphere(), r_in.time()); + attenuation = albedo->value(rec.u, rec.v, rec.p); + return true; + } + +public: + shared_ptr albedo; +}; #endif diff --git a/src/TheNextWeek/moving_sphere.h b/src/TheNextWeek/moving_sphere.h index 2cf9221d..d6529143 100644 --- a/src/TheNextWeek/moving_sphere.h +++ b/src/TheNextWeek/moving_sphere.h @@ -3,91 +3,91 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" #include "hittable.h" - class moving_sphere : public hittable { - public: - moving_sphere() {} - moving_sphere( - point3 cen0, point3 cen1, double t0, double t1, double r, shared_ptr m) - : center0(cen0), center1(cen1), time0(t0), time1(t1), radius(r), mat_ptr(m) - {}; - - virtual bool hit(const ray& r, double tmin, double tmax, hit_record& rec) const; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const; - - point3 center(double time) const; - - public: - point3 center0, center1; - double time0, time1; - double radius; - shared_ptr mat_ptr; +public: + moving_sphere() {} + moving_sphere(point3 cen0, point3 cen1, double t0, double t1, double r, + shared_ptr m) + : center0(cen0), center1(cen1), time0(t0), time1(t1), radius(r), + mat_ptr(m){}; + + bool hit(const ray &r, double tmin, double tmax, + hit_record &rec) const override; + bool bounding_box(double t0, double t1, aabb &output_box) const override; + + point3 center(double time) const; + +public: + point3 center0, center1; + double time0, time1; + double radius; + shared_ptr mat_ptr; }; - -point3 moving_sphere::center(double time) const{ - return center0 + ((time - time0) / (time1 - time0))*(center1 - center0); +point3 moving_sphere::center(double time) const { + return center0 + ((time - time0) / (time1 - time0)) * (center1 - center0); } - -bool moving_sphere::bounding_box(double t0, double t1, aabb& output_box) const { - aabb box0( - center(t0) - vec3(radius, radius, radius), - center(t0) + vec3(radius, radius, radius)); - aabb box1( - center(t1) - vec3(radius, radius, radius), - center(t1) + vec3(radius, radius, radius)); - output_box = surrounding_box(box0, box1); - return true; +bool moving_sphere::bounding_box(double t0, double t1, aabb &output_box) const { + aabb box0(center(t0) - vec3(radius, radius, radius), + center(t0) + vec3(radius, radius, radius)); + aabb box1(center(t1) - vec3(radius, radius, radius), + center(t1) + vec3(radius, radius, radius)); + output_box = surrounding_box(box0, box1); + return true; } - // replace "center" with "center(r.time())" -bool moving_sphere::hit(const ray& r, double t_min, double t_max, hit_record& rec) const { - vec3 oc = r.origin() - center(r.time()); - 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) { - auto root = sqrt(discriminant); - - auto temp = (-half_b - root)/a; - if (temp < t_max && temp > t_min) { - rec.t = temp; - rec.p = r.at(rec.t); - vec3 outward_normal = (rec.p - center(r.time())) / radius; - rec.set_face_normal(r, outward_normal); - rec.mat_ptr = mat_ptr; - return true; - } +bool moving_sphere::hit(const ray &r, double t_min, double t_max, + hit_record &rec) const { + vec3 oc = r.origin() - center(r.time()); + 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) { + auto root = sqrt(discriminant); + + auto temp = (-half_b - root) / a; + if (temp < t_max && temp > t_min) { + rec.t = temp; + rec.p = r.at(rec.t); + vec3 outward_normal = (rec.p - center(r.time())) / radius; + rec.set_face_normal(r, outward_normal); + rec.mat_ptr = mat_ptr; + return true; + } - temp = (-half_b + root)/a; - if (temp < t_max && temp > t_min) { - rec.t = temp; - rec.p = r.at(rec.t); - vec3 outward_normal = (rec.p - center(r.time())) / radius; - rec.set_face_normal(r, outward_normal); - rec.mat_ptr = mat_ptr; - return true; - } + temp = (-half_b + root) / a; + if (temp < t_max && temp > t_min) { + rec.t = temp; + rec.p = r.at(rec.t); + vec3 outward_normal = (rec.p - center(r.time())) / radius; + rec.set_face_normal(r, outward_normal); + rec.mat_ptr = mat_ptr; + return true; } + } - return false; + return false; } #endif diff --git a/src/TheNextWeek/sphere.h b/src/TheNextWeek/sphere.h index d6ba3259..e7e32742 100644 --- a/src/TheNextWeek/sphere.h +++ b/src/TheNextWeek/sphere.h @@ -3,86 +3,86 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" #include "hittable.h" - -class sphere: public hittable { - public: - sphere() {} - sphere(point3 cen, double r, shared_ptr m) - : center(cen), radius(r), mat_ptr(m) {}; - virtual bool hit(const ray& r, double tmin, double tmax, hit_record& rec) const; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const; - - public: - point3 center; - double radius; - shared_ptr mat_ptr; +class sphere : public hittable { +public: + sphere() {} + sphere(point3 cen, double r, shared_ptr m) + : center(cen), radius(r), mat_ptr(m){}; + bool hit(const ray &r, double tmin, double tmax, + hit_record &rec) const override; + bool bounding_box(double t0, double t1, aabb &output_box) const override; + +public: + point3 center; + double radius; + shared_ptr mat_ptr; }; - -bool sphere::bounding_box(double t0, double t1, aabb& output_box) const { - output_box = aabb( - center - vec3(radius, radius, radius), - center + vec3(radius, radius, radius)); - return true; +bool sphere::bounding_box(double t0, double t1, aabb &output_box) const { + output_box = aabb(center - vec3(radius, radius, radius), + center + vec3(radius, radius, radius)); + return true; } - -void get_sphere_uv(const point3& p, double& u, double& v) { - auto phi = atan2(p.z(), p.x()); - auto theta = asin(p.y()); - u = 1-(phi + pi) / (2*pi); - v = (theta + pi/2) / pi; +void get_sphere_uv(const point3 &p, double &u, double &v) { + auto phi = atan2(p.z(), p.x()); + auto theta = asin(p.y()); + u = 1 - (phi + pi) / (2 * pi); + v = (theta + pi / 2) / pi; } +bool sphere::hit(const ray &r, double t_min, double t_max, + hit_record &rec) const { + 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) { + auto root = sqrt(discriminant); + + auto temp = (-half_b - root) / a; + if (temp < t_max && temp > t_min) { + rec.t = temp; + rec.p = r.at(rec.t); + vec3 outward_normal = (rec.p - center) / radius; + rec.set_face_normal(r, outward_normal); + get_sphere_uv((rec.p - center) / radius, rec.u, rec.v); + rec.mat_ptr = mat_ptr; + return true; + } -bool sphere::hit(const ray& r, double t_min, double t_max, hit_record& rec) const { - 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) { - auto root = sqrt(discriminant); - - auto temp = (-half_b - root) / a; - if (temp < t_max && temp > t_min) { - rec.t = temp; - rec.p = r.at(rec.t); - vec3 outward_normal = (rec.p - center) / radius; - rec.set_face_normal(r, outward_normal); - get_sphere_uv((rec.p-center)/radius, rec.u, rec.v); - rec.mat_ptr = mat_ptr; - return true; - } - - temp = (-half_b + root) / a; - if (temp < t_max && temp > t_min) { - rec.t = temp; - rec.p = r.at(rec.t); - vec3 outward_normal = (rec.p - center) / radius; - rec.set_face_normal(r, outward_normal); - get_sphere_uv((rec.p-center)/radius, rec.u, rec.v); - rec.mat_ptr = mat_ptr; - return true; - } + temp = (-half_b + root) / a; + if (temp < t_max && temp > t_min) { + rec.t = temp; + rec.p = r.at(rec.t); + vec3 outward_normal = (rec.p - center) / radius; + rec.set_face_normal(r, outward_normal); + get_sphere_uv((rec.p - center) / radius, rec.u, rec.v); + rec.mat_ptr = mat_ptr; + return true; } + } - return false; + return false; } - #endif diff --git a/src/TheRestOfYourLife/aarect.h b/src/TheRestOfYourLife/aarect.h index dedd9b49..6e58ad33 100644 --- a/src/TheRestOfYourLife/aarect.h +++ b/src/TheRestOfYourLife/aarect.h @@ -3,163 +3,166 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" #include "hittable.h" +class xy_rect : public hittable { +public: + xy_rect() {} -class xy_rect: public hittable { - public: - xy_rect() {} + xy_rect(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){}; - xy_rect( - 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) {}; + bool hit(const ray &r, double t0, double t1, hit_record &rec) const override; - virtual bool hit(const ray& r, double t0, double t1, hit_record& rec) const; - - virtual bool bounding_box(double t0, double t1, aabb& output_box) const { - // The bounding box must have non-zero width in each dimension, so pad the Z - // dimension a small amount. - output_box = aabb(point3(x0,y0, k-0.0001), point3(x1, y1, k+0.0001)); - return true; - } + bool bounding_box(double t0, double t1, aabb &output_box) const override { + // The bounding box must have non-zero width in each dimension, so pad the Z + // dimension a small amount. + output_box = aabb(point3(x0, y0, k - 0.0001), point3(x1, y1, k + 0.0001)); + return true; + } - public: - shared_ptr mp; - double x0, x1, y0, y1, k; +public: + shared_ptr mp; + double x0, x1, y0, y1, k; }; -class xz_rect: public hittable { - public: - xz_rect() {} +class xz_rect : public hittable { +public: + xz_rect() {} - xz_rect( - 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) {}; + xz_rect(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 t0, double t1, hit_record& rec) const; + bool hit(const ray &r, double t0, double t1, hit_record &rec) const override; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const { - // The bounding box must have non-zero width in each dimension, so pad the Y - // dimension a small amount. - output_box = aabb(point3(x0,k-0.0001,z0), point3(x1, k+0.0001, z1)); - return true; - } + bool bounding_box(double t0, double t1, aabb &output_box) const override { + // The bounding box must have non-zero width in each dimension, so pad the Y + // dimension a small amount. + output_box = aabb(point3(x0, k - 0.0001, z0), point3(x1, k + 0.0001, z1)); + return true; + } - virtual double pdf_value(const point3& origin, const vec3& v) const { - hit_record rec; - if (!this->hit(ray(origin, v), 0.001, infinity, rec)) - return 0; + double pdf_value(const point3 &origin, const vec3 &v) const override { + hit_record rec; + if (!this->hit(ray(origin, v), 0.001, infinity, rec)) + return 0; - auto area = (x1-x0)*(z1-z0); - auto distance_squared = rec.t * rec.t * v.length_squared(); - auto cosine = fabs(dot(v, rec.normal) / v.length()); + auto area = (x1 - x0) * (z1 - z0); + auto distance_squared = rec.t * rec.t * v.length_squared(); + auto cosine = fabs(dot(v, rec.normal) / v.length()); - return distance_squared / (cosine * area); - } + return distance_squared / (cosine * area); + } - virtual vec3 random(const point3& origin) const { - auto random_point = point3(random_double(x0,x1), k, random_double(z0,z1)); - return random_point - origin; - } + vec3 random(const point3 &origin) const override { + auto random_point = point3(random_double(x0, x1), k, random_double(z0, z1)); + return random_point - origin; + } - public: - shared_ptr mp; - double x0, x1, z0, z1, k; +public: + shared_ptr mp; + double x0, x1, z0, z1, k; }; -class yz_rect: public hittable { - public: - yz_rect() {} +class yz_rect : public hittable { +public: + yz_rect() {} - yz_rect( - 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) {}; + yz_rect(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 t0, double t1, hit_record& rec) const; + bool hit(const ray &r, double t0, double t1, hit_record &rec) const override; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const { - // The bounding box must have non-zero width in each dimension, so pad the X - // dimension a small amount. - output_box = aabb(point3(k-0.0001, y0, z0), point3(k+0.0001, y1, z1)); - return true; - } + bool bounding_box(double t0, double t1, aabb &output_box) const override { + // The bounding box must have non-zero width in each dimension, so pad the X + // dimension a small amount. + output_box = aabb(point3(k - 0.0001, y0, z0), point3(k + 0.0001, y1, z1)); + return true; + } - public: - shared_ptr mp; - double y0, y1, z0, z1, k; +public: + shared_ptr mp; + double y0, y1, z0, z1, k; }; -bool xy_rect::hit(const ray& r, double t0, double t1, hit_record& rec) const { - auto t = (k-r.origin().z()) / r.direction().z(); - if (t < t0 || t > t1) - return false; - - auto x = r.origin().x() + t*r.direction().x(); - auto y = r.origin().y() + t*r.direction().y(); - if (x < x0 || x > x1 || y < y0 || y > y1) - return false; - - rec.u = (x-x0)/(x1-x0); - rec.v = (y-y0)/(y1-y0); - rec.t = t; - auto outward_normal = vec3(0, 0, 1); - rec.set_face_normal(r, outward_normal); - rec.mat_ptr = mp; - rec.p = r.at(t); - - return true; +bool xy_rect::hit(const ray &r, double t0, double t1, hit_record &rec) const { + auto t = (k - r.origin().z()) / r.direction().z(); + if (t < t0 || t > t1) + return false; + + auto x = r.origin().x() + t * r.direction().x(); + auto y = r.origin().y() + t * r.direction().y(); + if (x < x0 || x > x1 || y < y0 || y > y1) + return false; + + rec.u = (x - x0) / (x1 - x0); + rec.v = (y - y0) / (y1 - y0); + rec.t = t; + auto outward_normal = vec3(0, 0, 1); + rec.set_face_normal(r, outward_normal); + rec.mat_ptr = mp; + rec.p = r.at(t); + + return true; } -bool xz_rect::hit(const ray& r, double t0, double t1, hit_record& rec) const { - auto t = (k-r.origin().y()) / r.direction().y(); - if (t < t0 || t > t1) - return false; - - auto x = r.origin().x() + t*r.direction().x(); - auto z = r.origin().z() + t*r.direction().z(); - if (x < x0 || x > x1 || z < z0 || z > z1) - return false; - - rec.u = (x-x0)/(x1-x0); - rec.v = (z-z0)/(z1-z0); - rec.t = t; - auto outward_normal = vec3(0, 1, 0); - rec.set_face_normal(r, outward_normal); - rec.mat_ptr = mp; - rec.p = r.at(t); - - return true; +bool xz_rect::hit(const ray &r, double t0, double t1, hit_record &rec) const { + auto t = (k - r.origin().y()) / r.direction().y(); + if (t < t0 || t > t1) + return false; + + auto x = r.origin().x() + t * r.direction().x(); + auto z = r.origin().z() + t * r.direction().z(); + if (x < x0 || x > x1 || z < z0 || z > z1) + return false; + + rec.u = (x - x0) / (x1 - x0); + rec.v = (z - z0) / (z1 - z0); + rec.t = t; + auto outward_normal = vec3(0, 1, 0); + rec.set_face_normal(r, outward_normal); + rec.mat_ptr = mp; + rec.p = r.at(t); + + return true; } -bool yz_rect::hit(const ray& r, double t0, double t1, hit_record& rec) const { - auto t = (k-r.origin().x()) / r.direction().x(); - if (t < t0 || t > t1) - return false; - - auto y = r.origin().y() + t*r.direction().y(); - auto z = r.origin().z() + t*r.direction().z(); - if (y < y0 || y > y1 || z < z0 || z > z1) - return false; - - rec.u = (y-y0)/(y1-y0); - rec.v = (z-z0)/(z1-z0); - rec.t = t; - auto outward_normal = vec3(1, 0, 0); - rec.set_face_normal(r, outward_normal); - rec.mat_ptr = mp; - rec.p = r.at(t); - - return true; +bool yz_rect::hit(const ray &r, double t0, double t1, hit_record &rec) const { + auto t = (k - r.origin().x()) / r.direction().x(); + if (t < t0 || t > t1) + return false; + + auto y = r.origin().y() + t * r.direction().y(); + auto z = r.origin().z() + t * r.direction().z(); + if (y < y0 || y > y1 || z < z0 || z > z1) + return false; + + rec.u = (y - y0) / (y1 - y0); + rec.v = (z - z0) / (z1 - z0); + rec.t = t; + auto outward_normal = vec3(1, 0, 0); + rec.set_face_normal(r, outward_normal); + rec.mat_ptr = mp; + rec.p = r.at(t); + + return true; } #endif diff --git a/src/TheRestOfYourLife/box.h b/src/TheRestOfYourLife/box.h index 4f57c10f..bdb70522 100644 --- a/src/TheRestOfYourLife/box.h +++ b/src/TheRestOfYourLife/box.h @@ -3,12 +3,16 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" @@ -16,46 +20,43 @@ #include "aarect.h" #include "hittable_list.h" +class box : public hittable { +public: + box() {} + box(const point3 &p0, const point3 &p1, shared_ptr ptr); -class box: public hittable { - public: - box() {} - box(const point3& p0, const point3& p1, shared_ptr ptr); + bool hit(const ray &r, double t0, double t1, hit_record &rec) const override; - virtual bool hit(const ray& r, double t0, double t1, hit_record& rec) const; + bool bounding_box(double t0, double t1, aabb &output_box) const override { + output_box = aabb(box_min, box_max); + return true; + } - virtual bool bounding_box(double t0, double t1, aabb& output_box) const { - output_box = aabb(box_min, box_max); - return true; - } - - public: - point3 box_min; - point3 box_max; - hittable_list sides; +public: + point3 box_min; + point3 box_max; + hittable_list sides; }; +box::box(const point3 &p0, const point3 &p1, shared_ptr ptr) { + box_min = p0; + box_max = p1; -box::box(const point3& p0, const point3& p1, shared_ptr ptr) { - box_min = p0; - box_max = p1; - - sides.add(make_shared(p0.x(), p1.x(), p0.y(), p1.y(), p1.z(), ptr)); - sides.add(make_shared( - make_shared(p0.x(), p1.x(), p0.y(), p1.y(), p0.z(), ptr))); + sides.add(make_shared(p0.x(), p1.x(), p0.y(), p1.y(), p1.z(), ptr)); + sides.add(make_shared( + make_shared(p0.x(), p1.x(), p0.y(), p1.y(), p0.z(), ptr))); - sides.add(make_shared(p0.x(), p1.x(), p0.z(), p1.z(), p1.y(), ptr)); - sides.add(make_shared( - make_shared(p0.x(), p1.x(), p0.z(), p1.z(), p0.y(), ptr))); + sides.add(make_shared(p0.x(), p1.x(), p0.z(), p1.z(), p1.y(), ptr)); + sides.add(make_shared( + make_shared(p0.x(), p1.x(), p0.z(), p1.z(), p0.y(), ptr))); - sides.add(make_shared(p0.y(), p1.y(), p0.z(), p1.z(), p1.x(), ptr)); - sides.add(make_shared( - make_shared(p0.y(), p1.y(), p0.z(), p1.z(), p0.x(), ptr))); + sides.add(make_shared(p0.y(), p1.y(), p0.z(), p1.z(), p1.x(), ptr)); + sides.add(make_shared( + make_shared(p0.y(), p1.y(), p0.z(), p1.z(), p0.x(), ptr))); } -bool box::hit(const ray& r, double t0, double t1, hit_record& rec) const { - return sides.hit(r, t0, t1, rec); +bool box::hit(const ray &r, double t0, double t1, hit_record &rec) const { + return sides.hit(r, t0, t1, rec); } - #endif diff --git a/src/TheRestOfYourLife/bvh.h b/src/TheRestOfYourLife/bvh.h index 84455457..96247aa9 100644 --- a/src/TheRestOfYourLife/bvh.h +++ b/src/TheRestOfYourLife/bvh.h @@ -3,12 +3,16 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" @@ -17,108 +21,98 @@ #include +class bvh_node : public hittable { +public: + bvh_node(); -class bvh_node : public hittable { - public: - bvh_node(); + bvh_node(hittable_list &list, double time0, double time1) + : bvh_node(list.objects, 0, list.objects.size(), time0, time1) {} - bvh_node(hittable_list& list, double time0, double time1) - : bvh_node(list.objects, 0, list.objects.size(), time0, time1) - {} + bvh_node(std::vector> &objects, size_t start, size_t end, + double time0, double time1); - bvh_node( - std::vector>& objects, - size_t start, size_t end, double time0, double time1); + bool hit(const ray &r, double t_min, double t_max, + hit_record &rec) const override; + bool bounding_box(double t0, double t1, aabb &output_box) const override; - virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const; - - public: - shared_ptr left; - shared_ptr right; - aabb box; +public: + shared_ptr left; + shared_ptr right; + aabb box; }; +inline bool box_compare(const shared_ptr a, + const shared_ptr b, int axis) { + aabb box_a; + aabb box_b; -inline bool box_compare(const shared_ptr a, const shared_ptr b, int axis) { - aabb box_a; - aabb box_b; - - if (!a->bounding_box(0,0, box_a) || !b->bounding_box(0,0, box_b)) - std::cerr << "No bounding box in bvh_node constructor.\n"; + if (!a->bounding_box(0, 0, box_a) || !b->bounding_box(0, 0, box_b)) + std::cerr << "No bounding box in bvh_node constructor.\n"; - return box_a.min().e[axis] < box_b.min().e[axis]; + return box_a.min().e[axis] < box_b.min().e[axis]; } - -bool box_x_compare (const shared_ptr a, const shared_ptr b) { - return box_compare(a, b, 0); +bool box_x_compare(const shared_ptr a, const shared_ptr b) { + return box_compare(a, b, 0); } -bool box_y_compare (const shared_ptr a, const shared_ptr b) { - return box_compare(a, b, 1); +bool box_y_compare(const shared_ptr a, const shared_ptr b) { + return box_compare(a, b, 1); } -bool box_z_compare (const shared_ptr a, const shared_ptr b) { - return box_compare(a, b, 2); +bool box_z_compare(const shared_ptr a, const shared_ptr b) { + return box_compare(a, b, 2); } +bvh_node::bvh_node(std::vector> &objects, size_t start, + size_t end, double time0, double time1) { + int axis = random_int(0, 2); + auto comparator = + (axis == 0) ? box_x_compare : (axis == 1) ? box_y_compare : box_z_compare; -bvh_node::bvh_node( - std::vector>& objects, - size_t start, size_t end, double time0, double time1 -) { - int axis = random_int(0,2); - auto comparator = (axis == 0) ? box_x_compare - : (axis == 1) ? box_y_compare - : box_z_compare; - - size_t object_span = end - start; - - if (object_span == 1) { - left = right = objects[start]; - } else if (object_span == 2) { - if (comparator(objects[start], objects[start+1])) { - left = objects[start]; - right = objects[start+1]; - } else { - left = objects[start+1]; - right = objects[start]; - } - } else { - std::sort(objects.begin() + start, objects.begin() + end, comparator); + size_t object_span = end - start; - auto mid = start + object_span/2; - left = make_shared(objects, start, mid, time0, time1); - right = make_shared(objects, mid, end, time0, time1); + if (object_span == 1) { + left = right = objects[start]; + } else if (object_span == 2) { + if (comparator(objects[start], objects[start + 1])) { + left = objects[start]; + right = objects[start + 1]; + } else { + left = objects[start + 1]; + right = objects[start]; } + } else { + std::sort(objects.begin() + start, objects.begin() + end, comparator); - aabb box_left, box_right; + auto mid = start + object_span / 2; + left = make_shared(objects, start, mid, time0, time1); + right = make_shared(objects, mid, end, time0, time1); + } - if ( !left->bounding_box (time0, time1, box_left) - || !right->bounding_box(time0, time1, box_right) - ) - std::cerr << "No bounding box in bvh_node constructor.\n"; + aabb box_left, box_right; - box = surrounding_box(box_left, box_right); -} + if (!left->bounding_box(time0, time1, box_left) || + !right->bounding_box(time0, time1, box_right)) + std::cerr << "No bounding box in bvh_node constructor.\n"; + box = surrounding_box(box_left, box_right); +} -bool bvh_node::hit(const ray& r, double t_min, double t_max, hit_record& rec) const { - if (!box.hit(r, t_min, t_max)) - return false; +bool bvh_node::hit(const ray &r, double t_min, double t_max, + hit_record &rec) const { + if (!box.hit(r, t_min, t_max)) + return false; - bool hit_left = left->hit(r, t_min, t_max, rec); - bool hit_right = right->hit(r, t_min, hit_left ? rec.t : t_max, rec); + bool hit_left = left->hit(r, t_min, t_max, rec); + bool hit_right = right->hit(r, t_min, hit_left ? rec.t : t_max, rec); - return hit_left || hit_right; + return hit_left || hit_right; } - -bool bvh_node::bounding_box(double t0, double t1, aabb& output_box) const { - output_box = box; - return true; +bool bvh_node::bounding_box(double t0, double t1, aabb &output_box) const { + output_box = box; + return true; } - #endif diff --git a/src/TheRestOfYourLife/hittable.h b/src/TheRestOfYourLife/hittable.h index aeec5f82..2df8d9a9 100644 --- a/src/TheRestOfYourLife/hittable.h +++ b/src/TheRestOfYourLife/hittable.h @@ -3,200 +3,193 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" #include "aabb.h" - class material; -void get_sphere_uv(const point3& p, double& u, double& v) { - auto phi = atan2(p.z(), p.x()); - auto theta = asin(p.y()); - u = 1-(phi + pi) / (2*pi); - v = (theta + pi/2) / pi; +void get_sphere_uv(const point3 &p, double &u, double &v) { + auto phi = atan2(p.z(), p.x()); + auto theta = asin(p.y()); + u = 1 - (phi + pi) / (2 * pi); + v = (theta + pi / 2) / pi; } - struct hit_record { - point3 p; - vec3 normal; - shared_ptr mat_ptr; - double t; - double u; - double v; - bool front_face; - - inline void set_face_normal(const ray& r, const vec3& outward_normal) { - front_face = dot(r.direction(), outward_normal) < 0; - normal = front_face ? outward_normal :-outward_normal; - } + point3 p; + vec3 normal; + shared_ptr mat_ptr; + double t; + double u; + double v; + bool front_face; + + inline void set_face_normal(const ray &r, const vec3 &outward_normal) { + front_face = dot(r.direction(), outward_normal) < 0; + normal = front_face ? outward_normal : -outward_normal; + } }; - class hittable { - public: - virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const = 0; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const = 0; +public: + virtual bool hit(const ray &r, double t_min, double t_max, + hit_record &rec) const = 0; + virtual bool bounding_box(double t0, double t1, aabb &output_box) const = 0; - virtual double pdf_value(const vec3& o, const vec3& v) const { - return 0.0; - } + virtual double pdf_value(const vec3 &o, const vec3 &v) const { return 0.0; } - virtual vec3 random(const vec3& o) const { - return vec3(1,0,0); - } + virtual vec3 random(const vec3 &o) const { return vec3(1, 0, 0); } }; - class flip_face : public hittable { - public: - flip_face(shared_ptr p) : ptr(p) {} +public: + flip_face(shared_ptr p) : ptr(p) {} - virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const { - if (!ptr->hit(r, t_min, t_max, rec)) - return false; + bool hit(const ray &r, double t_min, double t_max, + hit_record &rec) const override { + if (!ptr->hit(r, t_min, t_max, rec)) + return false; - rec.front_face = !rec.front_face; - return true; - } + rec.front_face = !rec.front_face; + return true; + } - virtual bool bounding_box(double t0, double t1, aabb& output_box) const { - return ptr->bounding_box(t0, t1, output_box); - } + bool bounding_box(double t0, double t1, aabb &output_box) const override { + return ptr->bounding_box(t0, t1, output_box); + } - public: - shared_ptr ptr; +public: + shared_ptr ptr; }; - class translate : public hittable { - public: - translate(shared_ptr p, const vec3& displacement) - : ptr(p), offset(displacement) {} +public: + translate(shared_ptr p, const vec3 &displacement) + : ptr(p), offset(displacement) {} - virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const; + bool hit(const ray &r, double t_min, double t_max, + hit_record &rec) const override; + bool bounding_box(double t0, double t1, aabb &output_box) const override; - public: - shared_ptr ptr; - vec3 offset; +public: + shared_ptr ptr; + vec3 offset; }; +bool translate::hit(const ray &r, double t_min, double t_max, + hit_record &rec) const { + ray moved_r(r.origin() - offset, r.direction(), r.time()); + if (!ptr->hit(moved_r, t_min, t_max, rec)) + return false; -bool translate::hit(const ray& r, double t_min, double t_max, hit_record& rec) const { - ray moved_r(r.origin() - offset, r.direction(), r.time()); - if (!ptr->hit(moved_r, t_min, t_max, rec)) - return false; - - rec.p += offset; - rec.set_face_normal(moved_r, rec.normal); + rec.p += offset; + rec.set_face_normal(moved_r, rec.normal); - return true; + return true; } +bool translate::bounding_box(double t0, double t1, aabb &output_box) const { + if (!ptr->bounding_box(t0, t1, output_box)) + return false; -bool translate::bounding_box(double t0, double t1, aabb& output_box) const { - if (!ptr->bounding_box(t0, t1, output_box)) - return false; + output_box = aabb(output_box.min() + offset, output_box.max() + offset); - output_box = aabb( - output_box.min() + offset, - output_box.max() + offset); - - return true; + return true; } - class rotate_y : public hittable { - public: - rotate_y(shared_ptr p, double angle); +public: + rotate_y(shared_ptr p, double angle); + + bool hit(const ray &r, double t_min, double t_max, + hit_record &rec) const override; + bool bounding_box(double t0, double t1, aabb &output_box) const override { + output_box = bbox; + return hasbox; + } + +public: + shared_ptr ptr; + double sin_theta; + double cos_theta; + bool hasbox; + aabb bbox; +}; - virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const { - output_box = bbox; - return hasbox; - } +rotate_y::rotate_y(shared_ptr p, double angle) : ptr(p) { + auto radians = degrees_to_radians(angle); + sin_theta = sin(radians); + cos_theta = cos(radians); + hasbox = ptr->bounding_box(0, 1, bbox); - public: - shared_ptr ptr; - double sin_theta; - double cos_theta; - bool hasbox; - aabb bbox; -}; + point3 min(infinity, infinity, infinity); + point3 max(-infinity, -infinity, -infinity); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { + auto x = i * bbox.max().x() + (1 - i) * bbox.min().x(); + auto y = j * bbox.max().y() + (1 - j) * bbox.min().y(); + auto z = k * bbox.max().z() + (1 - k) * bbox.min().z(); -rotate_y::rotate_y(shared_ptr p, double angle) : ptr(p) { - auto radians = degrees_to_radians(angle); - sin_theta = sin(radians); - cos_theta = cos(radians); - hasbox = ptr->bounding_box(0, 1, bbox); - - point3 min( infinity, infinity, infinity); - point3 max(-infinity, -infinity, -infinity); - - for (int i = 0; i < 2; i++) { - for (int j = 0; j < 2; j++) { - for (int k = 0; k < 2; k++) { - auto x = i*bbox.max().x() + (1-i)*bbox.min().x(); - auto y = j*bbox.max().y() + (1-j)*bbox.min().y(); - auto z = k*bbox.max().z() + (1-k)*bbox.min().z(); - - auto newx = cos_theta*x + sin_theta*z; - auto newz = -sin_theta*x + cos_theta*z; - - vec3 tester(newx, y, newz); - - for (int c = 0; c < 3; c++) { - min[c] = fmin(min[c], tester[c]); - max[c] = fmax(max[c], tester[c]); - } - } + auto newx = cos_theta * x + sin_theta * z; + auto newz = -sin_theta * x + cos_theta * z; + + vec3 tester(newx, y, newz); + + for (int c = 0; c < 3; c++) { + min[c] = fmin(min[c], tester[c]); + max[c] = fmax(max[c], tester[c]); } + } } + } - bbox = aabb(min, max); + bbox = aabb(min, max); } +bool rotate_y::hit(const ray &r, double t_min, double t_max, + hit_record &rec) const { + auto origin = r.origin(); + auto direction = r.direction(); -bool rotate_y::hit(const ray& r, double t_min, double t_max, hit_record& rec) const { - auto origin = r.origin(); - auto direction = r.direction(); + origin[0] = cos_theta * r.origin()[0] - sin_theta * r.origin()[2]; + origin[2] = sin_theta * r.origin()[0] + cos_theta * r.origin()[2]; - origin[0] = cos_theta*r.origin()[0] - sin_theta*r.origin()[2]; - origin[2] = sin_theta*r.origin()[0] + cos_theta*r.origin()[2]; + direction[0] = cos_theta * r.direction()[0] - sin_theta * r.direction()[2]; + direction[2] = sin_theta * r.direction()[0] + cos_theta * r.direction()[2]; - direction[0] = cos_theta*r.direction()[0] - sin_theta*r.direction()[2]; - direction[2] = sin_theta*r.direction()[0] + cos_theta*r.direction()[2]; + ray rotated_r(origin, direction, r.time()); - ray rotated_r(origin, direction, r.time()); + if (!ptr->hit(rotated_r, t_min, t_max, rec)) + return false; - if (!ptr->hit(rotated_r, t_min, t_max, rec)) - return false; + auto p = rec.p; + auto normal = rec.normal; - auto p = rec.p; - auto normal = rec.normal; + p[0] = cos_theta * rec.p[0] + sin_theta * rec.p[2]; + p[2] = -sin_theta * rec.p[0] + cos_theta * rec.p[2]; - p[0] = cos_theta*rec.p[0] + sin_theta*rec.p[2]; - p[2] = -sin_theta*rec.p[0] + cos_theta*rec.p[2]; + normal[0] = cos_theta * rec.normal[0] + sin_theta * rec.normal[2]; + normal[2] = -sin_theta * rec.normal[0] + cos_theta * rec.normal[2]; - normal[0] = cos_theta*rec.normal[0] + sin_theta*rec.normal[2]; - normal[2] = -sin_theta*rec.normal[0] + cos_theta*rec.normal[2]; + rec.p = p; + rec.set_face_normal(rotated_r, normal); - rec.p = p; - rec.set_face_normal(rotated_r, normal); - - return true; + return true; } - #endif diff --git a/src/TheRestOfYourLife/hittable_list.h b/src/TheRestOfYourLife/hittable_list.h index 68057462..89a46538 100644 --- a/src/TheRestOfYourLife/hittable_list.h +++ b/src/TheRestOfYourLife/hittable_list.h @@ -3,12 +3,16 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" @@ -17,78 +21,75 @@ #include +class hittable_list : public hittable { +public: + hittable_list() {} + hittable_list(shared_ptr object) { add(object); } -class hittable_list: public hittable { - public: - hittable_list() {} - hittable_list(shared_ptr object) { add(object); } + void clear() { objects.clear(); } + void add(shared_ptr object) { objects.push_back(object); } - void clear() { objects.clear(); } - void add(shared_ptr object) { objects.push_back(object); } + bool hit(const ray &r, double tmin, double tmax, + hit_record &rec) const override; + bool bounding_box(double t0, double t1, aabb &output_box) const override; + double pdf_value(const vec3 &o, const vec3 &v) const override; + vec3 random(const vec3 &o) const override; - virtual bool hit(const ray& r, double tmin, double tmax, hit_record& rec) const; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const; - virtual double pdf_value(const vec3 &o, const vec3 &v) const; - virtual vec3 random(const vec3 &o) const; - - public: - std::vector> objects; +public: + std::vector> objects; }; - -bool hittable_list::hit(const ray& r, double t_min, double t_max, hit_record& rec) const { - hit_record temp_rec; - auto hit_anything = false; - auto closest_so_far = t_max; - - for (const auto& object : objects) { - if (object->hit(r, t_min, closest_so_far, temp_rec)) { - hit_anything = true; - closest_so_far = temp_rec.t; - rec = temp_rec; - } +bool hittable_list::hit(const ray &r, double t_min, double t_max, + hit_record &rec) const { + hit_record temp_rec; + auto hit_anything = false; + auto closest_so_far = t_max; + + for (const auto &object : objects) { + if (object->hit(r, t_min, closest_so_far, temp_rec)) { + hit_anything = true; + closest_so_far = temp_rec.t; + rec = temp_rec; } + } - return hit_anything; + return hit_anything; } +bool hittable_list::bounding_box(double t0, double t1, aabb &output_box) const { + if (objects.empty()) + return false; -bool hittable_list::bounding_box(double t0, double t1, aabb& output_box) const { - if (objects.empty()) return false; - - aabb temp_box; - bool first_true = objects[0]->bounding_box(t0, t1, temp_box); + aabb temp_box; + bool first_true = objects[0]->bounding_box(t0, t1, temp_box); - if (!first_true) - return false; + if (!first_true) + return false; - output_box = temp_box; + output_box = temp_box; - for (const auto& object : objects) { - if (!object->bounding_box(t0, t1, temp_box)) - return false; - output_box = surrounding_box(output_box, temp_box); - } + for (const auto &object : objects) { + if (!object->bounding_box(t0, t1, temp_box)) + return false; + output_box = surrounding_box(output_box, temp_box); + } - return true; + return true; } +double hittable_list::pdf_value(const point3 &o, const vec3 &v) const { + auto weight = 1.0 / objects.size(); + auto sum = 0.0; -double hittable_list::pdf_value(const point3& o, const vec3& v) const { - auto weight = 1.0/objects.size(); - auto sum = 0.0; - - for (const auto& object : objects) - sum += weight * object->pdf_value(o, v); + for (const auto &object : objects) + sum += weight * object->pdf_value(o, v); - return sum; + return sum; } - vec3 hittable_list::random(const vec3 &o) const { - auto int_size = static_cast(objects.size()); - return objects[random_int(0, int_size-1)]->random(o); + auto int_size = static_cast(objects.size()); + return objects[random_int(0, int_size - 1)]->random(o); } - #endif diff --git a/src/TheRestOfYourLife/main.cc b/src/TheRestOfYourLife/main.cc index 93be1c24..76b2cb03 100644 --- a/src/TheRestOfYourLife/main.cc +++ b/src/TheRestOfYourLife/main.cc @@ -1,12 +1,16 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" @@ -21,126 +25,125 @@ #include +color ray_color(const ray &r, const color &background, const hittable &world, + shared_ptr lights, int depth) { + hit_record rec; -color ray_color( - const ray& r, - const color& background, - const hittable& world, - shared_ptr lights, - int depth -) { - hit_record rec; + // If we've exceeded the ray bounce limit, no more light is gathered. + if (depth <= 0) + return color(0, 0, 0); - // If we've exceeded the ray bounce limit, no more light is gathered. - if (depth <= 0) - return color(0,0,0); + // If the ray hits nothing, return the background color. + if (!world.hit(r, 0.001, infinity, rec)) + return background; - // If the ray hits nothing, return the background color. - if (!world.hit(r, 0.001, infinity, rec)) - return background; + scatter_record srec; + color emitted = rec.mat_ptr->emitted(r, rec, rec.u, rec.v, rec.p); - scatter_record srec; - color emitted = rec.mat_ptr->emitted(r, rec, rec.u, rec.v, rec.p); + if (!rec.mat_ptr->scatter(r, rec, srec)) + return emitted; - if (!rec.mat_ptr->scatter(r, rec, srec)) - return emitted; + if (srec.is_specular) { + return srec.attenuation * + ray_color(srec.specular_ray, background, world, lights, depth - 1); + } - if (srec.is_specular) { - return srec.attenuation - * ray_color(srec.specular_ray, background, world, lights, depth-1); - } - - auto light_ptr = make_shared(lights, rec.p); - mixture_pdf p(light_ptr, srec.pdf_ptr); - ray scattered = ray(rec.p, p.generate(), r.time()); - auto pdf_val = p.value(scattered.direction()); + auto light_ptr = make_shared(lights, rec.p); + mixture_pdf p(light_ptr, srec.pdf_ptr); + ray scattered = ray(rec.p, p.generate(), r.time()); + auto pdf_val = p.value(scattered.direction()); - return emitted - + srec.attenuation * rec.mat_ptr->scattering_pdf(r, rec, scattered) - * ray_color(scattered, background, world, lights, depth-1) - / pdf_val; + return emitted + + srec.attenuation * rec.mat_ptr->scattering_pdf(r, rec, scattered) * + ray_color(scattered, background, world, lights, depth - 1) / + pdf_val; } - -hittable_list cornell_box(camera& cam, double aspect) { - hittable_list world; - - auto red = make_shared(color(.65, .05, .05)); - auto white = make_shared(color(.73, .73, .73)); - auto green = make_shared(color(.12, .45, .15)); - auto light = make_shared(color(15, 15, 15)); - - world.add(make_shared(make_shared(0, 555, 0, 555, 555, green))); - world.add(make_shared(0, 555, 0, 555, 0, red)); - world.add(make_shared(make_shared(213, 343, 227, 332, 554, light))); - world.add(make_shared(make_shared(0, 555, 0, 555, 555, white))); - world.add(make_shared(0, 555, 0, 555, 0, white)); - world.add(make_shared(make_shared(0, 555, 0, 555, 555, white))); - - shared_ptr box1 = make_shared(point3(0,0,0), point3(165,330,165), white); - box1 = make_shared(box1, 15); - box1 = make_shared(box1, vec3(265,0,295)); - world.add(box1); - - auto glass = make_shared(1.5); - world.add(make_shared(point3(190,90,190), 90 , glass)); - - point3 lookfrom(278, 278, -800); - point3 lookat(278, 278, 0); - vec3 up(0, 1, 0); - auto dist_to_focus = 10.0; - auto aperture = 0.0; - auto vfov = 40.0; - auto t0 = 0.0; - auto t1 = 1.0; - - cam = camera(lookfrom, lookat, up, vfov, aspect, aperture, dist_to_focus, t0, t1); - - return world; +hittable_list cornell_box(camera &cam, double aspect) { + hittable_list world; + + auto red = make_shared(color(.65, .05, .05)); + auto white = make_shared(color(.73, .73, .73)); + auto green = make_shared(color(.12, .45, .15)); + auto light = make_shared(color(15, 15, 15)); + + world.add( + make_shared(make_shared(0, 555, 0, 555, 555, green))); + world.add(make_shared(0, 555, 0, 555, 0, red)); + world.add(make_shared( + make_shared(213, 343, 227, 332, 554, light))); + world.add( + make_shared(make_shared(0, 555, 0, 555, 555, white))); + world.add(make_shared(0, 555, 0, 555, 0, white)); + world.add( + make_shared(make_shared(0, 555, 0, 555, 555, white))); + + shared_ptr box1 = + make_shared(point3(0, 0, 0), point3(165, 330, 165), white); + box1 = make_shared(box1, 15); + box1 = make_shared(box1, vec3(265, 0, 295)); + world.add(box1); + + auto glass = make_shared(1.5); + world.add(make_shared(point3(190, 90, 190), 90, glass)); + + point3 lookfrom(278, 278, -800); + point3 lookat(278, 278, 0); + vec3 up(0, 1, 0); + auto dist_to_focus = 10.0; + auto aperture = 0.0; + auto vfov = 40.0; + auto t0 = 0.0; + auto t1 = 1.0; + + cam = camera(lookfrom, lookat, up, vfov, aspect, aperture, dist_to_focus, t0, + t1); + + return world; } - int main() { - // Image - - const auto aspect_ratio = 1.0 / 1.0; - const int image_width = 600; - const int image_height = static_cast(image_width / aspect_ratio); - const int samples_per_pixel = 100; - const int max_depth = 50; + // Image - // World + const auto aspect_ratio = 1.0 / 1.0; + const int image_width = 600; + const int image_height = static_cast(image_width / aspect_ratio); + const int samples_per_pixel = 100; + const int max_depth = 50; - auto lights = make_shared(); - lights->add(make_shared(213, 343, 227, 332, 554, shared_ptr())); - lights->add(make_shared(point3(190, 90, 190), 90, shared_ptr())); + // Camera + camera cam; - auto world = cornell_box(cam, aspect_ratio); + // World - // Camera + auto lights = make_shared(); + lights->add( + make_shared(213, 343, 227, 332, 554, shared_ptr())); + lights->add( + make_shared(point3(190, 90, 190), 90, shared_ptr())); - color background(0,0,0); + auto world = cornell_box(cam, aspect_ratio); - camera cam; + color background(0, 0, 0); - // Render + // Render - std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n"; + std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n"; - for (int j = image_height-1; j >= 0; --j) { - std::cerr << "\rScanlines remaining: " << j << ' ' << std::flush; - for (int i = 0; i < image_width; ++i) { - color pixel_color(0,0,0); - for (int s = 0; s < samples_per_pixel; ++s) { - auto u = (i + random_double()) / (image_width-1); - auto v = (j + random_double()) / (image_height-1); - ray r = cam.get_ray(u, v); - pixel_color += ray_color(r, background, world, lights, max_depth); - } - write_color(std::cout, pixel_color, samples_per_pixel); - } + for (int j = image_height - 1; j >= 0; --j) { + std::cerr << "\rScanlines remaining: " << j << ' ' << std::flush; + for (int i = 0; i < image_width; ++i) { + color pixel_color(0, 0, 0); + for (int s = 0; s < samples_per_pixel; ++s) { + auto u = (i + random_double()) / (image_width - 1); + auto v = (j + random_double()) / (image_height - 1); + ray r = cam.get_ray(u, v); + pixel_color += ray_color(r, background, world, lights, max_depth); + } + write_color(std::cout, pixel_color, samples_per_pixel); } + } - std::cerr << "\nDone.\n"; + std::cerr << "\nDone.\n"; } diff --git a/src/TheRestOfYourLife/material.h b/src/TheRestOfYourLife/material.h index 262865a4..ebe45d40 100644 --- a/src/TheRestOfYourLife/material.h +++ b/src/TheRestOfYourLife/material.h @@ -3,12 +3,16 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" @@ -16,159 +20,140 @@ #include "pdf.h" #include "texture.h" - double schlick(double cosine, double ref_idx) { - auto r0 = (1-ref_idx) / (1+ref_idx); - r0 = r0*r0; - return r0 + (1-r0)*pow((1 - cosine),5); + auto r0 = (1 - ref_idx) / (1 + ref_idx); + r0 = r0 * r0; + return r0 + (1 - r0) * pow((1 - cosine), 5); } - struct scatter_record { - ray specular_ray; - bool is_specular; - color attenuation; - shared_ptr pdf_ptr; + ray specular_ray; + bool is_specular; + color attenuation; + shared_ptr pdf_ptr; }; - class material { - public: - virtual color emitted( - const ray& r_in, const hit_record& rec, double u, double v, const point3& p - ) const { - return color(0,0,0); - } - - virtual bool scatter( - const ray& r_in, const hit_record& rec, scatter_record& srec - ) const { - return false; - } - - virtual double scattering_pdf( - const ray& r_in, const hit_record& rec, const ray& scattered - ) const { - return 0; - } +public: + virtual color emitted(const ray &r_in, const hit_record &rec, double u, + double v, const point3 &p) const { + return color(0, 0, 0); + } + + virtual bool scatter(const ray &r_in, const hit_record &rec, + scatter_record &srec) const { + return false; + } + + virtual double scattering_pdf(const ray &r_in, const hit_record &rec, + const ray &scattered) const { + return 0; + } }; - class lambertian : public material { - public: - lambertian(const color& a) : albedo(make_shared(a)) {} - lambertian(shared_ptr a) : albedo(a) {} - - virtual bool scatter( - const ray& r_in, const hit_record& rec, scatter_record& srec - ) const { - srec.is_specular = false; - srec.attenuation = albedo->value(rec.u, rec.v, rec.p); - srec.pdf_ptr = make_shared(rec.normal); - return true; - } - - double scattering_pdf( - const ray& r_in, const hit_record& rec, const ray& scattered - ) const { - auto cosine = dot(rec.normal, unit_vector(scattered.direction())); - return cosine < 0 ? 0 : cosine/pi; - } - - public: - shared_ptr albedo; +public: + lambertian(const color &a) : albedo(make_shared(a)) {} + lambertian(shared_ptr a) : albedo(a) {} + + bool scatter(const ray &r_in, const hit_record &rec, + scatter_record &srec) const override { + srec.is_specular = false; + srec.attenuation = albedo->value(rec.u, rec.v, rec.p); + srec.pdf_ptr = make_shared(rec.normal); + return true; + } + + double scattering_pdf(const ray &r_in, const hit_record &rec, + const ray &scattered) const override { + auto cosine = dot(rec.normal, unit_vector(scattered.direction())); + return cosine < 0 ? 0 : cosine / pi; + } + +public: + shared_ptr albedo; }; - class metal : public material { - public: - metal(const color& a, double f) : albedo(a), fuzz(f < 1 ? f : 1) {} - - virtual bool scatter( - const ray& r_in, const hit_record& rec, scatter_record& srec - ) const { - vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal); - srec.specular_ray = - ray(rec.p, reflected + fuzz*random_in_unit_sphere(), r_in.time()); - srec.attenuation = albedo; - srec.is_specular = true; - srec.pdf_ptr = nullptr; - return true; - } - - public: - color albedo; - double fuzz; +public: + metal(const color &a, double f) : albedo(a), fuzz(f < 1 ? f : 1) {} + + bool scatter(const ray &r_in, const hit_record &rec, + scatter_record &srec) const override { + vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal); + srec.specular_ray = + ray(rec.p, reflected + fuzz * random_in_unit_sphere(), r_in.time()); + srec.attenuation = albedo; + srec.is_specular = true; + srec.pdf_ptr = nullptr; + return true; + } + +public: + color albedo; + double fuzz; }; - class dielectric : public material { - public: - dielectric(double ri) : ref_idx(ri) {} - - virtual bool scatter( - const ray& r_in, const hit_record& rec, scatter_record& srec - ) const { - srec.is_specular = true; - srec.pdf_ptr = nullptr; - srec.attenuation = color(1.0, 1.0, 1.0); - double etai_over_etat = (rec.front_face) ? (1.0 / ref_idx) : ref_idx; - - vec3 unit_direction = unit_vector(r_in.direction()); - double cos_theta = fmin(dot(-unit_direction, rec.normal), 1.0); - double sin_theta = sqrt(1.0 - cos_theta*cos_theta); - - if ( (etai_over_etat * sin_theta > 1.0) - || (random_double() < schlick(cos_theta, etai_over_etat)) - ) { - vec3 reflected = reflect(unit_direction, rec.normal); - srec.specular_ray = ray(rec.p, reflected, r_in.time()); - return true; - } - - vec3 refracted = refract(unit_direction, rec.normal, etai_over_etat); - srec.specular_ray = ray(rec.p, refracted, r_in.time()); - return true; - } - - public: - double ref_idx; +public: + dielectric(double ri) : ref_idx(ri) {} + + bool scatter(const ray &r_in, const hit_record &rec, + scatter_record &srec) const override { + srec.is_specular = true; + srec.pdf_ptr = nullptr; + srec.attenuation = color(1.0, 1.0, 1.0); + double etai_over_etat = (rec.front_face) ? (1.0 / ref_idx) : ref_idx; + + vec3 unit_direction = unit_vector(r_in.direction()); + double cos_theta = fmin(dot(-unit_direction, rec.normal), 1.0); + double sin_theta = sqrt(1.0 - cos_theta * cos_theta); + + if ((etai_over_etat * sin_theta > 1.0) || + (random_double() < schlick(cos_theta, etai_over_etat))) { + vec3 reflected = reflect(unit_direction, rec.normal); + srec.specular_ray = ray(rec.p, reflected, r_in.time()); + return true; + } + + vec3 refracted = refract(unit_direction, rec.normal, etai_over_etat); + srec.specular_ray = ray(rec.p, refracted, r_in.time()); + return true; + } + +public: + double ref_idx; }; - class diffuse_light : public material { - public: - diffuse_light(shared_ptr a) : emit(a) {} - diffuse_light(color c) : emit(make_shared(c)) {} - - virtual color emitted( - const ray& r_in, const hit_record& rec, double u, double v, const point3& p - ) const { - if (!rec.front_face) - return color(0,0,0); - return emit->value(u, v, p); - } - - public: - shared_ptr emit; +public: + diffuse_light(shared_ptr a) : emit(a) {} + diffuse_light(color c) : emit(make_shared(c)) {} + + color emitted(const ray &r_in, const hit_record &rec, double u, double v, + const point3 &p) const override { + if (!rec.front_face) + return color(0, 0, 0); + return emit->value(u, v, p); + } + +public: + shared_ptr emit; }; - class isotropic : public material { - public: - isotropic(shared_ptr a) : albedo(a) {} - - virtual bool scatter( - const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered - ) const { - scattered = ray(rec.p, random_in_unit_sphere(), r_in.time()); - attenuation = albedo->value(rec.u, rec.v, rec.p); - return true; - } - - public: - shared_ptr albedo; +public: + isotropic(shared_ptr a) : albedo(a) {} + + bool scatter(const ray &r_in, const hit_record &rec, color &attenuation, + ray &scattered) const { + scattered = ray(rec.p, random_in_unit_sphere(), r_in.time()); + attenuation = albedo->value(rec.u, rec.v, rec.p); + return true; + } + +public: + shared_ptr albedo; }; - #endif diff --git a/src/TheRestOfYourLife/pdf.h b/src/TheRestOfYourLife/pdf.h index d673a65e..48dd2bc4 100644 --- a/src/TheRestOfYourLife/pdf.h +++ b/src/TheRestOfYourLife/pdf.h @@ -3,111 +3,107 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" #include "onb.h" - inline vec3 random_cosine_direction() { - auto r1 = random_double(); - auto r2 = random_double(); - auto z = sqrt(1-r2); + auto r1 = random_double(); + auto r2 = random_double(); + auto z = sqrt(1 - r2); - auto phi = 2*pi*r1; - auto x = cos(phi)*sqrt(r2); - auto y = sin(phi)*sqrt(r2); + auto phi = 2 * pi * r1; + auto x = cos(phi) * sqrt(r2); + auto y = sin(phi) * sqrt(r2); - return vec3(x, y, z); + return vec3(x, y, z); } - inline vec3 random_to_sphere(double radius, double distance_squared) { - auto r1 = random_double(); - auto r2 = random_double(); - auto z = 1 + r2*(sqrt(1-radius*radius/distance_squared) - 1); + auto r1 = random_double(); + auto r2 = random_double(); + auto z = 1 + r2 * (sqrt(1 - radius * radius / distance_squared) - 1); - auto phi = 2*pi*r1; - auto x = cos(phi)*sqrt(1-z*z); - auto y = sin(phi)*sqrt(1-z*z); + auto phi = 2 * pi * r1; + auto x = cos(phi) * sqrt(1 - z * z); + auto y = sin(phi) * sqrt(1 - z * z); - return vec3(x, y, z); + return vec3(x, y, z); } +class pdf { +public: + virtual ~pdf() {} -class pdf { - public: - virtual ~pdf() {} - - virtual double value(const vec3& direction) const = 0; - virtual vec3 generate() const = 0; + virtual double value(const vec3 &direction) const = 0; + virtual vec3 generate() const = 0; }; - class cosine_pdf : public pdf { - public: - cosine_pdf(const vec3& w) { uvw.build_from_w(w); } +public: + cosine_pdf(const vec3 &w) { uvw.build_from_w(w); } - virtual double value(const vec3& direction) const { - auto cosine = dot(unit_vector(direction), uvw.w()); - return (cosine <= 0) ? 0 : cosine/pi; - } + double value(const vec3 &direction) const override { + auto cosine = dot(unit_vector(direction), uvw.w()); + return (cosine <= 0) ? 0 : cosine / pi; + } - virtual vec3 generate() const { - return uvw.local(random_cosine_direction()); - } + vec3 generate() const override { + return uvw.local(random_cosine_direction()); + } - public: - onb uvw; +public: + onb uvw; }; - class hittable_pdf : public pdf { - public: - hittable_pdf(shared_ptr p, const point3& origin) : ptr(p), o(origin) {} +public: + hittable_pdf(shared_ptr p, const point3 &origin) + : ptr(p), o(origin) {} - virtual double value(const vec3& direction) const { - return ptr->pdf_value(o, direction); - } + double value(const vec3 &direction) const override { + return ptr->pdf_value(o, direction); + } - virtual vec3 generate() const { - return ptr->random(o); - } + vec3 generate() const override { return ptr->random(o); } - public: - point3 o; - shared_ptr ptr; +public: + point3 o; + shared_ptr ptr; }; - class mixture_pdf : public pdf { - public: - mixture_pdf(shared_ptr p0, shared_ptr p1) { - p[0] = p0; - p[1] = p1; - } - - virtual double value(const vec3& direction) const { - return 0.5 * p[0]->value(direction) + 0.5 *p[1]->value(direction); - } - - virtual vec3 generate() const { - if (random_double() < 0.5) - return p[0]->generate(); - else - return p[1]->generate(); - } - - public: - shared_ptr p[2]; +public: + mixture_pdf(shared_ptr p0, shared_ptr p1) { + p[0] = p0; + p[1] = p1; + } + + double value(const vec3 &direction) const override { + return 0.5 * p[0]->value(direction) + 0.5 * p[1]->value(direction); + } + + vec3 generate() const override { + if (random_double() < 0.5) + return p[0]->generate(); + else + return p[1]->generate(); + } + +public: + shared_ptr p[2]; }; - #endif diff --git a/src/TheRestOfYourLife/sphere.h b/src/TheRestOfYourLife/sphere.h index 79da458e..f46c6213 100644 --- a/src/TheRestOfYourLife/sphere.h +++ b/src/TheRestOfYourLife/sphere.h @@ -3,12 +3,16 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" @@ -16,86 +20,85 @@ #include "hittable.h" #include "onb.h" - -class sphere: public hittable { - public: - sphere() {} - sphere(point3 cen, double r, shared_ptr m) - : center(cen), radius(r), mat_ptr(m) {}; - virtual bool hit(const ray& r, double tmin, double tmax, hit_record& rec) const; - virtual bool bounding_box(double t0, double t1, aabb& output_box) const; - virtual double pdf_value(const point3& o, const vec3& v) const; - virtual vec3 random(const point3& o) const; - - public: - point3 center; - double radius; - shared_ptr mat_ptr; +class sphere : public hittable { +public: + sphere() {} + sphere(point3 cen, double r, shared_ptr m) + : center(cen), radius(r), mat_ptr(m){}; + bool hit(const ray &r, double tmin, double tmax, + hit_record &rec) const override; + bool bounding_box(double t0, double t1, aabb &output_box) const override; + double pdf_value(const point3 &o, const vec3 &v) const override; + vec3 random(const point3 &o) const override; + +public: + point3 center; + double radius; + shared_ptr mat_ptr; }; -double sphere::pdf_value(const point3& o, const vec3& v) const { - hit_record rec; - if (!this->hit(ray(o, v), 0.001, infinity, rec)) - return 0; +double sphere::pdf_value(const point3 &o, const vec3 &v) const { + hit_record rec; + if (!this->hit(ray(o, v), 0.001, infinity, rec)) + return 0; - auto cos_theta_max = sqrt(1 - radius*radius/(center-o).length_squared()); - auto solid_angle = 2*pi*(1-cos_theta_max); + auto cos_theta_max = + sqrt(1 - radius * radius / (center - o).length_squared()); + auto solid_angle = 2 * pi * (1 - cos_theta_max); - return 1 / solid_angle; + return 1 / solid_angle; } -vec3 sphere::random(const point3& o) const { - vec3 direction = center - o; - auto distance_squared = direction.length_squared(); - onb uvw; - uvw.build_from_w(direction); - return uvw.local(random_to_sphere(radius, distance_squared)); +vec3 sphere::random(const point3 &o) const { + vec3 direction = center - o; + auto distance_squared = direction.length_squared(); + onb uvw; + uvw.build_from_w(direction); + return uvw.local(random_to_sphere(radius, distance_squared)); } - -bool sphere::bounding_box(double t0, double t1, aabb& output_box) const { - output_box = aabb( - center - vec3(radius, radius, radius), - center + vec3(radius, radius, radius)); - return true; +bool sphere::bounding_box(double t0, double t1, aabb &output_box) const { + output_box = aabb(center - vec3(radius, radius, radius), + center + vec3(radius, radius, radius)); + return true; } -bool sphere::hit(const ray& r, double t_min, double t_max, hit_record& rec) const { - 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) { - auto root = sqrt(discriminant); - - auto temp = (-half_b - root) / a; - if (temp < t_max && temp > t_min) { - rec.t = temp; - rec.p = r.at(rec.t); - vec3 outward_normal = (rec.p - center) / radius; - rec.set_face_normal(r, outward_normal); - get_sphere_uv((rec.p-center)/radius, rec.u, rec.v); - rec.mat_ptr = mat_ptr; - return true; - } - - temp = (-half_b + root) / a; - if (temp < t_max && temp > t_min) { - rec.t = temp; - rec.p = r.at(rec.t); - vec3 outward_normal = (rec.p - center) / radius; - rec.set_face_normal(r, outward_normal); - get_sphere_uv((rec.p-center)/radius, rec.u, rec.v); - rec.mat_ptr = mat_ptr; - return true; - } +bool sphere::hit(const ray &r, double t_min, double t_max, + hit_record &rec) const { + 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) { + auto root = sqrt(discriminant); + + auto temp = (-half_b - root) / a; + if (temp < t_max && temp > t_min) { + rec.t = temp; + rec.p = r.at(rec.t); + vec3 outward_normal = (rec.p - center) / radius; + rec.set_face_normal(r, outward_normal); + get_sphere_uv((rec.p - center) / radius, rec.u, rec.v); + rec.mat_ptr = mat_ptr; + return true; } - return false; -} + temp = (-half_b + root) / a; + if (temp < t_max && temp > t_min) { + rec.t = temp; + rec.p = r.at(rec.t); + vec3 outward_normal = (rec.p - center) / radius; + rec.set_face_normal(r, outward_normal); + get_sphere_uv((rec.p - center) / radius, rec.u, rec.v); + rec.mat_ptr = mat_ptr; + return true; + } + } + return false; +} #endif diff --git a/src/common/texture.h b/src/common/texture.h index e4973afd..eaefa352 100644 --- a/src/common/texture.h +++ b/src/common/texture.h @@ -3,12 +3,16 @@ //============================================================================================== // Originally written in 2016 by Peter Shirley // -// 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 +// 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 . +// You should have received a copy (see file COPYING.txt) of the CC0 Public +// Domain Dedication +// along with this software. If not, see +// . //============================================================================================== #include "rtweekend.h" @@ -18,123 +22,118 @@ #include - -class texture { - public: - virtual color value(double u, double v, const vec3& p) const = 0; +class texture { +public: + virtual color value(double u, double v, const vec3 &p) const = 0; }; - class solid_color : public texture { - public: - solid_color() {} - solid_color(color c) : color_value(c) {} +public: + solid_color() {} + solid_color(color c) : color_value(c) {} - solid_color(double red, double green, double blue) - : solid_color(color(red,green,blue)) {} + solid_color(double red, double green, double blue) + : solid_color(color(red, green, blue)) {} - virtual color value(double u, double v, const vec3& p) const { - return color_value; - } + color value(double u, double v, const vec3 &p) const override { + return color_value; + } - private: - color color_value; +private: + color color_value; }; - class checker_texture : public texture { - public: - checker_texture() {} - - checker_texture(shared_ptr t0, shared_ptr t1) - : even(t0), odd(t1) {} - - checker_texture(color c1, color c2) - : even(make_shared(c1)) , odd(make_shared(c2)) {} - - virtual color value(double u, double v, const vec3& p) const { - auto sines = sin(10*p.x())*sin(10*p.y())*sin(10*p.z()); - if (sines < 0) - return odd->value(u, v, p); - else - return even->value(u, v, p); - } - - public: - shared_ptr odd; - shared_ptr even; +public: + checker_texture() {} + + checker_texture(shared_ptr t0, shared_ptr t1) + : even(t0), odd(t1) {} + + checker_texture(color c1, color c2) + : even(make_shared(c1)), odd(make_shared(c2)) {} + + color value(double u, double v, const vec3 &p) const override { + auto sines = sin(10 * p.x()) * sin(10 * p.y()) * sin(10 * p.z()); + if (sines < 0) + return odd->value(u, v, p); + else + return even->value(u, v, p); + } + +public: + shared_ptr odd; + shared_ptr even; }; - class noise_texture : public texture { - public: - noise_texture() {} - noise_texture(double sc) : scale(sc) {} - - virtual color value(double u, double v, const vec3& p) const { - // return color(1,1,1)*0.5*(1 + noise.turb(scale * p)); - // return color(1,1,1)*noise.turb(scale * p); - return color(1,1,1)*0.5*(1 + sin(scale*p.z() + 10*noise.turb(p))); - } - - public: - perlin noise; - double scale; +public: + noise_texture() {} + noise_texture(double sc) : scale(sc) {} + + color value(double u, double v, const vec3 &p) const override { + // return color(1,1,1)*0.5*(1 + noise.turb(scale * p)); + // return color(1,1,1)*noise.turb(scale * p); + return color(1, 1, 1) * 0.5 * (1 + sin(scale * p.z() + 10 * noise.turb(p))); + } + +public: + perlin noise; + double scale; }; - class image_texture : public texture { - public: - const static int bytes_per_pixel = 3; +public: + const static int bytes_per_pixel = 3; - image_texture() - : data(nullptr), width(0), height(0), bytes_per_scanline(0) {} + image_texture() : data(nullptr), width(0), height(0), bytes_per_scanline(0) {} - image_texture(const char* filename) { - auto components_per_pixel = bytes_per_pixel; + image_texture(const char *filename) { + auto components_per_pixel = bytes_per_pixel; - data = stbi_load( - filename, &width, &height, &components_per_pixel, components_per_pixel); + data = stbi_load(filename, &width, &height, &components_per_pixel, + components_per_pixel); - if (!data) { - std::cerr << "ERROR: Could not load texture image file '" << filename << "'.\n"; - width = height = 0; - } + if (!data) { + std::cerr << "ERROR: Could not load texture image file '" << filename + << "'.\n"; + width = height = 0; + } - bytes_per_scanline = bytes_per_pixel * width; - } + bytes_per_scanline = bytes_per_pixel * width; + } - ~image_texture() { - delete data; - } + ~image_texture() { delete data; } - virtual color value(double u, double v, const vec3& p) const { - // If we have no texture data, then return solid cyan as a debugging aid. - if (data == nullptr) - return color(0,1,1); + color value(double u, double v, const vec3 &p) const override { + // If we have no texture data, then return solid cyan as a debugging aid. + if (data == nullptr) + return color(0, 1, 1); - // Clamp input texture coordinates to [0,1] x [1,0] - u = clamp(u, 0.0, 1.0); - v = 1.0 - clamp(v, 0.0, 1.0); // Flip V to image coordinates + // Clamp input texture coordinates to [0,1] x [1,0] + u = clamp(u, 0.0, 1.0); + v = 1.0 - clamp(v, 0.0, 1.0); // Flip V to image coordinates - auto i = static_cast(u * width); - auto j = static_cast(v * height); + auto i = static_cast(u * width); + auto j = static_cast(v * height); - // Clamp integer mapping, since actual coordinates should be less than 1.0 - if (i >= width) i = width-1; - if (j >= height) j = height-1; + // Clamp integer mapping, since actual coordinates should be less than 1.0 + if (i >= width) + i = width - 1; + if (j >= height) + j = height - 1; - const auto color_scale = 1.0 / 255.0; - auto pixel = data + j*bytes_per_scanline + i*bytes_per_pixel; + const auto color_scale = 1.0 / 255.0; + auto pixel = data + j * bytes_per_scanline + i * bytes_per_pixel; - return color(color_scale*pixel[0], color_scale*pixel[1], color_scale*pixel[2]); - } + return color(color_scale * pixel[0], color_scale * pixel[1], + color_scale * pixel[2]); + } - private: - unsigned char *data; - int width, height; - int bytes_per_scanline; +private: + unsigned char *data; + int width, height; + int bytes_per_scanline; }; - #endif