[FEAT] add world.color_at
This commit is contained in:
@@ -112,21 +112,25 @@ uint8_t Intersections::count(void) const
|
||||
|
||||
Intersection Intersections::hit(void)
|
||||
{
|
||||
Intersection the_current_int;
|
||||
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)
|
||||
for (const Intersection &the_it : m_data)
|
||||
{
|
||||
if (the_it.distance_t() > 0 &&
|
||||
(the_current_int.is_nothing() || the_it.distance_t() < the_current_int.distance_t()))
|
||||
{
|
||||
the_current_int = the_it;
|
||||
}
|
||||
}
|
||||
|
||||
if (the_current_int.is_nothing())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return *the_it;
|
||||
return the_current_int;
|
||||
}
|
||||
|
||||
@@ -163,6 +163,31 @@ Color World::shade_hit(const IntersectionData &an_intersection_data)
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
Color World::color_at(const Ray &a_ray)
|
||||
{
|
||||
Color the_color = Color::Black();
|
||||
|
||||
Intersections the_intersections = intersect_world(a_ray);
|
||||
if (the_intersections.count() == 0)
|
||||
{
|
||||
return the_color;
|
||||
}
|
||||
|
||||
Intersection the_intersec = the_intersections.hit();
|
||||
if (the_intersec.is_nothing())
|
||||
{
|
||||
return the_color;
|
||||
}
|
||||
|
||||
IntersectionData the_comps = the_intersec.prepare_computations(a_ray);
|
||||
|
||||
the_color = shade_hit(the_comps);
|
||||
|
||||
return the_color;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
World World::default_world(void)
|
||||
{
|
||||
World the_world;
|
||||
|
||||
@@ -62,6 +62,7 @@ namespace Raytracer
|
||||
|
||||
Intersections intersect_world(const Ray &a_ray);
|
||||
Color shade_hit(const IntersectionData &an_intersection_data);
|
||||
Color color_at(const Ray &a_ray);
|
||||
|
||||
static World default_world(void);
|
||||
|
||||
|
||||
@@ -308,3 +308,85 @@ SCENARIO("Shading an intersection from the inside", "[features/world.feature]")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
SCENARIO("The color when a ray misses", "[features/world.feature]")
|
||||
{
|
||||
GIVEN("w <- default_world()")
|
||||
{
|
||||
World w = World::default_world();
|
||||
AND_GIVEN("r <- ray(point(0, 0, -5), vector(0, 1, 0))")
|
||||
{
|
||||
Ray r(Tuple::Point(0, 0, -5), Tuple::Vector(0, 1, 0));
|
||||
WHEN("c <- color_at(w, r)")
|
||||
{
|
||||
Color c = w.color_at(r);
|
||||
THEN("c = color(0, 0, 0)")
|
||||
{
|
||||
REQUIRE(c == Color(0, 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
SCENARIO("The color when a ray hits", "[features/world.feature]")
|
||||
{
|
||||
GIVEN("w <- default_world()")
|
||||
{
|
||||
World w = World::default_world();
|
||||
AND_GIVEN("r <- ray(point(0, 0, -5), vector(0, 0, 1))")
|
||||
{
|
||||
Ray r(Tuple::Point(0, 0, -5), Tuple::Vector(0, 0, 1));
|
||||
WHEN("c <- color_at(w, r)")
|
||||
{
|
||||
Color c = w.color_at(r);
|
||||
THEN("c = color(0.38066, 0.47583, 0.2855)")
|
||||
{
|
||||
REQUIRE(c == Color(0.38066, 0.47583, 0.2855));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
SCENARIO("The color with an intersection behind the ray", "[features/world.feature]")
|
||||
{
|
||||
GIVEN("w <- default_world()")
|
||||
{
|
||||
World w = World::default_world();
|
||||
AND_GIVEN("outer <- the first object in w")
|
||||
{
|
||||
Shape *outer = w.objects(0);
|
||||
AND_GIVEN("outer.material.ambient <- 1")
|
||||
{
|
||||
outer->material().set_ambient(1);
|
||||
AND_GIVEN("inner <- the second object in w")
|
||||
{
|
||||
Shape *inner = w.objects(1);
|
||||
AND_GIVEN("inner.material.ambient <- 1")
|
||||
{
|
||||
inner->material().set_ambient(1);
|
||||
AND_GIVEN("r <- ray(point(0, 0, 0.75), vector(0, 0, -1))")
|
||||
{
|
||||
Ray r(Tuple::Point(0, 0, 0.75), Tuple::Vector(0, 0, -1));
|
||||
WHEN("c <- color_at(w, r)")
|
||||
{
|
||||
Color c = w.color_at(r);
|
||||
THEN("c = inner.material.color")
|
||||
{
|
||||
REQUIRE(c == inner->material().color());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user