[WIP] Add reflective parameter into material
This commit is contained in:
@@ -20,6 +20,7 @@ DerivePointerAlignment: false
|
||||
PointerAlignment: Right
|
||||
ReferenceAlignment: Right
|
||||
AlignArrayOfStructures: Right
|
||||
IndentCaseLabels: true
|
||||
|
||||
# AlignConsecutiveAssignments: Consecutive
|
||||
AlignConsecutiveBitFields: Consecutive
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user