aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/hittable.hpp23
-rw-r--r--include/hittable_list.hpp21
-rw-r--r--include/ray.hpp2
-rw-r--r--include/rt.hpp18
-rw-r--r--include/sphere.hpp16
-rw-r--r--include/vec3.hpp8
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/hittable_list.cpp28
-rw-r--r--src/main.cpp32
-rw-r--r--src/ray.cpp2
-rw-r--r--src/sphere.cpp37
-rw-r--r--src/vec3.cpp16
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();
}