diff --git a/raytracing/CMakeLists.txt b/raytracing/CMakeLists.txt index 366622d..293dcce 100644 --- a/raytracing/CMakeLists.txt +++ b/raytracing/CMakeLists.txt @@ -14,7 +14,9 @@ add_library(raytracing src/color.cpp src/intersection.cpp src/intersections.cpp + src/material.cpp src/matrix.cpp + src/point-light.cpp src/shape.cpp src/ray.cpp src/sphere.cpp diff --git a/raytracing/include/raytracing.h b/raytracing/include/raytracing.h index 1070b31..1621d16 100644 --- a/raytracing/include/raytracing.h +++ b/raytracing/include/raytracing.h @@ -30,7 +30,9 @@ #include "common.h" #include "intersection.h" #include "intersections.h" +#include "material.h" #include "matrix.h" +#include "point-light.h" #include "ray.h" #include "sphere.h" #include "tuple.h" diff --git a/raytracing/src/material.cpp b/raytracing/src/material.cpp new file mode 100644 index 0000000..3ea7b14 --- /dev/null +++ b/raytracing/src/material.cpp @@ -0,0 +1,113 @@ +/*! + * material.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: 19/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 "common.h" + +#include "material.h" + +using namespace Raytracer; + +/* ------------------------------------------------------------------------- */ + +Material::Material(void) : m_color(1, 1, 1), m_ambient(0.1), m_diffuse(0.9), m_specular(0.9), m_shininess(200) +{ +} + +/* ------------------------------------------------------------------------- */ + +bool Material::operator==(const Material &a_material) const +{ + return (m_color == a_material.m_color) && double_equal(m_ambient, a_material.m_ambient) && + double_equal(m_diffuse, a_material.m_diffuse) && double_equal(m_specular, a_material.m_specular) && + double_equal(m_shininess, a_material.m_shininess); +} + +/* ------------------------------------------------------------------------- */ + +const Color &Material::color(void) const +{ + return m_color; +} + +/* ------------------------------------------------------------------------- */ + +const double &Material::ambient(void) const +{ + return m_ambient; +} + +/* ------------------------------------------------------------------------- */ + +void Material::set_ambient(double a_value) +{ + m_ambient = a_value; +} + +/* ------------------------------------------------------------------------- */ + +const double &Material::diffuse(void) const +{ + return m_diffuse; +} + +/* ------------------------------------------------------------------------- */ + +void Material::set_diffuse(double a_value) +{ + m_diffuse = a_value; +} + +/* ------------------------------------------------------------------------- */ + +const double &Material::specular(void) const +{ + return m_specular; +} + +/* ------------------------------------------------------------------------- */ + +void Material::set_specular(double a_value) +{ + m_specular = a_value; +} + +/* ------------------------------------------------------------------------- */ + +const double &Material::shininess(void) const +{ + return m_shininess; +} + +/* ------------------------------------------------------------------------- */ + +void Material::set_shininess(double a_value) +{ + m_shininess = a_value; +} diff --git a/raytracing/src/material.h b/raytracing/src/material.h new file mode 100644 index 0000000..4efd17d --- /dev/null +++ b/raytracing/src/material.h @@ -0,0 +1,67 @@ +/*! + * material.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: 19/02/2024 + * + */ + +#ifndef _RAYTRACER_MATERIAL_H +#define _RAYTRACER_MATERIAL_H + +/* ------------------------------------------------------------------------- */ + +#include "color.h" + +/* ------------------------------------------------------------------------- */ + +namespace Raytracer +{ + class Material + { + public: + Material(void); + + bool operator==(const Material &a_material) const; + + const Color &color(void) const; + + const double &ambient(void) const; + void set_ambient(double a_value); + + const double &diffuse(void) const; + void set_diffuse(double a_value); + + const double &specular(void) const; + void set_specular(double a_value); + + const double &shininess(void) const; + void set_shininess(double a_value); + + private: + Color m_color; + double m_ambient; + double m_diffuse; + double m_specular; + double m_shininess; + }; +}; // namespace Raytracer + +#endif /* _RAYTRACER_MATERIAL_H */ diff --git a/raytracing/src/point-light.cpp b/raytracing/src/point-light.cpp new file mode 100644 index 0000000..cab3c1b --- /dev/null +++ b/raytracing/src/point-light.cpp @@ -0,0 +1,57 @@ +/*! + * point-light.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: 19/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 "common.h" + +#include "point-light.h" + +using namespace Raytracer; + +/* ------------------------------------------------------------------------- */ + +PointLight::PointLight(const Tuple &a_position, const Color &an_intensity) : + m_position(a_position), + m_intensity(an_intensity) +{ +} + +/* ------------------------------------------------------------------------- */ + +const Tuple &PointLight::position(void) const +{ + return m_position; +} + +/* ------------------------------------------------------------------------- */ + +const Color &PointLight::intensity(void) const +{ + return m_intensity; +} diff --git a/raytracing/src/point-light.h b/raytracing/src/point-light.h new file mode 100644 index 0000000..4562580 --- /dev/null +++ b/raytracing/src/point-light.h @@ -0,0 +1,52 @@ +/*! + * point-light.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: 19/02/2024 + * + */ + +#ifndef _RAYTRACER_POINT_LIGHT_H +#define _RAYTRACER_POINT_LIGHT_H + +/* ------------------------------------------------------------------------- */ + +#include "color.h" +#include "tuple.h" + +/* ------------------------------------------------------------------------- */ + +namespace Raytracer +{ + class PointLight + { + public: + PointLight(const Tuple &a_position, const Color &an_intensity); + + const Tuple &position(void) const; + const Color &intensity(void) const; + + private: + Tuple m_position; + Color m_intensity; + }; +}; // namespace Raytracer + +#endif /* _RAYTRACER_POINT_LIGHT_H */ diff --git a/raytracing/src/shape.cpp b/raytracing/src/shape.cpp index 064af6c..9af2d2e 100644 --- a/raytracing/src/shape.cpp +++ b/raytracing/src/shape.cpp @@ -96,6 +96,20 @@ void Shape::set_transform(const Matrix &a_transform_matrix) /* ------------------------------------------------------------------------- */ +const Material &Shape::material(void) const +{ + return m_material; +} + +/* ------------------------------------------------------------------------- */ + +void Shape::set_material(const Material &a_material) +{ + m_material = a_material; +} + +/* ------------------------------------------------------------------------- */ + Tuple Shape::normal_at(const Tuple &a_world_point) { Tuple the_object_point = m_transform.inverse() * a_world_point; diff --git a/raytracing/src/shape.h b/raytracing/src/shape.h index ba60887..8bd21fe 100644 --- a/raytracing/src/shape.h +++ b/raytracing/src/shape.h @@ -30,6 +30,7 @@ #include +#include "material.h" #include "matrix.h" #include "ray.h" @@ -54,6 +55,9 @@ namespace Raytracer Matrix &transform(void); void set_transform(const Matrix &a_transform_matrix); + const Material &material(void) const; + void set_material(const Material &a_material); + Tuple normal_at(const Tuple &a_point); virtual Intersections intersect(Ray &a_ray); @@ -64,6 +68,7 @@ namespace Raytracer private: uint32_t m_id; Matrix m_transform; + Material m_material; static uint32_t s_current_index; }; }; // namespace Raytracer diff --git a/tests/06_light_shading.cpp b/tests/06_light_shading.cpp index 78b40c8..400e387 100644 --- a/tests/06_light_shading.cpp +++ b/tests/06_light_shading.cpp @@ -212,3 +212,103 @@ SCENARIO("Reflecting a vector off a slanted surface", "[features/tuples.feature] } } } + +/* ------------------------------------------------------------------------- */ + +SCENARIO("A point light has a position and intensity", "[features/lights.feature]") +{ + GIVEN("intensity <- color(1, 1, 1)") + { + Color intensity(1, 1, 1); + AND_GIVEN("position <- point(0, 0, 0)") + { + Tuple position = Tuple::Point(0, 0, 0); + WHEN("light <- point_light(position(position, intensity))") + { + PointLight light = PointLight(position, intensity); + THEN("light.position = position") + { + REQUIRE(light.position() == position); + } + AND_THEN("light.intensity = intensity") + { + REQUIRE(light.intensity() == intensity); + } + } + } + } +} + +/* ------------------------------------------------------------------------- */ + +SCENARIO("The default material", "[features/materials.feature]") +{ + GIVEN("m <- material()") + { + Material m; + THEN("m.color = color(1,1,1)") + { + REQUIRE(m.color() == Color(1, 1, 1)); + } + AND_THEN("m.ambient = 0.1") + { + REQUIRE(m.ambient() == 0.1); + } + AND_THEN("m.diffuse = 0.9") + { + REQUIRE(m.diffuse() == 0.9); + } + AND_THEN("m.specular = 0.9") + { + REQUIRE(m.specular() == 0.9); + } + AND_THEN("m.shininess = 200.0") + { + REQUIRE(m.shininess() == 200.0); + } + } +} + +/* ------------------------------------------------------------------------- */ + +SCENARIO("A sphere has a default material", "[features/spheres.feature]") +{ + GIVEN("s <- sphere()") + { + Sphere s; + WHEN("m <- s.material") + { + Material m = s.material(); + THEN("m = material()") + { + REQUIRE(m == Material()); + } + } + } +} + +/* ------------------------------------------------------------------------- */ + +SCENARIO("A sphere may be assigned a material", "[features/spheres.feature]") +{ + GIVEN("s <- sphere()") + { + Sphere s; + AND_GIVEN("m <- material") + { + Material m; + AND_GIVEN("m.ambient <- 1") + { + m.set_ambient(1); + WHEN("s.material <- m") + { + s.set_material(m); + THEN("s.material = m") + { + s.material() == m; + } + } + } + } + } +}