add interval

This commit is contained in:
zongor 2025-07-24 14:55:28 -04:00
parent 82984e1a5a
commit 5bbfb17684
6 changed files with 77 additions and 42 deletions

View File

@ -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));
}

View File

@ -2,10 +2,11 @@
#define RTWEEKEND_H
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <limits>
#include <memory>
#include <random>
// 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<double> 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

View File

@ -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

View File

@ -20,14 +20,13 @@ public:
void add(shared_ptr<hittable> 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;

22
src/interval.h Normal file
View File

@ -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

View File

@ -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 &center, 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