From 1b78b8815f87535bc4ae02e3b8c72649468e70b4 Mon Sep 17 00:00:00 2001 From: Nigel Date: Sat, 4 Mar 2023 19:48:03 +0100 Subject: [PATCH] Adding a abstractions like a world list --- src/hittable.h | 20 ++++++++++++++++++++ src/hittable_list.h | 41 +++++++++++++++++++++++++++++++++++++++++ src/program.cpp | 36 +++++++++++++++--------------------- src/rtweekend.h | 25 +++++++++++++++++++++++++ src/sphere.h | 43 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 144 insertions(+), 21 deletions(-) create mode 100644 src/hittable.h create mode 100644 src/hittable_list.h create mode 100644 src/rtweekend.h create mode 100644 src/sphere.h diff --git a/src/hittable.h b/src/hittable.h new file mode 100644 index 0000000..f4ea713 --- /dev/null +++ b/src/hittable.h @@ -0,0 +1,20 @@ +#pragma once + +#include "ray.h" + +struct hit_record{ + point3 p; + vec3 normal; + double t; + 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& rc) const = 0; +}; \ No newline at end of file diff --git a/src/hittable_list.h b/src/hittable_list.h new file mode 100644 index 0000000..e7cb1bc --- /dev/null +++ b/src/hittable_list.h @@ -0,0 +1,41 @@ +#pragma once + +#include "hittable.h" + +#include +#include + +using std::shared_ptr; +using std::make_shared; + +class hittable_list : public hittable{ + public: + hittable_list() {} + hittable_list(shared_ptr object) {objects.push_back(object);} + + void clear(){objects.clear();} + void add(shared_ptr object){objects.push_back(object);} + + virtual bool hit (const ray& r, double t_min, double t_max, hit_record& rec) const override; + + 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; + bool 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; +} + diff --git a/src/program.cpp b/src/program.cpp index 8db45fb..1468ead 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -1,30 +1,19 @@ +#include "rtweekend.h" + #include "color.h" -#include "ray.h" -#include "vector3.h" +#include "hittable_list.h" +#include "sphere.h" #include -double hit_sphere (const point3& center, double radius, const ray& r) { - vec3 oc = r.origin() - center; - auto a = dot(r.direction(), r.direction()); - auto b = 2.0 * dot(oc, r.direction()); - auto c = dot(oc, oc) - radius*radius; - auto discriminant = b*b - 4*a*c; - if ( discriminant < 0) { - return -1.0; - }else{ - return (-b - sqrt(discriminant) ) / (2.0*a); +color ray_color(const ray& r, const hittable& world){ + hit_record rec; + if(world.hit(r, 0, infinity, rec)){ + return 0.5 * (rec.normal + color(1,1,1)); } -} -color ray_color(const ray& r){ - auto t = hit_sphere(point3(0,0,-1), 0.5, r); - if(t > 0.0){ - vec3 N = unit_vector(r.at(t) - vec3(0,0,-1)); - return 0.5*color(N.x()+1, N.y()+1, N.z()+1); - } vec3 unit_direction = unit_vector(r.direction()); - t = 0.5*(unit_direction.y() + 1.0); + auto t = 0.5*(unit_direction.y() + 1.0); return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5,0.7,1.0); } @@ -36,6 +25,11 @@ int main () const int image_width = 400; const int image_height = static_cast(image_width /aspect_ratio); + // World + hittable_list world; + world.add(make_shared(point3(0,0,-1), 0.5)); + world.add(make_shared(point3(0,-100.5,-1), 100)); + // Camera auto viewport_height = 2.0; @@ -57,7 +51,7 @@ int main () auto u = double(i) / (image_width-1); auto v = double(j) / (image_height-1); ray r(origin, lower_left_corner+u*horizontal + v* vertical -origin); - color pixel_color = ray_color(r); + color pixel_color = ray_color(r, world); write_color(std::cout , pixel_color); } } diff --git a/src/rtweekend.h b/src/rtweekend.h new file mode 100644 index 0000000..1e39604 --- /dev/null +++ b/src/rtweekend.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include + +// Usings +using std::shared_ptr; +using std::make_shared; +using std::sqrt; + + +// Constants +const double infinity = std::numeric_limits::infinity(); +const double pi = 3.1415926535897932385; + +// Utility functions +inline double degrees_to_radians(double degrees){ + return degrees * pi / 180.0; +} + +// Common Headers +#include "ray.h" +#include "vector3.h" + diff --git a/src/sphere.h b/src/sphere.h new file mode 100644 index 0000000..5560baf --- /dev/null +++ b/src/sphere.h @@ -0,0 +1,43 @@ +#pragma once + +#include "hittable.h" +#include "vector3.h" + +class sphere : public hittable{ + public: + sphere(){} + sphere(point3 cen, double r): center(cen), radius(r){}; + + virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const override; + + public: + point3 center; + double radius; +}; + + +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) return false; + auto sqrtd = sqrt(discriminant); + + // Find the nearest root that lies in the acceptable range + auto root = (-half_b - sqrtd) /a; + if(root < t_min || t_max < root){ + root = (-half_b + sqrtd) /a; + if (root < t_min || t_max < root) + return false; + } + + rec.t = root; + rec.p = r.at(rec.t); + vec3 outward_normal = (rec.p - center) /radius; + rec.set_face_normal(r, outward_normal); + + return true; +} \ No newline at end of file