From 3e8f83ddfb86406eaeae043110c3973368aa01e8 Mon Sep 17 00:00:00 2001 From: josh Date: Sun, 12 May 2024 11:51:10 -0400 Subject: [PATCH] Implement Matrix3x3 missing members and documentation --- include/J3ML/LinearAlgebra/Matrix3x3.h | 121 +++++++++++++++++++++--- include/J3ML/LinearAlgebra/Quaternion.h | 2 +- src/J3ML/LinearAlgebra/Matrix3x3.cpp | 4 +- src/J3ML/LinearAlgebra/Matrix4x4.cpp | 2 +- src/J3ML/LinearAlgebra/Quaternion.cpp | 2 +- 5 files changed, 111 insertions(+), 20 deletions(-) diff --git a/include/J3ML/LinearAlgebra/Matrix3x3.h b/include/J3ML/LinearAlgebra/Matrix3x3.h index b950bdb..f13ae93 100644 --- a/include/J3ML/LinearAlgebra/Matrix3x3.h +++ b/include/J3ML/LinearAlgebra/Matrix3x3.h @@ -228,31 +228,63 @@ namespace J3ML::LinearAlgebra { Vector3 Column(int index) const; Vector3 Col(int index) const; /// This method also allows assignment to the retrieved column. - Vector3& Col(int index); + //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; /// This method also allows assignment to the retrieved column. - Vector3& Col3(int index); + //Vector3& Col3(int index); + + /// Sets the value of a given row. + /** @param row The index of the row to a set, in the range [0-2]. + @param data A pointer to an array of 3 floats that contain the new x, y, and z values for the row.*/ + void SetRow(int row, const float* data); + void SetRow(int row, const Vector3 & data); + void SetRow(int row, float x, float y, float z); + + /// Sets the value of a given column. + /** @param column The index of the column to set, in the range [0-2] + @param data A pointer ot an array of 3 floats that contain the new x, y, and z values for the column.*/ + void SetColumn(int column, const float* data); + void SetColumn(int column, const Vector3 & data); + void SetColumn(int column, float x, float y, float z); - - void SetRow(int i, const Vector3 &vector3); - void SetColumn(int i, const Vector3& vector); + /// Sets a single element of this matrix + /** @param row The row index (y-coordinate) of the element to set, in the range [0-2]. + @param col The col index (x-coordinate) of the element to set, in the range [0-2]. + @param value The new value to set to the cell [row][col]. */ void SetAt(int x, int y, float value); + + /// Sets this matrix to equal the identity. + void SetIdentity(); + + + void SwapColumns(int col1, int col2); + + void SwapRows(int row1, int row2); + float &At(int row, int col); float At(int x, int y) const; - void Set(const Matrix3x3 &x3); - + /// Sets this to be a copy of the matrix rhs. + void Set(const Matrix3x3 &rhs); + /// Sets all values of this matrix/ + void Set(float _00, float _01, float _02, + float _10, float _11, float _12, + float _20, float _21, float _22); + /// Sets all values of this matrix. + /// @param valuesThe values in this array will be copied over to this matrix. The source must contain 9 floats in row-major order + /// (the same order as the Set() function aove has its input parameters in). + void Set(const float *values); + /// Orthonormalizes the basis formed by the column vectors of this matrix. void Orthonormalize(int c0, int c1, int c2); - /// 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; @@ -261,11 +293,8 @@ namespace J3ML::LinearAlgebra { bool TryConvertToQuat(Quaternion& q) const; - - - - /// Returns the main diagonal. + /// The main diagonal consists of the elements at m[0][0], m[1][1], m[2][2] 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. @@ -286,16 +315,78 @@ namespace J3ML::LinearAlgebra { // @note This function computes 9 LOADs, 9 MULs and 5 ADDs. */ float Determinant() const; - // Returns an inverted copy of this matrix. This - Matrix3x3 Inverse() 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; + + // Returns an inverted copy of this matrix. + Matrix3x3 Inverted() const; // Returns a transposed copy of this matrix. - Matrix3x3 Transpose() const; + Matrix3x3 Transposed() const; + + /// Returns the inverse transpose of this matrix. + Matrix3x3 InverseTransposed() const; + + /// Inverts this matrix using numerically stable Gaussian elimination. + /// @return Returns true on success, false otherwise; + bool Inverse(float epsilon = 1e-6f); + + /// Inverts this matrix using Cramer's rule. + /// @return Returns true on success, false otherwise. + bool InverseFast(float epsilon = 1e-6f); + + + /// Solves the linear equation Ax=b. + /** The matrix A in the equations is this matrix. */ + bool SolveAxb(Vector3 b, Vector3& x) const; + + /// Inverts a column-orthogonal matrix. + /** If a matrix is of form M=R*S, where + R is a rotation matrix and S is a diagonal matrix with non-zero but potentially non-uniform scaling + factors (possibly mirroring), then the matrix M is column-orthogonal and this function can be used to compute the inverse. + Calling this function is faster than calling the generic matrix Inverse() function.\ + Returns true on success. On failure, the matrix is not modified. This function fails if any of the + elements of this vector are not finite, or if the matrix contains a zero scaling factor on X, Y, or Z. + @note The returned matrix will be row-orthogonal, but not column-orthogonal in general. + The returned matrix will be column-orthogonal if the original matrix M was row-orthogonal as well. + (in which case S had uniform scale, InverseOrthogonalUniformScale() could have been used instead)*/ + bool InverseColOrthogonal(); + + /// 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.*/ + bool InverseOrthogonalUniformScale(); + + void InverseOrthonormal(); + + bool InverseSymmetric(); + + void Transpose(); + + bool InverseTranspose(); + + 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; + /// Performs a batch transformation of the given array. + void BatchTransform(Vector3 *pointArray, int numPoints) const; + void BatchTransform(Vector3 *pointArray, int numPoints, int stride) const; + + /// Returns the sum of the diagonal elements of this matrix. + float Trace() const; + Matrix3x3 ScaleBy(const Vector3& rhs); Vector3 GetScale() const; diff --git a/include/J3ML/LinearAlgebra/Quaternion.h b/include/J3ML/LinearAlgebra/Quaternion.h index a10ff33..388ba89 100644 --- a/include/J3ML/LinearAlgebra/Quaternion.h +++ b/include/J3ML/LinearAlgebra/Quaternion.h @@ -35,7 +35,7 @@ namespace J3ML::LinearAlgebra Quaternion(const Vector3 &rotationAxis, float rotationAngleBetween); Quaternion(const Vector4 &rotationAxis, float rotationAngleBetween); - //void Inverse(); + //void Inverted(); explicit Quaternion(Vector4 vector4); explicit Quaternion(const EulerAngle& angle); diff --git a/src/J3ML/LinearAlgebra/Matrix3x3.cpp b/src/J3ML/LinearAlgebra/Matrix3x3.cpp index f7df632..4d326f9 100644 --- a/src/J3ML/LinearAlgebra/Matrix3x3.cpp +++ b/src/J3ML/LinearAlgebra/Matrix3x3.cpp @@ -124,7 +124,7 @@ namespace J3ML::LinearAlgebra { return a*(e*i - f*h) + b*(f*g - d*i) + c*(d*h - e*g); } - Matrix3x3 Matrix3x3::Inverse() const { + Matrix3x3 Matrix3x3::Inverted() const { // Compute the inverse directly using Cramer's rule // Warning: This method is numerically very unstable! float d = Determinant(); @@ -148,7 +148,7 @@ namespace J3ML::LinearAlgebra { return i; } - Matrix3x3 Matrix3x3::Transpose() const { + Matrix3x3 Matrix3x3::Transposed() const { auto m00 = this->elems[0][0]; auto m01 = this->elems[0][1]; auto m02 = this->elems[0][2]; diff --git a/src/J3ML/LinearAlgebra/Matrix4x4.cpp b/src/J3ML/LinearAlgebra/Matrix4x4.cpp index dd959f0..b27bdaa 100644 --- a/src/J3ML/LinearAlgebra/Matrix4x4.cpp +++ b/src/J3ML/LinearAlgebra/Matrix4x4.cpp @@ -667,7 +667,7 @@ namespace J3ML::LinearAlgebra { { assert(!ContainsProjection()); - // a) Transpose the top-left 3x3 part in-place to produce R^t. + // a) Transposed the top-left 3x3 part in-place to produce R^t. Swap(elems[0][1], elems[1][0]); Swap(elems[0][2], elems[2][0]); Swap(elems[1][2], elems[2][1]); diff --git a/src/J3ML/LinearAlgebra/Quaternion.cpp b/src/J3ML/LinearAlgebra/Quaternion.cpp index 4b92bac..d28d378 100644 --- a/src/J3ML/LinearAlgebra/Quaternion.cpp +++ b/src/J3ML/LinearAlgebra/Quaternion.cpp @@ -137,7 +137,7 @@ namespace J3ML::LinearAlgebra { AxisAngle Quaternion::ToAxisAngle() const { float halfAngle = std::acos(w); float angle = halfAngle * 2.f; - // TODO: Can Implement Fast Inverse Sqrt Here + // TODO: Can Implement Fast Inverted Sqrt Here float reciprocalSinAngle = 1.f / std::sqrt(1.f - w*w); Vector3 axis = {