[WIP] Add reflective parameter into material

This commit is contained in:
NADAL Jean-Baptiste
2024-03-05 17:01:38 +01:00
parent 17a75a841d
commit 41ea86d3ec
24 changed files with 184 additions and 91 deletions

View File

@@ -20,6 +20,7 @@ DerivePointerAlignment: false
PointerAlignment: Right
ReferenceAlignment: Right
AlignArrayOfStructures: Right
IndentCaseLabels: true
# AlignConsecutiveAssignments: Consecutive
AlignConsecutiveBitFields: Consecutive

View File

@@ -50,7 +50,7 @@ int shadow_sphere(uint8_t a_canvas_pixels, double a_wall_size, uint8_t a_wall_z)
Tuple the_ray_origin = Tuple::Point(0, 0, -5);
double the_pixel_size = a_wall_size / a_canvas_pixels;
double the_half = a_wall_size / 2;
double the_half = a_wall_size / 2;
double the_world_x, the_world_y;
// For each row of pixels in the canvas
@@ -70,7 +70,7 @@ int shadow_sphere(uint8_t a_canvas_pixels, double a_wall_size, uint8_t a_wall_z)
the_position -= the_ray_origin;
Ray the_ray(the_ray_origin, the_position.normalize());
auto the_xs = the_shape.intersect(the_ray);
auto the_xs = the_shape.intersect(the_ray);
auto the_intersec = the_xs.hit();
if (the_intersec.is_defined())
{
@@ -94,8 +94,8 @@ int main(void)
printf("Chapter 05 example.\n");
the_start = chrono::high_resolution_clock::now();
the_ret = shadow_sphere(kImageSize, kWallSize, kWallZ);
the_end = chrono::high_resolution_clock::now();
the_ret = shadow_sphere(kImageSize, kWallSize, kWallZ);
the_end = chrono::high_resolution_clock::now();
chrono::duration<double> the_elapsed_time = the_end - the_start;
printf("Execution Time: %f secondes\n", the_elapsed_time.count());

View File

@@ -52,7 +52,7 @@ int shadow_sphere(uint8_t a_canvas_pixels, double a_wall_size, uint8_t a_wall_z)
the_shape.material().set_color(Color(1, 0.2, 1));
double the_pixel_size = a_wall_size / a_canvas_pixels;
double the_half = a_wall_size / 2;
double the_half = a_wall_size / 2;
double the_world_x, the_world_y;
// For each row of pixels in the canvas
@@ -72,15 +72,15 @@ int shadow_sphere(uint8_t a_canvas_pixels, double a_wall_size, uint8_t a_wall_z)
the_position -= the_ray_origin;
Ray the_ray(the_ray_origin, the_position.normalize());
auto the_xs = the_shape.intersect(the_ray);
auto the_xs = the_shape.intersect(the_ray);
auto the_intersec = the_xs.hit();
if (the_intersec.is_defined())
{
Tuple the_point = the_ray.position(the_intersec.distance_t());
Tuple the_point = the_ray.position(the_intersec.distance_t());
Tuple the_normal = the_intersec.object()->normal_at(the_point);
Tuple the_eye = -the_ray.direction();
Color the_color = the_intersec.object()->material().lighting(nullptr, the_light, the_point, the_eye,
the_normal, false);
Tuple the_eye = -the_ray.direction();
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);
}
}
@@ -101,8 +101,8 @@ int main(void)
printf("Chapter 06 example.\n");
the_start = chrono::high_resolution_clock::now();
the_ret = shadow_sphere(kImageSize, kWallSize, kWallZ);
the_end = chrono::high_resolution_clock::now();
the_ret = shadow_sphere(kImageSize, kWallSize, kWallZ);
the_end = chrono::high_resolution_clock::now();
chrono::duration<double> the_elapsed_time = the_end - the_start;
printf("Execution Time: %f secondes\n", the_elapsed_time.count());

View File

@@ -107,9 +107,9 @@ int main(void)
the_camera.set_transform(
Matrix::view_transform(Tuple::Point(0, 1.5, -5), Tuple::Point(0, 1, 0), Tuple::Vector(0, 1, 0)));
the_start = chrono::high_resolution_clock::now();
the_start = chrono::high_resolution_clock::now();
the_canvas = the_camera.render(the_world);
the_end = chrono::high_resolution_clock::now();
the_end = chrono::high_resolution_clock::now();
the_canvas.save_to_file("chapter07.ppm");

View File

