[FEAT] Add all test intersections

This commit is contained in:
NADAL Jean-Baptiste
2024-02-12 17:13:47 +01:00
parent 6571fe27ee
commit 8c8e378ebd
9 changed files with 200 additions and 39 deletions

View File

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

View File

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

View File

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

View File

@@ -29,6 +29,8 @@
/* ------------------------------------------------------------------------- */
#include <cstdint>
#include <initializer_list>
#include <vector>
#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<Intersection> 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<Intersection> m_data;
};
}; // namespace Raytracer

View File

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

View File

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

View File

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

View File

@@ -37,4 +37,5 @@ using namespace Raytracer;
Sphere::Sphere(void)
{
inc_id();
}

View File

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