From 03c825bd3ae2c4d8407e88c1805351512e262cb8 Mon Sep 17 00:00:00 2001 From: NADAL Jean-Baptiste Date: Thu, 14 Mar 2024 17:32:14 +0100 Subject: [PATCH] [FEAT] Add a test for Cube --- raytracing/src/shapes/cube.cpp | 40 ++++++++++++++++++++++++++++ raytracing/src/shapes/cube.h | 3 +++ tests/12_cubes.cpp | 48 ++++++++++++++++++++++++++-------- 3 files changed, 80 insertions(+), 11 deletions(-) diff --git a/raytracing/src/shapes/cube.cpp b/raytracing/src/shapes/cube.cpp index 02ff638..35dd931 100644 --- a/raytracing/src/shapes/cube.cpp +++ b/raytracing/src/shapes/cube.cpp @@ -41,8 +41,19 @@ using namespace Raytracer; Intersections Cube::local_intersect(const Ray &a_ray) { + double the_tmin, the_max; Intersections the_intersections; + const auto [the_xtmin, the_xtmax] = check_axis(a_ray.origin().x(), a_ray.direction().x()); + const auto [the_ytmin, the_ytmax] = check_axis(a_ray.origin().y(), a_ray.direction().y()); + const auto [the_ztmin, the_ztmax] = check_axis(a_ray.origin().z(), a_ray.direction().z()); + + the_tmin = std::max({the_xtmin, the_ytmin, the_ztmin}); + the_max = std::min({the_xtmax, the_ytmax, the_ztmax}); + + the_intersections.add(Intersection(the_tmin, this)); + the_intersections.add(Intersection(the_max, this)); + return the_intersections; } @@ -52,3 +63,32 @@ Tuple Cube::local_normal_at(const Tuple &a_local_point) const { return Tuple::Vector(0, 1, 0); } + +/* ------------------------------------------------------------------------- */ + +std::pair Cube::check_axis(double an_origin, double a_direction) const +{ + double the_tmin, the_tmax; + double the_tmin_numerator, the_tmax_numerator; + + the_tmin_numerator = (-1 - an_origin); + the_tmax_numerator = (1 - an_origin); + + if (std::abs(a_direction) >= kEpsilon) + { + the_tmin = the_tmin_numerator / a_direction; + the_tmax = the_tmax_numerator / a_direction; + } + else + { + the_tmin = the_tmin_numerator * std::numeric_limits::infinity(); + the_tmax = the_tmax_numerator * std::numeric_limits::infinity(); + } + + if (the_tmin > the_tmax) + { + std::swap(the_tmin, the_tmax); + } + + return {the_tmin, the_tmax}; +} diff --git a/raytracing/src/shapes/cube.h b/raytracing/src/shapes/cube.h index 74d7d84..66fd472 100644 --- a/raytracing/src/shapes/cube.h +++ b/raytracing/src/shapes/cube.h @@ -40,6 +40,9 @@ namespace Raytracer Cube(void) = default; Intersections local_intersect(const Ray &a_ray) override; Tuple local_normal_at(const Tuple &a_local_point) const override; + + private: + std::pair check_axis(double an_origin, double a_direction) const; }; }; // namespace Raytracer diff --git a/tests/12_cubes.cpp b/tests/12_cubes.cpp index ddbd9f0..2ad1c02 100644 --- a/tests/12_cubes.cpp +++ b/tests/12_cubes.cpp @@ -33,7 +33,18 @@ using namespace Raytracer; /* ------------------------------------------------------------------------- */ -SCENARIO("Reflectivity for the default material", "[features/cubes.feature]") +class CubeTest +{ +public: + Tuple origin; + Tuple direction; + double t1; + double t2; +}; + +/* ------------------------------------------------------------------------- */ + +SCENARIO("A Ray intersects a cube", "[features/cubes.feature]") { // | | origin | direction | t1 | t2 | // | +x | point(5, 0.5, 0) | vector(-1, 0, 0) | 4 | 6 | @@ -43,6 +54,16 @@ SCENARIO("Reflectivity for the default material", "[features/cubes.feature]") // | +z | point(0.5, 0, 5) | vector( 0, 0,-1) | 4 | 6 | // | -z | point(0.5, 0, -5) | vector( 0, 0, 1) | 4 | 6 | // | inside | point(0, 0.5, 0) | vector( 0, 0, 1) | -1 | -1 | + CubeTest the_test[7] = { + { Tuple::Point(5.0, 0.5, 0.0), Tuple::Vector(-1, 0, 0), 4, 6}, + {Tuple::Point(-5.0, 0.5, 0.0), Tuple::Vector(1, 0, 0), 4, 6}, + { Tuple::Point(0.5, 5.0, 0.0), Tuple::Vector(0, -1, 0), 4, 6}, + { Tuple::Point(0.5, -5.0, 0.0), Tuple::Vector(0, 1, 0), 4, 6}, + { Tuple::Point(0.5, 0.0, 5.0), Tuple::Vector(0, 0, -1), 4, 6}, + { Tuple::Point(0.5, 0.0, -5.0), Tuple::Vector(0, 0, 1), 4, 6}, + { Tuple::Point(0.0, 0.5, 0.0), Tuple::Vector(0, 0, 1), -1, -1} + }; + GIVEN("c <- cube()") { Cube c; @@ -50,17 +71,22 @@ SCENARIO("Reflectivity for the default material", "[features/cubes.feature]") { WHEN("xs <- local_intersect(c,r)") { - THEN("xs.count = 2") + for (int i = 0; i < 7; i++) { - // REQUIRE(); - } - AND_THEN("xs[0].t = ") - { - // REQUIRE(); - } - AND_THEN("xs[1].t = ") - { - // REQUIRE(); + Ray r(the_test[i].origin, the_test[i].direction); + Intersections xs = c.local_intersect(r); + THEN("xs.count = 2") + { + REQUIRE(xs.count() == 2); + } + AND_THEN("xs[0].t = ") + { + REQUIRE(xs[0].distance_t() == the_test[i].t1); + } + AND_THEN("xs[1].t = ") + { + REQUIRE(xs[1].distance_t() == the_test[i].t2); + } } } }