[WIP] Refraction Wip
This commit is contained in:
@@ -37,7 +37,9 @@ using namespace Raytracer;
|
|||||||
IntersectionData::IntersectionData(void) :
|
IntersectionData::IntersectionData(void) :
|
||||||
m_is_inside(false),
|
m_is_inside(false),
|
||||||
m_distance(0),
|
m_distance(0),
|
||||||
m_shape(nullptr)
|
m_shape(nullptr),
|
||||||
|
m_n1(0),
|
||||||
|
m_n2(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,3 +162,31 @@ void IntersectionData::set_inside(void)
|
|||||||
m_is_inside = false;
|
m_is_inside = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void IntersectionData::set_n1(double an_n1)
|
||||||
|
{
|
||||||
|
m_n1 = an_n1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
const double IntersectionData::n1(void) const
|
||||||
|
{
|
||||||
|
return m_n1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void IntersectionData::set_n2(double an_n2)
|
||||||
|
{
|
||||||
|
m_n2 = an_n2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
const double IntersectionData::n2(void) const
|
||||||
|
{
|
||||||
|
return m_n2;
|
||||||
|
}
|
||||||
|
|||||||
@@ -65,6 +65,12 @@ namespace Raytracer
|
|||||||
const bool is_inside(void) const;
|
const bool is_inside(void) const;
|
||||||
void set_inside(void);
|
void set_inside(void);
|
||||||
|
|
||||||
|
void set_n1(double an_n1);
|
||||||
|
const double n1(void) const;
|
||||||
|
|
||||||
|
void set_n2(double an_n2);
|
||||||
|
const double n2(void) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_is_inside;
|
bool m_is_inside;
|
||||||
double m_distance;
|
double m_distance;
|
||||||
@@ -74,6 +80,8 @@ namespace Raytracer
|
|||||||
Tuple m_eyev;
|
Tuple m_eyev;
|
||||||
Tuple m_normalv;
|
Tuple m_normalv;
|
||||||
Tuple m_reflectv;
|
Tuple m_reflectv;
|
||||||
|
double m_n1;
|
||||||
|
double m_n2;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace Raytracer
|
}; // namespace Raytracer
|
||||||
|
|||||||
@@ -32,6 +32,8 @@
|
|||||||
|
|
||||||
#include "intersection.h"
|
#include "intersection.h"
|
||||||
|
|
||||||
|
#include "intersections.h"
|
||||||
|
|
||||||
using namespace Raytracer;
|
using namespace Raytracer;
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
@@ -165,9 +167,10 @@ bool Intersection::is_defined(void)
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
IntersectionData Intersection::prepare_computations(const Ray &a_ray) const
|
IntersectionData Intersection::prepare_computations(const Ray &a_ray, Intersections *a_collection) const
|
||||||
{
|
{
|
||||||
IntersectionData the_data;
|
IntersectionData the_data;
|
||||||
|
std::vector<Shape *> the_container;
|
||||||
|
|
||||||
// Copy intersections properties for convenance
|
// Copy intersections properties for convenance
|
||||||
the_data.set_distance_t(m_distance_t);
|
the_data.set_distance_t(m_distance_t);
|
||||||
@@ -181,5 +184,26 @@ IntersectionData Intersection::prepare_computations(const Ray &a_ray) const
|
|||||||
the_data.set_inside();
|
the_data.set_inside();
|
||||||
the_data.set_reflectv(a_ray.direction().reflect(the_data.normalv()));
|
the_data.set_reflectv(a_ray.direction().reflect(the_data.normalv()));
|
||||||
|
|
||||||
|
if (a_collection == nullptr)
|
||||||
|
{
|
||||||
|
return the_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manage the container
|
||||||
|
for (const Intersection &the_it : a_collection->data())
|
||||||
|
{
|
||||||
|
if (the_it == a_collection->hit())
|
||||||
|
{
|
||||||
|
if (the_container.empty())
|
||||||
|
{
|
||||||
|
the_data.set_n1(1.0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return the_data;
|
return the_data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,8 @@
|
|||||||
|
|
||||||
namespace Raytracer
|
namespace Raytracer
|
||||||
{
|
{
|
||||||
|
class Intersections;
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
class Intersection
|
class Intersection
|
||||||
@@ -60,7 +62,7 @@ namespace Raytracer
|
|||||||
bool is_nothing(void);
|
bool is_nothing(void);
|
||||||
bool is_defined(void);
|
bool is_defined(void);
|
||||||
|
|
||||||
IntersectionData prepare_computations(const Ray &a_ray) const;
|
IntersectionData prepare_computations(const Ray &a_ray, Intersections *a_collection = nullptr) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_is_nothing;
|
bool m_is_nothing;
|
||||||
|
|||||||
@@ -95,6 +95,13 @@ const Intersections &Intersections::operator+=(const Intersections &an_other)
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
const std::vector<Intersection> &Intersections::data(void) const
|
||||||
|
{
|
||||||
|
return m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
bool Intersections::add(const Intersection &an_intersection)
|
bool Intersections::add(const Intersection &an_intersection)
|
||||||
{
|
{
|
||||||
m_data.push_back(an_intersection);
|
m_data.push_back(an_intersection);
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ namespace Raytracer
|
|||||||
const Intersections &operator=(const Intersections &an_other);
|
const Intersections &operator=(const Intersections &an_other);
|
||||||
const Intersections &operator+=(const Intersections &an_other);
|
const Intersections &operator+=(const Intersections &an_other);
|
||||||
|
|
||||||
|
const std::vector<Intersection> &data(void) const;
|
||||||
|
|
||||||
bool add(const Intersection &an_intersection);
|
bool add(const Intersection &an_intersection);
|
||||||
|
|
||||||
uint8_t count(void) const;
|
uint8_t count(void) const;
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#include "core/common.h"
|
||||||
#include "core/matrix.h"
|
#include "core/matrix.h"
|
||||||
|
|
||||||
#include "shapes/shape.h"
|
#include "shapes/shape.h"
|
||||||
@@ -177,7 +178,7 @@ Color World::reflected_color(const IntersectionData &a_data, uint32_t a_remaingi
|
|||||||
return Color(0, 0, 0);
|
return Color(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a_data.object()->material().reflective() == 0.0)
|
if (double_equal(a_data.object()->material().reflective(), 0.0))
|
||||||
{
|
{
|
||||||
return Color(0, 0, 0);
|
return Color(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -256,7 +256,7 @@ SCENARIO("The reflected color at the maximum recursive depth", "[features/world.
|
|||||||
AND_GIVEN("shape is added to w")
|
AND_GIVEN("shape is added to w")
|
||||||
{
|
{
|
||||||
w.add_object(&shape);
|
w.add_object(&shape);
|
||||||
AND_GIVEN("ray(point(0, 0, -3), vector(0, -sqrt(2) / 2, sqrt(2) / 2)")
|
AND_GIVEN("r <- ray(point(0, 0, -3), vector(0, -sqrt(2) / 2, sqrt(2) / 2)")
|
||||||
{
|
{
|
||||||
Ray r(Tuple::Point(0, 0, -3), Tuple::Vector(0, -sqrt(2) / 2, sqrt(2) / 2));
|
Ray r(Tuple::Point(0, 0, -3), Tuple::Vector(0, -sqrt(2) / 2, sqrt(2) / 2));
|
||||||
AND_GIVEN("i <- intersection(sqrt(2), shape)")
|
AND_GIVEN("i <- intersection(sqrt(2), shape)")
|
||||||
@@ -320,3 +320,93 @@ SCENARIO("A helper for producing a sphere with a glassy material", "[features/sp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
struct TestData
|
||||||
|
{
|
||||||
|
Intersection i;
|
||||||
|
double n1;
|
||||||
|
double n2;
|
||||||
|
};
|
||||||
|
|
||||||
|
void fill_test_various(TestData *a_test, const Intersection &an_in, double a_n1, double a_n2)
|
||||||
|
{
|
||||||
|
a_test->i = an_in;
|
||||||
|
a_test->n1 = a_n1;
|
||||||
|
a_test->n2 = a_n2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
SCENARIO("Finding n1 and n2 at various intersections", "[features/intersections.feature]")
|
||||||
|
{
|
||||||
|
|
||||||
|
TestData the_tests[6];
|
||||||
|
|
||||||
|
GIVEN("A <- glass_sphere() with:")
|
||||||
|
// | transform | scaling(2, 2, 2) |
|
||||||
|
// | material.refractive_index | 1.5 |
|
||||||
|
{
|
||||||
|
Sphere A = Sphere::Glass();
|
||||||
|
A.set_transform(Matrix::scaling(2, 2, 2));
|
||||||
|
A.material().set_refractive_index(1.5);
|
||||||
|
GIVEN("B <- glass_sphere() with:")
|
||||||
|
// | transform | translation(0, 0, -0.25) |
|
||||||
|
// | material.refractive_index | 2.0 |
|
||||||
|
{
|
||||||
|
Sphere B = Sphere::Glass();
|
||||||
|
B.set_transform(Matrix::translation(0, 0, -0.25));
|
||||||
|
B.material().set_refractive_index(2.0);
|
||||||
|
GIVEN("C <- glass_sphere() with:")
|
||||||
|
// | transform | translation(0, 0, 0.25) |
|
||||||
|
// | material.refractive_index | 2.5 |
|
||||||
|
{
|
||||||
|
Sphere C = Sphere::Glass();
|
||||||
|
C.set_transform(Matrix::translation(0, 0, 0.25));
|
||||||
|
C.material().set_refractive_index(2.5);
|
||||||
|
AND_GIVEN("r <- ray(point(0, 0, -4), vector(0, 0, 1)")
|
||||||
|
{
|
||||||
|
Ray r(Tuple::Point(0, 0, -4), Tuple::Vector(0, 0, 1));
|
||||||
|
|
||||||
|
AND_GIVEN("xs <- intersections(2:A, 2.75:B, 3.25:C, 4.75:B, 5.25:C, 6:A)")
|
||||||
|
{
|
||||||
|
// Examples:
|
||||||
|
// | index | n1 | n2 |
|
||||||
|
// | 0 |1.0 |1.5 |
|
||||||
|
// | 1 |1.5 |2.0 |
|
||||||
|
// | 2 |2.0 |2.5 |
|
||||||
|
// | 3 |2.5 |2.5 |
|
||||||
|
// | 4 |2.5 |1.5 |
|
||||||
|
// | 5 |1.5 |1.0 |
|
||||||
|
fill_test_various(&the_tests[0], Intersection(2.0, &A), 1.0, 1.5);
|
||||||
|
fill_test_various(&the_tests[1], Intersection(2.75, &B), 1.5, 2.0);
|
||||||
|
fill_test_various(&the_tests[2], Intersection(3.25, &C), 2.0, 2.5);
|
||||||
|
fill_test_various(&the_tests[3], Intersection(4.75, &B), 2.5, 2.5);
|
||||||
|
fill_test_various(&the_tests[4], Intersection(5.25, &C), 2.5, 1.5);
|
||||||
|
fill_test_various(&the_tests[5], Intersection(6.0, &A), 1.5, 1.0);
|
||||||
|
|
||||||
|
Intersections xs = Intersections({the_tests[0].i, the_tests[1].i, the_tests[2].i, the_tests[3].i,
|
||||||
|
the_tests[4].i, the_tests[5].i});
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
WHEN("comps <- prepare_computations(xs[index], r, xs)")
|
||||||
|
{
|
||||||
|
IntersectionData comps = the_tests[i].i.prepare_computations(r, &xs);
|
||||||
|
THEN("comps.n1 = <n1>")
|
||||||
|
{
|
||||||
|
REQUIRE(comps.n1() == the_tests[i].n1);
|
||||||
|
}
|
||||||
|
AND_THEN("comps.n2 = <n2>")
|
||||||
|
{
|
||||||
|
REQUIRE(comps.n2() == the_tests[i].n2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user