From bc047cd89e50801142ceca69cd7cc66032e4c0b7 Mon Sep 17 00:00:00 2001 From: Godzil Date: Thu, 20 Feb 2020 15:11:40 +0000 Subject: [PATCH] Add viewTransform transformation --- source/include/transformation.h | 2 ++ source/transformation.cpp | 15 +++++++++ tests/transformation_test.cpp | 58 ++++++++++++++++++++++++++++++++- 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/source/include/transformation.h b/source/include/transformation.h index b37baa0..dd4828e 100644 --- a/source/include/transformation.h +++ b/source/include/transformation.h @@ -21,4 +21,6 @@ Matrix rotationZ(double angle); Matrix shearing(double Xy, double Xx, double Yx, double Yz, double Zx, double Zy); +Matrix viewTransform(Tuple from, Tuple to, Tuple up); + #endif /* DORAYME_TRANSFORMATION_H */ \ No newline at end of file diff --git a/source/transformation.cpp b/source/transformation.cpp index 9238da4..0967f90 100644 --- a/source/transformation.cpp +++ b/source/transformation.cpp @@ -81,4 +81,19 @@ Matrix shearing(double Xy, double Xz, double Yx, double Yz, double Zx, double Zy ret.set(2, 1, Zy); return ret; +} + +Matrix viewTransform(Tuple from, Tuple to, Tuple up) +{ + Tuple forward = (to - from).normalise(); + Tuple left = forward.cross(up.normalise()); + Tuple true_up = left.cross(forward); + + double orientationValues[] = { left.x, left.y, left.z, 0, + true_up.x, true_up.y, true_up.z, 0, + -forward.x, -forward.y, -forward.z, 0, + 0, 0, 0, 1 }; + Matrix orientation = Matrix4(orientationValues); + + return orientation * translation(-from.x, -from.y, -from.z); } \ No newline at end of file diff --git a/tests/transformation_test.cpp b/tests/transformation_test.cpp index d151b66..ef3c9dd 100644 --- a/tests/transformation_test.cpp +++ b/tests/transformation_test.cpp @@ -190,6 +190,61 @@ TEST(TransformationTest, Chained_transformation_must_be_applied_in_reverse_order ASSERT_EQ(T * p, Point(15, 0, 7)); } +TEST(TransformationTest, The_transformation_matrix_for_the_default_orientation) +{ + Tuple from = Point(0, 0, 0); + Tuple to = Point(0, 0, -1); + Tuple up = Vector(0, 1, 0); + + Matrix t = viewTransform(from, to, up); + + ASSERT_EQ(t, Matrix4().identity()); +} + + +TEST(TransformationTest, A_view_transformation_matrix_looking_in_positive_z_direction) +{ + Tuple from = Point(0, 0, 0); + Tuple to = Point(0, 0, 1); + Tuple up = Vector(0, 1, 0); + + Matrix t = viewTransform(from, to, up); + + ASSERT_EQ(t, scaling(-1, 1, -1)); +} + +TEST(TransformationTest, The_view_transformation_move_the_world) +{ + Tuple from = Point(0, 0, 8); + Tuple to = Point(0, 0, 0); + Tuple up = Vector(0, 1, 0); + + Matrix t = viewTransform(from, to, up); + + ASSERT_EQ(t, translation(0, 0, -8)); +} + +TEST(TransformationTest, An_arbitrary_view_transformation) +{ + Tuple from = Point(1, 3, 2); + Tuple to = Point(4, -2, 8); + Tuple up = Vector(1, 1, 0); + + Matrix t = viewTransform(from, to, up); + + double values[] = {-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}; + + /* Temporary lower the precision */ + set_equal_precision(0.00001); + + ASSERT_EQ(t, Matrix4(values)); + + set_equal_precision(FLT_EPSILON); +} + TEST(TransformationTest, Check_that_deg_to_rad_is_working) { double angle180 = deg_to_rad(180); @@ -199,4 +254,5 @@ TEST(TransformationTest, Check_that_deg_to_rad_is_working) ASSERT_EQ(angle180, M_PI); ASSERT_EQ(angle90, M_PI / 2.); ASSERT_EQ(angle270, M_PI * 1.5); -} \ No newline at end of file +} +