diff --git a/include/J3ML/LinearAlgebra/Matrix4x4.h b/include/J3ML/LinearAlgebra/Matrix4x4.h index a45c3dc..fbd24f2 100644 --- a/include/J3ML/LinearAlgebra/Matrix4x4.h +++ b/include/J3ML/LinearAlgebra/Matrix4x4.h @@ -65,6 +65,37 @@ namespace LinearAlgebra { /// Logically, the translation occurs after the rotation has been performed. Matrix4x4(const Quaternion& orientation, const Vector3 &translation); + /// Creates a LookAt matrix from a look-at direction vector. + /** A LookAt matrix is a rotation matrix that orients an object to face towards a specified target direction. + @param localForward Specifies the forward direction in the local space of the object. This is the direction + the model is facing at in its own local/object space, often +X (1,0,0), +Y (0,1,0) or +Z (0,0,1). The + vector to pass in here depends on the conventions you or your modeling software is using, and it is best + pick one convention for all your objects, and be consistent. + This input parameter must be a normalized vector. + @param targetDirection Specifies the desired world space direction the object should look at. This function + will compute a rotation matrix which will rotate the localForward vector to orient towards this targetDirection + vector. This input parameter must be a normalized vector. + @param localUp Specifies the up direction in the local space of the object. This is the up direction the model + was authored in, often +Y (0,1,0) or +Z (0,0,1). The vector to pass in here depends on the conventions you + or your modeling software is using, and it is best to pick one convention for all your objects, and be + consistent. This input parameter must be a normalized vector. This vector must be perpendicular to the + vector localForward, i.e. localForward.Dot(localUp) == 0. + @param worldUp Specifies the global up direction of the scene in world space. Simply rotating one vector to + coincide with another (localForward->targetDirection) would cause the up direction of the resulting + orientation to drift (e.g. the model could be looking at its target its head slanted sideways). To keep + the up direction straight, this function orients the localUp direction of the model to point towards the + specified worldUp direction (as closely as possible). The worldUp and targetDirection vectors cannot be + collinear, but they do not need to be perpendicular either. + @return A matrix that maps the given local space forward direction vector to point towards the given target + direction, and the given local up direction towards the given target world up direction. The returned + matrix M is orthonormal with a determinant of +1. For the matrix M it holds that + M * localForward = targetDirection, and M * localUp lies in the plane spanned by the vectors targetDirection + and worldUp. + @note The position of (the translation performed by) the resulting matrix will be set to (0,0,0), i.e. the object + will be placed to origin. Call SetTranslatePart() on the resulting matrix to set the position of the model. + @see RotateFromTo(). */ + static Matrix4x4 LookAt(const Vector3& localFwd, const Vector3& targetDir, const Vector3& localUp, const Vector3& worldUp); + /// Returns the translation part. /** The translation part is stored in the fourth column of this matrix. This is equivalent to decomposing this matrix in the form M = T * M', i.e. this translation is applied last, diff --git a/src/J3ML/LinearAlgebra/Matrix4x4.cpp b/src/J3ML/LinearAlgebra/Matrix4x4.cpp index 09103ad..9047b6c 100644 --- a/src/J3ML/LinearAlgebra/Matrix4x4.cpp +++ b/src/J3ML/LinearAlgebra/Matrix4x4.cpp @@ -419,4 +419,13 @@ namespace LinearAlgebra { Vector3 Matrix4x4::GetTranslatePart() const { return GetColumn3(3); } + + Matrix4x4 + Matrix4x4::LookAt(const Vector3 &localFwd, const Vector3 &targetDir, const Vector3 &localUp, const Vector3 &worldUp) { + Matrix4x4 m; + m.Set3x3Part(Matrix3x3::LookAt(localFwd, targetDir, localUp, worldUp)); + m.SetTranslatePart(0,0,0); + m.SetRow(3, 0,0,0,1); + return m; + } } \ No newline at end of file