// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. #pragma once #include "Vector2.h" #include "Vector3.h" #include "Engine/Platform/Platform.h" /// /// Represents a 3x3 mathematical matrix. /// API_STRUCT(InBuild) struct FLAXENGINE_API Matrix3x3 { public: union { struct { /// Value at row 1 column 1 of the matrix. float M11; /// Value at row 1 column 2 of the matrix. float M12; /// Value at row 1 column 3 of the matrix. float M13; /// Value at row 2 column 1 of the matrix. float M21; /// Value at row 2 column 2 of the matrix. float M22; /// Value at row 2 column 3 of the matrix. float M23; /// Value at row 3 column 1 of the matrix. float M31; /// Value at row 3 column 2 of the matrix. float M32; /// Value at row 3 column 3 of the matrix. float M33; }; float Values[3][3]; float Raw[9]; }; public: /// /// A matrix with all of its components set to zero. /// static const Matrix3x3 Zero; /// /// The identity matrix. /// static const Matrix3x3 Identity; public: /// /// Empty constructor. /// Matrix3x3() { } /// /// Initializes a new instance of the struct. /// /// The value to assign at row 1 column 1 of the matrix. /// The value to assign at row 1 column 2 of the matrix. /// The value to assign at row 1 column 3 of the matrix. /// The value to assign at row 2 column 1 of the matrix. /// The value to assign at row 2 column 2 of the matrix. /// The value to assign at row 2 column 3 of the matrix. /// The value to assign at row 3 column 1 of the matrix. /// The value to assign at row 3 column 2 of the matrix. /// The value to assign at row 3 column 3 of the matrix. Matrix3x3(float m11, float m12, float m13, float m21, float m22, float m23, float m31, float m32, float m33) : M11(m11) , M12(m12) , M13(m13) , M21(m21) , M22(m22) , M23(m23) , M31(m31) , M32(m32) , M33(m33) { } /// /// Initializes a new instance of the struct. /// /// The values to assign to the components of the matrix. This must be an array with nine elements. Matrix3x3(float values[9]) { Platform::MemoryCopy(Raw, values, sizeof(float) * 9); } /// /// Initializes a new instance of the struct. /// /// The values to assign to the components of the matrix. This must be an array with 3 by 3 elements. Matrix3x3(float values[3][3]) { Platform::MemoryCopy(Raw, values, sizeof(float) * 9); } /// /// Initializes a new instance of the struct. /// /// The 4 by 4 matrix to initialize from with rotation and scale (translation is skipped). explicit Matrix3x3(const Matrix& matrix); public: String ToString() const; public: // Gets the up Float3 of the matrix; that is M21, M22, and M23. Float3 GetUp() const { return Float3(M21, M22, M23); } // Sets Float3 of the matrix; that is M21, M22, and M23. void SetUp(const Float3& value) { M21 = value.X; M22 = value.Y; M23 = value.Z; } // Gets the down Float3 of the matrix; that is -M21, -M22, and -M23. Float3 GetDown() const { return -Float3(M21, M22, M23); } // Sets the down Float3 of the matrix; that is -M21, -M22, and -M23. void SetDown(const Float3& value) { M21 = -value.X; M22 = -value.Y; M23 = -value.Z; } // Gets the right Float3 of the matrix; that is M11, M12, and M13. Float3 GetRight() const { return Float3(M11, M12, M13); } // Sets the right Float3 of the matrix; that is M11, M12, and M13. void SetRight(const Float3& value) { M11 = value.X; M12 = value.Y; M13 = value.Z; } // Gets the left Float3 of the matrix; that is -M11, -M12, and -M13. Float3 GetLeft() const { return -Float3(M11, M12, M13); } // Sets the left Float3 of the matrix; that is -M11, -M12, and -M13. void SetLeft(const Float3& value) { M11 = -value.X; M12 = -value.Y; M13 = -value.Z; } // Gets the forward Float3 of the matrix; that is -M31, -M32, and -M33. Float3 GetForward() const { return -Float3(M31, M32, M33); } // Sets the forward Float3 of the matrix; that is -M31, -M32, and -M33. void SetForward(const Float3& value) { M31 = -value.X; M32 = -value.Y; M33 = -value.Z; } // Gets the backward Float3 of the matrix; that is M31, M32, and M33. Float3 GetBackward() const { return Float3(M31, M32, M33); } // Sets the backward Float3 of the matrix; that is M31, M32, and M33. void SetBackward(const Float3& value) { M31 = value.X; M32 = value.Y; M33 = value.Z; } // Gets the first row in the matrix; that is M11, M12 and M13. Float3 GetRow1() const { return Float3(M11, M12, M13); } // Sets the first row in the matrix; that is M11, M12 and M13. void SetRow1(const Float3& value) { M11 = value.X; M12 = value.Y; M13 = value.Z; } // Gets the second row in the matrix; that is M21, M22 and M23. Float3 GetRow2() const { return Float3(M21, M22, M23); } // Sets the second row in the matrix; that is M21, M22 and M23. void SetRow2(const Float3& value) { M21 = value.X; M22 = value.Y; M23 = value.Z; } // Gets the third row in the matrix; that is M31, M32 and M33. Float3 GetRow3() const { return Float3(M31, M32, M33); } // Sets the third row in the matrix; that is M31, M32 and M33. void SetRow3(const Float3& value) { M31 = value.X; M32 = value.Y; M33 = value.Z; } // Gets the first column in the matrix; that is M11, M21 and M31. Float3 GetColumn1() const { return Float3(M11, M21, M31); } // Sets the first column in the matrix; that is M11, M21 and M31. void SetColumn1(const Float3& value) { M11 = value.X; M21 = value.Y; M31 = value.Z; } // Gets the second column in the matrix; that is M12, M22 and M32. Float3 GetColumn2() const { return Float3(M12, M22, M32); } // Sets the second column in the matrix; that is M12, M22 and M32. void SetColumn2(const Float3& value) { M12 = value.X; M22 = value.Y; M32 = value.Z; } // Gets the third column in the matrix; that is M13, M23 and M33. Float3 GetColumn3() const { return Float3(M13, M23, M33); } // Sets the third column in the matrix; that is M13, M23 and M33. void SetColumn3(const Float3& value) { M13 = value.X; M23 = value.Y; M33 = value.Z; } // Gets the scale of the matrix; that is M11, M22, and M33. Float3 GetScaleVector() const { return Float3(M11, M22, M33); } // Sets the scale of the matrix; that is M11, M22, and M33. void SetScaleVector(const Float3& value) { M11 = value.X; M22 = value.Y; M33 = value.Z; } /// /// Gets a value indicating whether this instance is an identity Matrix3x3. /// bool IsIdentity() const { return *this == Identity; } /// /// Calculates the determinant of the Matrix3x3. /// float GetDeterminant() const { return M11 * M22 * M33 + M12 * M23 * M31 + M13 * M21 * M32 - M13 * M22 * M31 - M12 * M21 * M33 - M11 * M23 * M32; } public: /// /// Inverts the Matrix3x3. /// void Invert() { Invert(*this, *this); } /// /// Transposes the Matrix3x3. /// void Transpose() { Transpose(*this, *this); } /// /// Removes any scaling from the matrix by performing the normalization (each row magnitude is 1). /// void NormalizeScale(); public: /// /// Calculates the inverse of the specified Matrix3x3. /// /// The Matrix3x3 whose inverse is to be calculated. /// When the method completes, contains the inverse of the specified Matrix3x3. static void Invert(const Matrix3x3& value, Matrix3x3& result); /// /// Calculates the inverse of the specified Matrix3x3. /// /// The Matrix3x3 whose inverse is to be calculated. /// The inverse of the specified Matrix3x3. static Matrix3x3 Invert(Matrix3x3 value) { Matrix3x3 result; Invert(value, result); return result; } /// /// Calculates the transpose of the specified Matrix3x3. /// /// The Matrix3x3 whose transpose is to be calculated. /// When the method completes, contains the transpose of the specified Matrix3x3. static void Transpose(const Matrix3x3& value, Matrix3x3& result); /// /// Calculates the transpose of the specified Matrix3x3. /// /// The Matrix3x3 whose transpose is to be calculated. /// The transpose of the specified Matrix3x3. static Matrix3x3 Transpose(const Matrix3x3& value) { Matrix3x3 result; Transpose(value, result); return result; } public: /// /// Determines the sum of two matrices. /// /// The first Matrix3x3 to add. /// The second Matrix3x3 to add. /// When the method completes, contains the sum of the two matrices. static void Add(const Matrix3x3& left, const Matrix3x3& right, Matrix3x3& result); /// /// Determines the sum of two matrices. /// /// The first Matrix3x3 to add. /// The second Matrix3x3 to add. /// The sum of the two matrices. static Matrix3x3 Add(const Matrix3x3& left, const Matrix3x3& right) { Matrix3x3 result; Add(left, right, result); return result; } /// /// Determines the difference between two matrices. /// /// The first Matrix3x3 to subtract. /// The second Matrix3x3 to subtract. /// When the method completes, contains the difference between the two matrices. static void Subtract(const Matrix3x3& left, const Matrix3x3& right, Matrix3x3& result); /// /// Determines the difference between two matrices. /// /// The first Matrix3x3 to subtract. /// The second Matrix3x3 to subtract. /// The difference between the two matrices. static Matrix3x3 Subtract(const Matrix3x3& left, const Matrix3x3& right) { Matrix3x3 result; Subtract(left, right, result); return result; } /// /// Scales a Matrix3x3 by the given value. /// /// The Matrix3x3 to scale. /// The amount by which to scale. /// When the method completes, contains the scaled Matrix3x3. static void Multiply(const Matrix3x3& left, float right, Matrix3x3& result); /// /// Scales a Matrix3x3 by the given value. /// /// The Matrix3x3 to scale. /// The amount by which to scale. /// The scaled Matrix3x3. static Matrix3x3 Multiply(const Matrix3x3& left, float right) { Matrix3x3 result; Multiply(left, right, result); return result; } /// /// Determines the product of two matrices. /// /// The first Matrix3x3 to multiply. /// The second Matrix3x3 to multiply. /// The product of the two matrices. static void Multiply(const Matrix3x3& left, const Matrix3x3& right, Matrix3x3& result); /// /// Determines the product of two matrices. /// /// The first Matrix3x3 to multiply. /// The second Matrix3x3 to multiply. /// The product of the two matrices. static Matrix3x3 Multiply(const Matrix3x3& left, const Matrix3x3& right) { Matrix3x3 result; Multiply(left, right, result); return result; } /// /// Scales a Matrix3x3 by the given value. /// /// The Matrix3x3 to scale. /// The amount by which to scale. /// When the method completes, contains the scaled Matrix3x3. static void Divide(const Matrix3x3& left, float right, Matrix3x3& result); /// /// Scales a Matrix3x3 by the given value. /// /// The Matrix3x3 to scale. /// The amount by which to scale. /// The scaled Matrix3x3. static Matrix3x3 Divide(const Matrix3x3& left, float right) { Matrix3x3 result; Divide(left, right, result); return result; } /// /// Determines the quotient of two matrices. /// /// The first Matrix3x3 to divide. /// The second Matrix3x3 to divide. /// When the method completes, contains the quotient of the two matrices. static void Divide(const Matrix3x3& left, const Matrix3x3& right, Matrix3x3& result); /// /// Determines the quotient of two matrices. /// /// The first Matrix3x3 to divide. /// The second Matrix3x3 to divide. /// The quotient of the two matrices. static Matrix3x3 Divide(const Matrix3x3& left, const Matrix3x3& right) { Matrix3x3 result; Divide(left, right, result); return result; } public: /// /// Creates 2D translation matrix. /// /// The translation vector. /// The result. static void Translation2D(const Float2& translation, Matrix3x3& result) { result = Matrix3x3( 1, 0, 0, 0, 1, 0, translation.X, translation.Y, 1 ); } /// /// Creates 2D translation matrix. /// /// The translation vector. /// The result. static Matrix3x3 Translation2D(const Float2& translation) { Matrix3x3 result; Translation2D(translation, result); return result; } /// /// Transforms given point by the matrix (in 2D). /// Useful to transform location of point. /// /// The point. /// The transform. /// The result. static void Transform2DPoint(const Float2& point, const Matrix3x3& transform, Float2& result) { result = Float2( point.X * transform.M11 + point.Y * transform.M21 + transform.M31, point.X * transform.M12 + point.Y * transform.M22 + transform.M32); } /// /// Transforms given vector by the matrix (in 2D). /// Useful to transform size or distance. /// /// The vector. /// The transform. /// The result. static void Transform2DVector(const Float2& vector, const Matrix3x3& transform, Float2& result) { result = Float2( vector.X * transform.M11 + vector.Y * transform.M21, vector.X * transform.M12 + vector.Y * transform.M22); } public: /// /// Creates a rotation matrix from a quaternion /// /// The quaternion to use to build the matrix. /// The created rotation matrix static Matrix3x3 RotationQuaternion(const Quaternion& rotation) { Matrix3x3 result; RotationQuaternion(rotation, result); return result; } /// /// Creates a rotation matrix from a quaternion /// /// The quaternion to use to build the matrix. /// The created rotation matrix. static void RotationQuaternion(const Quaternion& rotation, Matrix3x3& result); /// /// Decomposes a matrix into a scale and rotation. /// /// When the method completes, contains the scaling component of the decomposed matrix. /// When the method completes, contains the rotation component of the decomposed matrix. /// This method is designed to decompose an scale-rotation transformation matrix only. void Decompose(Float3& scale, Matrix3x3& rotation) const; /// /// Decomposes a matrix into a scale and rotation. /// /// When the method completes, contains the scaling component of the decomposed matrix. /// When the method completes, contains the rotation component of the decomposed matrix. /// This method is designed to decompose an scale-rotation transformation matrix only. void Decompose(Float3& scale, Quaternion& rotation) const; public: /// /// Tests for equality between two objects. /// /// The other value to compare. /// true if object has the same value as ; otherwise, false. bool operator==(const Matrix3x3& other) const; /// /// Tests for equality between two objects. /// /// The other value to compare. /// true if object has a different value as ; otherwise, false. FORCE_INLINE bool operator!=(const Matrix3x3& other) const { return !operator==(other); } }; template<> struct TIsPODType { enum { Value = true }; }; DEFINE_DEFAULT_FORMATTING(Matrix3x3, "[M11:{0} M12:{1} M13:{2}] [M21:{3} M22:{5} M23:{5}] [M31:{6} M32:{7} M33:{8}]", v.M11, v.M12, v.M13, v.M21, v.M22, v.M23, v.M31, v.M32, v.M33);