Implement Matrix4x4::Equals

This commit is contained in:
2024-05-27 13:34:48 -04:00
parent ee86082c84
commit aa8bc4d1c4
2 changed files with 111 additions and 11 deletions

View File

@@ -690,6 +690,88 @@ namespace J3ML::LinearAlgebra {
return true;
}
bool Matrix3x3::SolveAxb(Vector3 b, Vector3 &x) const {
// Solve by pivotization.
float v00 = At(0, 0);
float v10 = At(1, 0);
float v20 = At(2, 0);
float v01 = At(0, 1);
float v11 = At(1, 1);
float v21 = At(2, 1);
float v02 = At(0, 2);
float v12 = At(1, 2);
float v22 = At(2, 2);
float av00 = std::abs(v00);
float av10 = std::abs(v10);
float av20 = std::abs(v20);
// Find which item in first column has largest absolute value.
if (av10 >= av00 && av10 >= av20) {
Swap(v00, v10);
Swap(v01, v11);
Swap(v02, v12);
Swap(b[0], b[1]);
} else if (av20 >= av00) {
Swap(v00, v20);
Swap(v01, v21);
Swap(v02, v22);
Swap(b[0], b[2]);
}
/* a b c | x
d e f | y
g h i | z, where |a| >= |d| && |a| >= |g| */
if (Math::EqualAbs(v00, 0.f))
return false;
// Scale row so that leading element is one.
float denom = 1.f / v00;
v01 *= denom;
v02 *= denom;
b[0] *= denom;
/* 1 b c | x
d e f | y
g h i | z */
// Pivotize again.
if (std::abs(v21) >= std::abs(v11))
{
Swap(v11, v21);
Swap(v12, v22);
Swap(b[1], b[2]);
}
if (Math::EqualAbs(v11, 0.f))
return false;
/* 1 b c | x
0 e f | y
0 h i | z, where |e| >= |h| */
denom = 1.f / v11;
// v11 = 1.f;
v12 *= denom;
b[1] *= denom;
/* 1 b c | x
0 1 f | y
0 h i | z */
if (Math::EqualAbs(v22, 0.f))
return false;
x[2] = b[2] / v22;
x[1] = b[1] - x[2] * v12;
x[0] = b[0] - x[2] * v02 - x[1] * v01;
}
}

View File

@@ -242,9 +242,6 @@ namespace J3ML::LinearAlgebra {
0, 0, 0, 1.f);
}
Matrix4x4 Matrix4x4::Translate(const Vector3 &rhs) const {
return *this * FromTranslation(rhs);
}
Vector3 Matrix4x4::Transform(const Vector3 &rhs) const {
return Transform(rhs.x, rhs.y, rhs.z);
@@ -424,15 +421,7 @@ namespace J3ML::LinearAlgebra {
return GetColumn3(3);
}
Matrix4x4 Matrix4x4::Scale(const Vector3& scale)
{
auto mat = *this;
mat.At(3, 0) *= scale.x;
mat.At(3, 1) *= scale.y;
mat.At(3, 2) *= scale.z;
return mat;
}
Matrix4x4
Matrix4x4::LookAt(const Vector3 &localFwd, const Vector3 &targetDir, const Vector3 &localUp, const Vector3 &worldUp) {
@@ -476,6 +465,7 @@ namespace J3ML::LinearAlgebra {
}
void Matrix4x4::Pivot() {
/// Algorithm from Eric Lengyel's Mathematics for 3D Game Programming & Computer Graphics, 2nd Ed.
int rowIndex = 0;
for(int col = 0; col < Cols; ++col)
@@ -941,4 +931,32 @@ namespace J3ML::LinearAlgebra {
return m;
}
void Matrix4x4::Decompose(Vector3 &translate, Quaternion &rotate, Vector3 &scale) const {
assert(this->IsColOrthogonal3());
Matrix3x3 r;
Decompose(translate, r, scale);
rotate = Quaternion(r);
/// Test that composing back yields the original Matrix4x4.
assert(Matrix4x4::FromTRS(translate, rotate, scale).Equals(*this, 0.1f));
}
void Matrix4x4::Decompose(Vector3 &translate, Matrix4x4 &rotate, Vector3 &scale) const {
assert(this->IsColOrthogonal3());
Matrix3x3 r;
Decompose(translate, r, scale);
rotate.SetRotatePart(r);
rotate.SetTranslatePart(0,0,0);
}
bool Matrix4x4::Equals(const Matrix4x4 &other, float epsilon) const {
for (int iy = 0; iy < Rows; ++iy)
for (int ix = 0; ix < Cols; ++ix)
if (!Math::EqualAbs(At(iy, ix), other[iy][ix], epsilon))
return false;
return true;
}
}