/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #pragma once // includes #include #include "StandardHeaders.h" #include "Vector.h" #include "PlaneEq.h" #include "LogManager.h" #include #include #include // matrix order #define MCORE_MATRIX_ROWMAJOR // matrix element access #ifdef MCORE_MATRIX_ROWMAJOR #define MMAT(matrix, row, col) matrix.m44[row][col] #define TMAT(row, col) m44[row][col] #else #define MMAT(matrix, row, col) matrix.m44[col][row] #define TMAT(row, col) m44[col][row] #endif namespace AZ { class Quaternion; } namespace MCore { /** * Depracated. Please use AZ::Transform instead. * A 4x4 matrix class. * Matrices can for example be used to transform points or vectors. * Transforming means moving to another coordinate system. With matrices you can do things like: translate (move), rotate and scale. * One single matrix can store a translation, rotation and scale. If we have only a rotation inside the matrix, this means that if we * multiply the matrix with a vector, the vector will rotate by the rotation inside the matrix! The cool thing is that you can also * concatenate matrices. In other words, you can multiply matrices with eachother. If you have a rotation matrix, like described above, and * also have a translation matrix, then multiplying these two matrices with eachother will result in a new matrix, which contains both the * rotation and the translation! So when you multiply this resulting matrix with a vector, it will both translate and rotate. * But, does it first rotate and then translate in the rotated space? Or does it first translate and then rotate? * For example if you want to rotate a planet, while it's moving, you want to rotate it in it's local coordinate system. Like when you spin * a globe you can have on your desk. So where it spins around it's own center. However, if the planet is at location (10,10,10) in 3D space for example * it is also possible that rotates around the origin in world space (0,0,0). The order of multiplication between matrices matters. * This means that (matrixA * matrixB) does not have to not result in the same as (matrixB * matrixA). * * Here is some information about how the matrices are stored internally: * * [00 01 02 03] // m16 offsets
* [04 05 06 07]
* [08 09 10 11]
* [12 13 14 15]
* * [00 01 02 03] // m44 offsets --> [row][column]
* [10 11 12 13]
* [20 21 22 23]
* [30 31 32 33]
* * [Xx Xy Xz 0] // right
* [Yx Yy Yz 0] // up
* [Zx Zy Zz 0] // forward
* [Tx Ty Tz 1] // translation
* */ MCORE_ALIGN_PRE(16) class MCORE_API Matrix { public: /** * Default constructor. * This leaves the matrix uninitialized. */ MCORE_INLINE Matrix() {} /** * Init the matrix using given float data. * The number of elements stored at the float pointer location that is used as parameter must be at least 16 floats in size. * @param elementData A pointer to the matrix float data, which must be 16 floats in size, or more, although only the first 16 floats are used. */ MCORE_INLINE explicit Matrix(const float* elementData) { MCore::MemCopy(m16, elementData, sizeof(float) * 16); } /** * Copy constructor. * @param m The matrix to copy the data from. */ MCORE_INLINE Matrix(const Matrix& m); MCORE_INLINE Matrix(const AZ::Matrix4x4& m) { TMAT(0, 0) = m.GetElement(0, 0); TMAT(0, 1) = m.GetElement(0, 1); TMAT(0, 2) = m.GetElement(0, 2); TMAT(0, 3) = m.GetElement(0, 3); TMAT(1, 0) = m.GetElement(1, 0); TMAT(1, 1) = m.GetElement(1, 1); TMAT(1, 2) = m.GetElement(1, 2); TMAT(1, 3) = m.GetElement(1, 3); TMAT(2, 0) = m.GetElement(2, 0); TMAT(2, 1) = m.GetElement(2, 1); TMAT(2, 2) = m.GetElement(2, 2); TMAT(2, 3) = m.GetElement(2, 3); TMAT(3, 0) = m.GetElement(3, 0); TMAT(3, 1) = m.GetElement(3, 1); TMAT(3, 2) = m.GetElement(3, 2); TMAT(3, 3) = m.GetElement(3, 3); } void InitFromPosRot(const AZ::Vector3& pos, const AZ::Quaternion& rot); void InitFromPosRotScale(const AZ::Vector3& pos, const AZ::Quaternion& rot, const AZ::Vector3& scale); void InitFromNoScaleInherit(const AZ::Vector3& translation, const AZ::Quaternion& rotation, const AZ::Vector3& scale, const AZ::Vector3& invParentScale); void InitFromPosRotScaleScaleRot(const AZ::Vector3& pos, const AZ::Quaternion& rot, const AZ::Vector3& scale, const AZ::Quaternion& scaleRot); void InitFromPosRotScaleShear(const AZ::Vector3& pos, const AZ::Quaternion& rot, const AZ::Vector3& scale, const AZ::Vector3& shear); /** * Sets the matrix to identity. * When a matrix is an identity matrix it will have no influence. */ void Identity(); /** * Makes the matrix a scaling matrix. * Values of 1.0 would have no influence on the scale. Values of for example 2.0 would scale up by a factor of two. * @param s The vector containing the scale values for each axis. */ void SetScaleMatrix(const AZ::Vector3& s); /** * Makes this matrix a shear matrix from three different shear matrices: XY, XZ and YZ. * The multiplication order is YZ * XZ * XY. * @param s The shear values (x=XY, y=XZ, z=YZ) */ void SetShearMatrix(const AZ::Vector3& s); /** * Makes this matrix a translation matrix. * @param t The translation value. */ void SetTranslationMatrix(const AZ::Vector3& t); /** * Initialize this matrix into a rotation matrix from a AZ::Quaternion. * @param rotation The AZ::Quaternion representing the rotatation. */ void SetRotationMatrix(const AZ::Quaternion& rotation); /** * Makes the matrix an rotation matrix along the x-axis. * @param angle The angle to rotate around this axis, in radians. */ void SetRotationMatrixX(float angle); /** * Makes the matrix a rotation matrix along the y-axis. * @param angle The angle to rotate around this axis, in radians. */ void SetRotationMatrixY(float angle); /** * Makes the matrix a rotation matrix along the z-axis. * @param angle The angle to rotate around this axis, in radians. */ void SetRotationMatrixZ(float angle); /** * Makes the matrix a rotation matrix around a given axis with a given angle. * @param axis The axis to rotate around. * @param angle The angle to rotate around this axis, in radians. */ void SetRotationMatrixAxisAngle(const AZ::Vector3& axis, float angle); /** * Makes the matrix a rotation matrix given the euler angles. * The multiplication order is RotMatrix(v.z) * RotMatrix(v.y) * RotMatrix(v.x). * @param anglevec The vector containing the angles for each axis, in radians, so (pitch, yaw, roll) as (x,y,z). */ void SetRotationMatrixEulerZYX(const AZ::Vector3& anglevec); /** * Initialize the matrix from a yaw, pitch and roll. * Pitch is the rotation around the x-axis. * Yaw is the rotation aroudn the y-axis. * Roll is the rotation around the z-axis. * All angles are in radians. * @param pitch The pitch angle (rotation around x-axis), in radians. * @param yaw The yaw angle (rotation around y-axis), in radians. * @param roll The roll angle (rotation around z-axis), in radians. */ void SetRotationMatrixPitchYawRoll(float pitch, float yaw, float roll); /** * Initialize the matrix from a yaw, pitch and roll. * Pitch is the rotation around the x-axis. * Yaw is the rotation aroudn the y-axis. * Roll is the rotation around the z-axis. * All angles are in radians. * @param angles The angle for each axis, in radians. */ MCORE_INLINE void SetRotationMatrixPitchYawRoll(const AZ::Vector3& angles) { SetRotationMatrixPitchYawRoll(angles.GetX(), angles.GetY(), angles.GetZ()); } /** * Makes the matrix a rotation matrix given the euler angles. * The multiplication order is RotMatrix(v.x) * RotMatrix(v.y) * RotMatrix(v.z). * @param anglevec The vector containing the angles for each axis, in radians, so (pitch, yaw, roll) as (x,y,z). */ void SetRotationMatrixEulerXYZ(const AZ::Vector3& anglevec); /** * Inverse rotate a vector with this matrix. * This means that the vector will be multiplied with the inverse rotation of this matrix. * @param v The vector to rotate. * @result The rotated vector. */ AZ::Vector3 InverseRot(const AZ::Vector3& v); /** * Multiply this matrix with another matrix and stores the result in itself. * @param right The matrix to multiply with. */ void MultMatrix(const Matrix& right); /** * Multiply this matrix with another matrix, but only multiply the 4x3 part. * So treat the other matrix as 4x3 matrix instead of 4x4 matrix. Stores the result in itself. * @param right The matrix to multiply with. */ void MultMatrix4x3(const Matrix& right); /** * Multiply two matrices together, but only the 4x3 part, and store the result in itself. * @param left The left matrix. * @param right The right matrix. */ void MultMatrix4x3(const Matrix& left, const Matrix& right); /** * Multiply the left matrix with the right matrix and store the result in this matrix object. * So basically this is a fast version of:
*
         * Matrix result = left * right;    // where left and right are also Matrix objects
         * 
* * @param left The left matrix of the matrix multiply. * @param right The right matrix of the matrix multiply. */ void MultMatrix(const Matrix& left, const Matrix& right); /** * Multiply this matrix with the 3x3 rotation part of the other given matrix, and modify itself. * @param right The matrix to multiply with. */ void MultMatrix3x3(const Matrix& right); MCORE_INLINE void Skin(const AZ::Vector3* inPos, const AZ::Vector3* inNormal, AZ::Vector3* outPos, AZ::Vector3* outNormal, float weight); MCORE_INLINE void Skin(const AZ::Vector3* inPos, const AZ::Vector3* inNormal, const AZ::Vector4* inTangent, AZ::Vector3* outPos, AZ::Vector3* outNormal, AZ::Vector4* outTangent, float weight); MCORE_INLINE void Skin(const AZ::Vector3* inPos, const AZ::Vector3* inNormal, const AZ::Vector4* inTangent, const AZ::Vector3* inBitangent, AZ::Vector3* outPos, AZ::Vector3* outNormal, AZ::Vector4* outTangent, AZ::Vector3* outBitangent, float weight); /** * Perform skinning on an input vertex, and add the result to the output, weighted by a weight value. * The calculation performed is: * *
         * out += (in * thisMatrix) * weight;
         * 
* * Only the 4x3 part of the matrix is used during the matrix multiply. * So this should be used when skinning for example positions. * @param in The input vector to skin. * @param out The output vector. Keep in mind that the result will be added to the output vector. * @param weight The weight value. */ MCORE_INLINE void Skin4x3(const AZ::Vector3& in, AZ::Vector3& out, float weight); /** * Perform skinning on an input vertex, and add the result to the output, weighted by a weight value. * The calculation performed is: * *
         * out += (in * thisMatrix) * weight;
         * 
* * Only the 3x3 part of the matrix is used during the matrix multiply. * So this should be used to skin normals and tangents. * @param in The input vector to skin. * @param out The output vector. Keep in mind that the result will be added to the output vector. * @param weight The weight value. */ MCORE_INLINE void Skin3x3(const AZ::Vector3& in, AZ::Vector3& out, float weight); /** * Transpose the matrix (swap rows with columns). */ void Transpose(); /** * Transpose the translation 1x3 translation part. * Leaves the rotation in tact. */ void TransposeTranslation(); /** * Adjoint this matrix. */ void Adjoint(); /** * Inverse this matrix. */ void Inverse(); /** * Makes this the inverse tranpose version of this matrix. * The inverse transpose is the transposed version of the inverse. */ MCORE_INLINE void InverseTranspose(); /** * Returns the inverse transposed version of this matrix. * The inverse transpose is the transposed version of the inverse. * @result The inverse transposed version of this matrix. */ MCORE_INLINE Matrix InverseTransposed() const; /** * Orthonormalize this matrix (to prevent skewing or other errors). * This normalizes the x, y and z vectors of the matrix. * It makes sure that the axis vectors are perpendicular to eachother. */ void OrthoNormalize(); /** * Normalizes the matrix, which means that all axis vectors (right, up, forward) * will be made of unit length. */ void Normalize(); /** * Returns a normalized version of this matrix. * @result The normalized version of this matrix, where the right, up and forward vectors are of unit length. */ MCORE_INLINE Matrix Normalized() const; /** * Scale this matrix. * @param scale The scale factors for each axis. */ MCORE_INLINE void Scale(const AZ::Vector3& scale); /** * Scale only the upper left 3x3 part of this matrix. * So this doesn't scale the translation part. * @param scale The scale factors for each axis. */ void Scale3x3(const AZ::Vector3& scale); AZ::Vector3 ExtractScale(); /** * Rotate this matrix around the x-axis. * @param angle The rotation in radians. */ void RotateX(float angle); /** * Rotate this matrix around the y-axis. * @param angle The rotation in radians. */ void RotateY(float angle); /** * Rotate this matrix around the z-axis. * @param angle The rotation in radians. */ void RotateZ(float angle); /** * Initialize the matrix as a rotation matrix given two vectors. The resulting matrix rotates the vector 'from' such that it points * in the same direction as the vector 'to'. * @param from The vector that the resulting matrix rotates from. * @param to The vector that the resulting matrix rotates to. */ void SetRotationMatrixTwoVectors(const AZ::Vector3& from, const AZ::Vector3& to); /** * Multiply a vector with the 3x3 rotation part of this matrix. * @param v The vector to transform. * @result The transformed (rotated) vector. */ MCORE_INLINE AZ::Vector3 Mul3x3(const AZ::Vector3& v) const; /** * Returns the inversed version of this matrix. * @result The inversed version of this matrix. */ MCORE_INLINE Matrix Inversed() const { Matrix m(*this); m.Inverse(); return m; } /** * Returns the transposed version of this matrix. * @result The transposed version of this matrix. */ MCORE_INLINE Matrix Transposed() const { Matrix m(*this); m.Transpose(); return m; } /** * Returns the adjointed version of this matrix. * @result The adjointed version of this matrix. */ MCORE_INLINE Matrix Adjointed() const { Matrix m(*this); m.Adjoint(); return m; } /** * Translate the matrix. * @param x The number of units to add to the current translation along the x-axis. * @param y The number of units to add to the current translation along the y-axis. * @param z The number of units to add to the current translation along the z-axis. */ MCORE_INLINE void Translate(float x, float y, float z) { TMAT(3, 0) += x; TMAT(3, 1) += y; TMAT(3, 2) += z; } /** * Translate the matrix. * @param t The vector containing the translation to add to the current translation of the matrix. */ MCORE_INLINE void Translate(const AZ::Vector3& t) { TMAT(3, 0) += t.GetX(); TMAT(3, 1) += t.GetY(); TMAT(3, 2) += t.GetZ(); } /** * Set the values for a given row, using a 3D vector. * Only the first 3 values on the row will be touched, so the 4th value will remain untouched inside the specified row of the matrix. * @param row A zero-based index of the row. * @param value The values to set in the row. */ MCORE_INLINE void SetRow(uint32 row, const AZ::Vector3& value) { TMAT(row, 0) = value.GetX(); TMAT(row, 1) = value.GetY(); TMAT(row, 2) = value.GetZ(); } /** * Set the values in the given row, using a 4D vector. * @param row A zero-based index of the row. * @param value The values to set in the row. */ MCORE_INLINE void SetRow(uint32 row, const AZ::Vector4& value) { TMAT(row, 0) = value.GetX(); TMAT(row, 1) = value.GetY(); TMAT(row, 2) = value.GetZ(); TMAT(row, 3) = value.GetW(); } /** * Set the values for a given column, using a 3D vector. * Only the first 3 values on the column will be touched, so the 4th value will remain untouched inside the specified column of the matrix. * @param column A zero-based index of the column. * @param value The values to set in the column. */ MCORE_INLINE void SetColumn(uint32 column, const AZ::Vector3& value) { TMAT(0, column) = value.GetX(); TMAT(1, column) = value.GetY(); TMAT(2, column) = value.GetZ(); } /** * Set the values for a given column, using a 4D vector. * @param column A zero-based index of the column. * @param value The values to set in the column. */ MCORE_INLINE void SetColumn(uint32 column, const AZ::Vector4& value) { TMAT(0, column) = value.GetX(); TMAT(1, column) = value.GetY(); TMAT(2, column) = value.GetZ(); TMAT(3, column) = value.GetW(); } /** * Get the values of a given row as 3D vector. * @param row A zero-based index of the row number ot get. * @result The vector containing the values of the specified row. */ MCORE_INLINE AZ::Vector3 GetRow(uint32 row) const { return AZ::Vector3(TMAT(row, 0), TMAT(row, 1), TMAT(row, 2)); } /** * Get the values of a given row as 4D vector. * @param column A zero-based index of the row number ot get. * @result The vector containing the values of the specified row. */ MCORE_INLINE AZ::Vector3 GetColumn(uint32 column) const { return AZ::Vector3(TMAT(0, column), TMAT(1, column), TMAT(2, column)); } /** * Get the values of a given column as 3D vector. * @param row A zero-based index of the column number ot get. * @result The vector containing the values of the specified column. */ MCORE_INLINE AZ::Vector4 GetRow4D(uint32 row) const { return AZ::Vector4(TMAT(row, 0), TMAT(row, 1), TMAT(row, 2), TMAT(row, 3)); } /** * Get the values of a given column as 4D vector. * @param column A zero-based index of the column number ot get. * @result The vector containing the values of the specified column. */ MCORE_INLINE AZ::Vector4 GetColumn4D(uint32 column) const { return AZ::Vector4(TMAT(0, column), TMAT(1, column), TMAT(2, column), TMAT(3, column)); } /** * Set the right vector (must be normalized). * @param xx The x component of the right vector. * @param xy The y component of the right vector. * @param xz The z component of the right vector. */ MCORE_INLINE void SetRight(float xx, float xy, float xz); /** * Set the right vector. * @param x The right vector, must be normalized. */ MCORE_INLINE void SetRight(const AZ::Vector3& x); /** * Set the up vector (must be normalized). * @param yx The x component of the up vector. * @param yy The y component of the up vector. * @param yz The z component of the up vector. */ MCORE_INLINE void SetUp(float yx, float yy, float yz); /** * Set the up vector (must be normalized). * @param y The up vector. */ MCORE_INLINE void SetUp(const AZ::Vector3& y); /** * Set the forward vector (must be normalized). * @param zx The x component of the forward vector. * @param zy The y component of the forward vector. * @param zz The z component of the forward vector. */ MCORE_INLINE void SetForward(float zx, float zy, float zz); /** * Set the forward vector (must be normalized). * @param z The forward vector. */ MCORE_INLINE void SetForward(const AZ::Vector3& z); /** * Set the translation part of the matrix. * @param tx The translation along the x-axis. * @param ty The translation along the y-axis. * @param tz The translation along the z-axis. */ MCORE_INLINE void SetTranslation(float tx, float ty, float tz); /** * Set the translation part of the matrix. * @param t The translation vector. */ MCORE_INLINE void SetTranslation(const AZ::Vector3& t); /** * Get the right vector. * @result The right vector (x-axis). */ MCORE_INLINE AZ::Vector3 GetRight() const; /** * Get the up vector. * @result The up vector (z-axis). */ MCORE_INLINE AZ::Vector3 GetUp() const; /** * Get the forward vector. * @result The forward vector (y-axis). */ MCORE_INLINE AZ::Vector3 GetForward() const; /** * Get the translation part of the matrix. * @result The vector containing the translation. */ MCORE_INLINE AZ::Vector3 GetTranslation() const; /** * Calculates the determinant of the matrix. * @result The determinant. */ float CalcDeterminant() const; /** * Calculates the euler angles. * @result The euler angles, describing the rotation along each axis, in radians. */ AZ::Vector3 CalcEulerAngles() const; /** * Calculate the pitch, yaw and roll. * Pitch is the rotation around the x axis. * Yaw is the rotation around the y axis. * Roll is the rotation around the z axis. * All angles returned are in radians. * @result The vector containing the rotation around each axis (x=pitch, y=yaw, z=roll). */ AZ::Vector3 CalcPitchYawRoll() const; /** * Makes this matrix a mirrored version of a specified matrix. * After executing this operation this matrix is the mirrored version of the specified matrix. * @param transform The transformation matrix to mirror (so the original matrix). * @param plane The plane to use as mirror. */ void Mirror(const Matrix& transform, const PlaneEq& plane); /** * Makes this matrix a lookat matrix (also known as camera or view matrix). * @param view The view position, so the position of the camera. * @param target The target position, so where the camera is looking at. * @param up The up vector, describing the roll of the camera, where (0,1,0) would mean the camera is straight up and has no roll and * where (0,-1,0) would mean the camera is upside down, etc. */ void LookAt(const AZ::Vector3& view, const AZ::Vector3& target, const AZ::Vector3& up); /** * Makes this matrix a lookat matrix (also known as camera or view matrix), in right handed mode. * @param view The view position, so the position of the camera. * @param target The target position, so where the camera is looking at. * @param up The up vector, describing the roll of the camera, where (0,1,0) would mean the camera is straight up and has no roll and * where (0,-1,0) would mean the camera is upside down, etc. */ void LookAtRH(const AZ::Vector3& view, const AZ::Vector3& target, const AZ::Vector3& up); /** * Makes this matrix a perspective projection matrix. * @param fov The field of view, in radians. * @param aspect The aspect ratio which is the width divided by height. * @param zNear The distance to the near plane. * @param zFar The distance to the far plane. */ void Perspective(float fov, float aspect, float zNear, float zFar); /** * Makes this matrix a perspective projection matrix, in right handed mode. * @param fov The field of view, in radians. * @param aspect The aspect ratio which is the width divided by height. * @param zNear The distance to the near plane. * @param zFar The distance to the far plane. */ void PerspectiveRH(float fov, float aspect, float zNear, float zFar); /** * Makes this matrix an ortho projection matrix, so without perspective. * @param left The left of the image plane. * @param right The right of the image plane. * @param top The top of the image plane. * @param bottom The bottom of the image plane. * @param znear The distance to the near plane. * @param zfar The distance to the far plane. */ void Ortho(float left, float right, float top, float bottom, float znear, float zfar); /** * Makes this matrix an ortho projection matrix, so without perspective. * @param left The left of the image plane. * @param right The right of the image plane. * @param top The top of the image plane. * @param bottom The bottom of the image plane. * @param znear The distance to the near plane. * @param zfar The distance to the far plane. */ void OrthoRH(float left, float right, float top, float bottom, float znear, float zfar); /** * Makes this matrix an ortho projection matrix, so without perspective. * @param left The left of the image plane. * @param right The right of the image plane. * @param top The top of the image plane. * @param bottom The bottom of the image plane. * @param znear The distance to the near plane. * @param zfar The distance to the far plane. */ void OrthoOffCenter(float left, float right, float top, float bottom, float znear, float zfar); /** * Makes this matrix an ortho projection matrix, so without perspective. * @param left The left of the image plane. * @param right The right of the image plane. * @param top The top of the image plane. * @param bottom The bottom of the image plane. * @param znear The distance to the near plane. * @param zfar The distance to the far plane. */ void OrthoOffCenterRH(float left, float right, float top, float bottom, float znear, float zfar); /** * Makes this matrix a frustum matrix. * @param left The left of the image plane. * @param right The right of the image plane. * @param top The top of the image plane. * @param bottom The bottom of the image plane. * @param znear The distance to the near plane. * @param zfar The distance to the far plane. */ void Frustum(float left, float right, float top, float bottom, float znear, float zfar); /** * Decompose a transformation matrix into translation and rotation components. * The translation part is just the translation part of the matrix. * The rotation AZ::Quaternion is calculated by normalizing the basis vectors and converting the * 3x3 rotation part of the matrix to a AZ::Quaternion. * It is allowed for the matrix to contain scaling. * The matrix where you call Decompose on remains unchanged. * @param outTranslation A pointer to a vector where the translation will be written to. * @param outRotation A pointer to a AZ::Quaternion where the rotation will be written to. * @note Please keep in mind that nullptr values for the parameters are NOT allowed. */ void Decompose(AZ::Vector3* outTranslation, AZ::Quaternion* outRotation) const; // QR Gram-Schmidt decomposition void DecomposeQRGramSchmidt(AZ::Vector3& translation, AZ::Quaternion& rot) const; void DecomposeQRGramSchmidt(AZ::Vector3& translation, Matrix& rot) const; void DecomposeQRGramSchmidt(AZ::Vector3& translation, Matrix& rot, AZ::Vector3& scale) const; void DecomposeQRGramSchmidt(AZ::Vector3& translation, Matrix& rot, AZ::Vector3& scale, AZ::Vector3& shear) const; void DecomposeQRGramSchmidt(AZ::Vector3& translation, AZ::Quaternion& rot, AZ::Vector3& scale, AZ::Vector3& shear) const; void DecomposeQRGramSchmidt(AZ::Vector3& translation, AZ::Quaternion& rot, AZ::Vector3& scale) const; static Matrix OuterProduct(const AZ::Vector4& column, const AZ::Vector4& row); /** * Get the handedness of the matrix, which described if the matrix is left- or right-handed. * The value returned by this method is the dot product between the forward vector and the result of the * cross product between the right and up vector. So: DotProduct( Cross(right, up), forward ); * If the value returned by this method is positive we are dealing with a matrix which is in a right-handed * coordinate system, otherwise we are dealing with a left-handed coordinate system. * Performing an odd number of reflections reverses the handedness. An even number of reflections is always * equivalent to a rotation, so any series of reflections can always be regarded as a single rotation followed * by at most one reflection. * If a reflection is present (think of a mirror) the handedness will be reversed. A reflection can be detected * by looking at the determinant of the matrix. If the determinant is negative, then a reflection is present. * @result The handedness of the matrix. If this value is positive we are dealing with a matrix in a right handed * coordinate system. Otherwise we are dealing with one in a left-handed coordinate system. * @see IsRightHanded() * @see IsLeftHanded() */ float CalcHandedness() const; /** * Check if this matrix is symmetric or not. * A materix is said to be symmetric if and only if M(i, j) = M(j, i). * That is, a matrix whose entries are symmetric about the main diagonal. * @param tolerance The maximum difference tolerance between the M(i, j) and M(j, i) entries. * The reason for having this tolerance is of course floating point inaccuracy which might have * caused some entries to be a bit different. * @result Returns true when the matrix is symmetric, or false when not. */ bool CheckIfIsSymmetric(float tolerance = 0.00001f) const; /** * Check if this matrix is a diagonal matrix or not. * A matrix is said to be a diagonal matrix when only the entries on the diagonal contain non-zero values. * The tolerance value is needed because of possible floating point inaccuracies. * @param tolerance The maximum difference between 0 and the entry on the diagonal. * @result Returns true when the matrix is a diagonal matrix, otherwise false is returned. */ bool CheckIfIsDiagonal(float tolerance = 0.00001f) const; /** * Check if the matrix is orthogonal or not. * A matrix is orthogonal if the vectors in the matrix form an orthonormal set. * This is when the vectors (right, up and forward) are perpendicular to eachother. * If a matrix is orthogonal, the inverse of the matrix is equal to the transpose of the matrix. * This assumption can be used to optimize specific calculations, since the inverse is slower to calculate than * the transpose of the matrix. Also it can speed up by transforming normals with the matrix. * In that example instead of having to use the inverse transpose matrix, you could just use the transpose of the matrix. * @param tolerance The maximum tolerance in the orthonormal test. * @result Returns true when the matrix is orthogonal, otherwise false is returned. */ bool CheckIfIsOrthogonal(float tolerance = 0.00001f) const; /** * Check if the matrix is an identity matrix or not. * @param tolerance The maximum error value per entry in the matrix. * @result Returns true if this matrix is an identity matrix, otherwise false is returned. */ bool CheckIfIsIdentity(float tolerance = 0.00001f) const; /** * Check if the matrix is left handed or not. * @result Returns true when the matrix is left handed, otherwise false is returned (so then it is right handed). */ bool CheckIfIsLeftHanded() const; /** * Check if the matrix is right handed or not. * @result Returns true when the matrix is right handed, otherwise false is returned (so then it is left handed). */ bool CheckIfIsRightHanded() const; /** * Check if this matrix is a pure rotation matrix or not. * @param tolerance The maximum error in the measurement. * @result Returns true when the matrix represents only a rotation, otherwise false is returned. */ bool CheckIfIsPureRotationMatrix(float tolerance = 0.00001f) const; /** * Check if this matrix contains a reflection or not. * @result Returns true when the matrix represents a reflection, otherwise false is returned. */ bool CheckIfIsReflective() const; AZ::Matrix4x4 ToAzMatrix() const { #ifdef MCORE_MATRIX_ROWMAJOR return AZ::Matrix4x4::CreateFromRowMajorFloat16(m16); #else return AZ::Matrix4x4::CreateFromColumnMajorFloat16(m16); #endif } /** * Prints the matrix into the logfile or debug output, using MCore::LogDetailedInfo(). * Please note that the values are printed using floats or doubles. So it is not possible * to use this method for printing matrices of vectors or something other than real numbers. */ void Log() const; /** * Returns a translation matrix. * @param v The translation of the matrix. * @result The translation matrix having the specified translation. */ static MCORE_INLINE Matrix TranslationMatrix(const AZ::Vector3& v) { Matrix m; m.SetTranslationMatrix(v); return m; } /** * Returns a rotation matrix from a AZ::Quaternion. * @param rot The AZ::Quaternion that represents the rotation. * @result A rotation matrix. */ static MCORE_INLINE Matrix RotationMatrix(const AZ::Quaternion& rot) { Matrix m; m.SetRotationMatrix(rot); return m; } /** * Returns a rotation matrix, including a translation, where the rotation is represented by a AZ::Quaternion. * @param rot The AZ::Quaternion that represents the rotation. * @param trans The translation of the matrix. * @result The rotation matrix, that includes a translation as well. */ static MCORE_INLINE Matrix RotationTranslationMatrix(const AZ::Quaternion& rot, const AZ::Vector3& trans) { Matrix m; m.InitFromPosRot(trans, rot); return m; } /** * Returns a rotation matrix along the x-axis. * @param rad The angle of rotation, in radians. * @result A rotation matrix. */ static MCORE_INLINE Matrix RotationMatrixX(float rad) { Matrix m; m.SetRotationMatrixX(rad); return m; } /** * Returns a rotation matrix along the y-axis. * @param rad The angle of rotation, in radians. * @result A rotation matrix. */ static MCORE_INLINE Matrix RotationMatrixY(float rad) { Matrix m; m.SetRotationMatrixY(rad); return m; } /** * Returns a rotation matrix along the z-axis. * @param rad The angle of rotation, in radians. * @result A rotation matrix. */ static MCORE_INLINE Matrix RotationMatrixZ(float rad) { Matrix m; m.SetRotationMatrixZ(rad); return m; } /** * Returns a rotation matrix along the x, y and z-axis. * The multiplication order is RotMatrix(v.x) * RotMatrix(v.y) * RotMatrix(v.z). * @param eulerAngles The euler angles in radians. * @result A rotation matrix. */ static MCORE_INLINE Matrix RotationMatrixEulerXYZ(const AZ::Vector3& eulerAngles) { Matrix m; m.SetRotationMatrixEulerXYZ(eulerAngles); return m; } /** * Returns a rotation matrix along the x, y and z-axis. * The multiplication order is RotMatrix(v.z) * RotMatrix(v.y) * RotMatrix(v.x). * @param eulerAngles The euler angles in radians. * @result A rotation matrix. */ static MCORE_INLINE Matrix RotationMatrixEulerZYX(const AZ::Vector3& eulerAngles) { Matrix m; m.SetRotationMatrixEulerZYX(eulerAngles); return m; } /** * Returns a rotation matrix given a pitch, yaw and roll. * Pitch is the rotation around the x-axis. * Yaw is the rotation aroudn the y-axis. * Roll is the rotation around the z-axis. * @param angles The rotation angles for each axis, in radians. * @result A rotation matrix. */ static MCORE_INLINE Matrix RotationMatrixPitchYawRoll(const AZ::Vector3& angles) { Matrix m; m.SetRotationMatrixPitchYawRoll(angles); return m; } /** * Constructs a rotation matrix given two vectors. The resulting matrix rotates the vector 'from' such that it points * in the same direction as the vector 'to'. * @param from The vector that the resulting matrix rotates to. * @param to The vector that the resulting matrix rotates from. * @result The rotation matrix that rotates the vector 'from' into the vector 'to'. */ static MCORE_INLINE Matrix RotationMatrixTwoVectors(const AZ::Vector3& from, const AZ::Vector3& to) { Matrix m; m.SetRotationMatrixTwoVectors(from, to); return m; } /** * Returns a rotation matrix from a given axis and angle. * @param axis The axis to rotate around. * @param angle The angle of rotation, in radians. * @result A rotation matrix. */ static MCORE_INLINE Matrix RotationMatrixAxisAngle(const AZ::Vector3& axis, float angle) { Matrix m; m.SetRotationMatrixAxisAngle(axis, angle); return m; } /** * Returns a scale matrix from a given scaling factor. * @param s The vector containing the scaling factors for each axis. * @result A scaling matrix. */ static MCORE_INLINE Matrix ScaleMatrix(const AZ::Vector3& s) { Matrix m; m.SetScaleMatrix(s); return m; } /** * Returns a shear matrix created from three different shear matrices: XY, XZ and YZ. * The multiplication order is YZ * XZ * XY. * @param s The shear values (x=XY, y=XZ, z=YZ) * @result The shear matrix. */ static MCORE_INLINE Matrix ShearMatrix(const AZ::Vector3& s) { Matrix m; m.SetShearMatrix(s); return m; } // operators Matrix operator + (const Matrix& right) const; Matrix operator - (const Matrix& right) const; Matrix operator * (const Matrix& right) const; Matrix operator * (float value) const; Matrix& operator += (const Matrix& right); Matrix& operator -= (const Matrix& right); Matrix& operator *= (const Matrix& right); Matrix& operator *= (float value); MCORE_INLINE void operator = (const Matrix& right); // attributes union { float m16[16]; // 16 floats as 1D array float m44[4][4]; // as 2D array }; } MCORE_ALIGN_POST(16); // include inline code #include "Matrix4.inl" } // namespace MCore