diff options
| author | ladevieq <ladevie.quentin@gmail.com> | 2020-12-20 21:59:33 +0100 |
|---|---|---|
| committer | ladevieq <ladevie.quentin@gmail.com> | 2020-12-20 21:59:33 +0100 |
| commit | c7c4f8f82c66cfe89b72d176ee51dab8bd30dc95 (patch) | |
| tree | d0c2caeccda953d86806cb7c7b27c8941e0ef845 | |
| parent | fc601fd503ec1ebd08e4daffeb9aa0812aff2b71 (diff) | |
Add hittable interface and hit infos on hit
| -rw-r--r-- | include/hittable.hpp | 23 | ||||
| -rw-r--r-- | include/hittable_list.hpp | 21 | ||||
| -rw-r--r-- | include/ray.hpp | 2 | ||||
| -rw-r--r-- | include/rt.hpp | 18 | ||||
| -rw-r--r-- | include/sphere.hpp | 16 | ||||
| -rw-r--r-- | include/vec3.hpp | 8 | ||||
| -rw-r--r-- | src/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/hittable_list.cpp | 28 | ||||
| -rw-r--r-- | src/main.cpp | 32 | ||||
| -rw-r--r-- | src/ray.cpp | 2 | ||||
| -rw-r--r-- | src/sphere.cpp | 37 | ||||
| -rw-r--r-- | src/vec3.cpp | 16 |
12 files changed, 171 insertions, 34 deletions
diff --git a/include/hittable.hpp b/include/hittable.hpp new file mode 100644 index 0000000..4978e57 --- /dev/null +++ b/include/hittable.hpp @@ -0,0 +1,23 @@ +#ifndef __HITTABLE_HPP_ +#define __HITTABLE_HPP_ + +#include "ray.hpp" + +struct hit_info { + double t; + point3 point; + vec3 normal; + bool front_face; + + inline void set_face_normal(const ray& r, const vec3& outward_normal) { + front_face = r.direction.dot(outward_normal) < 0.0; + normal = front_face ? outward_normal : -outward_normal; + } +}; + +class hittable { + public: + virtual bool hit(const ray& r, double t_min, double t_max, struct hit_info& info) const = 0; +}; + +#endif // !__HITTABLE_HPP_ diff --git a/include/hittable_list.hpp b/include/hittable_list.hpp new file mode 100644 index 0000000..41d8f4a --- /dev/null +++ b/include/hittable_list.hpp @@ -0,0 +1,21 @@ +#ifndef __HITTABLE_LIST_HPP_ +#define __HITTABLE_LIST_HPP_ + +#include <vector> +#include <memory> + +#include "hittable.hpp" + +class hittable_list : public hittable { + public: + hittable_list(); + + void add(std::shared_ptr<hittable> hittable); + void clear(); + + virtual bool hit(const ray&r, double t_min, double t_max, struct hit_info& info) const; + + std::vector<std::shared_ptr<hittable>> hittables; +}; + +#endif // !__HITTABLE_LIST_HPP_ diff --git a/include/ray.hpp b/include/ray.hpp index 3f8542b..b3d88ae 100644 --- a/include/ray.hpp +++ b/include/ray.hpp @@ -8,7 +8,7 @@ class ray { ray(const point3& origin, const vec3& direction); - point3 at(double t); + point3 at(double t) const; point3 origin; vec3 direction; diff --git a/include/rt.hpp b/include/rt.hpp new file mode 100644 index 0000000..60170ac --- /dev/null +++ b/include/rt.hpp @@ -0,0 +1,18 @@ +#ifndef __RT_HPP_ +#define __RT_HPP_ + +#include <limits> + +const double pi = 3.1415926535897932385; +const double infinity = std::numeric_limits<double>::infinity(); + +inline double deg_to_rad(double deg) { + return deg * pi / 180.0; +} + +#include "vec3.hpp" +#include "ray.hpp" +#include "color.hpp" +#include "sphere.hpp" + +#endif // !__RT_HPP_ diff --git a/include/sphere.hpp b/include/sphere.hpp new file mode 100644 index 0000000..5bf0ab9 --- /dev/null +++ b/include/sphere.hpp @@ -0,0 +1,16 @@ +#ifndef __SPHERE_HPP_ +#define __SPHERE_HPP_ + +#include "hittable.hpp" + +class sphere : public hittable { + public: + sphere(point3 center, double radius = 1.0); + + virtual bool hit(const ray& r, double t_min, double t_max, struct hit_info& info) const; + + point3 center; + double radius; +}; + +#endif // !__SPHERE_HPP_ diff --git a/include/vec3.hpp b/include/vec3.hpp index 48f0ae3..e658e71 100644 --- a/include/vec3.hpp +++ b/include/vec3.hpp @@ -10,7 +10,7 @@ class vec3 { vec3(double x, double y, double z); - void operator-(); + vec3 operator-() const; vec3& operator+=(vec3& vec); @@ -18,15 +18,15 @@ class vec3 { vec3& operator/=(double numerator); - double length(); + double length() const; - double length_sq(); + double length_sq() const; double dot(const vec3& vec) const; vec3 cross(const vec3& vec) const; - vec3 unit(); + vec3 unit() const; double x, y, z; }; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4d8b1f6..268dd02 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,3 +1,3 @@ include_directories(${CMAKE_SOURCE_DIR}/include) -add_executable(path-tracer main.cpp vec3.cpp color.cpp ray.cpp) +add_executable(path-tracer main.cpp vec3.cpp color.cpp ray.cpp sphere.cpp hittable_list.cpp) diff --git a/src/hittable_list.cpp b/src/hittable_list.cpp new file mode 100644 index 0000000..9140304 --- /dev/null +++ b/src/hittable_list.cpp @@ -0,0 +1,28 @@ +#include "hittable_list.hpp" + +hittable_list::hittable_list() {}; + +void hittable_list::add(std::shared_ptr<hittable> hittable) { + hittables.push_back(hittable); +} + +void hittable_list::clear() { + hittables.clear(); +} + + +bool hittable_list::hit(const ray& r, double t_min, double t_max, struct hit_info& info) const { + struct hit_info temp_info; + bool hit_anything = false; + double closest_hit = t_max; + + for (auto& hittable: hittables) { + if (hittable->hit(r, t_min, closest_hit, temp_info)) { + hit_anything = true; + closest_hit = temp_info.t; + info = temp_info; + } + } + + return hit_anything; +} diff --git a/src/main.cpp b/src/main.cpp index e2ef071..f6b3012 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,31 +1,22 @@ #include <iostream> -#include "color.hpp" -#include "vec3.hpp" -#include "ray.hpp" +#include "rt.hpp" +#include "hittable_list.hpp" color ground_color { 1.0, 1.0, 1.0 }; color sky_color { 0.5, 0.7, 1.0 }; -bool hit_sphere(const point3& sphere_pos, double sphere_radius, const ray& r) { - // Vector from the ray origin to sphere position - vec3 origin_center = r.origin - sphere_pos; - double a = r.direction.dot(r.direction); - double b = 2.0 * r.direction.dot(origin_center); - double c = origin_center.dot(origin_center) - sphere_radius * sphere_radius; - double discriminant = b * b - 4.0 * a * c; +color ray_color(ray& r, const hittable& world) { + sphere sphere { { 0.0, 0.0, -1.0 }, 0.5 }; - return (discriminant > 0); -} - -color ray_color(ray& r) { auto unit_dir = r.direction.unit(); auto t = (unit_dir.y + 1.0) * 0.5; auto c = lerp(ground_color, sky_color, t); - if (hit_sphere(point3{ 0.0, 0.0, -1.0 }, .5, r)) { - c = color { 1.0, 0.0, 0.0 }; + struct hit_info info; + if (world.hit(r, 0.0, infinity, info)) { + c = 0.5 * (info.normal + vec3{ 1.0, 1.0, 1.0}); } return c; @@ -36,10 +27,11 @@ int main() { const double aspect_ratio = 16.0 / 9.0; const size_t width = 400; const size_t height = width / aspect_ratio; - // const size_t width = 256; - // const size_t height = 256; - // const double aspect_ratio = width / height; + // World hittable objects + hittable_list world {}; + world.add(std::make_shared<sphere>(point3(0,0,-1), 0.5)); + world.add(std::make_shared<sphere>(point3(0,-100.5,-1), 100)); // Viewport dimensions const double viewport_height = 2.0; @@ -78,7 +70,7 @@ int main() { ray ray { eye_pos, direction }; - write_color(std::cout, ray_color(ray)); + write_color(std::cout, ray_color(ray, world)); // write_color(std::cout, color(direction.unit().y, direction.unit().y, direction.unit().y)); // write_color(std::cout, color(y.y, y.y, y.y)); } diff --git a/src/ray.cpp b/src/ray.cpp index 2d479b7..ebf392b 100644 --- a/src/ray.cpp +++ b/src/ray.cpp @@ -3,6 +3,6 @@ ray::ray(const point3& origin, const vec3& direction): origin(origin), direction(direction) {} -point3 ray::at(double t) { +point3 ray::at(double t) const { return origin + direction * t; } diff --git a/src/sphere.cpp b/src/sphere.cpp new file mode 100644 index 0000000..31915a2 --- /dev/null +++ b/src/sphere.cpp @@ -0,0 +1,37 @@ +#include "sphere.hpp" + +sphere::sphere(point3 center, double radius) : center(center), radius(radius) +{} + +bool sphere::hit(const ray& r, double t_min, double t_max, struct hit_info& info) const { + // Vector from the ray origin to sphere position + vec3 origin_center = r.origin - center; + + double a = r.direction.dot(r.direction); + double half_b = r.direction.dot(origin_center); + double c = origin_center.dot(origin_center) - radius * radius; + double discriminant = half_b * half_b - a * c; + + if (discriminant < 0) { + return false; + } + + double sq_discriminant = sqrt(discriminant); + double t = (-half_b - sq_discriminant) / a ; + + if (t_min > t || t_max < t) { + t = (-half_b + sq_discriminant) / a ; + + if (t_min > t || t_max < t) { + return false; + } + } + + info.t = t; + info.point = r.at(t); + + vec3 out_normal = (info.point - center).unit(); + info.set_face_normal(r, out_normal); + + return true; +} diff --git a/src/vec3.cpp b/src/vec3.cpp index fdd8969..b850bfc 100644 --- a/src/vec3.cpp +++ b/src/vec3.cpp @@ -4,10 +4,12 @@ vec3::vec3(): x(0.0), y(0.0), z(0.0) {} vec3::vec3(double x, double y, double z): x(x), y(y), z(z) {} -void vec3::operator-() { - x = -x; - y = -y; - z = -z; +vec3 vec3::operator-() const { + return vec3 { + -x, + -y, + -z + }; } vec3& vec3::operator+=(vec3& vec) { @@ -34,11 +36,11 @@ vec3& vec3::operator/=(double numerator) { return *this; } -double vec3::length() { +double vec3::length() const { return sqrt(length_sq()); } -double vec3::length_sq() { +double vec3::length_sq() const { return x * x + y * y + z * z; } @@ -54,7 +56,7 @@ vec3 vec3::cross(const vec3& vec) const { ); } -vec3 vec3::unit() { +vec3 vec3::unit() const { return *this / length(); } |
