diff --git a/include/aiMatrix3x3.h b/include/aiMatrix3x3.h index 2bd8356df..cc7ea5a32 100644 --- a/include/aiMatrix3x3.h +++ b/include/aiMatrix3x3.h @@ -103,6 +103,14 @@ public: */ aiMatrix3x3& Transpose(); + // ------------------------------------------------------------------- + /** @brief Invert the matrix. + * If the matrix is not invertible all elements are set to qnan. + * Beware, use (f != f) to check whether a float f is qnan. + */ + aiMatrix3x3& Inverse(); + float Determinant() const; + public: // ------------------------------------------------------------------- /** @brief Returns a rotation matrix for a rotation around z diff --git a/include/aiMatrix3x3.inl b/include/aiMatrix3x3.inl index f8c86a3ad..a9bd420dd 100644 --- a/include/aiMatrix3x3.inl +++ b/include/aiMatrix3x3.inl @@ -9,6 +9,7 @@ #ifdef __cplusplus #include "aiMatrix4x4.h" #include +#include // ------------------------------------------------------------------------------------------------ // Construction from a 4x4 matrix. The remaining parts of the matrix are ignored. @@ -78,6 +79,45 @@ inline aiMatrix3x3& aiMatrix3x3::Transpose() return *this; } +// ---------------------------------------------------------------------------------------- +inline float aiMatrix3x3::Determinant() const +{ + return a1*b2*c3 - a1*b3*c2 + a2*b3*c1 - a2*b1*c3 + a3*b1*c2 - a3*b2*c1; +} + +// ---------------------------------------------------------------------------------------- +inline aiMatrix3x3& aiMatrix3x3::Inverse() +{ + // Compute the reciprocal determinant + float det = Determinant(); + if(det == 0.0f) + { + // Matrix not invertible. Setting all elements to nan is not really + // correct in a mathematical sense but it is easy to debug for the + // programmer. + const float nan = std::numeric_limits::quiet_NaN(); + *this = aiMatrix3x3( nan,nan,nan,nan,nan,nan,nan,nan,nan); + + return *this; + } + + float invdet = 1.0f / det; + + aiMatrix3x3 res; + res.a1 = invdet * (b2 * c3 - b3 * c2); + res.a2 = -invdet * (a2 * c3 - a3 * c2); + res.a3 = invdet * (a2 * b3 - a3 * b2); + res.b1 = -invdet * (b1 * c3 - b3 * c1); + res.b2 = invdet * (a1 * c3 - a3 * c1); + res.b3 = -invdet * (a1 * b3 - a3 * b1); + res.c1 = invdet * (b1 * c2 - b2 * c1); + res.c2 = -invdet * (a1 * c2 - a2 * c1); + res.c3 = invdet * (a1 * b2 - a2 * b1); + *this = res; + + return *this; +} + // ------------------------------------------------------------------------------------------------ inline aiMatrix3x3& aiMatrix3x3::RotationZ(float a, aiMatrix3x3& out) { diff --git a/include/aiMatrix4x4.h b/include/aiMatrix4x4.h index 91aab17fc..d43de7202 100644 --- a/include/aiMatrix4x4.h +++ b/include/aiMatrix4x4.h @@ -70,7 +70,8 @@ struct aiMatrix4x4 a1(1.0f), a2(0.0f), a3(0.0f), a4(0.0f), b1(0.0f), b2(1.0f), b3(0.0f), b4(0.0f), c1(0.0f), c2(0.0f), c3(1.0f), c4(0.0f), - d1(0.0f), d2(0.0f), d3(0.0f), d4(1.0f){} + d1(0.0f), d2(0.0f), d3(0.0f), d4(1.0f) + {} // from single values aiMatrix4x4 ( float _a1, float _a2, float _a3, float _a4, @@ -81,7 +82,7 @@ struct aiMatrix4x4 b1(_b1), b2(_b2), b3(_b3), b4(_b4), c1(_c1), c2(_c2), c3(_c3), c4(_c4), d1(_d1), d2(_d2), d3(_d3), d4(_d4) - {} + {} // ------------------------------------------------------------------- diff --git a/include/aiMatrix4x4.inl b/include/aiMatrix4x4.inl index cd65a7006..94d0fca2a 100644 --- a/include/aiMatrix4x4.inl +++ b/include/aiMatrix4x4.inl @@ -304,7 +304,7 @@ inline bool aiMatrix4x4::IsIdentity() const b4 <= epsilon && b4 >= -epsilon && c1 <= epsilon && c1 >= -epsilon && c2 <= epsilon && c2 >= -epsilon && - c3 <= epsilon && c3 >= -epsilon && + c4 <= epsilon && c4 >= -epsilon && d1 <= epsilon && d1 >= -epsilon && d2 <= epsilon && d2 >= -epsilon && d3 <= epsilon && d3 >= -epsilon &&