[FEAT] Add strip pattern to material

This commit is contained in:
NADAL Jean-Baptiste
2024-02-29 13:56:39 +01:00
parent a8cf2d984f
commit 5e540a995b
7 changed files with 210 additions and 5 deletions

View File

@@ -16,3 +16,6 @@ target_link_libraries(chapter_07 PRIVATE raytracing gcov)
add_executable(chapter_09 chapter_09.cpp) add_executable(chapter_09 chapter_09.cpp)
target_link_libraries(chapter_09 PRIVATE raytracing gcov OpenMP::OpenMP_CXX) target_link_libraries(chapter_09 PRIVATE raytracing gcov OpenMP::OpenMP_CXX)
add_executable(chapter_10 chapter_10.cpp)
target_link_libraries(chapter_10 PRIVATE raytracing gcov)

106
apps/chapter_10.cpp Normal file
View File

@@ -0,0 +1,106 @@
/*!
* chapter_10.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: 29/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 <chrono>
#include <cstdio>
#include <raytracing.h>
/* ------------------------------------------------------------------------- */
using namespace Raytracer;
using namespace std;
/* ------------------------------------------------------------------------- */
int main(void)
{
World the_world;
Camera the_camera;
Canvas the_canvas;
Plane *the_floor;
Sphere *the_middle, *the_right, *the_left;
chrono::time_point<chrono::high_resolution_clock> the_start, the_end;
printf("Chapter 10 example.\n");
// Floor is an extremely flattened sphere with a matte texture.
the_floor = new Plane();
Material &the_floor_material = the_floor->material();
the_floor_material.set_color(Color(1, 0.9, 0.9));
the_floor_material.set_specular(0);
the_floor_material.set_pattern(new StripePattern(Color(1, 1, 1), Color(0, 0, 0)));
the_world.add_object(the_floor);
// The large sphere in the middle is a unit sphere, translated upward slightly and colored green.
the_middle = new Sphere();
the_middle->set_transform(Matrix::translation(-0.5, 1, 0.5));
Material &the_middle_material = the_middle->material();
the_middle_material.set_color(Color(0.1, 1, 0.5));
the_middle_material.set_diffuse(0.7);
the_middle_material.set_specular(0.3);
the_world.add_object(the_middle);
// The smaller green sphere on the right is scaled in half
the_right = new Sphere();
the_right->set_transform(Matrix::translation(1.5, 0.5, -0.5) * Matrix::scaling(0.5, 0.5, 0.5));
Material &the_right_material = the_right->material();
the_right_material.set_color(Color(0.5, 1, 0.1));
the_right_material.set_diffuse(0.7);
the_right_material.set_specular(0.3);
the_world.add_object(the_right);
// The smallest sphere is scaled by a third, before being translated
the_left = new Sphere();
the_left->set_transform(Matrix::translation(-1.5, 0.33, -0.75) * Matrix::scaling(0.33, 0.33, 0.33));
Material &the_left_material = the_left->material();
the_left_material.set_color(Color(1, 0.8, 0.1));
the_left_material.set_diffuse(0.7);
the_left_material.set_specular(0.3);
the_world.add_object(the_left);
// The Light source is white, shining from above and to the left
the_world.set_light(PointLight(Tuple::Point(-10, 10, -10), Color(1, 1, 1)));
// Configure the camera.
// the_camera = Camera(100, 50, std::numbers::pi / 2);
the_camera = Camera(320, 200, std::numbers::pi / 2);
the_camera.set_transform(
Matrix::view_transform(Tuple::Point(0, 1.5, -3.5), Tuple::Point(0, 1, 0), Tuple::Vector(0, 1, 0)));
the_start = chrono::high_resolution_clock::now();
the_canvas = the_camera.render(the_world);
the_end = chrono::high_resolution_clock::now();
the_canvas.save_to_file("chapter10.ppm");
chrono::duration<double> the_elapsed_time = the_end - the_start;
printf("Execution Time: %f secondes\n", the_elapsed_time.count());
return 0;
}

View File

