From f5d2bcf8c24fc90b55e27481797ba8efaff0093b Mon Sep 17 00:00:00 2001 From: Bill Robinson Date: Sun, 1 Feb 2015 20:59:12 +0000 Subject: [PATCH] Added Matrix4::lookAt --- src/Magnum/Math/Matrix4.h | 21 +++++++++++ src/Magnum/Math/Test/Matrix4Test.cpp | 53 ++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/src/Magnum/Math/Matrix4.h b/src/Magnum/Math/Matrix4.h index 8d713cc82..6a92dd3ea 100644 --- a/src/Magnum/Math/Matrix4.h +++ b/src/Magnum/Math/Matrix4.h @@ -224,6 +224,14 @@ template class Matrix4: public Matrix4x4 { return perspectiveProjection(Vector2(xyScale, xyScale/aspectRatio), near, far); } + /** + * @brief Matrix orientated towards a specific point + * @param eye Location to place the matrix + * @param target Location towards which the matrix is orientated + * @param up Vector as a guide of which way is up (should not be same direction as target - eye) + */ + static Matrix4 lookAt(const Vector3& eye, const Vector3& target, const Vector3& up); + /** * @brief Create matrix from rotation/scaling part and translation part * @param rotationScaling Rotation/scaling part (upper-left 3x3 @@ -528,6 +536,19 @@ template Matrix4 Matrix4::perspectiveProjection(const Vector2& { T(0), T(0), T(2)*far*near*zScale, T(0)}}; } +template Matrix4 Matrix4::lookAt(const Vector3& eye, const Vector3& target, const Vector3& up) { + Vector3 zaxis = (eye - target).normalized(); // The "forward" vector. + Vector3 xaxis = Vector3::cross(up,zaxis).normalized();// The "right" vector. + Vector3 yaxis = Vector3::cross(zaxis, xaxis); // The "up" vector. + + return { + {xaxis.x(), xaxis.y(), xaxis.z(), 0 }, + {yaxis.x(), yaxis.y(), yaxis.z(), 0 }, + {zaxis.x(), zaxis.y(), zaxis.z(), 0 }, + {eye.x(), eye.y(), eye.z(), 1 } + }; +} + template inline Matrix3x3 Matrix4::rotation() const { CORRADE_ASSERT(TypeTraits::equals((*this)[0].xyz().dot(), (*this)[1].xyz().dot()) && TypeTraits::equals((*this)[1].xyz().dot(), (*this)[2].xyz().dot()), diff --git a/src/Magnum/Math/Test/Matrix4Test.cpp b/src/Magnum/Math/Test/Matrix4Test.cpp index f3b832d55..f2afd7154 100644 --- a/src/Magnum/Math/Test/Matrix4Test.cpp +++ b/src/Magnum/Math/Test/Matrix4Test.cpp @@ -93,6 +93,7 @@ struct Matrix4Test: Corrade::TestSuite::Tester { void vectorParts(); void invertedRigid(); void transform(); + void lookAt(); void debug(); void configuration(); @@ -139,6 +140,7 @@ Matrix4Test::Matrix4Test() { &Matrix4Test::vectorParts, &Matrix4Test::invertedRigid, &Matrix4Test::transform, + &Matrix4Test::lookAt, &Matrix4Test::debug, &Matrix4Test::configuration}); @@ -507,6 +509,57 @@ void Matrix4Test::transform() { CORRADE_COMPARE(a.transformPoint(v), Vector3(3.0f, -4.0f, 9.0f)); } +void Matrix4Test::lookAt() { + Matrix4 m; + m = Matrix4::lookAt( + {0.0f, 0.0f, 0.0f}, // eye + {0.0f, 1.0f, 0.0f}, // target + {0.0f, 0.0f, 1.0f} // up + ); + CORRADE_VERIFY(m.isRigidTransformation()); + CORRADE_COMPARE(m, Matrix4( + {1,0,0,0}, + {0,0,1,0}, + {0,-1,0,0}, + {0,0,0,1})); + + m = Matrix4::lookAt( + {100.0f, 200.0f, 300.0f}, // eye + {0.0f, 0.0f, 0.0f}, // target + {0.0f, 1.0f, 0.0f} // up + ); + CORRADE_VERIFY(m.isRigidTransformation()); + CORRADE_COMPARE(m, Matrix4( + {0.948683f, 0, -0.316228f, 0}, + {-0.169031f, 0.845154f, -0.507093f, 0}, + {0.267261f, 0.534522f, 0.801784f, 0}, + {100, 200, 300, 1})); + + m = Matrix4::lookAt( + {3.0f, 0.0f, 0.0f}, // eye + {0.0f, 4.0f, 5.0f}, // target + {0.0f, 0.0f, 1.0f} // up + ); + CORRADE_VERIFY(m.isRigidTransformation()); + CORRADE_COMPARE(m, Matrix4( + {0.8f, 0.6f, 0, 0}, + {0.424264f, -0.565685f, 0.707107f, 0}, + {0.424264f, -0.565685f, -0.707107f, 0}, + {3, 0, 0, 1})); + + m = Matrix4::lookAt( + {0.0f, 3.0f, 0.0f}, // eye + {-5.0f, 0.0f, -4.0f}, // target + {0.0f, 1.0f, 0.0f} // up + ); + CORRADE_VERIFY(m.isRigidTransformation()); + CORRADE_COMPARE(m, Matrix4( + {0.624695f, 0.0f, -0.780869f, 0.0f}, + {-0.331295f, 0.905539f, -0.265036f, 0.0f}, + {0.707107f, 0.424264f, 0.565685f, 0.0f}, + {0.0f, 3.0f, 0.0f, 1.0f})); +} + void Matrix4Test::debug() { Matrix4 m({3.0f, 5.0f, 8.0f, 4.0f}, {4.0f, 4.0f, 7.0f, 3.0f},