[WIP] stripe-pattern is now ok.

This commit is contained in:
NADAL Jean-Baptiste
2024-02-29 18:39:45 +01:00
parent 5e540a995b
commit 0576ccaccb
19 changed files with 192 additions and 56 deletions

View File

@@ -77,10 +77,10 @@ int shadow_sphere(uint8_t a_canvas_pixels, double a_wall_size, uint8_t a_wall_z)
if (the_intersec.is_defined())
{
Tuple the_point = the_ray.position(the_intersec.distance_t());
Tuple the_normal = the_intersec.object().normal_at(the_point);
Tuple the_normal = the_intersec.object()->normal_at(the_point);
Tuple the_eye = -the_ray.direction();
Color the_color =
the_intersec.object().material().lighting(the_light, the_point, the_eye, the_normal, false);
Color the_color = the_intersec.object()->material().lighting(nullptr, the_light, the_point, the_eye,
the_normal, false);
the_canvas.write_pixel(x, y, the_color);
}
}

View File

@@ -54,7 +54,7 @@ int main(void)
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_floor_material.set_pattern(new StripePattern(Color(1, 1, 1), Color(1, 0.9, 0.9)));
the_world.add_object(the_floor);
// The large sphere in the middle is a unit sphere, translated upward slightly and colored green.
@@ -62,6 +62,7 @@ int main(void)
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_pattern(new StripePattern(Color(1, 1, 1), 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);

View File

@@ -54,9 +54,9 @@ void IntersectionData::set_distance_t(double a_value)
/* ------------------------------------------------------------------------- */
const Shape &IntersectionData::object(void) const
Shape *IntersectionData::object(void) const
{
return *m_shape;
return m_shape;
}
/* ------------------------------------------------------------------------- */

View File

@@ -44,7 +44,7 @@ namespace Raytracer
double distance_t(void) const;
void set_distance_t(double a_value);
const Shape &object(void) const;
Shape *object(void) const;
void set_object(Shape *a_shape);
const Tuple &point(void) const;

View File

@@ -141,9 +141,9 @@ double Intersection::distance_t(void) const
/* ------------------------------------------------------------------------- */
const Shape &Intersection::object(void) const
const Shape *Intersection::object(void) const
{
return *m_shape;
return m_shape;
}
/* ------------------------------------------------------------------------- */

View File

@@ -56,7 +56,7 @@ namespace Raytracer
bool operator<=(double a_distance) const;
double distance_t(void) const;
const Shape &object(void) const;
const Shape *object(void) const;
bool is_nothing(void);
bool is_defined(void);

View File

@@ -31,6 +31,9 @@
#include <cmath>
#include "core/common.h"
#include "shapes/shape.h"
#include "renderer/stripe-pattern.h"
#include "material.h"
@@ -144,8 +147,8 @@ void Material::set_pattern(StripePattern *a_pattern)
/* ------------------------------------------------------------------------- */
Color Material::lighting(const PointLight &a_light, const Tuple &a_point, const Tuple &an_eyev, const Tuple &a_normalv,
bool is_shadowed) const
Color Material::lighting(Shape *an_object, const PointLight &a_light, const Tuple &a_point, const Tuple &an_eyev,
const Tuple &a_normalv, bool is_shadowed) const
{
Color the_effective_color;
Tuple the_light_v, the_reflect_v;
@@ -153,7 +156,7 @@ Color Material::lighting(const PointLight &a_light, const Tuple &a_point, const
if (m_pattern != nullptr)
{
the_color = m_pattern->stripe_at(a_point);
the_color = m_pattern->stripe_at_object(an_object, a_point);
}
else
{

View File

@@ -30,13 +30,16 @@
#include "core/color.h"
#include "core/tuple.h"
#include "lights/point-light.h"
#include "stripe-pattern.h"
/* ------------------------------------------------------------------------- */
namespace Raytracer
{
class Shape;
class StripePattern;
class Material
{
public:
@@ -62,8 +65,8 @@ namespace Raytracer
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,
bool is_shadowed) const;
Color lighting(Shape *an_object, const PointLight &a_light, const Tuple &a_point, const Tuple &an_eyev,
const Tuple &a_normalv, bool is_shadowed) const;
private:
Color m_color;

View File

@@ -40,6 +40,7 @@ using namespace Raytracer;
StripePattern::StripePattern(const Color &a_color_a, const Color &a_color_b) : m_a(a_color_a), m_b(a_color_b)
{
m_transform = Matrix::identity();
}
/* ------------------------------------------------------------------------- */
@@ -72,3 +73,20 @@ const Color &StripePattern::stripe_at(const Tuple &a_point) const
return m_b;
}
/* ------------------------------------------------------------------------- */
void StripePattern::set_pattern_transform(const Matrix &a_transform_matrix)
{
m_transform = a_transform_matrix;
}
/* ------------------------------------------------------------------------- */
const Color &StripePattern::stripe_at_object(Shape *an_object, const Tuple &a_world_point) const
{
Tuple the_objet_point = an_object->transform().inverse() * a_world_point;
Tuple the_pattern_point = m_transform.inverse() * the_objet_point;
return stripe_at(the_pattern_point);
}

View File

@@ -29,8 +29,11 @@
/* ------------------------------------------------------------------------- */
#include "core/color.h"
#include "core/matrix.h"
#include "core/tuple.h"
#include "shapes/shape.h"
/* ------------------------------------------------------------------------- */
namespace Raytracer
@@ -47,7 +50,12 @@ namespace Raytracer
const Color &stripe_at(const Tuple &a_point) const;
void set_pattern_transform(const Matrix &a_transform_matrix);
const Color &stripe_at_object(Shape *an_object, const Tuple &a_world_point) const;
private:
Matrix m_transform;
Color m_a;
Color m_b;
};

View File

@@ -29,6 +29,8 @@
/* ------------------------------------------------------------------------- */
#include "core/matrix.h"
#include "shapes/shape.h"
#include "shapes/sphere.h"
#include "world.h"
@@ -158,9 +160,9 @@ Intersections World::intersect_world(const Ray &a_ray) const
Color World::shade_hit(const IntersectionData &an_intersection_data) const
{
bool the_shadowed = is_shadowed(an_intersection_data.over_point());
return an_intersection_data.object().material().lighting(m_light, an_intersection_data.over_point(),
an_intersection_data.eyev(),
an_intersection_data.normalv(), the_shadowed);
Shape *the_object = an_intersection_data.object();
return the_object->material().lighting(the_object, m_light, an_intersection_data.over_point(),
an_intersection_data.eyev(), an_intersection_data.normalv(), the_shadowed);
}
/* ------------------------------------------------------------------------- */

View File

@@ -41,6 +41,8 @@
namespace Raytracer
{
class Shape;
class World
{
public:

View File

@@ -80,6 +80,13 @@ bool Shape::operator==(const Shape &a_shape) const
/* ------------------------------------------------------------------------- */
bool Shape::operator==(const Shape *a_shape) const
{
return (m_transform == a_shape->m_transform) && (m_material == a_shape->m_material);
}
/* ------------------------------------------------------------------------- */
Matrix &Shape::transform(void)
{
return m_transform;

View File

@@ -51,6 +51,7 @@ namespace Raytracer
const Shape &operator=(const Shape &a_shape);
bool operator==(const Shape &a_shape) const;
bool operator==(const Shape *a_shape) const;
Matrix &transform(void);
const Matrix &transform(void) const;

View File

@@ -242,7 +242,7 @@ SCENARIO("An intersection encapsulates t and object", "[features/intersections.f
}
AND_THEN("i.object = s")
{
REQUIRE(i.object() == s);
REQUIRE(*i.object() == s);
}
}
}
@@ -270,7 +270,7 @@ SCENARIO("An intersection could be affected", "[features/intersections.feature]"
}
AND_THEN("i2.object = s")
{
REQUIRE(i2.object() == s);
REQUIRE(*i2.object() == s);
}
}
}
@@ -403,11 +403,11 @@ SCENARIO("Intersect sets the object on the intersection", "[features/spheres.fea
}
AND_THEN("xs[0].object = s")
{
REQUIRE(xs[0].object() == s);
REQUIRE(*xs[0].object() == s);
}
AND_THEN("xs[1].object = s")
{
REQUIRE(xs[1].object() == s);
REQUIRE(*xs[1].object() == s);
}
}
}

