From 0bd81de8a1d47d0acda8a38b1a12f4ed66219cb0 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sun, 6 Nov 2022 16:08:52 -0800 Subject: [PATCH] Add Matrix::LookAt (flutter/engine#37361) --- .../impeller/geometry/geometry_unittests.cc | 46 +++++++++++++++++++ engine/src/flutter/impeller/geometry/matrix.h | 17 +++++++ 2 files changed, 63 insertions(+) diff --git a/engine/src/flutter/impeller/geometry/geometry_unittests.cc b/engine/src/flutter/impeller/geometry/geometry_unittests.cc index 42da1d65b3..9392b12947 100644 --- a/engine/src/flutter/impeller/geometry/geometry_unittests.cc +++ b/engine/src/flutter/impeller/geometry/geometry_unittests.cc @@ -424,6 +424,52 @@ TEST(GeometryTest, MatrixIsAligned) { } } +TEST(GeometryTest, MatrixLookAt) { + { + auto m = Matrix::MakeLookAt(Vector3(0, 0, -1), Vector3(0, 0, 1), + Vector3(0, 1, 0)); + auto expected = Matrix{ + 1, 0, 0, 0, // + 0, 1, 0, 0, // + 0, 0, 1, 0, // + 0, 0, 1, 1, // + }; + ASSERT_MATRIX_NEAR(m, expected); + } + + // Sideways tilt. + { + auto m = Matrix::MakeLookAt(Vector3(0, 0, -1), Vector3(0, 0, 1), + Vector3(1, 1, 0).Normalize()); + + // clang-format off + auto expected = Matrix{ + k1OverSqrt2, k1OverSqrt2, 0, 0, + -k1OverSqrt2, k1OverSqrt2, 0, 0, + 0, 0, 1, 0, + 0, 0, 1, 1, + }; + // clang-format on + ASSERT_MATRIX_NEAR(m, expected); + } + + // Half way between +x and -y, yaw 90 + { + auto m = + Matrix::MakeLookAt(Vector3(), Vector3(10, -10, 0), Vector3(0, 0, -1)); + + // clang-format off + auto expected = Matrix{ + -k1OverSqrt2, 0, k1OverSqrt2, 0, + -k1OverSqrt2, 0, -k1OverSqrt2, 0, + 0, -1, 0, 0, + 0, 0, 0, 1, + }; + // clang-format on + ASSERT_MATRIX_NEAR(m, expected); + } +} + TEST(GeometryTest, QuaternionLerp) { auto q1 = Quaternion{{0.0, 0.0, 1.0}, 0.0}; auto q2 = Quaternion{{0.0, 0.0, 1.0}, kPiOver4}; diff --git a/engine/src/flutter/impeller/geometry/matrix.h b/engine/src/flutter/impeller/geometry/matrix.h index c5025336b0..2d50f30450 100644 --- a/engine/src/flutter/impeller/geometry/matrix.h +++ b/engine/src/flutter/impeller/geometry/matrix.h @@ -435,6 +435,23 @@ struct Matrix { return MakePerspective(fov_y, static_cast(size.width) / size.height, z_near, z_far); } + + static constexpr Matrix MakeLookAt(Vector3 position, + Vector3 target, + Vector3 up) { + Vector3 forward = (target - position).Normalize(); + Vector3 right = up.Cross(forward); + up = forward.Cross(right); + + // clang-format off + return { + right.x, up.x, forward.x, 0.0f, + right.y, up.y, forward.y, 0.0f, + right.z, up.z, forward.z, 0.0f, + -right.Dot(position), -up.Dot(position), -forward.Dot(position), 1.0f + }; + // clang-format on + } }; static_assert(sizeof(struct Matrix) == sizeof(Scalar) * 16,