From 8c8e378ebdbc707d69eafaca929f1a4526931143 Mon Sep 17 00:00:00 2001 From: NADAL Jean-Baptiste Date: Mon, 12 Feb 2024 17:13:47 +0100 Subject: [PATCH] [FEAT] Add all test intersections --- raytracing/src/intersection.cpp | 60 +++++++++++++++++++++++++++++++- raytracing/src/intersection.h | 11 +++++- raytracing/src/intersections.cpp | 59 +++++++++++++++++-------------- raytracing/src/intersections.h | 12 ++++--- raytracing/src/object.cpp | 24 ++++++++++++- raytracing/src/object.h | 6 ++++ raytracing/src/ray.cpp | 6 ++-- raytracing/src/sphere.cpp | 1 + tests/05_rays.cpp | 60 +++++++++++++++++++++++++++++++- 9 files changed, 200 insertions(+), 39 deletions(-) diff --git a/raytracing/src/intersection.cpp b/raytracing/src/intersection.cpp index 8024eda..ed2999e 100644 --- a/raytracing/src/intersection.cpp +++ b/raytracing/src/intersection.cpp @@ -29,6 +29,7 @@ /* ------------------------------------------------------------------------- */ #include "intersection.h" +#include "common.h" using namespace Raytracer; @@ -54,6 +55,14 @@ Intersection::Intersection(Intersection &an_intersection) : /* ------------------------------------------------------------------------- */ +Intersection::Intersection(const Intersection &an_intersection) : + m_distance_t(an_intersection.m_distance_t), + m_object(an_intersection.m_object) +{ +} + +/* ------------------------------------------------------------------------- */ + const Intersection &Intersection::operator=(const Intersection &an_intersection) { if (this == &an_intersection) @@ -69,7 +78,56 @@ const Intersection &Intersection::operator=(const Intersection &an_intersection) /* ------------------------------------------------------------------------- */ -double Intersection::distance_t(void) +bool Intersection::operator==(const Intersection &an_other) const +{ + return (double_equal(m_distance_t, an_other.m_distance_t) && (m_object == an_other.m_object)); +} + +/* ------------------------------------------------------------------------- */ + +bool Intersection::operator<(const Intersection &an_other) const +{ + return m_distance_t < an_other.m_distance_t; +} + +/* ------------------------------------------------------------------------- */ + +bool Intersection::operator>(const Intersection &an_other) const +{ + return m_distance_t > an_other.m_distance_t; +} + +/* ------------------------------------------------------------------------- */ + +bool Intersection::operator>(double a_distance) const +{ + return m_distance_t > a_distance; +} + +/* ------------------------------------------------------------------------- */ + +bool Intersection::operator>=(double a_distance) const +{ + return m_distance_t >= a_distance; +} + +/* ------------------------------------------------------------------------- */ + +bool Intersection::operator<(double a_distance) const +{ + return m_distance_t < a_distance; +} + +/* ------------------------------------------------------------------------- */ + +bool Intersection::operator<=(double a_distance) const +{ + return m_distance_t <= a_distance; +} + +/* ------------------------------------------------------------------------- */ + +double Intersection::distance_t(void) const { return m_distance_t; } diff --git a/raytracing/src/intersection.h b/raytracing/src/intersection.h index c62a59a..aa72970 100644 --- a/raytracing/src/intersection.h +++ b/raytracing/src/intersection.h @@ -40,10 +40,19 @@ namespace Raytracer Intersection(void); Intersection(double a_distance_t, Object an_object); Intersection(Intersection &an_intersection); + Intersection(const Intersection &an_intersection); const Intersection &operator=(const Intersection &an_intersection); + bool operator==(const Intersection &an_intersection) const; + bool operator<(const Intersection &an_other) const; + bool operator>(const Intersection &an_other) const; - double distance_t(void); + bool operator>(double a_distance) const; + bool operator>=(double a_distance) const; + bool operator<(double a_distance) const; + bool operator<=(double a_distance) const; + + double distance_t(void) const; Object &object(void); private: diff --git a/raytracing/src/intersections.cpp b/raytracing/src/intersections.cpp index 2e53129..8c485a1 100644 --- a/raytracing/src/intersections.cpp +++ b/raytracing/src/intersections.cpp @@ -34,42 +34,31 @@ using namespace Raytracer; /* ------------------------------------------------------------------------- */ -Intersections::Intersections(void) : m_count(0) +Intersections::Intersections(void) { } /* ------------------------------------------------------------------------- */ -Intersections::Intersections(const Intersection &an_intersection1, const Intersection &an_intersection2) +Intersections::Intersections(const std::initializer_list a_list) { - m_array[0] = an_intersection1; - m_array[1] = an_intersection2; - m_count = 2; -} -/* ------------------------------------------------------------------------- */ - -Intersections::Intersections(Intersection &an_intersection1, Intersection &an_intersection2) -{ - m_array[0] = an_intersection1; - m_array[1] = an_intersection2; - m_count = 2; + m_data.reserve(a_list.size()); + m_data.assign(a_list.begin(), a_list.end()); } /* ------------------------------------------------------------------------- */ Intersections::Intersections(Intersections &an_other) { - m_array[0] = an_other.m_array[0]; - m_array[1] = an_other.m_array[1]; - m_count = an_other.m_count; + std::copy(an_other.m_data.begin(), an_other.m_data.end(), m_data.begin()); } /* ------------------------------------------------------------------------- */ Intersection &Intersections::operator[](uint8_t an_index) { - return m_array[an_index]; + return m_data[an_index]; } /* ------------------------------------------------------------------------- */ @@ -81,21 +70,16 @@ const Intersections &Intersections::operator=(const Intersections &an_other) return *this; } - m_array[0] = an_other.m_array[0]; - m_array[1] = an_other.m_array[1]; - m_count = an_other.m_count; + std::copy(an_other.m_data.begin(), an_other.m_data.end(), m_data.begin()); return *this; } /* ------------------------------------------------------------------------- */ -bool Intersections::set(Intersection an_intersection1, Intersection an_intersection2) +bool Intersections::add(const Intersection &an_intersection) { - m_array[0] = an_intersection1; - m_array[1] = an_intersection2; - m_count = 2; - + m_data.push_back(an_intersection); return true; } @@ -103,5 +87,28 @@ bool Intersections::set(Intersection an_intersection1, Intersection an_intersect uint8_t Intersections::count(void) const { - return m_count; + return m_data.size(); +} + +/* ------------------------------------------------------------------------- */ + +Intersection Intersections::hit(void) +{ + if (m_data.size() == 0) + { + return {}; + } + auto the_it = std::min_element(m_data.begin(), m_data.end(), + [](const Intersection &a, const Intersection &b) + { + // Use < comparison for strict positivity check + return a.distance_t() < b.distance_t() && a.distance_t() > 0; + }); + + if (the_it == m_data.end() || the_it->distance_t() <= 0) + { + return {}; + } + + return *the_it; } diff --git a/raytracing/src/intersections.h b/raytracing/src/intersections.h index a98fe54..1ed89f7 100644 --- a/raytracing/src/intersections.h +++ b/raytracing/src/intersections.h @@ -29,6 +29,8 @@ /* ------------------------------------------------------------------------- */ #include +#include +#include #include "intersection.h" @@ -40,20 +42,20 @@ namespace Raytracer { public: Intersections(void); - Intersections(const Intersection &an_intersection1, const Intersection &an_intersection2); - Intersections(Intersection &an_intersection1, Intersection &an_intersection2); + Intersections(const std::initializer_list a_list); Intersections(Intersections &an_intersections); Intersection &operator[](uint8_t an_index); const Intersections &operator=(const Intersections &an_other); - bool set(Intersection an_intersection1, Intersection an_intersection2); + bool add(const Intersection &an_intersection); uint8_t count(void) const; + Intersection hit(void); + private: - uint8_t m_count; - Intersection m_array[2]; + std::vector m_data; }; }; // namespace Raytracer diff --git a/raytracing/src/object.cpp b/raytracing/src/object.cpp index 8ba8852..76538bd 100644 --- a/raytracing/src/object.cpp +++ b/raytracing/src/object.cpp @@ -34,11 +34,13 @@ using namespace Raytracer; /* ------------------------------------------------------------------------- */ +#define kNothing 0 + uint32_t Object::s_current_index = 0; /* ------------------------------------------------------------------------- */ -Object::Object(void) : m_id(s_current_index++) +Object::Object(void) : m_id(kNothing) { } @@ -50,6 +52,12 @@ Object::Object(Object &a_copy) : m_id(a_copy.m_id) /* ------------------------------------------------------------------------- */ +Object::Object(const Object &a_copy) : m_id(a_copy.m_id) +{ +} + +/* ------------------------------------------------------------------------- */ + const Object &Object::operator=(const Object &an_other) { if (this == &an_other) @@ -68,3 +76,17 @@ bool Object::operator==(const Object &an_object) const { return m_id == an_object.m_id; } + +/* ------------------------------------------------------------------------- */ + +bool Object::is_nothing(void) +{ + return (m_id == kNothing); +} + +/* ------------------------------------------------------------------------- */ + +void Object::inc_id(void) +{ + m_id = s_current_index++; +} diff --git a/raytracing/src/object.h b/raytracing/src/object.h index 4977fd1..e7d62b4 100644 --- a/raytracing/src/object.h +++ b/raytracing/src/object.h @@ -39,10 +39,16 @@ namespace Raytracer public: Object(void); Object(Object &a_copy); + Object(const Object &a_copy); const Object &operator=(const Object &an_other); bool operator==(const Object &an_object) const; + bool is_nothing(void); + + protected: + void inc_id(void); + private: uint32_t m_id; static uint32_t s_current_index; diff --git a/raytracing/src/ray.cpp b/raytracing/src/ray.cpp index 5b9cf27..8582904 100644 --- a/raytracing/src/ray.cpp +++ b/raytracing/src/ray.cpp @@ -78,10 +78,8 @@ Intersections Ray::intersect(Sphere a_sphere) if (discriminant >= 0) { - the_intersections.set(Intersection((-the_b - the_sqrt) / (2 * the_a), a_sphere), - Intersection((-the_b + the_sqrt) / (2 * the_a), a_sphere) - - ); + the_intersections.add(Intersection((-the_b - the_sqrt) / (2 * the_a), a_sphere)); + the_intersections.add(Intersection((-the_b + the_sqrt) / (2 * the_a), a_sphere)); } return the_intersections; diff --git a/raytracing/src/sphere.cpp b/raytracing/src/sphere.cpp index e21ab25..ccdea8b 100644 --- a/raytracing/src/sphere.cpp +++ b/raytracing/src/sphere.cpp @@ -37,4 +37,5 @@ using namespace Raytracer; Sphere::Sphere(void) { + inc_id(); } diff --git a/tests/05_rays.cpp b/tests/05_rays.cpp index a259c67..e0fcd34 100644 --- a/tests/05_rays.cpp +++ b/tests/05_rays.cpp @@ -150,7 +150,7 @@ TEST_CASE("[05][Rays] Aggregating intersections", "[Intersections]") Sphere s; Intersection i1(1, s); Intersection i2(2, s); - Intersections xs = Intersections(i1, i2); + Intersections xs = Intersections({i1, i2}); REQUIRE(xs.count() == 2); REQUIRE(xs[0].distance_t() == 1); @@ -169,3 +169,61 @@ TEST_CASE("[05][Rays] Intersect set the object on the intersection", "[Intersect REQUIRE(xs[0].object() == s); REQUIRE(xs[1].object() == s); } + +/* ------------------------------------------------------------------------- */ + +TEST_CASE("[05][Rays] The hit, when all intersections have positive t", "[Intersections]") +{ + Sphere s; + Intersection i1(1, s); + Intersection i2(2, s); + Intersections xs = Intersections({i2, i1}); + + Intersection i = xs.hit(); + + REQUIRE(i == i1); +} + +/* ------------------------------------------------------------------------- */ + +TEST_CASE("[05][Rays] The hit, when some intersections have negative t", "[Intersections]") +{ + Sphere s; + Intersection i1(-1, s); + Intersection i2(1, s); + Intersections xs = Intersections({i2, i1}); + + Intersection i = xs.hit(); + + REQUIRE(i == i2); +} + +/* ------------------------------------------------------------------------- */ + +TEST_CASE("[05][Rays] The hit, when all intersections have negative t", "[Intersections]") +{ + Sphere s; + Intersection i1(-2, s); + Intersection i2(-1, s); + Intersections xs = Intersections({i1, i2}); + + Intersection i = xs.hit(); + + REQUIRE(i.object().is_nothing()); +} + +/* ------------------------------------------------------------------------- */ + +TEST_CASE("[05][Rays] The hit is always the lowest nonnegative intersection", "[Intersections]") +{ + Sphere s; + Intersection i1(5, s); + Intersection i2(7, s); + Intersection i3(-3, s); + Intersection i4(2, s); + Intersections xs = Intersections({i1, i2, i3, i4}); + + Intersection i = xs.hit(); + + REQUIRE(i == i4); +}