diff --git a/raytracing/CMakeLists.txt b/raytracing/CMakeLists.txt index 10f2158..918efec 100644 --- a/raytracing/CMakeLists.txt +++ b/raytracing/CMakeLists.txt @@ -9,6 +9,7 @@ add_definitions(--coverage) add_library(raytracing + src/camera.cpp src/canvas.cpp src/color.cpp src/common.cpp diff --git a/raytracing/include/raytracing.h b/raytracing/include/raytracing.h index cf71cab..90633d5 100644 --- a/raytracing/include/raytracing.h +++ b/raytracing/include/raytracing.h @@ -25,6 +25,7 @@ #pragma once +#include "camera.h" #include "canvas.h" #include "color.h" #include "common.h" diff --git a/raytracing/src/camera.cpp b/raytracing/src/camera.cpp new file mode 100644 index 0000000..d893b2c --- /dev/null +++ b/raytracing/src/camera.cpp @@ -0,0 +1,96 @@ +/*! + * camera.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: 23/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 "camera.h" + +using namespace Raytracer; + +/* ------------------------------------------------------------------------- */ + +Camera::Camera(uint16_t a_h_size, uint16_t a_v_size, double a_field_of_view) : + m_h_size(a_h_size), + m_v_size(a_v_size), + m_field_of_view(a_field_of_view), + m_half_width(0), + m_half_height(0), + m_pixel_size(0) +{ + double the_half_view = tan(m_field_of_view / 2); + double the_aspect_ratio = (double)m_h_size / m_v_size; + + if (the_aspect_ratio >= 1) + { + m_half_width = the_half_view; + m_half_height = the_half_view / the_aspect_ratio; + } + else + { + m_half_width = the_half_view * the_aspect_ratio; + m_half_height = the_half_view; + } + m_pixel_size = ceil(((m_half_width * 2) / m_h_size) * 100) / 100; +} + +/* ------------------------------------------------------------------------- */ + +uint16_t Camera::hsize(void) const +{ + return m_h_size; +} + +/* ------------------------------------------------------------------------- */ + +uint16_t Camera::vsize(void) const +{ + return m_v_size; +} + +/* ------------------------------------------------------------------------- */ + +double Camera::field_of_view(void) const +{ + return m_field_of_view; +} + +/* ------------------------------------------------------------------------- */ + +Matrix &Camera::transform(void) +{ + return m_transform; +} + +/* ------------------------------------------------------------------------- */ + +double Camera::pixel_size(void) +{ + return m_pixel_size; +} diff --git a/raytracing/src/camera.h b/raytracing/src/camera.h new file mode 100644 index 0000000..5303056 --- /dev/null +++ b/raytracing/src/camera.h @@ -0,0 +1,63 @@ +/*! + * camera.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: 23/02/2024 + * + */ + +#ifndef _RAYTRACER_CAMERA_H +#define _RAYTRACER_CAMERA_H + +/* ------------------------------------------------------------------------- */ + +#include + +#include "matrix.h" + +/* ------------------------------------------------------------------------- */ + +namespace Raytracer +{ + class Camera + { + public: + Camera(uint16_t a_h_size, uint16_t a_v_size, double a_field_of_view); + + uint16_t hsize(void) const; + uint16_t vsize(void) const; + double field_of_view(void) const; + Matrix &transform(void); + + double pixel_size(void); + + private: + uint16_t m_h_size; + + uint16_t m_v_size; + double m_field_of_view; + Matrix m_transform; + double m_half_width; + double m_half_height; + double m_pixel_size; + }; +}; // namespace Raytracer + +#endif /* _RAYTRACER_CAMERA_H */ \ No newline at end of file diff --git a/tests/07_making_scene.cpp b/tests/07_making_scene.cpp index d0a17d2..8eb4e1d 100644 --- a/tests/07_making_scene.cpp +++ b/tests/07_making_scene.cpp @@ -503,3 +503,69 @@ SCENARIO("An arbitrary view transformation", "[features/transformations.feature] } } } + +/* ------------------------------------------------------------------------- */ + +SCENARIO("Constructing a camera", "[features/camera.feature]") +{ + GIVEN("hsize <- 160") + { + uint16_t hsize = 160; + AND_GIVEN("vsize <- 120") + { + uint16_t vsize = 120; + AND_GIVEN("field_of_view <- pi / 2") + { + double field_of_view = std::numbers::pi / 2; + WHEN("c <- camera(hsize, vsize,field_of_view)") + { + Camera c(hsize, vsize, field_of_view); + THEN("c.hsize = 160") + { + REQUIRE(c.hsize() == 160); + } + AND_THEN("c.vsize = 120") + { + REQUIRE(c.vsize() == 120); + } + AND_THEN("c.field_of_view = pi / 2") + { + REQUIRE(c.field_of_view() == std::numbers::pi / 2); + } + AND_THEN("c.transform = identity_matrix") + { + REQUIRE(c.transform() == Matrix::identity()); + } + } + } + } + } +} + +/* ------------------------------------------------------------------------- */ + +SCENARIO("The pixel size for a horizontal canvas", "[features/camera.feature]") +{ + GIVEN("c <- camera(200, 125, pi/2)") + { + Camera c(200, 125, std::numbers::pi / 2); + THEN("c.pixel_size = 0.01") + { + REQUIRE(c.pixel_size() == 0.01); + } + } +} + +/* ------------------------------------------------------------------------- */ + +SCENARIO("The pixel size for a vertical canvas", "[features/camera.feature]") +{ + GIVEN("c <- camera(125, 200, pi/2)") + { + Camera c(125, 200, std::numbers::pi / 2); + THEN("c.pixel_size = 0.01") + { + REQUIRE(c.pixel_size() == 0.01); + } + } +}