View File

@@ -331,7 +331,7 @@ SCENARIO("Lighting with the eye between the light and the surface", "[features/m
PointLight light = PointLight(Tuple::Point(0, 0, -10), Color(1, 1, 1));
WHEN("result <- lighting(m, light, position, eyev, normalv)")
{
Color result = m.lighting(light, position, eyev, normalv, false);
Color result = m.lighting(nullptr, light, position, eyev, normalv, false);
THEN("result = color(1.9, 1.9, 1.9)")
{
REQUIRE(result == Color(1.9, 1.9, 1.9));
@@ -360,7 +360,7 @@ SCENARIO("Lighting with eye between the light & surface, eye offset 45°", "[fea
PointLight light = PointLight(Tuple::Point(0, 0, -10), Color(1, 1, 1));
WHEN("result <- lighting(m, light, position, eyev, normalv)")
{
Color result = m.lighting(light, position, eyev, normalv, false);
Color result = m.lighting(nullptr, light, position, eyev, normalv, false);
THEN("result = color(1.0, 1.0, 1.0)")
{
REQUIRE(result == Color(1.0, 1.0, 1.0));
@@ -389,7 +389,7 @@ SCENARIO("Lighting with the eye opposite surface, light offset 45°", "[features
PointLight light = PointLight(Tuple::Point(0, 10, -10), Color(1, 1, 1));
WHEN("result <- lighting(m, light, position, eyev, normalv)")
{
Color result = m.lighting(light, position, eyev, normalv, false);
Color result = m.lighting(nullptr, light, position, eyev, normalv, false);
THEN("result = color(0.7364, 0.7364, 0.7364)")
{
REQUIRE(result == Color(0.7364, 0.7364, 0.7364));
@@ -418,7 +418,7 @@ SCENARIO("Lighting with the eye in the path of the reflection vector", "[feature
PointLight light = PointLight(Tuple::Point(0, 10, -10), Color(1, 1, 1));
WHEN("result <- lighting(m, light, position, eyev, normalv)")
{
Color result = m.lighting(light, position, eyev, normalv, false);
Color result = m.lighting(nullptr, light, position, eyev, normalv, false);
THEN("result = color(1.6364, 1.6364, 1.6364)")
{
REQUIRE(result == Color(1.6364, 1.6364, 1.6364));
@@ -447,7 +447,7 @@ SCENARIO("Lighting with the light behind the surface", "[features/materials.feat
PointLight light = PointLight(Tuple::Point(0, 0, 10), Color(1, 1, 1));
WHEN("result <- lighting(m, light, position, eyev, normalv)")
{
Color result = m.lighting(light, position, eyev, normalv, false);
Color result = m.lighting(nullptr, light, position, eyev, normalv, false);
THEN("result = color(0.1, 0.1, 0.1)")
{
REQUIRE(result == Color(0.1, 0.1, 0.1));

View File

@@ -52,7 +52,7 @@ SCENARIO("Lightning with the surface in shadow", "[features/materials.feature]")
bool in_shadow = true;
WHEN("result <- lighting(m, light, position, eyev, normalv, in_shadow)")
{
Color result = m.lighting(light, position, eyev, normalv, in_shadow);
Color result = m.lighting(nullptr, light, position, eyev, normalv, in_shadow);
THEN("result = color(0.1, 0.1, 0.1)")
{
REQUIRE(result == Color(0.1, 0.1, 0.1));

View File

@@ -347,7 +347,7 @@ SCENARIO("A ray Intersecting a plane from above", "[features/planes.feature]")
}
AND_THEN("xs[0].object = p")
{
REQUIRE(xs[0].object() == p);
REQUIRE(*xs[0].object() == p);
}
}
}

View File

@@ -58,12 +58,15 @@ SCENARIO("A stripe pattern is constant in y", "[features/patterns.feature]")
StripePattern pattern(Color::White(), Color::Black());
THEN("stripe_at(pattern, point(0, 0, 0) = white")
{
REQUIRE(pattern.stripe_at(Tuple::Point(0, 0, 0)) == Color::White());
}
AND_THEN("stripe_at(pattern, point(0, 1, 0) = white")
{
REQUIRE(pattern.stripe_at(Tuple::Point(0, 1, 0)) == Color::White());
}
AND_THEN("stripe_at(pattern, point(0, 2, 0) = white")
{
REQUIRE(pattern.stripe_at(Tuple::Point(0, 2, 0)) == Color::White());
}
}
}
@@ -128,6 +131,9 @@ SCENARIO("A stripe pattern alternates in x", "[features/patterns.feature]")
SCENARIO("Lightning with a pattern applied", "[features/materials.feature]")
{
GIVEN("object <- sphere()")
{
Sphere object;
Material m;
GIVEN("m.pattern <- strip_pattern(color(1, 1, 1), color(0, 0, 0))")
{
@@ -153,10 +159,12 @@ SCENARIO("Lightning with a pattern applied", "[features/materials.feature]")
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);
Color c1 =
m.lighting(&object, 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);
Color c2 = m.lighting(&object, light, Tuple::Point(1.1, 0, 0), eyev,
normalv, false);
THEN("c1 = color(1, 1, 1)")
{
REQUIRE(c1 == Color(1, 1, 1));
@@ -175,3 +183,86 @@ SCENARIO("Lightning with a pattern applied", "[features/materials.feature]")
}
}
}
}
/* ------------------------------------------------------------------------- */
SCENARIO("Stripes with an object transformation", "[features/patterns.feature]")
{
GIVEN("object <- sphere()")
{
Sphere object;
AND_GIVEN("set_transform(object, scaling(2, 2, 2))")
{
object.set_transform(Matrix::scaling(2, 2, 2));
AND_GIVEN("pattern <- stripe_pattern(white, black)")
{
StripePattern pattern(Color::White(), Color::Black());
WHEN("c <- stripe_at_object(pattern, object, point(1.5, 0, 0))")
{
Color c = pattern.stripe_at_object(&object, Tuple::Point(1.5, 0, 0));
THEN("c = white")
{
REQUIRE(c == Color::White());
}
}
}
}
}
}
/* ------------------------------------------------------------------------- */
SCENARIO("Stripes with an pattern transformation", "[features/patterns.feature]")
{
GIVEN("object <- sphere()")
{
Sphere object;
AND_GIVEN("pattern <- stripe_pattern(white, black)")
{
StripePattern pattern(Color::White(), Color::Black());
AND_GIVEN("set_transform(pattern, scaling(2, 2, 2))")
{
pattern.set_pattern_transform(Matrix::scaling(2, 2, 2));
WHEN("c <- stripe_at_object(pattern, object, point(1.5, 0, 0))")
{
Color c = pattern.stripe_at_object(&object, Tuple::Point(1.5, 0, 0));
THEN("c = white")
{
REQUIRE(c == Color::White());
}
}
}
}
}
}
/* ------------------------------------------------------------------------- */
SCENARIO("Stripes with both an object and pattern transformation", "[features/patterns.feature]")
{
GIVEN("object <- sphere()")
{
Sphere object;
AND_GIVEN("set_transform(object, scaling(2, 2, 2))")
{
object.set_transform(Matrix::scaling(2, 2, 2));
AND_GIVEN("pattern <- stripe_pattern(white, black)")
{
StripePattern pattern(Color::White(), Color::Black());
AND_GIVEN("set_pattern_transform(pattern, translation(0.5, 0, 0)))")
{
pattern.set_pattern_transform(Matrix::translation(0.5, 0, 0));
WHEN("c <- stripe_at_object(pattern, object, point(2.5, 0, 0))")
{
Color c = pattern.stripe_at_object(&object, Tuple::Point(1.5, 0, 0));
THEN("c = white")
{
REQUIRE(c == Color::White());
}
}
}
}
}
}
}