[FEAT] Add Normal

This commit is contained in:
NADAL Jean-Baptiste
2024-02-16 16:14:51 +01:00
parent 53cf65fda2
commit 8c75d297a7
7 changed files with 99 additions and 17 deletions

View File

@@ -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<std::initializer_list<double>> &a_values) : Matrix::Matrix(const std::initializer_list<std::initializer_list<double>> &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<std::vector<double>>(m_rows, std::vector<double>(m_cols)); m_data = std::vector<std::vector<double>>(m_rows, std::vector<double>(m_cols));
if (!validate_dimensions(a_values)) 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<std::vector<double>> 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_row = 0; the_row < m_rows; the_row++)
{ {
for (int the_col = 0; the_col < m_cols; the_col++) 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++) for (int the_col = 0; the_col < m_cols; the_col++)
{ {
the_cofactor = cofactor(the_row, the_col); the_cofactor = cofactor(the_row, the_col);
the_value = the_cofactor / the_determinant; the_value = the_cofactor / the_determinant;
the_result[the_col][the_row] = the_value; the_result[the_col][the_row] = the_value;
} }
} }

View File

@@ -60,7 +60,7 @@ namespace Raytracer
Matrix &operator=(const Matrix &a_matrix); Matrix &operator=(const Matrix &a_matrix);
bool transpose(void); Matrix transpose(void);
double determinant(void) const; double determinant(void) const;
Matrix sub_matrix(uint8_t a_row, uint8_t a_col) const; Matrix sub_matrix(uint8_t a_row, uint8_t a_col) const;
double minor(uint8_t a_row, uint8_t a_col) const; double minor(uint8_t a_row, uint8_t a_col) const;

View File

@@ -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); Tuple the_object_point = m_transform.inverse() * a_world_point;
return the_result.normalize(); 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();
} }
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */

View File

@@ -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) bool Tuple::is_point(void)
{ {
return double_equal(m_w, kRaytracerTuplePoint); return double_equal(m_w, kRaytracerTuplePoint);

View File

@@ -31,7 +31,7 @@
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
#define kRaytracerTuplePoint 1.0 #define kRaytracerTuplePoint 1.0
#define kRaytracerTupleVector 0.0 #define kRaytracerTupleVector 0.0
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
@@ -73,6 +73,11 @@ namespace Raytracer
double z(void) const; double z(void) const;
double w(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_point(void);
bool is_vector(void); bool is_vector(void);

View File

@@ -324,9 +324,7 @@ SCENARIO("Transposing a matrix", "[features/matrices.feature]")
{0, 8, 3, 8} {0, 8, 3, 8}
}; };
A.transpose(); REQUIRE(A.transpose() == transposed);
REQUIRE(A == transposed);
} }
} }
} }
@@ -337,9 +335,8 @@ SCENARIO("Transposing the identity matrix", "[features/matrices.feature]")
{ {
GIVEN("A <- transpose(identity_matrix)") GIVEN("A <- transpose(identity_matrix)")
{ {
Matrix A = Matrix::identity(); Matrix A = Matrix::identity().transpose();
A.transpose();
THEN("A = identity_matrix") THEN("A = identity_matrix")
{ {
REQUIRE(A == Matrix::identity()); REQUIRE(A == Matrix::identity());

View File

@@ -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));
}
}
}
}
}
}