Implement several missing Matrix3x3 member functions
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
#include <J3ML/LinearAlgebra/Vector2.h>
|
||||
#include <J3ML/LinearAlgebra/Vector3.h>
|
||||
#include <J3ML/LinearAlgebra/Quaternion.h>
|
||||
#include <J3ML/LinearAlgebra/Matrices.inl>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace J3ML::LinearAlgebra {
|
||||
@@ -55,10 +55,11 @@ namespace J3ML::LinearAlgebra {
|
||||
static const Matrix3x3 NaN;
|
||||
public: /// Constructors
|
||||
/// Creates a new Matrix3x3 with uninitalized member values.
|
||||
Matrix3x3() {}
|
||||
Matrix3x3() = default;
|
||||
|
||||
Matrix3x3(const Matrix3x3& rhs) { Set(rhs); }
|
||||
Matrix3x3(float val);
|
||||
/// Creates a new Matrix3x3 by setting all matrix elements equal to val.
|
||||
explicit Matrix3x3(float val);
|
||||
/// Creates a new Matrix3x3 by explicitly specifying all the matrix elements.
|
||||
/// The elements are specified in row-major format, i.e. the first row first followed by the second and third row.
|
||||
/// E.g. The element m10 denotes the scalar at second (idx 1) row, first (idx 0) column.
|
||||
@@ -152,10 +153,7 @@ namespace J3ML::LinearAlgebra {
|
||||
void SetRotatePart(const Vector3& a, float angle);
|
||||
void SetRotatePart(const AxisAngle& axisAngle);
|
||||
/// Sets this matrix to perform the rotation expressed by the given quaternion.
|
||||
void SetRotatePart(const Quaternion& quat)
|
||||
{
|
||||
SetMatrixRotatePart(*this, quat);
|
||||
}
|
||||
void SetRotatePart(const Quaternion& quat);
|
||||
|
||||
/// Returns the given row.
|
||||
/** @param row The zero-based index [0, 2] of the row to get. */
|
||||
@@ -172,16 +170,16 @@ namespace J3ML::LinearAlgebra {
|
||||
|
||||
/// Returns the given column.
|
||||
/** @param col The zero-based index [0, 2] of the column to get. */
|
||||
Vector3 GetColumn(int index) const;
|
||||
Vector3 Column(int index) const;
|
||||
Vector3 Col(int index) const;
|
||||
[[nodiscard]] Vector3 GetColumn(int index) const;
|
||||
[[nodiscard]] Vector3 Column(int index) const;
|
||||
[[nodiscard]] Vector3 Col(int index) const;
|
||||
/// This method also allows assignment to the retrieved column.
|
||||
//Vector3& Col(int index);
|
||||
|
||||
/// Returns only the first three elements of the given column.
|
||||
Vector3 GetColumn3(int index) const;
|
||||
Vector3 Column3(int index) const;
|
||||
Vector3 Col3(int index) const;
|
||||
[[nodiscard]] Vector3 GetColumn3(int index) const;
|
||||
[[nodiscard]] Vector3 Column3(int index) const;
|
||||
[[nodiscard]] Vector3 Col3(int index) const;
|
||||
/// This method also allows assignment to the retrieved column.
|
||||
//Vector3& Col3(int index);
|
||||
|
||||
@@ -210,12 +208,14 @@ namespace J3ML::LinearAlgebra {
|
||||
/// Sets this matrix to equal the identity.
|
||||
void SetIdentity();
|
||||
|
||||
/// Swaps two columns.
|
||||
void SwapColumns(int col1, int col2);
|
||||
|
||||
/// Swaps two rows.
|
||||
void SwapRows(int row1, int row2);
|
||||
|
||||
float &At(int row, int col);
|
||||
float At(int x, int y) const;
|
||||
[[nodiscard]] float At(int x, int y) const;
|
||||
|
||||
/// Sets this to be a copy of the matrix rhs.
|
||||
void Set(const Matrix3x3 &rhs);
|
||||
@@ -231,10 +231,16 @@ namespace J3ML::LinearAlgebra {
|
||||
/// Orthonormalizes the basis formed by the column vectors of this matrix.
|
||||
void Orthonormalize(int c0, int c1, int c2);
|
||||
|
||||
/// Accesses this structure as a float array.
|
||||
/// @return A pointer to the upper-left element. The data is contiguous in memory.
|
||||
/// ptr[0] gives the element [0][0], ptr[1] is [0][1]. ptr[2] is [0][2]
|
||||
inline float *ptr() { return &elems[0][0];}
|
||||
[[nodiscard]] inline const float *ptr() const {return &elems[0][0];}
|
||||
|
||||
|
||||
/// Convers this rotation matrix to a quaternion.
|
||||
/// This function assumes that the matrix is orthonormal (no shear or scaling) and does not perform any mirroring (determinant > 0)
|
||||
Quaternion ToQuat() const;
|
||||
[[nodiscard]] Quaternion ToQuat() const;
|
||||
/// Attempts to convert this matrix to a quaternion. Returns false if the conversion cannot succeed (this matrix was not a rotation
|
||||
/// matrix, and there is scaling ,shearing, or mirroring in this matrix)
|
||||
bool TryConvertToQuat(Quaternion& q) const;
|
||||
@@ -242,16 +248,16 @@ namespace J3ML::LinearAlgebra {
|
||||
|
||||
/// Returns the main diagonal.
|
||||
/// The main diagonal consists of the elements at m[0][0], m[1][1], m[2][2]
|
||||
Vector3 Diagonal() const;
|
||||
[[nodiscard]] Vector3 Diagonal() const;
|
||||
/// Returns the local +X/+Y/+Z axis in world space.
|
||||
/// This is the same as transforming the vector{1,0,0} by this matrix.
|
||||
Vector3 WorldX() const;
|
||||
[[nodiscard]] Vector3 WorldX() const;
|
||||
/// Returns the local +Y axis in world space.
|
||||
/// This is the same as transforming the vector{0,1,0} by this matrix.
|
||||
Vector3 WorldY() const;
|
||||
[[nodiscard]] Vector3 WorldY() const;
|
||||
/// Returns the local +Z axis in world space.
|
||||
/// This is the same as transforming the vector{0,0,1} by this matrix.
|
||||
Vector3 WorldZ() const;
|
||||
[[nodiscard]] Vector3 WorldZ() const;
|
||||
|
||||
/// Computes the determinant of this matrix.
|
||||
// If the determinant is nonzero, this matrix is invertible.
|
||||
@@ -260,24 +266,24 @@ namespace J3ML::LinearAlgebra {
|
||||
// "If the determinant is positive, the basis is said to be "positively" oriented (or right-handed).
|
||||
// If the determinant is negative, the basis is said to be "negatively" oriented (or left-handed)."
|
||||
// @note This function computes 9 LOADs, 9 MULs and 5 ADDs. */
|
||||
float Determinant() const;
|
||||
[[nodiscard]] float Determinant() const;
|
||||
|
||||
/// Computes the determinant of a symmetric matrix.
|
||||
/** This function can be used to compute the determinant of a matrix in the case the matrix is known beforehand
|
||||
to be symmetric. This function is slightly faster than Determinant().
|
||||
* @return
|
||||
*/
|
||||
float DeterminantSymmetric() const;
|
||||
[[nodiscard]] float DeterminantSymmetric() const;
|
||||
|
||||
// Returns an inverted copy of this matrix.
|
||||
Matrix3x3 Inverted() const;
|
||||
[[nodiscard]] Matrix3x3 Inverted() const;
|
||||
|
||||
// Returns a transposed copy of this matrix.
|
||||
Matrix3x3 Transposed() const;
|
||||
[[nodiscard]] Matrix3x3 Transposed() const;
|
||||
|
||||
/// Returns the inverse transpose of this matrix.
|
||||
/// Use the matrix to transform covariant vectors (normal vectors).
|
||||
Matrix3x3 InverseTransposed() const;
|
||||
[[nodiscard]] Matrix3x3 InverseTransposed() const;
|
||||
|
||||
/// Computes the inverse transpose of this matrix.
|
||||
/// Use the matrix to transform covariant vectors (normal vectors).
|
||||
@@ -316,6 +322,11 @@ namespace J3ML::LinearAlgebra {
|
||||
This function may not be called if this matrix contains any scaling or shearing, but it may contain mirroring.*/
|
||||
bool InverseOrthogonalUniformScale();
|
||||
|
||||
/// Inverts a rotation matrix.
|
||||
/// If a matrix is of form M = R*S, where R is a rotation matrix and S is either identity or a mirroring matrix, then
|
||||
/// the matrix M is orthonormal and this function can be used to compute the inverse.
|
||||
/// This function is faster than calling InverseOrthogonalUniformScale(), InverseColOrthogonal(), or the generic Inverse()
|
||||
/// This function may not be called if this matrix contains any scaling or shearing, but it may contain mirroring.
|
||||
void InverseOrthonormal();
|
||||
|
||||
/// Inverts a symmetric matrix.
|
||||
@@ -331,27 +342,34 @@ namespace J3ML::LinearAlgebra {
|
||||
void Transpose();
|
||||
|
||||
|
||||
|
||||
/// Removes the scaling performed by this matrix. That is, decomposes this matrix M into a form M = M' * S, where
|
||||
/// M' has unitary column vectors and S is a diagonal matrix. Then replaces this matrix with M'
|
||||
/// @note This function assumes that this matrix does not contain projection (the fourth row of this matrix is [0 0 0 1]).
|
||||
/// @note This function does not remove reflection (-1 scale along some axis).
|
||||
void RemoveScale();
|
||||
|
||||
|
||||
|
||||
// Transforms the given vectors by this matrix M, i.e. returns M * (x,y,z)
|
||||
Vector2 Transform(const Vector2& rhs) const;
|
||||
Vector3 Transform(const Vector3& rhs) const;
|
||||
[[nodiscard]] Vector2 Transform(const Vector2& rhs) const;
|
||||
[[nodiscard]] Vector3 Transform(const Vector3& rhs) const;
|
||||
|
||||
/// Performs a batch transformation of the given array.
|
||||
void BatchTransform(Vector3 *pointArray, int numPoints) const;
|
||||
/// Performs a batch transformation of the given array.
|
||||
void BatchTransform(Vector3 *pointArray, int numPoints, int stride) const;
|
||||
/// Performs a batch transformation of the given array.
|
||||
/// This function ignores the w component of the input vectors. These components are assumed to be either 0 or 1.
|
||||
void BatchTransform(Vector4 *vectorArray, int numVectors) const;
|
||||
/// Performs a batch transformation of the given array.
|
||||
/// This function ignores the w component of the input vectors. These components are assumed to be either 0 or 1.
|
||||
void BatchTransform(Vector4 *vectorArray, int numVectors, int stride) const;
|
||||
|
||||
/// Returns the sum of the diagonal elements of this matrix.
|
||||
float Trace() const;
|
||||
[[nodiscard]] float Trace() const;
|
||||
|
||||
|
||||
Matrix3x3 ScaleBy(const Vector3& rhs);
|
||||
Vector3 GetScale() const;
|
||||
[[nodiscard]] Vector3 GetScale() const;
|
||||
|
||||
/// Scales the given row by a scalar value.
|
||||
void ScaleRow(int row, float scalar);
|
||||
@@ -367,79 +385,84 @@ namespace J3ML::LinearAlgebra {
|
||||
/// This function ignores the W component of the given input vector. This component is assumed to be either 0 or 1.
|
||||
Vector4 operator * (const Vector4& rhs) const;
|
||||
|
||||
|
||||
Matrix3x3 operator * (const Quaternion& rhs) const
|
||||
{
|
||||
return *this * Matrix3x3(rhs);
|
||||
}
|
||||
/// Multiplies the two matrices.
|
||||
Matrix3x3 operator * (const Matrix3x3& rhs) const;
|
||||
Matrix3x3 Mul(const Matrix3x3& rhs) const;
|
||||
[[nodiscard]] Matrix3x3 Mul(const Matrix3x3& rhs) const;
|
||||
/// Multiplies the two matrices.
|
||||
Matrix4x4 operator * (const Matrix4x4& rhs) const;
|
||||
Matrix4x4 Mul(const Matrix4x4& rhs) const;
|
||||
[[nodiscard]] Matrix4x4 Mul(const Matrix4x4& rhs) const;
|
||||
|
||||
Vector2 Mul(const Vector2& rhs) const;
|
||||
Vector3 Mul(const Vector3& rhs) const;
|
||||
Vector4 Mul(const Vector4& rhs) const;
|
||||
[[nodiscard]] Vector2 Mul(const Vector2& rhs) const;
|
||||
[[nodiscard]] Vector3 Mul(const Vector3& rhs) const;
|
||||
[[nodiscard]] Vector4 Mul(const Vector4& rhs) const;
|
||||
|
||||
/// Converts the quaternion to a M3x3 and multiplies the two matrices together.
|
||||
Matrix3x3 operator *(const Quaternion& rhs) const;
|
||||
|
||||
Quaternion Mul(const Quaternion& rhs) const;
|
||||
[[nodiscard]] Matrix3x3 Mul(const Quaternion& rhs) const;
|
||||
|
||||
// Returns true if the column vectors of this matrix are all perpendicular to each other.
|
||||
bool IsColOrthogonal(float epsilon = 1e-3f) const;
|
||||
bool IsColOrthogonal3(float epsilon = 1e-3f) const { return IsColOrthogonal(epsilon);}
|
||||
[[nodiscard]] bool IsColOrthogonal(float epsilon = 1e-3f) const;
|
||||
[[nodiscard]] bool IsColOrthogonal3(float epsilon = 1e-3f) const { return IsColOrthogonal(epsilon);}
|
||||
// Returns true if the row vectors of this matrix are all perpendicular to each other.
|
||||
bool IsRowOrthogonal(float epsilon = 1e-3f) const;
|
||||
[[nodiscard]] bool IsRowOrthogonal(float epsilon = 1e-3f) const;
|
||||
|
||||
|
||||
bool HasUniformScale(float epsilon = 1e-3f) const;
|
||||
[[nodiscard]] bool HasUniformScale(float epsilon = 1e-3f) const;
|
||||
|
||||
Vector3 ExtractScale() const;
|
||||
[[nodiscard]] Vector3 ExtractScale() const;
|
||||
|
||||
|
||||
/// Tests if this matrix does not contain any NaNs or infs
|
||||
/// @return Returns true if the entries of this M3x3 are all finite.
|
||||
bool IsFinite() const;
|
||||
[[nodiscard]] bool IsFinite() const;
|
||||
|
||||
/// Tests if this is the identity matrix.
|
||||
/// @return Returns true if this matrix is the identity matrix, up to the given epsilon.
|
||||
bool IsIdentity(float epsilon = 1e-3f) const;
|
||||
[[nodiscard]] bool IsIdentity(float epsilon = 1e-3f) const;
|
||||
/// Tests if this matrix is in lower triangular form.
|
||||
/// @return Returns true if this matrix is in lower triangular form, up to the given epsilon.
|
||||
bool IsLowerTriangular(float epsilon = 1e-3f) const;
|
||||
[[nodiscard]] bool IsLowerTriangular(float epsilon = 1e-3f) const;
|
||||
/// Tests if this matrix is in upper triangular form.
|
||||
/// @return Returns true if this matrix is in upper triangular form, up to the given epsilon.
|
||||
bool IsUpperTriangular(float epsilon = 1e-3f) const;
|
||||
[[nodiscard]] bool IsUpperTriangular(float epsilon = 1e-3f) const;
|
||||
/// Tests if this matrix has an inverse.
|
||||
/// @return Returns true if this matrix can be inverted, up to the given epsilon.
|
||||
bool IsInvertible(float epsilon = 1e-3f) const;
|
||||
[[nodiscard]] bool IsInvertible(float epsilon = 1e-3f) const;
|
||||
/// Tests if this matrix is symmetric (M == M^T).
|
||||
/// The test compares the elements for equality. Up to the given epsilon. A matrix is symmetric if it is its own transpose.
|
||||
bool IsSymmetric(float epsilon = 1e-3f) const;
|
||||
[[nodiscard]] bool IsSymmetric(float epsilon = 1e-3f) const;
|
||||
/// Tests if this matrix is skew-symmetric (M == -M^T).
|
||||
/// The test compares the elements of this matrix up to the given epsilon. A matrix M is skew-symmetric if the identity M=-M^T holds.
|
||||
bool IsSkewSymmetric(float epsilon = 1e-3f) const;
|
||||
[[nodiscard]] bool IsSkewSymmetric(float epsilon = 1e-3f) const;
|
||||
/// Returns true if this matrix does not perform any scaling,
|
||||
/** A matrix does not do any scaling if the column vectors of this matrix are normalized in length,
|
||||
compared to the given epsilon. Note that this matrix may still perform reflection,
|
||||
i.e. it has a -1 scale along some axis.
|
||||
@note This function only examines the upper 3-by-3 part of this matrix.
|
||||
@note This function assumes that this matrix does not contain projection (the fourth row of this matrix is [0,0,0,1] */
|
||||
bool HasUnitaryScale(float epsilon = 1e-3f) const;
|
||||
[[nodiscard]] bool HasUnitaryScale(float epsilon = 1e-3f) const;
|
||||
/// Returns true if this matrix performs a reflection along some plane.
|
||||
/** In 3D space, an even number of reflections corresponds to a rotation about some axis, so a matrix consisting of
|
||||
an odd number of consecutive mirror operations can only reflect about one axis. A matrix that contains reflection reverses
|
||||
the handedness of the coordinate system. This function tests if this matrix does perform mirroring.
|
||||
This occurs if this matrix has a negative determinant.*/
|
||||
bool HasNegativeScale() const;
|
||||
[[nodiscard]] bool HasNegativeScale() const;
|
||||
|
||||
/// Returns true if the column and row vectors of this matrix form an orthonormal set.
|
||||
/// @note In math terms, there does not exist such a thing as an 'orthonormal matrix'. In math terms, a matrix
|
||||
/// is orthogonal if the column and row vectors are orthogonal *unit* vectors.
|
||||
/// In terms of this library however, a matrix is orthogonal if its column and row vectors are orthogonal. (no need to be unitary),
|
||||
/// and a matrix is orthonormal if the column and row vectors are orthonormal.
|
||||
bool IsOrthonormal(float epsilon = 1e-3f) const;
|
||||
[[nodiscard]] bool IsOrthonormal(float epsilon = 1e-3f) const;
|
||||
|
||||
|
||||
protected: /// Member values
|
||||
float elems[3][3];
|
||||
float elems[3][3]{};
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user