@@ -91,9 +91,9 @@ int main(void)
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_start = chrono::high_resolution_clock::now();
the_canvas = the_camera.render(the_world);
the_end = chrono::high_resolution_clock::now();
the_end = chrono::high_resolution_clock::now();
the_canvas.save_to_file("chapter09.ppm");

View File

@@ -38,20 +38,23 @@ using namespace Raytracer;
/* ------------------------------------------------------------------------- */
Color::Color(void) : m_red(0), m_green(0), m_blue(0)
Color::Color(void) :
m_red(0), m_green(0), m_blue(0)
{
// printf("%s red: %f green: %f, blue: %f\n", __PRETTY_FUNCTION__, m_red, m_green, m_blue);
}
/* ------------------------------------------------------------------------- */
Color::Color(const Color &a_copy) : m_red(a_copy.m_red), m_green(a_copy.m_green), m_blue(a_copy.m_blue)
Color::Color(const Color &a_copy) :
m_red(a_copy.m_red), m_green(a_copy.m_green), m_blue(a_copy.m_blue)
{
}
/* ------------------------------------------------------------------------- */
Color::Color(double a_red, double a_green, double a_blue) : m_red(a_red), m_green(a_green), m_blue(a_blue)
Color::Color(double a_red, double a_green, double a_blue) :
m_red(a_red), m_green(a_green), m_blue(a_blue)
{
}
@@ -77,9 +80,9 @@ const Color &Color::operator=(const Color &a_color)
return *this;
}
m_red = a_color.m_red;
m_red = a_color.m_red;
m_green = a_color.m_green;
m_blue = a_color.m_blue;
m_blue = a_color.m_blue;
return *this;
}
@@ -112,9 +115,9 @@ const Color Color::operator*(const Color &a_color) const
// Using the hadamard product.
double the_red, the_green, the_blue;
the_red = m_red * a_color.m_red;
the_red = m_red * a_color.m_red;
the_green = m_green * a_color.m_green;
the_blue = m_blue * a_color.m_blue;
the_blue = m_blue * a_color.m_blue;
return Color(the_red, the_green, the_blue);
}

View File

@@ -34,7 +34,8 @@ using namespace Raytracer;
/* ------------------------------------------------------------------------- */
IntersectionData::IntersectionData(void) : m_is_inside(false), m_distance(0), m_shape(nullptr)
IntersectionData::IntersectionData(void) :
m_is_inside(false), m_distance(0), m_shape(nullptr)
{
}
@@ -124,6 +125,20 @@ void IntersectionData::set_normalv(const Tuple &a_normalv)
/* ------------------------------------------------------------------------- */
const Tuple &IntersectionData::reflectv(void) const
{
return m_reflectv;
}
/* ------------------------------------------------------------------------- */
void IntersectionData::set_reflectv(const Tuple &a_reflectv)
{
m_reflectv = a_reflectv;
}
/* ------------------------------------------------------------------------- */
const bool IntersectionData::is_inside(void) const
{
return m_is_inside;
@@ -136,7 +151,7 @@ void IntersectionData::set_inside(void)
if (m_normalv.dot(m_eyev) < 0)
{
m_is_inside = true;
m_normalv = -m_normalv;
m_normalv = -m_normalv;
}
else
{

View File

@@ -59,6 +59,9 @@ namespace Raytracer
const Tuple &normalv(void) const;
void set_normalv(const Tuple &a_normalv);
const Tuple &reflectv(void) const;
void set_reflectv(const Tuple &a_reflectv);
const bool is_inside(void) const;
void set_inside(void);
@@ -70,6 +73,7 @@ namespace Raytracer
Tuple m_over_point;
Tuple m_eyev;
Tuple m_normalv;
Tuple m_reflectv;
};
}; // namespace Raytracer

View File

@@ -36,7 +36,8 @@ using namespace Raytracer;
/* ------------------------------------------------------------------------- */
Intersection::Intersection(void) : m_is_nothing(true), m_distance_t(0.0), m_shape(nullptr)
Intersection::Intersection(void) :
m_is_nothing(true), m_distance_t(0.0), m_shape(nullptr)
{
}
@@ -78,7 +79,7 @@ const Intersection &Intersection::operator=(const Intersection &an_intersection)
m_is_nothing = an_intersection.m_is_nothing;
m_distance_t = an_intersection.m_distance_t;
m_shape = an_intersection.m_shape;
m_shape = an_intersection.m_shape;
return *this;
}
@@ -162,11 +163,11 @@ bool Intersection::is_defined(void)
/* ------------------------------------------------------------------------- */
IntersectionData Intersection::prepare_computations(Ray a_ray) const
IntersectionData Intersection::prepare_computations(const Ray &a_ray) const
{
IntersectionData the_data;
// Copy intersections properties for conveniance
// Copy intersections properties for convenance
the_data.set_distance_t(m_distance_t);
the_data.set_object(m_shape);
@@ -176,6 +177,7 @@ IntersectionData Intersection::prepare_computations(Ray a_ray) const
the_data.set_normalv(m_shape->normal_at(the_data.point()));
the_data.set_over_point(the_data.point() + the_data.normalv() * kEpsilon);
the_data.set_inside();
the_data.set_reflectv(a_ray.direction().reflect(the_data.normalv()));
return the_data;
}

