From 5bbfb1768481f41743925cce1f66394ff2bb41b5 Mon Sep 17 00:00:00 2001 From: zongor Date: Thu, 24 Jul 2025 14:55:28 -0400 Subject: [PATCH] add interval --- src/camera.h | 2 +- src/common.h | 19 +++++++++++++--- src/hittable.h | 14 ++++++------ src/hittable_list.h | 7 +++--- src/interval.h | 22 ++++++++++++++++++ src/sphere.h | 55 +++++++++++++++++++++++---------------------- 6 files changed, 77 insertions(+), 42 deletions(-) create mode 100644 src/interval.h diff --git a/src/camera.h b/src/camera.h index cde4b3d..2767505 100644 --- a/src/camera.h +++ b/src/camera.h @@ -62,7 +62,7 @@ private: Color ray_color(const Ray &r, const hittable &world) { hit_record rec; - if (world.hit(r, 0, infinity, rec)) { + if (world.hit(r, interval(0, infinity), rec)) { return 0.5 * (rec.normal + Color(1, 1, 1)); } diff --git a/src/common.h b/src/common.h index ae54b29..2c09b74 100644 --- a/src/common.h +++ b/src/common.h @@ -2,10 +2,11 @@ #define RTWEEKEND_H #include +#include #include #include #include - +#include // C++ Std Usings @@ -20,13 +21,25 @@ const double pi = 3.1415926535897932385; // Utility Functions inline double degrees_to_radians(double degrees) { - return degrees * pi / 180.0; + return degrees * pi / 180.0; +} + +inline double random_double() { + static std::uniform_real_distribution distribution(0.0, 1.0); + static std::mt19937 generator; + return distribution(generator); +} + +inline double random_double(double min, double max) { + // Returns a random real in [min,max). + return min + (max - min) * random_double(); } // Common Headers +#include "canvas.h" +#include "interval.h" #include "ray.h" #include "vec3.h" -#include "canvas.h" #endif diff --git a/src/hittable.h b/src/hittable.h index 88516d7..8420feb 100644 --- a/src/hittable.h +++ b/src/hittable.h @@ -4,17 +4,17 @@ #include "ray.h" class hit_record { - public: - Point3 p; - Vec3 normal; - double t; +public: + Point3 p; + Vec3 normal; + double t; }; class hittable { - public: - virtual ~hittable() = default; +public: + virtual ~hittable() = default; - virtual bool hit(const Ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const = 0; + virtual bool hit(const Ray &r, interval ray_t, hit_record &rec) const = 0; }; #endif diff --git a/src/hittable_list.h b/src/hittable_list.h index a4a202e..c4047d1 100644 --- a/src/hittable_list.h +++ b/src/hittable_list.h @@ -20,14 +20,13 @@ public: void add(shared_ptr object) { objects.push_back(object); } - bool hit(const Ray &r, double ray_tmin, double ray_tmax, - hit_record &rec) const override { + bool hit(const Ray &r, interval ray_t, hit_record &rec) const override { hit_record temp_rec; bool hit_anything = false; - auto closest_so_far = ray_tmax; + auto closest_so_far = ray_t.max; for (const auto &object : objects) { - if (object->hit(r, ray_tmin, closest_so_far, temp_rec)) { + if (object->hit(r, interval(ray_t.min, closest_so_far), temp_rec)) { hit_anything = true; closest_so_far = temp_rec.t; rec = temp_rec; diff --git a/src/interval.h b/src/interval.h new file mode 100644 index 0000000..452d254 --- /dev/null +++ b/src/interval.h @@ -0,0 +1,22 @@ +#ifndef INTERVAL_H +#define INTERVAL_H + +class interval { +public: + double min, max; + + interval() : min(+infinity), max(-infinity) {} // Default interval is empty + + interval(double min, double max) : min(min), max(max) {} + + double size() const { return max - min; } + + bool contains(double x) const { return min <= x && x <= max; } + + bool surrounds(double x) const { return min < x && x < max; } +}; + +static inline const interval empty = interval(+infinity, -infinity); +static inline const interval universe = interval(-infinity, +infinity); + +#endif diff --git a/src/sphere.h b/src/sphere.h index 28865c8..6083e28 100644 --- a/src/sphere.h +++ b/src/sphere.h @@ -5,39 +5,40 @@ #include "vec3.h" class sphere : public hittable { - public: - sphere(const Point3& center, double radius) : center(center), radius(std::fmax(0,radius)) {} +public: + sphere(const Point3 ¢er, double radius) + : center(center), radius(std::fmax(0, radius)) {} - bool hit(const Ray& r, double ray_tmin, double ray_tmax, hit_record& rec) const override { - Vec3 oc = center - r.origin(); - auto a = r.direction().length_squared(); - auto h = dot(r.direction(), oc); - auto c = oc.length_squared() - radius*radius; + bool hit(const Ray &r, interval ray_t, hit_record &rec) const override { + Vec3 oc = center - r.origin(); + auto a = r.direction().length_squared(); + auto h = dot(r.direction(), oc); + auto c = oc.length_squared() - radius * radius; - auto discriminant = h*h - a*c; - if (discriminant < 0) - return false; + auto discriminant = h * h - a * c; + if (discriminant < 0) + return false; - auto sqrtd = std::sqrt(discriminant); + auto sqrtd = std::sqrt(discriminant); - // Find the nearest root that lies in the acceptable range. - auto root = (h - sqrtd) / a; - if (root <= ray_tmin || ray_tmax <= root) { - root = (h + sqrtd) / a; - if (root <= ray_tmin || ray_tmax <= root) - return false; - } - - rec.t = root; - rec.p = r.at(rec.t); - rec.normal = (rec.p - center) / radius; - - return true; + // Find the nearest root that lies in the acceptable range. + auto root = (h - sqrtd) / a; + if (!ray_t.surrounds(root)) { + root = (h + sqrtd) / a; + if (!ray_t.surrounds(root)) + return false; } - private: - Point3 center; - double radius; + rec.t = root; + rec.p = r.at(rec.t); + rec.normal = (rec.p - center) / radius; + + return true; + } + +private: + Point3 center; + double radius; }; #endif