@@ -38,7 +38,13 @@ 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) Material::Material(void) :
m_color(1, 1, 1),
m_ambient(0.1),
m_diffuse(0.9),
m_specular(0.9),
m_shininess(200),
m_pattern(nullptr)
{ {
} }
@@ -49,6 +55,7 @@ bool Material::operator==(const Material &a_material) const
return (m_color == a_material.m_color) && double_equal(m_ambient, a_material.m_ambient) && 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_diffuse, a_material.m_diffuse) && double_equal(m_specular, a_material.m_specular) &&
double_equal(m_shininess, a_material.m_shininess); double_equal(m_shininess, a_material.m_shininess);
// TODO m_pattern
} }
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
@@ -123,15 +130,38 @@ void Material::set_shininess(double a_value)
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
const StripePattern *Material::pattern(void) const
{
return m_pattern;
}
/* ------------------------------------------------------------------------- */
void Material::set_pattern(StripePattern *a_pattern)
{
m_pattern = a_pattern;
}
/* ------------------------------------------------------------------------- */
Color Material::lighting(const PointLight &a_light, const Tuple &a_point, const Tuple &an_eyev, const Tuple &a_normalv, Color Material::lighting(const PointLight &a_light, const Tuple &a_point, const Tuple &an_eyev, const Tuple &a_normalv,
bool is_shadowed) const bool is_shadowed) const
{ {
Color the_effective_color; Color the_effective_color;
Tuple the_light_v, the_reflect_v; Tuple the_light_v, the_reflect_v;
Color the_ambient, the_diffuse, the_specular; Color the_color, the_ambient, the_diffuse, the_specular;
if (m_pattern != nullptr)
{
the_color = m_pattern->stripe_at(a_point);
}
else
{
the_color = m_color;
}
// Combine the surface color with the light's color // Combine the surface color with the light's color
the_effective_color = m_color * a_light.intensity(); the_effective_color = the_color * a_light.intensity();
// Find the direction to the light source // Find the direction to the light source
the_light_v = (a_light.position() - a_point).normalize(); the_light_v = (a_light.position() - a_point).normalize();

View File

@@ -31,6 +31,7 @@
#include "core/color.h" #include "core/color.h"
#include "core/tuple.h" #include "core/tuple.h"
#include "lights/point-light.h" #include "lights/point-light.h"
#include "stripe-pattern.h"
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
@@ -58,6 +59,9 @@ namespace Raytracer
const double &shininess(void) const; const double &shininess(void) const;
void set_shininess(double a_value); void set_shininess(double a_value);
const StripePattern *pattern(void) const;
void set_pattern(StripePattern *a_pattern);
Color lighting(const PointLight &a_light, const Tuple &a_point, const Tuple &an_eyev, const Tuple &a_normalv, Color lighting(const PointLight &a_light, const Tuple &a_point, const Tuple &an_eyev, const Tuple &a_normalv,
bool is_shadowed) const; bool is_shadowed) const;
@@ -67,6 +71,7 @@ namespace Raytracer
double m_diffuse; double m_diffuse;
double m_specular; double m_specular;
double m_shininess; double m_shininess;
StripePattern *m_pattern;
}; };
}; // namespace Raytracer }; // namespace Raytracer

View File

@@ -44,6 +44,13 @@ StripePattern::StripePattern(const Color &a_color_a, const Color &a_color_b) : m
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
bool StripePattern::operator==(const StripePattern &a_pattern) const
{
return (m_a == a_pattern.m_a) && (m_b == a_pattern.m_b);
}
/* ------------------------------------------------------------------------- */
const Color &StripePattern::a(void) const const Color &StripePattern::a(void) const
{ {
return m_a; return m_a;
@@ -58,7 +65,7 @@ const Color &StripePattern::b(void) const
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
const Color &StripePattern::stripe_at(Tuple a_point) const const Color &StripePattern::stripe_at(const Tuple &a_point) const
{ {
if (((int)std::floor(a_point.x()) % 2) == 0) if (((int)std::floor(a_point.x()) % 2) == 0)
return m_a; return m_a;

View File

@@ -40,10 +40,12 @@ namespace Raytracer
public: public:
StripePattern(const Color &a_color_a, const Color &a_color_b); StripePattern(const Color &a_color_a, const Color &a_color_b);
bool operator==(const StripePattern &a_pattern) const;
const Color &a(void) const; const Color &a(void) const;
const Color &b(void) const; const Color &b(void) const;
const Color &stripe_at(Tuple a_point) const; const Color &stripe_at(const Tuple &a_point) const;
private: private:
Color m_a; Color m_a;

View File

@@ -123,3 +123,55 @@ SCENARIO("A stripe pattern alternates in x", "[features/patterns.feature]")
} }
} }
} }
/* ------------------------------------------------------------------------- */
SCENARIO("Lightning with a pattern applied", "[features/materials.feature]")
{
Material m;
GIVEN("m.pattern <- strip_pattern(color(1, 1, 1), color(0, 0, 0))")
{
m.set_pattern(new StripePattern(Color(1, 1, 1), Color(0, 0, 0)));
AND_GIVEN("m.ambient <- 1")
{
m.set_ambient(1);
AND_GIVEN("m.diffuse <- 0")
{
m.set_diffuse(0);
AND_GIVEN("m.specular <- 0")
{
m.set_specular(0);
AND_GIVEN("eyev <- vector(0, 0, -1)")
{
Tuple eyev = Tuple::Vector(0, 0, -1);
AND_GIVEN("normalv <- vector(0, 0, -1)")
{
Tuple normalv = Tuple::Vector(0, 0, -1);
AND_GIVEN("light <- point_light(point(0, 0, -10), color(1, 1, 1))")
{
PointLight light = PointLight(Tuple::Point(0, 0, -10), Color(1, 1, 1));
WHEN("c1 <- lighting(m, light, point(0.9, 0, 0), eyev, normalv, false)")
{
Color c1 = m.lighting(light, Tuple::Point(0.9, 0, 0), eyev, normalv, false);
AND_WHEN("c2 <- lighting(m, light, point(1.1, 0, 0), eyev, normalv, false)")
{
Color c2 = m.lighting(light, Tuple::Point(1.1, 0, 0), eyev, normalv, false);
THEN("c1 = color(1, 1, 1)")
{
REQUIRE(c1 == Color(1, 1, 1));
}
AND_THEN("c2 = color(0, 0, 0)")
{
REQUIRE(c2 == Color(0, 0, 0));
}
}
}
}
}
}
}
}
}
}
}