[FEAT] Add all test intersections
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -37,4 +37,5 @@ using namespace Raytracer;
|
||||
|
||||
Sphere::Sphere(void)
|
||||
{
|
||||
inc_id();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user