From 8c75d297a76ca57a11e86bf1ec88c72a485cd818 Mon Sep 17 00:00:00 2001 From: NADAL Jean-Baptiste Date: Fri, 16 Feb 2024 16:14:51 +0100 Subject: [PATCH] [FEAT] Add Normal --- raytracing/src/matrix.cpp | 15 ++++++------ raytracing/src/matrix.h | 2 +- raytracing/src/shape.cpp | 9 ++++--- raytracing/src/tuple.cpp | 28 ++++++++++++++++++++++ raytracing/src/tuple.h | 7 +++++- tests/03_matrix.cpp | 7 ++---- tests/06_light_shading.cpp | 48 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 99 insertions(+), 17 deletions(-) diff --git a/raytracing/src/matrix.cpp b/raytracing/src/matrix.cpp index f8cbf81..53011aa 100644 --- a/raytracing/src/matrix.cpp +++ b/raytracing/src/matrix.cpp @@ -65,7 +65,8 @@ Matrix::Matrix(const Matrix &an_other) : m_rows(an_other.m_rows), m_cols(an_othe /* ------------------------------------------------------------------------- */ Matrix::Matrix(const std::initializer_list> &a_values) : - m_rows(a_values.size()), m_cols(a_values.size()) + m_rows(a_values.size()), + m_cols(a_values.size()) { m_data = std::vector>(m_rows, std::vector(m_cols)); if (!validate_dimensions(a_values)) @@ -187,19 +188,19 @@ Matrix &Matrix::operator=(const Matrix &a_matrix) /* ------------------------------------------------------------------------- */ -bool Matrix::transpose(void) +Matrix Matrix::transpose(void) { - std::vector> the_copy = m_data; + Matrix the_transposed(m_rows, m_cols); for (int the_row = 0; the_row < m_rows; the_row++) { for (int the_col = 0; the_col < m_cols; the_col++) { - m_data[the_col][the_row] = the_copy[the_row][the_col]; + the_transposed[the_col][the_row] = m_data[the_row][the_col]; } } - return true; + return the_transposed; } /* ------------------------------------------------------------------------- */ @@ -287,8 +288,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; } } diff --git a/raytracing/src/matrix.h b/raytracing/src/matrix.h index 149bd90..b142cdc 100644 --- a/raytracing/src/matrix.h +++ b/raytracing/src/matrix.h @@ -60,7 +60,7 @@ namespace Raytracer Matrix &operator=(const Matrix &a_matrix); - bool transpose(void); + Matrix transpose(void); double determinant(void) const; Matrix sub_matrix(uint8_t a_row, uint8_t a_col) const; double minor(uint8_t a_row, uint8_t a_col) const; diff --git a/raytracing/src/shape.cpp b/raytracing/src/shape.cpp index 4f9eb07..064af6c 100644 --- a/raytracing/src/shape.cpp +++ b/raytracing/src/shape.cpp @@ -96,10 +96,13 @@ void Shape::set_transform(const Matrix &a_transform_matrix) /* ------------------------------------------------------------------------- */ -Tuple Shape::normal_at(const Tuple &a_point) +Tuple Shape::normal_at(const Tuple &a_world_point) { - Tuple the_result = a_point - Tuple::Point(0, 0, 0); - return the_result.normalize(); + Tuple the_object_point = m_transform.inverse() * a_world_point; + Tuple the_object_normal = the_object_point - Tuple::Point(0, 0, 0); + Tuple the_world_normal = m_transform.inverse().transpose() * the_object_normal; + the_world_normal.set_w(0); + return the_world_normal.normalize(); } /* ------------------------------------------------------------------------- */ diff --git a/raytracing/src/tuple.cpp b/raytracing/src/tuple.cpp index a6ade1d..d0ec55c 100644 --- a/raytracing/src/tuple.cpp +++ b/raytracing/src/tuple.cpp @@ -258,6 +258,34 @@ double Tuple::w(void) const /* ------------------------------------------------------------------------- */ +void Tuple::set_x(double an_x) +{ + m_x = an_x; +} + +/* ------------------------------------------------------------------------- */ + +void Tuple::set_y(double an_y) +{ + m_y = an_y; +} + +/* ------------------------------------------------------------------------- */ + +void Tuple::set_z(double a_z) +{ + m_z = a_z; +} + +/* ------------------------------------------------------------------------- */ + +void Tuple::set_w(double a_w) +{ + m_w = a_w; +} + +/* ------------------------------------------------------------------------- */ + bool Tuple::is_point(void) { return double_equal(m_w, kRaytracerTuplePoint); diff --git a/raytracing/src/tuple.h b/raytracing/src/tuple.h index c700bf4..d4e5b69 100644 --- a/raytracing/src/tuple.h +++ b/raytracing/src/tuple.h @@ -31,7 +31,7 @@ /* ------------------------------------------------------------------------- */ -#define kRaytracerTuplePoint 1.0 +#define kRaytracerTuplePoint 1.0 #define kRaytracerTupleVector 0.0 /* ------------------------------------------------------------------------- */ @@ -73,6 +73,11 @@ namespace Raytracer double z(void) const; double w(void) const; + void set_x(double an_x); + void set_y(double an_y); + void set_z(double a_z); + void set_w(double a_w); + bool is_point(void); bool is_vector(void); diff --git a/tests/03_matrix.cpp b/tests/03_matrix.cpp index 93140b1..528e31b 100644 --- a/tests/03_matrix.cpp +++ b/tests/03_matrix.cpp @@ -324,9 +324,7 @@ SCENARIO("Transposing a matrix", "[features/matrices.feature]") {0, 8, 3, 8} }; - A.transpose(); - - REQUIRE(A == transposed); + REQUIRE(A.transpose() == transposed); } } } @@ -337,9 +335,8 @@ SCENARIO("Transposing the identity matrix", "[features/matrices.feature]") { GIVEN("A <- transpose(identity_matrix)") { - Matrix A = Matrix::identity(); + Matrix A = Matrix::identity().transpose(); - A.transpose(); THEN("A = identity_matrix") { REQUIRE(A == Matrix::identity()); diff --git a/tests/06_light_shading.cpp b/tests/06_light_shading.cpp index d9776d7..99b5493 100644 --- a/tests/06_light_shading.cpp +++ b/tests/06_light_shading.cpp @@ -120,3 +120,51 @@ SCENARIO("The normal is a normalized vector", "[features/spheres.feature]") } } } + +/* ------------------------------------------------------------------------- */ + +SCENARIO("Computing the normal on a translated sphere", "[features/spheres.feature]") +{ + GIVEN("s <- sphere()") + { + Sphere s; + AND_GIVEN("set_transform(s, translation(0,1,0))") + { + s.set_transform(Matrix::translation(0, 1, 0)); + WHEN("n <- normal_at(s,point(0,1.70711,-0.70711))") + { + Tuple n = s.normal_at(Tuple::Point(0, 1.70711, -0.70711)); + THEN("n = vector(0,0.70711, -0.70711)") + { + REQUIRE(n == Tuple::Vector(0, 0.70711, -0.70711)); + } + } + } + } +} + +/* ------------------------------------------------------------------------- */ + +SCENARIO("Computing the normal on a transformed sphere", "[features/spheres.feature]") +{ + GIVEN("s <- sphere()") + { + Sphere s; + AND_GIVEN("m <- scaling(1,0.5,1) * rotation_z(pi/5)") + { + Matrix m = Matrix::scaling(1, 0.5, 1) * Matrix::rotation_z(std::numbers::pi / 5); + AND_GIVEN("set_transform(s, m)") + { + s.set_transform(m); + WHEN("n <- normal_at(s,point(0,sqrt(2)/2,sqrt(2)/2))") + { + Tuple n = s.normal_at(Tuple::Point(0, sqrt(2) / 2, -sqrt(2) / 2)); + THEN("n = vector(0,97014, -0.24254)") + { + REQUIRE(n == Tuple::Vector(0, 0.97014, -0.24254)); + } + } + } + } + } +}