From 480d8c56da2c20c085b33afdf5dc1bd613ef27c5 Mon Sep 17 00:00:00 2001 From: NADAL Jean-Baptiste Date: Mon, 5 Feb 2024 23:33:48 +0100 Subject: [PATCH] [WIP] Add ray and sphere basic --- raytracing/CMakeLists.txt | 2 + raytracing/include/raytracing.h | 2 + raytracing/src/ray.cpp | 86 +++++++++++++++++++++++ raytracing/src/ray.h | 57 +++++++++++++++ raytracing/src/sphere.cpp | 40 +++++++++++ raytracing/src/sphere.h | 44 ++++++++++++ tests/05_rays.cpp | 121 ++++++++++++++++++++++++++++++++ tests/CMakeLists.txt | 1 + 8 files changed, 353 insertions(+) create mode 100644 raytracing/src/ray.cpp create mode 100644 raytracing/src/ray.h create mode 100644 raytracing/src/sphere.cpp create mode 100644 raytracing/src/sphere.h create mode 100644 tests/05_rays.cpp diff --git a/raytracing/CMakeLists.txt b/raytracing/CMakeLists.txt index e3a14aa..5862210 100644 --- a/raytracing/CMakeLists.txt +++ b/raytracing/CMakeLists.txt @@ -12,6 +12,8 @@ add_library(raytracing src/color.cpp src/canvas.cpp src/matrix.cpp + src/ray.cpp + src/sphere.cpp ) target_include_directories(${PROJECT_NAME} diff --git a/raytracing/include/raytracing.h b/raytracing/include/raytracing.h index 39d8fb8..03ee123 100644 --- a/raytracing/include/raytracing.h +++ b/raytracing/include/raytracing.h @@ -28,4 +28,6 @@ #include "color.h" #include "common.h" #include "matrix.h" +#include "ray.h" +#include "sphere.h" #include "tuple.h" diff --git a/raytracing/src/ray.cpp b/raytracing/src/ray.cpp new file mode 100644 index 0000000..b2ce9e6 --- /dev/null +++ b/raytracing/src/ray.cpp @@ -0,0 +1,86 @@ +/*! + * ray.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: 05/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 + +#include "common.h" +#include "ray.h" + +using namespace Raytracer; + +/* ------------------------------------------------------------------------- */ + +Ray::Ray(Tuple an_origin, Tuple a_direction) : m_origin(an_origin), m_direction(a_direction) +{ +} + +/* ------------------------------------------------------------------------- */ + +const Tuple &Ray::origin(void) const +{ + return m_origin; +} + +/* ------------------------------------------------------------------------- */ + +const Tuple &Ray::direction(void) const +{ + return m_direction; +} + +/* ------------------------------------------------------------------------- */ + +Tuple Ray::position(double a_distance) +{ + return m_origin + m_direction * a_distance; +} + +/* ------------------------------------------------------------------------- */ + +std::vector Ray::intersect(Sphere a_sphere) +{ + std::vector the_result; + Tuple the_sphere_to_ray = m_origin - Tuple::Point(0, 0, 0); + + double the_a = m_direction.dot(m_direction); + double the_b = 2 * m_direction.dot(the_sphere_to_ray); + 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; + + 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); + } + + return the_result; +} diff --git a/raytracing/src/ray.h b/raytracing/src/ray.h new file mode 100644 index 0000000..0022a03 --- /dev/null +++ b/raytracing/src/ray.h @@ -0,0 +1,57 @@ +/*! + * ray.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: 05/02/2024 + * + */ + +#ifndef _RAYTRACER_RAY_H +#define _RAYTRACER_RAY_H + +/* ------------------------------------------------------------------------- */ + +#include + +#include "sphere.h" +#include "tuple.h" + +/* ------------------------------------------------------------------------- */ + +namespace Raytracer +{ + class Ray + { + public: + Ray(Tuple an_origin, Tuple a_direction); + + const Tuple &origin(void) const; + const Tuple &direction(void) const; + + Tuple position(double a_distance); + std::vector intersect(Sphere a_sphere); + + private: + Tuple m_origin; + Tuple m_direction; + }; +}; // namespace Raytracer + +#endif // _RAYTRACER_RAY_H diff --git a/raytracing/src/sphere.cpp b/raytracing/src/sphere.cpp new file mode 100644 index 0000000..e21ab25 --- /dev/null +++ b/raytracing/src/sphere.cpp @@ -0,0 +1,40 @@ +/*! + * sphere.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: 05/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 "sphere.h" +#include "common.h" + +using namespace Raytracer; + +/* ------------------------------------------------------------------------- */ + +Sphere::Sphere(void) +{ +} diff --git a/raytracing/src/sphere.h b/raytracing/src/sphere.h new file mode 100644 index 0000000..27135c9 --- /dev/null +++ b/raytracing/src/sphere.h @@ -0,0 +1,44 @@ +/*! + * sphere.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: 05/02/2024 + * + */ + +#ifndef _RAYTRACER_SPHERE_H +#define _RAYTRACER_SPHERE_H + +/* ------------------------------------------------------------------------- */ + +/* ------------------------------------------------------------------------- */ + +namespace Raytracer +{ + class Sphere + { + public: + Sphere(void); + + private: + }; +}; // namespace Raytracer + +#endif // _RAYTRACER_SPHERE_H diff --git a/tests/05_rays.cpp b/tests/05_rays.cpp new file mode 100644 index 0000000..1f18c92 --- /dev/null +++ b/tests/05_rays.cpp @@ -0,0 +1,121 @@ +/*! + * 05_rays.cpp + * + * Copyright (c) 2015-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: 05/02/2024 + * + */ + +/*---------------------------------------------------------------------------*/ + +#include + +#include "raytracing.h" + +using namespace Raytracer; + +/* ------------------------------------------------------------------------- */ + +/* ------------------------------------------------------------------------- */ + +TEST_CASE("[05][Rays] Creating and querying a ray", "[Rays]") +{ + Tuple origin = Tuple::Point(1, 2, 3); + Tuple direction = Tuple::Vector(4, 5, 6); + Ray r(origin, direction); + + REQUIRE(r.origin() == origin); + REQUIRE(r.direction() == direction); +} + +/* ------------------------------------------------------------------------- */ + +TEST_CASE("[05][Rays] Computing a point from a distance", "[Rays]") +{ + Ray r(Tuple::Point(2, 3, 4), Tuple::Vector(1, 0, 0)); + + REQUIRE(r.position(0) == Tuple::Point(2, 3, 4)); + REQUIRE(r.position(1) == Tuple::Point(3, 3, 4)); + REQUIRE(r.position(-1) == Tuple::Point(1, 3, 4)); + REQUIRE(r.position(2.5) == Tuple::Point(4.5, 3, 4)); +} + +/* ------------------------------------------------------------------------- */ + +TEST_CASE("[05][Rays] a ray intersects a sphere at two points", "[Rays]") +{ + Ray r(Tuple::Point(0, 0, -5), Tuple::Vector(0, 0, 1)); + Sphere s; + auto xs = r.intersect(s); + + REQUIRE(xs.size() == 2); + REQUIRE(xs[0] == 4.0); + REQUIRE(xs[1] == 6.0); +} + +/* ------------------------------------------------------------------------- */ + +TEST_CASE("[05][Rays] a ray intersects a sphere at a tangent", "[Rays]") +{ + Ray r(Tuple::Point(0, 1, -5), Tuple::Vector(0, 0, 1)); + Sphere s; + auto xs = r.intersect(s); + + REQUIRE(xs.size() == 2); + REQUIRE(xs[0] == 5.0); + REQUIRE(xs[1] == 5.0); +} + +/* ------------------------------------------------------------------------- */ + +TEST_CASE("[05][Rays] a ray misses a sphere", "[Rays]") +{ + Ray r(Tuple::Point(0, 2, -5), Tuple::Vector(0, 0, 1)); + Sphere s; + auto xs = r.intersect(s); + + REQUIRE(xs.size() == 0); +} + +/* ------------------------------------------------------------------------- */ + +TEST_CASE("[05][Rays] a originates inside a sphere", "[Rays]") +{ + Ray r(Tuple::Point(0, 0, 0), Tuple::Vector(0, 0, 1)); + Sphere s; + auto xs = r.intersect(s); + + REQUIRE(xs.size() == 2); + REQUIRE(xs[0] == -1.0); + REQUIRE(xs[1] == 1.0); +} + +/* ------------------------------------------------------------------------- */ + +TEST_CASE("[05][Rays] a sphere is behind a ray", "[Rays]") +{ + Ray r(Tuple::Point(0, 0, 5), Tuple::Vector(0, 0, 1)); + Sphere s; + auto xs = r.intersect(s); + + REQUIRE(xs.size() == 2); + REQUIRE(xs[0] == -6.0); + REQUIRE(xs[1] == -4.0); +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a35c2fa..db97323 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -15,6 +15,7 @@ add_executable(main_test 02_2_canvas.cpp 03_matrix.cpp 04_transformations.cpp + 05_rays.cpp ) include_directories("${CMAKE_SOURCE_DIR}/tests")