[ADD] Add View treansform

This commit is contained in:
2024-02-23 14:49:26 +01:00
parent ea33f1b985
commit 9b85b5940a
3 changed files with 132 additions and 0 deletions

View File

@@ -397,6 +397,24 @@ Matrix Matrix::shearing(double a_xy, double a_xz, double a_yx, double a_yz, doub
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
Matrix Matrix::view_transform(Tuple a_from, Tuple a_to, Tuple an_up)
{
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 = {
{ 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},
{ 0, 0, 0, 1}
};
return the_orientation * translation(-a_from.x(), -a_from.y(), -a_from.z());
}
/* ------------------------------------------------------------------------- */
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

@@ -77,6 +77,7 @@ namespace Raytracer
static Matrix rotation_y(double a_radians); static Matrix rotation_y(double a_radians);
static Matrix rotation_z(double a_radians); static Matrix rotation_z(double a_radians);
static Matrix shearing(double a_xy, double a_xz, double a_yx, double a_yz, double a_zx, double a_zy); static Matrix shearing(double a_xy, double a_xz, double a_yx, double a_yz, double a_zx, double a_zy);
static Matrix view_transform(Tuple a_from, Tuple a_to, Tuple an_up);
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

@@ -390,3 +390,116 @@ SCENARIO("The color with an intersection behind the ray", "[features/world.featu
} }
} }
} }
/* ------------------------------------------------------------------------- */
SCENARIO("The transformation matrix for the default orientation", "[features/transformations.feature]")
{
GIVEN("from <- point(0, 0, 0)")
{
Tuple from = Tuple::Point(0, 0, 0);
AND_GIVEN("to <- point(0, 0, -1)")
{
Tuple to = Tuple::Point(0, 0, -1);
AND_GIVEN("up <- vector(0, 1, 0)")
{
Tuple up = Tuple::Vector(0, 1, 0);
WHEN("t <- view_transform(from, to, up)")
{
Matrix t = Matrix::view_transform(from, to, up);
THEN("t = identify_matrix")
{
REQUIRE(t == Matrix::identity());
}
}
}
}
}
}
/* ------------------------------------------------------------------------- */
SCENARIO("A view transformation matrix looking in positive z direction", "[features/transformations.feature]")
{
GIVEN("from <- point(0, 0, 0)")
{
Tuple from = Tuple::Point(0, 0, 0);
AND_GIVEN("to <- point(0, 0, 1)")
{
Tuple to = Tuple::Point(0, 0, 1);
AND_GIVEN("up <- vector(0, 1, 0)")
{
Tuple up = Tuple::Vector(0, 1, 0);
WHEN("t <- view_transform(from, to, up)")
{
Matrix t = Matrix::view_transform(from, to, up);
THEN("t = scaling(-1, 1, -1)")
{
REQUIRE(t == Matrix::scaling(-1, 1, -1));
}
}
}
}
}
}
/* ------------------------------------------------------------------------- */
SCENARIO("A view transformation moves the world", "[features/transformations.feature]")
{
GIVEN("from <- point(0, 0, 8)")
{
Tuple from = Tuple::Point(0, 0, 8);
AND_GIVEN("to <- point(0, 0, 0)")
{
Tuple to = Tuple::Point(0, 0, 0);
AND_GIVEN("up <- vector(0, 1, 0)")
{
Tuple up = Tuple::Vector(0, 1, 0);
WHEN("t <- view_transform(from, to, up)")
{
Matrix t = Matrix::view_transform(from, to, up);
THEN("t = translation(0, 0, -8)")
{
REQUIRE(t == Matrix::translation(0, 0, -8));
}
}
}
}
}
}
/* ------------------------------------------------------------------------- */
SCENARIO("An arbitrary view transformation", "[features/transformations.feature]")
{
GIVEN("from <- point(1, 3, 2)")
{
Tuple from = Tuple::Point(1, 3, 2);
AND_GIVEN("to <- point(4, -2, 8)")
{
Tuple to = Tuple::Point(4, -2, 8);
AND_GIVEN("up <- vector(1, 1, 0)")
{
Tuple up = Tuple::Vector(1, 1, 0);
WHEN("t <- view_transform(from, to, up)")
{
Matrix t = Matrix::view_transform(from, to, up);
THEN("t iq the following 4x4 matrix")
{
// | -0.50709 | 0.50709 | 0.67612 | -2.36643 |
// | 0.76772 | 0.60609 | 0.12122 | -2.82843 |
// | -0.35857 | 0.59761 | -0.71714 | 0.00000 |
// | 0.00000 | 0.00000 | 0.00000 | 1.00000 |
REQUIRE(t == Matrix({
{-0.50709, 0.50709, 0.67612, -2.36643},
{ 0.76772, 0.60609, 0.12122, -2.82843},
{-0.35857, 0.59761, -0.71714, 0.00000},
{ 0.00000, 0.00000, 0.00000, 1.00000}
}));
}
}
}
}
}
}