diff --git a/README.md b/README.md index c56b6c7..0b3bfc1 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ +[![Build Status](https://drone.nadal-fr.com/api/badges/raytracing/raytracing_challenge/status.svg)](https://drone.nadal-fr.com/raytracing/raytracing_challenge) + ## Le Livre est ici: https://lire.amazon.fr/?asin=B07Q84TQ91&ref_=kwl_kr_iv_rec_1 diff --git a/raytracing/CMakeLists.txt b/raytracing/CMakeLists.txt index 9abf8dd..ebf7be1 100644 --- a/raytracing/CMakeLists.txt +++ b/raytracing/CMakeLists.txt @@ -11,6 +11,7 @@ add_library(raytracing src/common.cpp src/color.cpp src/intersection.cpp + src/intersections.cpp src/matrix.cpp src/object.cpp src/ray.cpp diff --git a/raytracing/include/raytracing.h b/raytracing/include/raytracing.h index 5054042..3189aa2 100644 --- a/raytracing/include/raytracing.h +++ b/raytracing/include/raytracing.h @@ -28,6 +28,7 @@ #include "color.h" #include "common.h" #include "intersection.h" +#include "intersections.h" #include "matrix.h" #include "ray.h" #include "sphere.h" diff --git a/raytracing/src/intersection.cpp b/raytracing/src/intersection.cpp index 650cf0b..8024eda 100644 --- a/raytracing/src/intersection.cpp +++ b/raytracing/src/intersection.cpp @@ -34,12 +34,41 @@ using namespace Raytracer; /* ------------------------------------------------------------------------- */ +Intersection::Intersection(void) : m_distance_t(0.0) +{ +} + +/* ------------------------------------------------------------------------- */ + Intersection::Intersection(double a_distance_t, Object an_object) : m_distance_t(a_distance_t), m_object(an_object) { } /* ------------------------------------------------------------------------- */ +Intersection::Intersection(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) + { + return *this; + } + + m_distance_t = an_intersection.m_distance_t; + m_object = an_intersection.m_object; + + return *this; +} + +/* ------------------------------------------------------------------------- */ + double Intersection::distance_t(void) { return m_distance_t; diff --git a/raytracing/src/intersection.h b/raytracing/src/intersection.h index 435f39a..c62a59a 100644 --- a/raytracing/src/intersection.h +++ b/raytracing/src/intersection.h @@ -37,7 +37,11 @@ namespace Raytracer class Intersection { public: + Intersection(void); Intersection(double a_distance_t, Object an_object); + Intersection(Intersection &an_intersection); + + const Intersection &operator=(const Intersection &an_intersection); double distance_t(void); Object &object(void); diff --git a/raytracing/src/intersections.cpp b/raytracing/src/intersections.cpp new file mode 100644 index 0000000..2e53129 --- /dev/null +++ b/raytracing/src/intersections.cpp @@ -0,0 +1,107 @@ +/*! + * intersections.cpp + * + * Copyright (c) 2024, NADAL Jean-Baptiste. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * @Author: NADAL Jean-Baptiste + * @Date: 12/02/2024 + * + */ + +// This is an independent project of an individual developer. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com + +/* ------------------------------------------------------------------------- */ + +#include "intersections.h" + +using namespace Raytracer; + +/* ------------------------------------------------------------------------- */ + +Intersections::Intersections(void) : m_count(0) +{ +} + +/* ------------------------------------------------------------------------- */ + +Intersections::Intersections(const Intersection &an_intersection1, const Intersection &an_intersection2) +{ + 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; +} + +/* ------------------------------------------------------------------------- */ + +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; +} + +/* ------------------------------------------------------------------------- */ + +Intersection &Intersections::operator[](uint8_t an_index) +{ + return m_array[an_index]; +} + +/* ------------------------------------------------------------------------- */ + +const Intersections &Intersections::operator=(const Intersections &an_other) +{ + if (this == &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; + + return *this; +} + +/* ------------------------------------------------------------------------- */ + +bool Intersections::set(Intersection an_intersection1, Intersection an_intersection2) +{ + m_array[0] = an_intersection1; + m_array[1] = an_intersection2; + m_count = 2; + + return true; +} + +/* ------------------------------------------------------------------------- */ + +uint8_t Intersections::count(void) const +{ + return m_count; +} diff --git a/raytracing/src/intersections.h b/raytracing/src/intersections.h new file mode 100644 index 0000000..a98fe54 --- /dev/null +++ b/raytracing/src/intersections.h @@ -0,0 +1,60 @@ +/*! + * intersections.h + * + * Copyright (c) 2024, NADAL Jean-Baptiste. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * @Author: NADAL Jean-Baptiste + * @Date: 12/02/2024 + * + */ + +#ifndef _RAYTRACER_INTERSECTIONS_H +#define _RAYTRACER_INTERSECTIONS_H + +/* ------------------------------------------------------------------------- */ + +#include + +#include "intersection.h" + +/* ------------------------------------------------------------------------- */ + +namespace Raytracer +{ + class Intersections + { + public: + Intersections(void); + Intersections(const Intersection &an_intersection1, const Intersection &an_intersection2); + Intersections(Intersection &an_intersection1, Intersection &an_intersection2); + 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); + + uint8_t count(void) const; + + private: + uint8_t m_count; + Intersection m_array[2]; + }; +}; // namespace Raytracer + +#endif // _RAYTRACER_INTERSECTION_H diff --git a/raytracing/src/ray.cpp b/raytracing/src/ray.cpp index b2ce9e6..5b9cf27 100644 --- a/raytracing/src/ray.cpp +++ b/raytracing/src/ray.cpp @@ -64,9 +64,9 @@ Tuple Ray::position(double a_distance) /* ------------------------------------------------------------------------- */ -std::vector Ray::intersect(Sphere a_sphere) +Intersections Ray::intersect(Sphere a_sphere) { - std::vector the_result; + Intersections the_intersections; Tuple the_sphere_to_ray = m_origin - Tuple::Point(0, 0, 0); double the_a = m_direction.dot(m_direction); @@ -74,13 +74,15 @@ std::vector Ray::intersect(Sphere a_sphere) double the_c = the_sphere_to_ray.dot(the_sphere_to_ray) - 1; double discriminant = std::pow(the_b, 2) - 4 * the_a * the_c; + double the_sqrt = std::sqrt(discriminant); if (discriminant >= 0) { - the_result.resize(2); - the_result[0] = (-the_b - std::sqrt(discriminant)) / (2 * the_a); - the_result[1] = (-the_b + std::sqrt(discriminant)) / (2 * the_a); + the_intersections.set(Intersection((-the_b - the_sqrt) / (2 * the_a), a_sphere), + Intersection((-the_b + the_sqrt) / (2 * the_a), a_sphere) + + ); } - return the_result; + return the_intersections; } diff --git a/raytracing/src/ray.h b/raytracing/src/ray.h index 0022a03..f3f930e 100644 --- a/raytracing/src/ray.h +++ b/raytracing/src/ray.h @@ -30,6 +30,7 @@ #include +#include "intersections.h" #include "sphere.h" #include "tuple.h" @@ -46,7 +47,7 @@ namespace Raytracer const Tuple &direction(void) const; Tuple position(double a_distance); - std::vector intersect(Sphere a_sphere); + Intersections intersect(Sphere a_sphere); private: Tuple m_origin; diff --git a/tests/05_rays.cpp b/tests/05_rays.cpp index 78f3790..a259c67 100644 --- a/tests/05_rays.cpp +++ b/tests/05_rays.cpp @@ -63,11 +63,11 @@ TEST_CASE("[05][Rays] a ray intersects a sphere at two points", "[Sphere]") { Ray r(Tuple::Point(0, 0, -5), Tuple::Vector(0, 0, 1)); Sphere s; - auto xs = r.intersect(s); + Intersections xs = r.intersect(s); - REQUIRE(xs.size() == 2); - REQUIRE(xs[0] == 4.0); - REQUIRE(xs[1] == 6.0); + REQUIRE(xs.count() == 2); + REQUIRE(xs[0].distance_t() == 4.0); + REQUIRE(xs[1].distance_t() == 6.0); } /* ------------------------------------------------------------------------- */ @@ -76,11 +76,11 @@ TEST_CASE("[05][Rays] a ray intersects a sphere at a tangent", "[Sphere]") { Ray r(Tuple::Point(0, 1, -5), Tuple::Vector(0, 0, 1)); Sphere s; - auto xs = r.intersect(s); + Intersections xs = r.intersect(s); - REQUIRE(xs.size() == 2); - REQUIRE(xs[0] == 5.0); - REQUIRE(xs[1] == 5.0); + REQUIRE(xs.count() == 2); + REQUIRE(xs[0].distance_t() == 5.0); + REQUIRE(xs[1].distance_t() == 5.0); } /* ------------------------------------------------------------------------- */ @@ -89,9 +89,9 @@ TEST_CASE("[05][Rays] a ray misses a sphere", "[Sphere]") { Ray r(Tuple::Point(0, 2, -5), Tuple::Vector(0, 0, 1)); Sphere s; - auto xs = r.intersect(s); + Intersections xs = r.intersect(s); - REQUIRE(xs.size() == 0); + REQUIRE(xs.count() == 0); } /* ------------------------------------------------------------------------- */ @@ -100,11 +100,11 @@ TEST_CASE("[05][Rays] a originates inside a sphere", "[Sphere]") { Ray r(Tuple::Point(0, 0, 0), Tuple::Vector(0, 0, 1)); Sphere s; - auto xs = r.intersect(s); + Intersections xs = r.intersect(s); - REQUIRE(xs.size() == 2); - REQUIRE(xs[0] == -1.0); - REQUIRE(xs[1] == 1.0); + REQUIRE(xs.count() == 2); + REQUIRE(xs[0].distance_t() == -1.0); + REQUIRE(xs[1].distance_t() == 1.0); } /* ------------------------------------------------------------------------- */ @@ -113,11 +113,11 @@ TEST_CASE("[05][Rays] a sphere is behind a ray", "[Sphere]") { Ray r(Tuple::Point(0, 0, 5), Tuple::Vector(0, 0, 1)); Sphere s; - auto xs = r.intersect(s); + Intersections xs = r.intersect(s); - REQUIRE(xs.size() == 2); - REQUIRE(xs[0] == -6.0); - REQUIRE(xs[1] == -4.0); + REQUIRE(xs.count() == 2); + REQUIRE(xs[0].distance_t() == -6.0); + REQUIRE(xs[1].distance_t() == -4.0); } /* ------------------------------------------------------------------------- */ @@ -143,7 +143,6 @@ TEST_CASE("[05][Rays] An intersection encapsulates t and object", "[Intersection REQUIRE(i.object() == s); } -#if 0 /* ------------------------------------------------------------------------- */ TEST_CASE("[05][Rays] Aggregating intersections", "[Intersections]") @@ -154,7 +153,19 @@ TEST_CASE("[05][Rays] Aggregating intersections", "[Intersections]") Intersections xs = Intersections(i1, i2); REQUIRE(xs.count() == 2); - REQUIRE(xs[0].t() == 1); - REQUIRE(xs[1].t() == 2); + REQUIRE(xs[0].distance_t() == 1); + REQUIRE(xs[1].distance_t() == 2); +} + +/* ------------------------------------------------------------------------- */ + +TEST_CASE("[05][Rays] Intersect set the object on the intersection", "[Intersections]") +{ + Ray r(Tuple::Point(0, 0, 5), Tuple::Vector(0, 0, 1)); + Sphere s; + Intersections xs = r.intersect(s); + + REQUIRE(xs.count() == 2); + REQUIRE(xs[0].object() == s); + REQUIRE(xs[1].object() == s); } -#endif \ No newline at end of file