[FEAT] Add Transformation Rotation

This commit is contained in:
NADAL Jean-Baptiste
2024-02-05 18:18:04 +01:00
parent dbac8a37c4
commit 4e6ce30a1d
3 changed files with 96 additions and 2 deletions

View File

@@ -120,7 +120,7 @@ bool Matrix::operator==(const Matrix &a_matrix) const
{ {
if (!double_equal(*the_elem1, *the_elem2)) if (!double_equal(*the_elem1, *the_elem2))
{ {
printf("Elem: %f != %f\n", *the_elem1, *the_elem2); // printf("Elem: %f != %f\n", *the_elem1, *the_elem2);
return false; return false;
} }
} }
@@ -262,7 +262,7 @@ double Matrix::cofactor(uint8_t a_row, uint8_t a_col) const
bool Matrix::invertible(void) const bool Matrix::invertible(void) const
{ {
if (determinant() == 0) if (double_equal(determinant(), 0))
return false; return false;
return true; return true;
@@ -340,6 +340,48 @@ Matrix Matrix::scaling(double an_x, double an_y, double an_z)
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
Matrix Matrix::rotation_x(double a_radians)
{
Matrix the_rotation = {
{1, 0, 0, 0},
{0, cos(a_radians), -sin(a_radians), 0},
{0, sin(a_radians), cos(a_radians), 0},
{0, 0, 0, 1}
};
return the_rotation;
}
/* ------------------------------------------------------------------------- */
Matrix Matrix::rotation_y(double a_radians)
{
Matrix the_rotation = {
{ cos(a_radians), 0, sin(a_radians), 0},
{ 0, 1, 0, 0},
{-sin(a_radians), 0, cos(a_radians), 0},
{ 0, 0, 0, 1}
};
return the_rotation;
}
/* ------------------------------------------------------------------------- */
Matrix Matrix::rotation_z(double a_radians)
{
Matrix the_rotation = {
{cos(a_radians), -sin(a_radians), 0, 0},
{sin(a_radians), cos(a_radians), 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1}
};
return the_rotation;
}
/* ------------------------------------------------------------------------- */
bool Matrix::validate_dimensions(const std::initializer_list<std::initializer_list<double>> &a_values) const bool Matrix::validate_dimensions(const std::initializer_list<std::initializer_list<double>> &a_values) const
{ {
for (const auto &the_row : a_values) for (const auto &the_row : a_values)

View File

@@ -73,6 +73,9 @@ namespace Raytracer
static Matrix identity(void); static Matrix identity(void);
static Matrix translation(double an_x, double an_y, double an_z); static Matrix translation(double an_x, double an_y, double an_z);
static Matrix scaling(double an_x, double an_y, double an_z); static Matrix scaling(double an_x, double an_y, double an_z);
static Matrix rotation_x(double a_radians);
static Matrix rotation_y(double a_radians);
static Matrix rotation_z(double a_radians);
private: private:
bool validate_dimensions(const std::initializer_list<std::initializer_list<double>> &a_values) const; bool validate_dimensions(const std::initializer_list<std::initializer_list<double>> &a_values) const;

View File

@@ -102,3 +102,52 @@ TEST_CASE("[04][TRANSFORMATION] Reflection is scaling by a negative value", "[Ma
REQUIRE(transform * p == Tuple::Point(-2, 3, 4)); REQUIRE(transform * p == Tuple::Point(-2, 3, 4));
} }
/* ------------------------------------------------------------------------- */
TEST_CASE("[04][TRANSFORMATION] Rotating a point around the x axis", "[Matrix]")
{
Tuple p = Tuple::Point(0, 1, 0);
Matrix half_quarter = Matrix::rotation_x(std::numbers::pi / 4);
Matrix full_quarter = Matrix::rotation_x(std::numbers::pi / 2);
REQUIRE(half_quarter * p == Tuple::Point(0, sqrt(2) / 2, sqrt(2) / 2));
REQUIRE(full_quarter * p == Tuple::Point(0, 0, 1));
}
/* ------------------------------------------------------------------------- */
TEST_CASE("[04][TRANSFORMATION] The inverse of an x-rotation rotates in the opposite direction", "[Matrix]")
{
Tuple p = Tuple::Point(0, 1, 0);
Matrix half_quarter = Matrix::rotation_x(std::numbers::pi / 4);
Matrix inv = half_quarter.inverse();
REQUIRE(inv * p == Tuple::Point(0, sqrt(2) / 2, -sqrt(2) / 2));
}
/* ------------------------------------------------------------------------- */
TEST_CASE("[04][TRANSFORMATION] Rotating a point around the y axis", "[Matrix]")
{
Tuple p = Tuple::Point(0, 0, 1);
Matrix half_quarter = Matrix::rotation_y(std::numbers::pi / 4);
Matrix full_quarter = Matrix::rotation_y(std::numbers::pi / 2);
REQUIRE(half_quarter * p == Tuple::Point(sqrt(2) / 2, 0, sqrt(2) / 2));
REQUIRE(full_quarter * p == Tuple::Point(1, 0, 0));
}
/* ------------------------------------------------------------------------- */
TEST_CASE("[04][TRANSFORMATION] Rotating a point around the z axis", "[Matrix]")
{
Tuple p = Tuple::Point(0, 1, 0);
Matrix half_quarter = Matrix::rotation_z(std::numbers::pi / 4);
Matrix full_quarter = Matrix::rotation_z(std::numbers::pi / 2);
Tuple z = half_quarter * p;
REQUIRE(half_quarter * p == Tuple::Point(-sqrt(2) / 2, sqrt(2) / 2, 0));
REQUIRE(full_quarter * p == Tuple::Point(-1, 0, 0));
}