View File

@@ -60,7 +60,7 @@ namespace Raytracer
bool is_nothing(void);
bool is_defined(void);
IntersectionData prepare_computations(Ray a_ray) const;
IntersectionData prepare_computations(const Ray &a_ray) const;
private:
bool m_is_nothing;

View File

@@ -38,13 +38,15 @@ using namespace Raytracer;
/* ------------------------------------------------------------------------- */
Matrix::Matrix(void) : m_rows(0), m_cols(0)
Matrix::Matrix(void) :
m_rows(0), m_cols(0)
{
}
/* ------------------------------------------------------------------------- */
Matrix::Matrix(uint8_t a_rows, uint8_t a_cols) : m_rows(a_rows), m_cols(a_cols)
Matrix::Matrix(uint8_t a_rows, uint8_t a_cols) :
m_rows(a_rows), m_cols(a_cols)
{
m_data = std::vector<std::vector<double>>(m_rows, std::vector<double>(m_cols));
for (int i = 0; i < m_rows; i++)
@@ -58,7 +60,8 @@ Matrix::Matrix(uint8_t a_rows, uint8_t a_cols) : m_rows(a_rows), m_cols(a_cols)
/* ------------------------------------------------------------------------- */
Matrix::Matrix(const Matrix &an_other) : m_rows(an_other.m_rows), m_cols(an_other.m_cols), m_data(an_other.m_data)
Matrix::Matrix(const Matrix &an_other) :
m_rows(an_other.m_rows), m_cols(an_other.m_cols), m_data(an_other.m_data)
{
}
@@ -288,8 +291,8 @@ Matrix Matrix::inverse(void) const
{
for (int the_col = 0; the_col < m_cols; the_col++)
{
the_cofactor = cofactor(the_row, the_col);
the_value = the_cofactor / the_determinant;
the_cofactor = cofactor(the_row, the_col);
the_value = the_cofactor / the_determinant;
the_result[the_col][the_row] = the_value;
}
}
@@ -399,11 +402,11 @@ Matrix Matrix::shearing(double a_xy, double a_xz, double a_yx, double a_yz, doub
Matrix Matrix::view_transform(const Tuple &a_from, const Tuple &a_to, const Tuple &an_up)
{
Tuple the_forward = (a_to - a_from).normalize();
Tuple the_forward = (a_to - a_from).normalize();
Tuple the_up_normalized = an_up.normalize();
Tuple the_left = the_forward.cross(the_up_normalized);
Tuple the_true_up = the_left.cross(the_forward);
Matrix the_orientation = {
Tuple the_left = the_forward.cross(the_up_normalized);
Tuple the_true_up = the_left.cross(the_forward);
Matrix the_orientation = {
{ the_left.x(), the_left.y(), the_left.z(), 0},
{ the_true_up.x(), the_true_up.y(), the_true_up.z(), 0},
{-the_forward.x(), -the_forward.y(), -the_forward.z(), 0},

View File

@@ -40,25 +40,29 @@ using namespace Raytracer;
/* ------------------------------------------------------------------------- */
Tuple::Tuple(void) : m_x(0.0), m_y(0.0), m_z(0.0), m_w(0.0)
Tuple::Tuple(void) :
m_x(0.0), m_y(0.0), m_z(0.0), m_w(0.0)
{
}
/* ------------------------------------------------------------------------- */
Tuple::Tuple(const Tuple &a_copy) : m_x(a_copy.m_x), m_y(a_copy.m_y), m_z(a_copy.m_z), m_w(a_copy.m_w)
Tuple::Tuple(const Tuple &a_copy) :
m_x(a_copy.m_x), m_y(a_copy.m_y), m_z(a_copy.m_z), m_w(a_copy.m_w)
{
}
/* ------------------------------------------------------------------------- */
Tuple::Tuple(double a_x, double a_y, double a_z, double a_w) : m_x(a_x), m_y(a_y), m_z(a_z), m_w(a_w)
Tuple::Tuple(double a_x, double a_y, double a_z, double a_w) :
m_x(a_x), m_y(a_y), m_z(a_z), m_w(a_w)
{
}
/* ------------------------------------------------------------------------- */
Tuple::Tuple(std::vector<double> a_data) : m_x(0.0), m_y(0.0), m_z(0.0), m_w(0.0)
Tuple::Tuple(std::vector<double> a_data) :
m_x(0.0), m_y(0.0), m_z(0.0), m_w(0.0)
{
int i = 0;
for (auto the_it1 = a_data.cbegin(); the_it1 != a_data.cend(); ++the_it1)
@@ -107,14 +111,9 @@ const Tuple &Tuple::operator=(const Tuple &an_other)
/* ------------------------------------------------------------------------- */
const Tuple &Tuple::operator-(void)
const Tuple Tuple::operator-(void) const
{
m_x = -m_x;
m_y = -m_y;
m_z = -m_z;
m_w = -m_w;
return *this;
return Tuple(-m_x, -m_y, -m_z, -m_w);
}
/* ------------------------------------------------------------------------- */

View File

@@ -49,7 +49,7 @@ namespace Raytracer
bool operator==(const Tuple &an_other) const;
const Tuple &operator=(const Tuple &an_other);
const Tuple &operator-(void);
const Tuple operator-(void) const;
const Tuple operator+(const Tuple &an_other) const;
const Tuple operator-(const Tuple &an_other) const;

View File

@@ -44,7 +44,8 @@ PointLight::PointLight(const Tuple &a_position, const Color &an_intensity) :
/* ------------------------------------------------------------------------- */
PointLight::PointLight(const PointLight &a_light) : m_position(a_light.m_position), m_intensity(a_light.m_intensity)
PointLight::PointLight(const PointLight &a_light) :
m_position(a_light.m_position), m_intensity(a_light.m_intensity)
{
}
@@ -57,7 +58,7 @@ const PointLight &PointLight::operator=(const PointLight &a_light)
return *this;
}
m_position = a_light.m_position;
m_position = a_light.m_position;
m_intensity = a_light.m_intensity;
return *this;

View File

@@ -39,7 +39,8 @@ using namespace Raytracer;
/* ------------------------------------------------------------------------- */
Camera::Camera(void) : m_h_size(0), m_v_size(0), m_field_of_view(0), m_half_width(0), m_half_height(0), m_pixel_size(0)
Camera::Camera(void) :
m_h_size(0), m_v_size(0), m_field_of_view(0), m_half_width(0), m_half_height(0), m_pixel_size(0)
{
}
@@ -55,17 +56,17 @@ Camera::Camera(uint16_t a_h_size, uint16_t a_v_size, double a_field_of_view) :
m_pixel_size(0)
{
double the_half_view = tan(m_field_of_view / 2);
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_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_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;
@@ -76,13 +77,13 @@ Camera::Camera(uint16_t a_h_size, uint16_t a_v_size, double a_field_of_view) :
Camera::Camera(const Camera &an_other)
{
m_h_size = an_other.m_h_size;
m_v_size = an_other.m_v_size;
m_h_size = an_other.m_h_size;
m_v_size = an_other.m_v_size;
m_field_of_view = an_other.m_field_of_view;
m_transform = an_other.m_transform;
m_half_width = an_other.m_half_width;
m_half_height = an_other.m_half_height;
m_pixel_size = an_other.m_pixel_size;
m_transform = an_other.m_transform;
m_half_width = an_other.m_half_width;
m_half_height = an_other.m_half_height;
m_pixel_size = an_other.m_pixel_size;
}
/* ------------------------------------------------------------------------- */
@@ -94,13 +95,13 @@ const Camera &Camera::operator=(const Camera &an_other)
return *this;
}
m_h_size = an_other.m_h_size;
m_v_size = an_other.m_v_size;
m_h_size = an_other.m_h_size;
m_v_size = an_other.m_v_size;
m_field_of_view = an_other.m_field_of_view;
m_transform = an_other.m_transform;
m_half_width = an_other.m_half_width;
m_half_height = an_other.m_half_height;
m_pixel_size = an_other.m_pixel_size;
m_transform = an_other.m_transform;
m_half_width = an_other.m_half_width;
m_half_height = an_other.m_half_height;
m_pixel_size = an_other.m_pixel_size;
return *this;
}
@@ -168,9 +169,9 @@ Ray Camera::ray_for_pixel(double an_x, double an_y) const
// and then compute the ray direction vector.
// (remember that the canvas is at z=-1)
Matrix the_invert = m_transform.inverse();
the_pixel = the_invert * Tuple::Point(the_world_x, the_world_y, -1);
the_origin = the_invert * Tuple::Point(0, 0, 0);
the_direction = (the_pixel - the_origin).normalize();
the_pixel = the_invert * Tuple::Point(the_world_x, the_world_y, -1);
the_origin = the_invert * Tuple::Point(0, 0, 0);
the_direction = (the_pixel - the_origin).normalize();
return Ray(the_origin, the_direction);
}
@@ -186,7 +187,7 @@ Canvas Camera::render(const World &a_world)
{
for (int x = 0; x < m_h_size - 1; x++)
{
Ray the_ray = ray_for_pixel(x, y);
Ray the_ray = ray_for_pixel(x, y);
Color the_color = a_world.color_at(the_ray);
the_image.write_pixel(x, y, the_color);
}

View File

@@ -38,13 +38,15 @@ using namespace Raytracer;
/* ------------------------------------------------------------------------- */
Canvas::Canvas(void) : m_width(0), m_height(0)
Canvas::Canvas(void) :
m_width(0), m_height(0)
{
}
/* ------------------------------------------------------------------------- */
Canvas::Canvas(uint16_t a_width, uint16_t a_height) : m_width(a_width), m_height(a_height)
Canvas::Canvas(uint16_t a_width, uint16_t a_height) :
m_width(a_width), m_height(a_height)
{
m_pixels = std::vector<std::vector<Color>>(m_width, std::vector<Color>(m_height));
@@ -70,7 +72,7 @@ Canvas::Canvas(const Canvas &a_canvas) :
Canvas &Canvas::operator=(const Canvas &a_canvas)
{
m_width = a_canvas.m_width;
m_width = a_canvas.m_width;
m_height = a_canvas.m_height;
m_pixels = a_canvas.m_pixels;

View File

@@ -47,6 +47,7 @@ Material::Material(void) :
m_diffuse(0.9),
m_specular(0.9),
m_shininess(200),
m_reflective(0.0),
m_pattern(nullptr)
{
}
@@ -57,7 +58,7 @@ 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);
double_equal(m_shininess, a_material.m_shininess) && double_equal(m_reflective, a_material.m_reflective);
// TODO m_pattern
}
@@ -133,6 +134,20 @@ void Material::set_shininess(double a_value)
/* ------------------------------------------------------------------------- */
const double &Material::reflective(void) const
{
return m_reflective;
}
/* ------------------------------------------------------------------------- */
void Material::set_reflective(double a_value)
{
m_reflective = a_value;
}
/* ------------------------------------------------------------------------- */
Pattern *Material::pattern(void)
{
return m_pattern;

View File

@@ -62,6 +62,9 @@ namespace Raytracer
const double &shininess(void) const;
void set_shininess(double a_value);
const double &reflective(void) const;
void set_reflective(double a_value);
Pattern *pattern(void);
void set_pattern(Pattern *a_pattern);
@@ -74,6 +77,7 @@ namespace Raytracer
double m_diffuse;
double m_specular;
double m_shininess;
double m_reflective;
Pattern *m_pattern;
};
}; // namespace Raytracer

View File

@@ -35,7 +35,8 @@ using namespace Raytracer;
/* ------------------------------------------------------------------------- */
Ray::Ray(Tuple an_origin, Tuple a_direction) : m_origin(an_origin), m_direction(a_direction)
Ray::Ray(Tuple an_origin, Tuple a_direction) :
m_origin(an_origin), m_direction(a_direction)
{
}
@@ -62,7 +63,7 @@ Tuple &Ray::direction(void)
/* ------------------------------------------------------------------------- */
Tuple Ray::position(double a_distance)
Tuple Ray::position(double a_distance) const
{
return m_origin + m_direction * a_distance;
}
@@ -73,7 +74,7 @@ Ray Ray::transform(const Matrix &a_matrix) const
{
Ray the_output_ray;
the_output_ray.m_origin = a_matrix * m_origin;
the_output_ray.m_origin = a_matrix * m_origin;
the_output_ray.m_direction = a_matrix * m_direction;
return the_output_ray;

View File

@@ -45,7 +45,7 @@ namespace Raytracer
const Tuple &direction(void) const;
Tuple &direction(void);
Tuple position(double a_distance);
Tuple position(double a_distance) const;
Ray transform(const Matrix &a_matrix) const;

View File

@@ -39,7 +39,8 @@ using namespace Raytracer;
/* ------------------------------------------------------------------------- */
World::World(void) : m_has_light(false)
World::World(void) :
m_has_light(false)
{
}
@@ -106,7 +107,7 @@ const PointLight &World::light(void) const
void World::set_light(const PointLight &a_light)
{
m_light = a_light;
m_light = a_light;
m_has_light = true;
}
@@ -194,13 +195,13 @@ Color World::color_at(const Ray &a_ray) const
bool World::is_shadowed(const Tuple &a_point) const
{
Tuple the_v = m_light.position() - a_point;
Tuple the_v = m_light.position() - a_point;
double the_distance = the_v.magnitude();
Tuple the_direction = the_v.normalize();
Ray the_ray(a_point, the_direction);
Intersections the_intersections = intersect_world(the_ray);
Intersection the_h = the_intersections.hit();
Intersection the_h = the_intersections.hit();
if ((the_h.is_defined()) && (the_h.distance_t() < the_distance))
{

View File

@@ -40,19 +40,22 @@ using namespace Raytracer;
/* ------------------------------------------------------------------------- */
Shape::Shape(void) : m_transform(Matrix::identity())
Shape::Shape(void) :
m_transform(Matrix::identity())
{
}
/* ------------------------------------------------------------------------- */
Shape::Shape(Shape &a_copy) : m_transform(a_copy.m_transform), m_material(a_copy.m_material)
Shape::Shape(Shape &a_copy) :
m_transform(a_copy.m_transform), m_material(a_copy.m_material)
{
}
/* ------------------------------------------------------------------------- */
Shape::Shape(const Shape &a_copy) : m_transform(a_copy.m_transform), m_material(a_copy.m_material)
Shape::Shape(const Shape &a_copy) :
m_transform(a_copy.m_transform), m_material(a_copy.m_material)
{
}
@@ -66,7 +69,7 @@ const Shape &Shape::operator=(const Shape &a_shape)
}
m_transform = a_shape.m_transform;
m_material = a_shape.m_material;
m_material = a_shape.m_material;
return *this;
}
@@ -131,7 +134,7 @@ void Shape::set_material(const Material &a_material)
Tuple Shape::normal_at(const Tuple &a_world_point) const
{
Tuple the_local_point = m_transform.inverse() * a_world_point;
Tuple the_local_point = m_transform.inverse() * a_world_point;
Tuple the_local_normal = local_normal_at(the_local_point);
Tuple the_world_normal = m_transform.inverse().transpose() * the_local_normal;
the_world_normal.set_w(0);

View File

@@ -43,7 +43,7 @@ Intersections Sphere::local_intersect(const Ray &a_ray)
{
Intersections the_intersections;
Tuple the_sphere_to_ray = a_ray.origin() - Tuple::Point(0, 0, 0);
Tuple the_direction = a_ray.direction();
Tuple the_direction = a_ray.direction();
double the_a = the_direction.dot(the_direction);
double the_b = 2 * the_direction.dot(the_sphere_to_ray);

View File

@@ -32,3 +32,41 @@
using namespace Raytracer;
/* ------------------------------------------------------------------------- */
SCENARIO("Reflectivity for the default material", "[features/materials.feature]")
{
GIVEN("m <- material()")
{
Material m;
THEN("m.reflective = 0.0")
{
REQUIRE(m.reflective() == 0);
}
}
}
/* ------------------------------------------------------------------------- */
SCENARIO("Precomputing the reflection vector", "[features/intersections.feature]")
{
GIVEN("shape <- plane()")
{
Plane shape;
AND_GIVEN("r <- ray(point(0, 1, -1), vector(0, -sqrt(2)/2, sqrt(2)/2))")
{
Ray r(Tuple::Point(0, 1, -1), Tuple::Vector(0, -sqrt(2) / 2, sqrt(2) / 2));
AND_GIVEN("i <- intersection(sqrt(2), shape)")
{
Intersection i(sqrt(2), &shape);
WHEN("comps <- prepare_computation(i, r)")
{
IntersectionData comps = i.prepare_computations(r);
THEN("comps.reflectv = vector(0, sqrt(2) / 2, sqrt(2) / 2)")
{
REQUIRE(comps.reflectv() == Tuple::Vector(0, sqrt(2) / 2, sqrt(2) / 2));
}
}
}
}
}
}