Fix Invert(ref Matrix3x2) (#962)

* Fix Invert(ref Matrix3x2)

* erroneous results were given by matrix fields being altered sequentially, some fields would use new state instead of the input

* Check for matrix.Determinant() = 0, now returns the identity instead of det becoming infinite"

* Add unit test for Matrix3x2.Invert
This commit is contained in:
Eb3yr
2024-11-08 18:57:39 +00:00
committed by GitHub
parent d3b4482573
commit 8b02498317
2 changed files with 30 additions and 7 deletions
+14 -7
View File
@@ -562,14 +562,21 @@ public struct Matrix3x2 : IEquatable<Matrix3x2>
{
var det = 1.0f / matrix.Determinant();
matrix.M11 = matrix.M22 * det;
matrix.M12 = -matrix.M12 * det;
if (float.IsInfinity(det)) // Det(M) = 0
{
matrix = Identity;
return;
}
matrix.M21 = -matrix.M21 * det;
matrix.M22 = matrix.M11 * det;
matrix.M31 = (matrix.M32 * matrix.M21 - matrix.M31 * matrix.M22) * det;
matrix.M32 = -(matrix.M32 * matrix.M11 - matrix.M31 * matrix.M12) * det;
// The new 3x2 matrix is the first and second column of the inverse of the 3x3 matrix given by adding the third column (0, 0, 1) to the input matrix
matrix = new(
matrix.M22 * det,
-matrix.M12 * det,
-matrix.M21 * det,
matrix.M11 * det,
(matrix.M32 * matrix.M21 - matrix.M31 * matrix.M22) * det,
(matrix.M31 * matrix.M12 - matrix.M32 * matrix.M11) * det
);
}
/// <summary>
@@ -17,4 +17,20 @@ public sealed class Matrix3x2Tests
Assert.Equal(y, matrix.Y);
Assert.Equal(z, matrix.Z);
}
[Fact]
public void InverseTest()
{
Matrix3x2 posDeterminant = new Matrix3x2(3, -7, 4, 2, 13, -2);
Matrix3x2 singular = new Matrix3x2(2, 1, 4, 2, 3, -4);
Matrix3x2 negDeterminant = new Matrix3x2(1, -5, 3, 2, 3, -4);
Matrix3x2 posExpected = new Matrix3x2(1f/17, 7f/34, -2f/17, 3f/34, -1f, -5f/2);
Matrix3x2 singularExpected = Matrix3x2.Identity;
Matrix3x2 negExpected = new Matrix3x2(2f/17, 5f/17, -3f/17, 1f/17, -18f/17, -11f/17);
Assert.Equal(Matrix3x2.Invert(posDeterminant), posExpected);
Assert.Equal(Matrix3x2.Invert(singular), singularExpected);
Assert.Equal(Matrix3x2.Invert(negDeterminant), negExpected);
}
}