Skip to content

Commit

Permalink
Fix Basis is_orthogonal and is_rotation methods, add is_orthonormal
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronfranke committed Oct 13, 2023
1 parent 51f81e1 commit d9a3563
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 4 deletions.
15 changes: 11 additions & 4 deletions core/math/basis.cpp
Expand Up @@ -90,10 +90,17 @@ Basis Basis::orthogonalized() const {
}

bool Basis::is_orthogonal() const {
Basis identity;
Basis m = (*this) * transposed();
const Vector3 x = get_column(0);
const Vector3 y = get_column(1);
const Vector3 z = get_column(2);
return Math::is_zero_approx(x.dot(y)) && Math::is_zero_approx(x.dot(z)) && Math::is_zero_approx(y.dot(z));
}

return m.is_equal_approx(identity);
bool Basis::is_orthonormal() const {
const Vector3 x = get_column(0);
const Vector3 y = get_column(1);
const Vector3 z = get_column(2);
return Math::is_equal_approx(x.length_squared(), 1) && Math::is_equal_approx(y.length_squared(), 1) && Math::is_equal_approx(z.length_squared(), 1) && Math::is_zero_approx(x.dot(y)) && Math::is_zero_approx(x.dot(z)) && Math::is_zero_approx(y.dot(z));
}

bool Basis::is_conformal() const {
Expand All @@ -112,7 +119,7 @@ bool Basis::is_diagonal() const {
}

bool Basis::is_rotation() const {
return Math::is_equal_approx(determinant(), 1, (real_t)UNIT_EPSILON) && is_orthogonal();
return is_conformal() && Math::is_equal_approx(determinant(), 1, (real_t)UNIT_EPSILON);
}

#ifdef MATH_CHECKS
Expand Down
1 change: 1 addition & 0 deletions core/math/basis.h
Expand Up @@ -138,6 +138,7 @@ struct _NO_DISCARD_ Basis {
_FORCE_INLINE_ Basis operator*(const real_t p_val) const;

bool is_orthogonal() const;
bool is_orthonormal() const;
bool is_conformal() const;
bool is_diagonal() const;
bool is_rotation() const;
Expand Down
78 changes: 78 additions & 0 deletions tests/core/math/test_basis.h
Expand Up @@ -326,6 +326,84 @@ TEST_CASE("[Basis] Is conformal checks") {
"Basis with the X axis skewed 45 degrees should not be conformal.");
}

TEST_CASE("[Basis] Is orthogonal checks") {
CHECK_MESSAGE(
Basis().is_orthogonal(),
"Identity Basis should be orthogonal.");

CHECK_MESSAGE(
Basis::from_euler(Vector3(1.2, 3.4, 5.6)).is_orthogonal(),
"Basis with only rotation should be orthogonal.");

CHECK_MESSAGE(
Basis::from_scale(Vector3(-1, -1, -1)).is_orthogonal(),
"Basis with only a flip should be orthogonal.");

CHECK_MESSAGE(
Basis::from_scale(Vector3(1.2, 3.4, 5.6)).is_orthogonal(),
"Basis with only scale should be orthogonal.");

CHECK_MESSAGE(
Basis(Vector3(3, 4, 0), Vector3(4, -3, 0), Vector3(0, 0, 5)).is_orthogonal(),
"Basis with a flip, rotation, and uniform scale should be orthogonal.");

CHECK_FALSE_MESSAGE(
Basis(Vector3(Math_SQRT12, Math_SQRT12, 0), Vector3(0, 1, 0), Vector3(0, 0, 1)).is_orthogonal(),
"Basis with the X axis skewed 45 degrees should not be orthogonal.");
}

TEST_CASE("[Basis] Is orthonormal checks") {
CHECK_MESSAGE(
Basis().is_orthonormal(),
"Identity Basis should be orthonormal.");

CHECK_MESSAGE(
Basis::from_euler(Vector3(1.2, 3.4, 5.6)).is_orthonormal(),
"Basis with only rotation should be orthonormal.");

CHECK_MESSAGE(
Basis::from_scale(Vector3(-1, -1, -1)).is_orthonormal(),
"Basis with only a flip should be orthonormal.");

CHECK_FALSE_MESSAGE(
Basis::from_scale(Vector3(1.2, 3.4, 5.6)).is_orthonormal(),
"Basis with only scale should not be orthonormal.");

CHECK_FALSE_MESSAGE(
Basis(Vector3(3, 4, 0), Vector3(4, -3, 0), Vector3(0, 0, 5)).is_orthonormal(),
"Basis with a flip, rotation, and uniform scale should not be orthonormal.");

CHECK_FALSE_MESSAGE(
Basis(Vector3(Math_SQRT12, Math_SQRT12, 0), Vector3(0, 1, 0), Vector3(0, 0, 1)).is_orthonormal(),
"Basis with the X axis skewed 45 degrees should not be orthonormal.");
}

TEST_CASE("[Basis] Is rotation checks") {
CHECK_MESSAGE(
Basis().is_rotation(),
"Identity Basis should be a rotation (a rotation of zero).");

CHECK_MESSAGE(
Basis::from_euler(Vector3(1.2, 3.4, 5.6)).is_rotation(),
"Basis with only rotation should be a rotation.");

CHECK_FALSE_MESSAGE(
Basis::from_scale(Vector3(-1, -1, -1)).is_rotation(),
"Basis with only a flip should not be a rotation.");

CHECK_FALSE_MESSAGE(
Basis::from_scale(Vector3(1.2, 3.4, 5.6)).is_rotation(),
"Basis with only scale should not be a rotation.");

CHECK_FALSE_MESSAGE(
Basis(Vector3(2, 0, 0), Vector3(0, 0.5, 0), Vector3(0, 0, 1)).is_rotation(),
"Basis with a squeeze should not be a rotation.");

CHECK_FALSE_MESSAGE(
Basis(Vector3(Math_SQRT12, Math_SQRT12, 0), Vector3(0, 1, 0), Vector3(0, 0, 1)).is_rotation(),
"Basis with the X axis skewed 45 degrees should not be a rotation.");
}

} // namespace TestBasis

#endif // TEST_BASIS_H

0 comments on commit d9a3563

Please sign in to comment.