Browse Source

Add viewTransform transformation

Godzil 4 years ago
parent
commit
bc047cd89e
3 changed files with 74 additions and 1 deletions
  1. 2 0
      source/include/transformation.h
  2. 15 0
      source/transformation.cpp
  3. 57 1
      tests/transformation_test.cpp

+ 2 - 0
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 */

+ 15 - 0
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);
 }

+ 57 - 1
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);
-}
+}
+