[WIP] stripe-pattern is now ok.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
|
||||
namespace Raytracer
|
||||
{
|
||||
class Shape;
|
||||
|
||||
class World
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,42 +131,48 @@ 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))")
|
||||
GIVEN("object <- sphere()")
|
||||
{
|
||||
m.set_pattern(new StripePattern(Color(1, 1, 1), Color(0, 0, 0)));
|
||||
AND_GIVEN("m.ambient <- 1")
|
||||
Sphere object;
|
||||
Material m;
|
||||
GIVEN("m.pattern <- strip_pattern(color(1, 1, 1), color(0, 0, 0))")
|
||||
{
|
||||
m.set_ambient(1);
|
||||
AND_GIVEN("m.diffuse <- 0")
|
||||
m.set_pattern(new StripePattern(Color(1, 1, 1), Color(0, 0, 0)));
|
||||
AND_GIVEN("m.ambient <- 1")
|
||||
{
|
||||
m.set_diffuse(0);
|
||||
AND_GIVEN("m.specular <- 0")
|
||||
m.set_ambient(1);
|
||||
AND_GIVEN("m.diffuse <- 0")
|
||||
{
|
||||
m.set_specular(0);
|
||||
AND_GIVEN("eyev <- vector(0, 0, -1)")
|
||||
m.set_diffuse(0);
|
||||
AND_GIVEN("m.specular <- 0")
|
||||
{
|
||||
Tuple eyev = Tuple::Vector(0, 0, -1);
|
||||
AND_GIVEN("normalv <- vector(0, 0, -1)")
|
||||
m.set_specular(0);
|
||||
AND_GIVEN("eyev <- vector(0, 0, -1)")
|
||||
{
|
||||
Tuple normalv = Tuple::Vector(0, 0, -1);
|
||||
AND_GIVEN("light <- point_light(point(0, 0, -10), color(1, 1, 1))")
|
||||
Tuple eyev = Tuple::Vector(0, 0, -1);
|
||||
AND_GIVEN("normalv <- vector(0, 0, -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)")
|
||||
Tuple normalv = Tuple::Vector(0, 0, -1);
|
||||
AND_GIVEN("light <- point_light(point(0, 0, -10), color(1, 1, 1))")
|
||||
{
|
||||
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)")
|
||||
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 c2 = m.lighting(light, Tuple::Point(1.1, 0, 0), eyev, normalv, false);
|
||||
THEN("c1 = color(1, 1, 1)")
|
||||
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)")
|
||||
{
|
||||
REQUIRE(c1 == Color(1, 1, 1));
|
||||
}
|
||||
AND_THEN("c2 = color(0, 0, 0)")
|
||||
{
|
||||
REQUIRE(c2 == Color(0, 0, 0));
|
||||
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));
|
||||
}
|
||||
AND_THEN("c2 = color(0, 0, 0)")
|
||||
{
|
||||
REQUIRE(c2 == Color(0, 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,3 +184,85 @@ 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user