[FEAT] Add all test intersections
This commit is contained in:
@@ -29,6 +29,7 @@
|
|||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#include "intersection.h"
|
#include "intersection.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
using namespace Raytracer;
|
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)
|
const Intersection &Intersection::operator=(const Intersection &an_intersection)
|
||||||
{
|
{
|
||||||
if (this == &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;
|
return m_distance_t;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,10 +40,19 @@ namespace Raytracer
|
|||||||
Intersection(void);
|
Intersection(void);
|
||||||
Intersection(double a_distance_t, Object an_object);
|
Intersection(double a_distance_t, Object an_object);
|
||||||
Intersection(Intersection &an_intersection);
|
Intersection(Intersection &an_intersection);
|
||||||
|
Intersection(const Intersection &an_intersection);
|
||||||
|
|
||||||
const Intersection &operator=(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);
|
Object &object(void);
|
||||||
|
|
||||||
private:
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
m_data.reserve(a_list.size());
|
||||||
|
m_data.assign(a_list.begin(), a_list.end());
|
||||||
Intersections::Intersections(Intersection &an_intersection1, Intersection &an_intersection2)
|
|
||||||
{
|
|
||||||
m_array[0] = an_intersection1;
|
|
||||||
m_array[1] = an_intersection2;
|
|
||||||
m_count = 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
Intersections::Intersections(Intersections &an_other)
|
Intersections::Intersections(Intersections &an_other)
|
||||||
{
|
{
|
||||||
m_array[0] = an_other.m_array[0];
|
std::copy(an_other.m_data.begin(), an_other.m_data.end(), m_data.begin());
|
||||||
m_array[1] = an_other.m_array[1];
|
|
||||||
m_count = an_other.m_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
Intersection &Intersections::operator[](uint8_t an_index)
|
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;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_array[0] = an_other.m_array[0];
|
std::copy(an_other.m_data.begin(), an_other.m_data.end(), m_data.begin());
|
||||||
m_array[1] = an_other.m_array[1];
|
|
||||||
m_count = an_other.m_count;
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
bool Intersections::set(Intersection an_intersection1, Intersection an_intersection2)
|
bool Intersections::add(const Intersection &an_intersection)
|
||||||
{
|
{
|
||||||
m_array[0] = an_intersection1;
|
m_data.push_back(an_intersection);
|
||||||
m_array[1] = an_intersection2;
|
|
||||||
m_count = 2;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,5 +87,28 @@ bool Intersections::set(Intersection an_intersection1, Intersection an_intersect
|
|||||||
|
|
||||||
uint8_t Intersections::count(void) const
|
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 <cstdint>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "intersection.h"
|
#include "intersection.h"
|
||||||
|
|
||||||
@@ -40,20 +42,20 @@ namespace Raytracer
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Intersections(void);
|
Intersections(void);
|
||||||
Intersections(const Intersection &an_intersection1, const Intersection &an_intersection2);
|
Intersections(const std::initializer_list<Intersection> a_list);
|
||||||
Intersections(Intersection &an_intersection1, Intersection &an_intersection2);
|
|
||||||
Intersections(Intersections &an_intersections);
|
Intersections(Intersections &an_intersections);
|
||||||
|
|
||||||
Intersection &operator[](uint8_t an_index);
|
Intersection &operator[](uint8_t an_index);
|
||||||
const Intersections &operator=(const Intersections &an_other);
|
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;
|
uint8_t count(void) const;
|
||||||
|
|
||||||
|
Intersection hit(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t m_count;
|
std::vector<Intersection> m_data;
|
||||||
Intersection m_array[2];
|
|
||||||
};
|
};
|
||||||
}; // namespace Raytracer
|
}; // namespace Raytracer
|
||||||
|
|
||||||
|
|||||||
@@ -34,11 +34,13 @@ using namespace Raytracer;
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#define kNothing 0
|
||||||
|
|
||||||
uint32_t Object::s_current_index = 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)
|
const Object &Object::operator=(const Object &an_other)
|
||||||
{
|
{
|
||||||
if (this == &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;
|
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:
|
public:
|
||||||
Object(void);
|
Object(void);
|
||||||
Object(Object &a_copy);
|
Object(Object &a_copy);
|
||||||
|
Object(const Object &a_copy);
|
||||||
|
|
||||||
const Object &operator=(const Object &an_other);
|
const Object &operator=(const Object &an_other);
|
||||||
bool operator==(const Object &an_object) const;
|
bool operator==(const Object &an_object) const;
|
||||||
|
|
||||||
|
bool is_nothing(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void inc_id(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t m_id;
|
uint32_t m_id;
|
||||||
static uint32_t s_current_index;
|
static uint32_t s_current_index;
|
||||||
|
|||||||
@@ -78,10 +78,8 @@ Intersections Ray::intersect(Sphere a_sphere)
|
|||||||
|
|
||||||
if (discriminant >= 0)
|
if (discriminant >= 0)
|
||||||
{
|
{
|
||||||
the_intersections.set(Intersection((-the_b - the_sqrt) / (2 * the_a), a_sphere),
|
the_intersections.add(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));
|
||||||
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return the_intersections;
|
return the_intersections;
|
||||||
|
|||||||
@@ -37,4 +37,5 @@ using namespace Raytracer;
|
|||||||
|
|
||||||
Sphere::Sphere(void)
|
Sphere::Sphere(void)
|
||||||
{
|
{
|
||||||
|
inc_id();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ TEST_CASE("[05][Rays] Aggregating intersections", "[Intersections]")
|
|||||||
Sphere s;
|
Sphere s;
|
||||||
Intersection i1(1, s);
|
Intersection i1(1, s);
|
||||||
Intersection i2(2, s);
|
Intersection i2(2, s);
|
||||||
Intersections xs = Intersections(i1, i2);
|
Intersections xs = Intersections({i1, i2});
|
||||||
|
|
||||||
REQUIRE(xs.count() == 2);
|
REQUIRE(xs.count() == 2);
|
||||||
REQUIRE(xs[0].distance_t() == 1);
|
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[0].object() == s);
|
||||||
REQUIRE(xs[1].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