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