diff --git a/include/Nazara/Math/Matrix4.hpp b/include/Nazara/Math/Matrix4.hpp index 51bdaf0ce..849934710 100644 --- a/include/Nazara/Math/Matrix4.hpp +++ b/include/Nazara/Math/Matrix4.hpp @@ -38,11 +38,16 @@ class NzMatrix4 NzMatrix4(NzMatrix4&& matrix) noexcept; ~NzMatrix4(); + NzMatrix4& ApplyScale(const NzVector3& scale); + NzMatrix4 Concatenate(const NzMatrix4& matrix) const; NzMatrix4 ConcatenateAffine(const NzMatrix4& matrix) const; + void Destroy(); + T GetDeterminant() const; - NzMatrix4 GetInverse() const; + NzMatrix4 GetInverse(bool* succeeded = nullptr) const; + NzMatrix4 GetInverseAffine(bool* succeeded = nullptr) const; NzQuaternion GetRotation() const; //NzMatrix3 GetRotationMatrix() const; NzVector3 GetScale() const; @@ -52,30 +57,34 @@ class NzMatrix4 bool HasNegativeScale() const; bool HasScale() const; + NzMatrix4& Inverse(bool* succeeded = nullptr); + NzMatrix4& InverseAffine(bool* succeeded = nullptr); + bool IsAffine() const; bool IsDefined() const; - void MakeIdentity(); - void MakeLookAt(const NzVector3& eye, const NzVector3& target, const NzVector3& up = NzVector3::Up()); - void MakeOrtho(T left, T top, T width, T height, T zNear = -1.0, T zFar = 1.0); - void MakePerspective(T angle, T ratio, T zNear, T zFar); - void MakeRotation(const NzQuaternion& rotation); - void MakeScale(const NzVector3& scale); - void MakeTranslation(const NzVector3& translation); - void MakeZero(); + NzMatrix4& MakeIdentity(); + NzMatrix4& MakeLookAt(const NzVector3& eye, const NzVector3& target, const NzVector3& up = NzVector3::Up()); + NzMatrix4& MakeOrtho(T left, T top, T width, T height, T zNear = -1.0, T zFar = 1.0); + NzMatrix4& MakePerspective(T angle, T ratio, T zNear, T zFar); + NzMatrix4& MakeRotation(const NzQuaternion& rotation); + NzMatrix4& MakeScale(const NzVector3& scale); + NzMatrix4& MakeTranslation(const NzVector3& translation); + NzMatrix4& MakeTransform(const NzVector3& translation, const NzVector3& scale, const NzQuaternion& rotation); + NzMatrix4& MakeZero(); - void Set(T r11, T r12, T r13, T r14, + NzMatrix4& Set(T r11, T r12, T r13, T r14, T r21, T r22, T r23, T r24, T r31, T r32, T r33, T r34, T r41, T r42, T r43, T r44); - void Set(const T matrix[16]); + NzMatrix4& Set(const T matrix[16]); //NzMatrix4(const NzMatrix3& matrix); - void Set(const NzMatrix4& matrix); - void Set(NzMatrix4&& matrix); - template void Set(const NzMatrix4& matrix); - void SetRotation(const NzQuaternion& rotation); - void SetScale(const NzVector3& scale); - void SetTranslation(const NzVector3& translation); + NzMatrix4& Set(const NzMatrix4& matrix); + NzMatrix4& Set(NzMatrix4&& matrix); + template NzMatrix4& Set(const NzMatrix4& matrix); + NzMatrix4& SetRotation(const NzQuaternion& rotation); + NzMatrix4& SetScale(const NzVector3& scale); + NzMatrix4& SetTranslation(const NzVector3& translation); NzString ToString() const; @@ -117,6 +126,7 @@ class NzMatrix4 static NzMatrix4 Rotate(const NzQuaternion& rotation); static NzMatrix4 Scale(const NzVector3& scale); static NzMatrix4 Translate(const NzVector3& translation); + static NzMatrix4 Transform(const NzVector3& translation, const NzVector3& scale, const NzQuaternion& rotation); static NzMatrix4 Zero(); struct SharedMatrix diff --git a/include/Nazara/Math/Matrix4.inl b/include/Nazara/Math/Matrix4.inl index 9b12fecfb..0deb8f00b 100644 --- a/include/Nazara/Math/Matrix4.inl +++ b/include/Nazara/Math/Matrix4.inl @@ -16,7 +16,7 @@ #include #include //#include -///FIXME: Le MLT détecte de faux-leaks ici (Problème lié aux inline ?) +///FIXME: Le MLT détecte des leaks ici, mais dont la véracité n'a pu être prouvée (Problème lié aux classes inlines ?) #define F(a) static_cast(a) @@ -68,6 +68,24 @@ NzMatrix4::~NzMatrix4() ReleaseMatrix(); } +template +NzMatrix4& NzMatrix4::ApplyScale(const NzVector3& scale) +{ + m_sharedMatrix->m11 *= scale.x; + m_sharedMatrix->m12 *= scale.x; + m_sharedMatrix->m13 *= scale.x; + + m_sharedMatrix->m21 *= scale.y; + m_sharedMatrix->m22 *= scale.y; + m_sharedMatrix->m23 *= scale.y; + + m_sharedMatrix->m31 *= scale.z; + m_sharedMatrix->m32 *= scale.z; + m_sharedMatrix->m33 *= scale.z; + + return *this; +} + template NzMatrix4 NzMatrix4::Concatenate(const NzMatrix4& matrix) const { @@ -80,6 +98,12 @@ NzMatrix4 NzMatrix4::ConcatenateAffine(const NzMatrix4& matrix) const return ConcatenateAffine(*this, matrix); } +template +void NzMatrix4::Destroy() +{ + ReleaseMatrix(); +} + template T NzMatrix4::GetDeterminant() const { @@ -100,45 +124,17 @@ T NzMatrix4::GetDeterminant() const } template -NzMatrix4 NzMatrix4::GetInverse() const +NzMatrix4 NzMatrix4::GetInverse(bool* succeeded) const { - #if NAZARA_MATH_SAFE - if (!IsDefined()) - { - NazaraError("Matrix not defined"); - return NzMatrix4(); - } - #endif + NzMatrix4f matInv(*this); + return matInv.Inverse(succeeded); +} - T det = GetDeterminant(); - if (!NzNumberEquals(det, F(0.0))) - { - return NzMatrix4((m_sharedMatrix->m22*(m_sharedMatrix->m33*m_sharedMatrix->m44 - m_sharedMatrix->m34*m_sharedMatrix->m43) - m_sharedMatrix->m32*(m_sharedMatrix->m23*m_sharedMatrix->m44 - m_sharedMatrix->m43*m_sharedMatrix->m24) + m_sharedMatrix->m42*(m_sharedMatrix->m23*m_sharedMatrix->m34 - m_sharedMatrix->m33*m_sharedMatrix->m24)) / det, - -(m_sharedMatrix->m12*(m_sharedMatrix->m33*m_sharedMatrix->m44 - m_sharedMatrix->m43*m_sharedMatrix->m34) - m_sharedMatrix->m32*(m_sharedMatrix->m13*m_sharedMatrix->m44 - m_sharedMatrix->m43*m_sharedMatrix->m14) + m_sharedMatrix->m42*(m_sharedMatrix->m13*m_sharedMatrix->m34 - m_sharedMatrix->m33*m_sharedMatrix->m14)) / det, - (m_sharedMatrix->m12*(m_sharedMatrix->m23*m_sharedMatrix->m44 - m_sharedMatrix->m43*m_sharedMatrix->m24) - m_sharedMatrix->m22*(m_sharedMatrix->m13*m_sharedMatrix->m44 - m_sharedMatrix->m43*m_sharedMatrix->m14) + m_sharedMatrix->m42*(m_sharedMatrix->m13*m_sharedMatrix->m24 - m_sharedMatrix->m23*m_sharedMatrix->m14)) / det, - -(m_sharedMatrix->m12*(m_sharedMatrix->m23*m_sharedMatrix->m34 - m_sharedMatrix->m33*m_sharedMatrix->m24) - m_sharedMatrix->m22*(m_sharedMatrix->m13*m_sharedMatrix->m34 - m_sharedMatrix->m33*m_sharedMatrix->m14) + m_sharedMatrix->m32*(m_sharedMatrix->m13*m_sharedMatrix->m24 - m_sharedMatrix->m23*m_sharedMatrix->m14)) / det, - - -(m_sharedMatrix->m21*(m_sharedMatrix->m33*m_sharedMatrix->m44 - m_sharedMatrix->m34*m_sharedMatrix->m43) - m_sharedMatrix->m23*(m_sharedMatrix->m31*m_sharedMatrix->m44 - m_sharedMatrix->m34*m_sharedMatrix->m41) + m_sharedMatrix->m24*(m_sharedMatrix->m31*m_sharedMatrix->m43 - m_sharedMatrix->m33*m_sharedMatrix->m41)) / det, - (m_sharedMatrix->m11*(m_sharedMatrix->m33*m_sharedMatrix->m44 - m_sharedMatrix->m34*m_sharedMatrix->m43) - m_sharedMatrix->m13*(m_sharedMatrix->m31*m_sharedMatrix->m44 - m_sharedMatrix->m34*m_sharedMatrix->m41) + m_sharedMatrix->m14*(m_sharedMatrix->m31*m_sharedMatrix->m43 - m_sharedMatrix->m33*m_sharedMatrix->m41)) / det, - -(m_sharedMatrix->m11*(m_sharedMatrix->m23*m_sharedMatrix->m44 - m_sharedMatrix->m24*m_sharedMatrix->m43) - m_sharedMatrix->m13*(m_sharedMatrix->m21*m_sharedMatrix->m44 - m_sharedMatrix->m24*m_sharedMatrix->m41) + m_sharedMatrix->m14*(m_sharedMatrix->m21*m_sharedMatrix->m43 - m_sharedMatrix->m23*m_sharedMatrix->m41)) / det, - (m_sharedMatrix->m11*(m_sharedMatrix->m23*m_sharedMatrix->m34 - m_sharedMatrix->m24*m_sharedMatrix->m33) - m_sharedMatrix->m13*(m_sharedMatrix->m21*m_sharedMatrix->m34 - m_sharedMatrix->m24*m_sharedMatrix->m31) + m_sharedMatrix->m14*(m_sharedMatrix->m21*m_sharedMatrix->m33 - m_sharedMatrix->m23*m_sharedMatrix->m31)) / det, - - (m_sharedMatrix->m21*(m_sharedMatrix->m32*m_sharedMatrix->m44 - m_sharedMatrix->m34*m_sharedMatrix->m42) - m_sharedMatrix->m22*(m_sharedMatrix->m31*m_sharedMatrix->m44 - m_sharedMatrix->m34*m_sharedMatrix->m41) + m_sharedMatrix->m24*(m_sharedMatrix->m31*m_sharedMatrix->m42 - m_sharedMatrix->m32*m_sharedMatrix->m41)) / det, - -(m_sharedMatrix->m11*(m_sharedMatrix->m32*m_sharedMatrix->m44 - m_sharedMatrix->m34*m_sharedMatrix->m42) - m_sharedMatrix->m12*(m_sharedMatrix->m31*m_sharedMatrix->m44 - m_sharedMatrix->m34*m_sharedMatrix->m41) + m_sharedMatrix->m14*(m_sharedMatrix->m31*m_sharedMatrix->m42 - m_sharedMatrix->m32*m_sharedMatrix->m41)) / det, - (m_sharedMatrix->m11*(m_sharedMatrix->m22*m_sharedMatrix->m44 - m_sharedMatrix->m24*m_sharedMatrix->m42) - m_sharedMatrix->m12*(m_sharedMatrix->m21*m_sharedMatrix->m44 - m_sharedMatrix->m24*m_sharedMatrix->m41) + m_sharedMatrix->m14*(m_sharedMatrix->m21*m_sharedMatrix->m42 - m_sharedMatrix->m22*m_sharedMatrix->m41)) / det, - -(m_sharedMatrix->m11*(m_sharedMatrix->m22*m_sharedMatrix->m34 - m_sharedMatrix->m24*m_sharedMatrix->m32) - m_sharedMatrix->m12*(m_sharedMatrix->m21*m_sharedMatrix->m34 - m_sharedMatrix->m24*m_sharedMatrix->m31) + m_sharedMatrix->m14*(m_sharedMatrix->m21*m_sharedMatrix->m32 - m_sharedMatrix->m22*m_sharedMatrix->m31)) / det, - - -(m_sharedMatrix->m21*(m_sharedMatrix->m32*m_sharedMatrix->m43 - m_sharedMatrix->m33*m_sharedMatrix->m42) - m_sharedMatrix->m22*(m_sharedMatrix->m31*m_sharedMatrix->m43 - m_sharedMatrix->m33*m_sharedMatrix->m41) + m_sharedMatrix->m23*(m_sharedMatrix->m31*m_sharedMatrix->m42 - m_sharedMatrix->m32*m_sharedMatrix->m41)) / det, - (m_sharedMatrix->m11*(m_sharedMatrix->m32*m_sharedMatrix->m43 - m_sharedMatrix->m33*m_sharedMatrix->m42) - m_sharedMatrix->m12*(m_sharedMatrix->m31*m_sharedMatrix->m43 - m_sharedMatrix->m33*m_sharedMatrix->m41) + m_sharedMatrix->m13*(m_sharedMatrix->m31*m_sharedMatrix->m42 - m_sharedMatrix->m32*m_sharedMatrix->m41)) / det, - -(m_sharedMatrix->m11*(m_sharedMatrix->m22*m_sharedMatrix->m43 - m_sharedMatrix->m23*m_sharedMatrix->m42) - m_sharedMatrix->m12*(m_sharedMatrix->m21*m_sharedMatrix->m43 - m_sharedMatrix->m23*m_sharedMatrix->m41) + m_sharedMatrix->m13*(m_sharedMatrix->m21*m_sharedMatrix->m42 - m_sharedMatrix->m22*m_sharedMatrix->m41)) / det, - (m_sharedMatrix->m11*(m_sharedMatrix->m22*m_sharedMatrix->m33 - m_sharedMatrix->m23*m_sharedMatrix->m32) - m_sharedMatrix->m12*(m_sharedMatrix->m21*m_sharedMatrix->m33 - m_sharedMatrix->m23*m_sharedMatrix->m31) + m_sharedMatrix->m13*(m_sharedMatrix->m21*m_sharedMatrix->m32 - m_sharedMatrix->m22*m_sharedMatrix->m31)) / det); - } - else - { - NazaraError("Matrix has no inverse"); - - return Identity(); - } +template +NzMatrix4 NzMatrix4::GetInverseAffine(bool* succeeded) const +{ + NzMatrix4f matInv(*this); + return matInv.InverseAffine(succeeded); } template @@ -220,6 +216,259 @@ bool NzMatrix4::HasScale() const return false; } +template +NzMatrix4& NzMatrix4::Inverse(bool* succeeded) +{ + #if NAZARA_MATH_SAFE + if (!IsDefined()) + { + NazaraError("Matrix not defined"); + if (succeeded) + *succeeded = false; + + return *this; + } + #endif + + T det = GetDeterminant(); + if (!NzNumberEquals(det, F(0.0))) + { + // http://stackoverflow.com/questions/1148309/inverting-a-4x4-matrix + T inv[16]; + inv[0] = m_sharedMatrix->m22 * m_sharedMatrix->m33 * m_sharedMatrix->m44 - + m_sharedMatrix->m22 * m_sharedMatrix->m34 * m_sharedMatrix->m43 - + m_sharedMatrix->m32 * m_sharedMatrix->m23 * m_sharedMatrix->m44 + + m_sharedMatrix->m32 * m_sharedMatrix->m24 * m_sharedMatrix->m43 + + m_sharedMatrix->m42 * m_sharedMatrix->m23 * m_sharedMatrix->m34 - + m_sharedMatrix->m42 * m_sharedMatrix->m24 * m_sharedMatrix->m33; + + inv[1] = -m_sharedMatrix->m12 * m_sharedMatrix->m33 * m_sharedMatrix->m44 + + m_sharedMatrix->m12 * m_sharedMatrix->m34 * m_sharedMatrix->m43 + + m_sharedMatrix->m32 * m_sharedMatrix->m13 * m_sharedMatrix->m44 - + m_sharedMatrix->m32 * m_sharedMatrix->m14 * m_sharedMatrix->m43 - + m_sharedMatrix->m42 * m_sharedMatrix->m13 * m_sharedMatrix->m34 + + m_sharedMatrix->m42 * m_sharedMatrix->m14 * m_sharedMatrix->m33; + + inv[2] = m_sharedMatrix->m12 * m_sharedMatrix->m23 * m_sharedMatrix->m44 - + m_sharedMatrix->m12 * m_sharedMatrix->m24 * m_sharedMatrix->m43 - + m_sharedMatrix->m22 * m_sharedMatrix->m13 * m_sharedMatrix->m44 + + m_sharedMatrix->m22 * m_sharedMatrix->m14 * m_sharedMatrix->m43 + + m_sharedMatrix->m42 * m_sharedMatrix->m13 * m_sharedMatrix->m24 - + m_sharedMatrix->m42 * m_sharedMatrix->m14 * m_sharedMatrix->m23; + + inv[3] = -m_sharedMatrix->m12 * m_sharedMatrix->m23 * m_sharedMatrix->m34 + + m_sharedMatrix->m12 * m_sharedMatrix->m24 * m_sharedMatrix->m33 + + m_sharedMatrix->m22 * m_sharedMatrix->m13 * m_sharedMatrix->m34 - + m_sharedMatrix->m22 * m_sharedMatrix->m14 * m_sharedMatrix->m33 - + m_sharedMatrix->m32 * m_sharedMatrix->m13 * m_sharedMatrix->m24 + + m_sharedMatrix->m32 * m_sharedMatrix->m14 * m_sharedMatrix->m23; + + inv[4] = -m_sharedMatrix->m21 * m_sharedMatrix->m33 * m_sharedMatrix->m44 + + m_sharedMatrix->m21 * m_sharedMatrix->m34 * m_sharedMatrix->m43 + + m_sharedMatrix->m31 * m_sharedMatrix->m23 * m_sharedMatrix->m44 - + m_sharedMatrix->m31 * m_sharedMatrix->m24 * m_sharedMatrix->m43 - + m_sharedMatrix->m41 * m_sharedMatrix->m23 * m_sharedMatrix->m34 + + m_sharedMatrix->m41 * m_sharedMatrix->m24 * m_sharedMatrix->m33; + + inv[5] = m_sharedMatrix->m11 * m_sharedMatrix->m33 * m_sharedMatrix->m44 - + m_sharedMatrix->m11 * m_sharedMatrix->m34 * m_sharedMatrix->m43 - + m_sharedMatrix->m31 * m_sharedMatrix->m13 * m_sharedMatrix->m44 + + m_sharedMatrix->m31 * m_sharedMatrix->m14 * m_sharedMatrix->m43 + + m_sharedMatrix->m41 * m_sharedMatrix->m13 * m_sharedMatrix->m34 - + m_sharedMatrix->m41 * m_sharedMatrix->m14 * m_sharedMatrix->m33; + + inv[6] = -m_sharedMatrix->m11 * m_sharedMatrix->m23 * m_sharedMatrix->m44 + + m_sharedMatrix->m11 * m_sharedMatrix->m24 * m_sharedMatrix->m43 + + m_sharedMatrix->m21 * m_sharedMatrix->m13 * m_sharedMatrix->m44 - + m_sharedMatrix->m21 * m_sharedMatrix->m14 * m_sharedMatrix->m43 - + m_sharedMatrix->m41 * m_sharedMatrix->m13 * m_sharedMatrix->m24 + + m_sharedMatrix->m41 * m_sharedMatrix->m14 * m_sharedMatrix->m23; + + inv[7] = m_sharedMatrix->m11 * m_sharedMatrix->m23 * m_sharedMatrix->m34 - + m_sharedMatrix->m11 * m_sharedMatrix->m24 * m_sharedMatrix->m33 - + m_sharedMatrix->m21 * m_sharedMatrix->m13 * m_sharedMatrix->m34 + + m_sharedMatrix->m21 * m_sharedMatrix->m14 * m_sharedMatrix->m33 + + m_sharedMatrix->m31 * m_sharedMatrix->m13 * m_sharedMatrix->m24 - + m_sharedMatrix->m31 * m_sharedMatrix->m14 * m_sharedMatrix->m23; + + inv[8] = m_sharedMatrix->m21 * m_sharedMatrix->m32 * m_sharedMatrix->m44 - + m_sharedMatrix->m21 * m_sharedMatrix->m34 * m_sharedMatrix->m42 - + m_sharedMatrix->m31 * m_sharedMatrix->m22 * m_sharedMatrix->m44 + + m_sharedMatrix->m31 * m_sharedMatrix->m24 * m_sharedMatrix->m42 + + m_sharedMatrix->m41 * m_sharedMatrix->m22 * m_sharedMatrix->m34 - + m_sharedMatrix->m41 * m_sharedMatrix->m24 * m_sharedMatrix->m32; + + inv[9] = -m_sharedMatrix->m11 * m_sharedMatrix->m32 * m_sharedMatrix->m44 + + m_sharedMatrix->m11 * m_sharedMatrix->m34 * m_sharedMatrix->m42 + + m_sharedMatrix->m31 * m_sharedMatrix->m12 * m_sharedMatrix->m44 - + m_sharedMatrix->m31 * m_sharedMatrix->m14 * m_sharedMatrix->m42 - + m_sharedMatrix->m41 * m_sharedMatrix->m12 * m_sharedMatrix->m34 + + m_sharedMatrix->m41 * m_sharedMatrix->m14 * m_sharedMatrix->m32; + + inv[10] = m_sharedMatrix->m11 * m_sharedMatrix->m22 * m_sharedMatrix->m44 - + m_sharedMatrix->m11 * m_sharedMatrix->m24 * m_sharedMatrix->m42 - + m_sharedMatrix->m21 * m_sharedMatrix->m12 * m_sharedMatrix->m44 + + m_sharedMatrix->m21 * m_sharedMatrix->m14 * m_sharedMatrix->m42 + + m_sharedMatrix->m41 * m_sharedMatrix->m12 * m_sharedMatrix->m24 - + m_sharedMatrix->m41 * m_sharedMatrix->m14 * m_sharedMatrix->m22; + + inv[11] = -m_sharedMatrix->m11 * m_sharedMatrix->m22 * m_sharedMatrix->m34 + + m_sharedMatrix->m11 * m_sharedMatrix->m24 * m_sharedMatrix->m32 + + m_sharedMatrix->m21 * m_sharedMatrix->m12 * m_sharedMatrix->m34 - + m_sharedMatrix->m21 * m_sharedMatrix->m14 * m_sharedMatrix->m32 - + m_sharedMatrix->m31 * m_sharedMatrix->m12 * m_sharedMatrix->m24 + + m_sharedMatrix->m31 * m_sharedMatrix->m14 * m_sharedMatrix->m22; + + inv[12] = -m_sharedMatrix->m21 * m_sharedMatrix->m32 * m_sharedMatrix->m43 + + m_sharedMatrix->m21 * m_sharedMatrix->m33 * m_sharedMatrix->m42 + + m_sharedMatrix->m31 * m_sharedMatrix->m22 * m_sharedMatrix->m43 - + m_sharedMatrix->m31 * m_sharedMatrix->m23 * m_sharedMatrix->m42 - + m_sharedMatrix->m41 * m_sharedMatrix->m22 * m_sharedMatrix->m33 + + m_sharedMatrix->m41 * m_sharedMatrix->m23 * m_sharedMatrix->m32; + + inv[13] = m_sharedMatrix->m11 * m_sharedMatrix->m32 * m_sharedMatrix->m43 - + m_sharedMatrix->m11 * m_sharedMatrix->m33 * m_sharedMatrix->m42 - + m_sharedMatrix->m31 * m_sharedMatrix->m12 * m_sharedMatrix->m43 + + m_sharedMatrix->m31 * m_sharedMatrix->m13 * m_sharedMatrix->m42 + + m_sharedMatrix->m41 * m_sharedMatrix->m12 * m_sharedMatrix->m33 - + m_sharedMatrix->m41 * m_sharedMatrix->m13 * m_sharedMatrix->m32; + + inv[14] = -m_sharedMatrix->m11 * m_sharedMatrix->m22 * m_sharedMatrix->m43 + + m_sharedMatrix->m11 * m_sharedMatrix->m23 * m_sharedMatrix->m42 + + m_sharedMatrix->m21 * m_sharedMatrix->m12 * m_sharedMatrix->m43 - + m_sharedMatrix->m21 * m_sharedMatrix->m13 * m_sharedMatrix->m42 - + m_sharedMatrix->m41 * m_sharedMatrix->m12 * m_sharedMatrix->m23 + + m_sharedMatrix->m41 * m_sharedMatrix->m13 * m_sharedMatrix->m22; + + inv[15] = m_sharedMatrix->m11 * m_sharedMatrix->m22 * m_sharedMatrix->m33 - + m_sharedMatrix->m11 * m_sharedMatrix->m23 * m_sharedMatrix->m32 - + m_sharedMatrix->m21 * m_sharedMatrix->m12 * m_sharedMatrix->m33 + + m_sharedMatrix->m21 * m_sharedMatrix->m13 * m_sharedMatrix->m32 + + m_sharedMatrix->m31 * m_sharedMatrix->m12 * m_sharedMatrix->m23 - + m_sharedMatrix->m31 * m_sharedMatrix->m13 * m_sharedMatrix->m22; + + T invDet = F(1.0) / det; + for (unsigned int i = 0; i < 16; ++i) + inv[i] *= invDet; + + Set(inv); + if (succeeded) + *succeeded = true; + } + else + { + NazaraError("Matrix has no inverse"); + if (succeeded) + *succeeded = false; + } + + return *this; +} + +template +NzMatrix4& NzMatrix4::InverseAffine(bool* succeeded) +{ + #if NAZARA_MATH_SAFE + if (!IsDefined()) + { + NazaraError("Matrix not defined"); + if (succeeded) + *succeeded = false; + + return *this; + } + + if (!IsAffine()) + { + NazaraError("Matrix not affine"); + if (succeeded) + *succeeded = false; + + return *this; + } + #endif + + T det = GetDeterminant(); + if (!NzNumberEquals(det, F(0.0))) + { + // http://stackoverflow.com/questions/1148309/inverting-a-4x4-matrix + T inv[16]; + inv[0] = m_sharedMatrix->m22 * m_sharedMatrix->m33 - + m_sharedMatrix->m32 * m_sharedMatrix->m23; + + inv[1] = -m_sharedMatrix->m12 * m_sharedMatrix->m33 + + m_sharedMatrix->m32 * m_sharedMatrix->m13; + + inv[2] = m_sharedMatrix->m12 * m_sharedMatrix->m23 - + m_sharedMatrix->m22 * m_sharedMatrix->m13; + + inv[3] = F(0.0); + + inv[4] = -m_sharedMatrix->m21 * m_sharedMatrix->m33 + + m_sharedMatrix->m31 * m_sharedMatrix->m23; + + inv[5] = m_sharedMatrix->m11 * m_sharedMatrix->m33 - + m_sharedMatrix->m31 * m_sharedMatrix->m13; + + inv[6] = -m_sharedMatrix->m11 * m_sharedMatrix->m23 + + m_sharedMatrix->m21 * m_sharedMatrix->m13; + + inv[7] = F(0.0); + + inv[8] = m_sharedMatrix->m21 * m_sharedMatrix->m32 - + m_sharedMatrix->m31 * m_sharedMatrix->m22; + + inv[9] = -m_sharedMatrix->m11 * m_sharedMatrix->m32 + + m_sharedMatrix->m31 * m_sharedMatrix->m12; + + inv[10] = m_sharedMatrix->m11 * m_sharedMatrix->m22 - + m_sharedMatrix->m21 * m_sharedMatrix->m12; + + inv[11] = F(0.0); + + inv[12] = -m_sharedMatrix->m21 * m_sharedMatrix->m32 * m_sharedMatrix->m43 + + m_sharedMatrix->m21 * m_sharedMatrix->m33 * m_sharedMatrix->m42 + + m_sharedMatrix->m31 * m_sharedMatrix->m22 * m_sharedMatrix->m43 - + m_sharedMatrix->m31 * m_sharedMatrix->m23 * m_sharedMatrix->m42 - + m_sharedMatrix->m41 * m_sharedMatrix->m22 * m_sharedMatrix->m33 + + m_sharedMatrix->m41 * m_sharedMatrix->m23 * m_sharedMatrix->m32; + + inv[13] = m_sharedMatrix->m11 * m_sharedMatrix->m32 * m_sharedMatrix->m43 - + m_sharedMatrix->m11 * m_sharedMatrix->m33 * m_sharedMatrix->m42 - + m_sharedMatrix->m31 * m_sharedMatrix->m12 * m_sharedMatrix->m43 + + m_sharedMatrix->m31 * m_sharedMatrix->m13 * m_sharedMatrix->m42 + + m_sharedMatrix->m41 * m_sharedMatrix->m12 * m_sharedMatrix->m33 - + m_sharedMatrix->m41 * m_sharedMatrix->m13 * m_sharedMatrix->m32; + + inv[14] = -m_sharedMatrix->m11 * m_sharedMatrix->m22 * m_sharedMatrix->m43 + + m_sharedMatrix->m11 * m_sharedMatrix->m23 * m_sharedMatrix->m42 + + m_sharedMatrix->m21 * m_sharedMatrix->m12 * m_sharedMatrix->m43 - + m_sharedMatrix->m21 * m_sharedMatrix->m13 * m_sharedMatrix->m42 - + m_sharedMatrix->m41 * m_sharedMatrix->m12 * m_sharedMatrix->m23 + + m_sharedMatrix->m41 * m_sharedMatrix->m13 * m_sharedMatrix->m22; + + inv[15] = F(0.0); + + T invDet = F(1.0) / det; + for (unsigned int i = 0; i < 16; ++i) + inv[i] *= invDet; + + inv[15] = F(1.0); + + Set(inv); + if (succeeded) + *succeeded = true; + } + else + { + NazaraError("Matrix has no inverse"); + if (succeeded) + *succeeded = false; + } + + return *this; +} + template bool NzMatrix4::IsAffine() const { @@ -244,26 +493,30 @@ bool NzMatrix4::IsDefined() const } template -void NzMatrix4::MakeIdentity() +NzMatrix4& NzMatrix4::MakeIdentity() { Set(F(1.0), F(0.0), F(0.0), F(0.0), F(0.0), F(1.0), F(0.0), F(0.0), F(0.0), F(0.0), F(1.0), F(0.0), F(0.0), F(0.0), F(0.0), F(1.0)); + + return *this; } template -void NzMatrix4::MakeOrtho(T left, T top, T width, T height, T zNear, T zFar) +NzMatrix4& NzMatrix4::MakeOrtho(T left, T top, T width, T height, T zNear, T zFar) { // http://msdn.microsoft.com/en-us/library/windows/desktop/bb204941(v=vs.85).aspx Set(F(2.0)/(width-left), F(0.0), F(0.0), -(width+left)/(width-left), F(0.0), F(2.0)/(top-height), F(0.0), -(top+height)/(top-height), F(0.0), F(0.0), F(-2.0)/(zFar-zNear), -(zFar+zNear)/(zFar-zNear), F(0.0), F(0.0), F(0.0), F(1.0)); + + return *this; } template -void NzMatrix4::MakeLookAt(const NzVector3& eye, const NzVector3& target, const NzVector3& up) +NzMatrix4& NzMatrix4::MakeLookAt(const NzVector3& eye, const NzVector3& target, const NzVector3& up) { NzVector3 f = NzVector3::Normalize(target - eye); NzVector3 u(up.GetNormal()); @@ -274,10 +527,12 @@ void NzMatrix4::MakeLookAt(const NzVector3& eye, const NzVector3& targe s.y, u.y, -f.y, T(0.0), s.z, u.z, -f.z, T(0.0), -s.DotProduct(eye), -u.DotProduct(eye), f.DotProduct(eye), T(1.0)); + + return *this; } template -void NzMatrix4::MakePerspective(T angle, T ratio, T zNear, T zFar) +NzMatrix4& NzMatrix4::MakePerspective(T angle, T ratio, T zNear, T zFar) { // http://msdn.microsoft.com/en-us/library/windows/desktop/bb204944(v=vs.85).aspx #if NAZARA_MATH_ANGLE_RADIAN @@ -292,10 +547,12 @@ void NzMatrix4::MakePerspective(T angle, T ratio, T zNear, T zFar) F(0.0), yScale, F(0.0), F(0.0), F(0.0), F(0.0), zFar / (zNear-zFar), F(-1.0), F(0.0), F(0.0), (zNear*zFar) / (zNear-zFar), F(0.0)); + + return *this; } template -void NzMatrix4::MakeRotation(const NzQuaternion& rotation) +NzMatrix4& NzMatrix4::MakeRotation(const NzQuaternion& rotation) { // http://www.flipcode.com/documents/matrfaq.html#Q54 /* @@ -329,43 +586,71 @@ void NzMatrix4::MakeRotation(const NzQuaternion& rotation) F(0.0), F(0.0), F(1.0)); + + return *this; } template -void NzMatrix4::MakeScale(const NzVector3& scale) +NzMatrix4& NzMatrix4::MakeScale(const NzVector3& scale) { Set(scale.x, F(0.0), F(0.0), F(0.0), F(0.0), scale.y, F(0.0), F(0.0), F(0.0), F(0.0), scale.z, F(0.0), F(0.0), F(0.0), F(0.0), F(1.0)); + + return *this; } template -void NzMatrix4::MakeTranslation(const NzVector3& translation) +NzMatrix4& NzMatrix4::MakeTranslation(const NzVector3& translation) { Set(F(1.0), F(0.0), F(0.0), F(0.0), F(0.0), F(1.0), F(0.0), F(0.0), F(0.0), F(0.0), F(1.0), F(0.0), translation.x, translation.y, translation.z, F(1.0)); + + return *this; } template -void NzMatrix4::MakeZero() +NzMatrix4& NzMatrix4::MakeTransform(const NzVector3& translation, const NzVector3& scale, const NzQuaternion& rotation) +{ + // La rotation et la translation peuvent être appliquées directement + SetRotation(rotation); + SetTranslation(translation); + + // On complète la matrice (les transformations sont affines) + m_sharedMatrix->m14 = F(0.0); + m_sharedMatrix->m24 = F(0.0); + m_sharedMatrix->m34 = F(0.0); + m_sharedMatrix->m44 = F(1.0); + + // Ensuite on fait une mise à l'échelle des valeurs déjà présentes + ApplyScale(scale); + + return *this; +} + +template +NzMatrix4& NzMatrix4::MakeZero() { Set(F(0.0), F(0.0), F(0.0), F(0.0), F(0.0), F(0.0), F(0.0), F(0.0), F(0.0), F(0.0), F(0.0), F(0.0), F(0.0), F(0.0), F(0.0), F(0.0)); + + return *this; } template -void NzMatrix4::Set(T r11, T r12, T r13, T r14, +NzMatrix4& NzMatrix4::Set(T r11, T r12, T r13, T r14, T r21, T r22, T r23, T r24, T r31, T r32, T r33, T r34, T r41, T r42, T r43, T r44) { - EnsureOwnership(); + ReleaseMatrix(); + m_sharedMatrix = new SharedMatrix; m_sharedMatrix->m11 = r11; m_sharedMatrix->m12 = r12; m_sharedMatrix->m13 = r13; @@ -382,19 +667,24 @@ void NzMatrix4::Set(T r11, T r12, T r13, T r14, m_sharedMatrix->m42 = r42; m_sharedMatrix->m43 = r43; m_sharedMatrix->m44 = r44; + + return *this; } template -void NzMatrix4::Set(const T matrix[16]) +NzMatrix4& NzMatrix4::Set(const T matrix[16]) { - EnsureOwnership(); + ReleaseMatrix(); + m_sharedMatrix = new SharedMatrix; // Ici nous sommes certains de la continuité des éléments en mémoire std::memcpy(&m_sharedMatrix->m11, matrix, 16*sizeof(T)); + + return *this; } template -void NzMatrix4::Set(const NzMatrix4& matrix) +NzMatrix4& NzMatrix4::Set(const NzMatrix4& matrix) { ReleaseMatrix(); @@ -405,26 +695,32 @@ void NzMatrix4::Set(const NzMatrix4& matrix) m_sharedMatrix->refCount++; NazaraMutexUnlock(m_sharedMatrix->mutex); } + + return *this; } template -void NzMatrix4::Set(NzMatrix4&& matrix) +NzMatrix4& NzMatrix4::Set(NzMatrix4&& matrix) { std::swap(m_sharedMatrix, matrix.m_sharedMatrix); + + return *this; } template template -void NzMatrix4::Set(const NzMatrix4& matrix) +NzMatrix4& NzMatrix4::Set(const NzMatrix4& matrix) { Set(F(matrix.m_sharedMatrix->m11), F(matrix.m_sharedMatrix->m12), F(matrix.m_sharedMatrix->m13), F(matrix.m_sharedMatrix->m14), F(matrix.m_sharedMatrix->m21), F(matrix.m_sharedMatrix->m22), F(matrix.m_sharedMatrix->m23), F(matrix.m_sharedMatrix->m24), F(matrix.m_sharedMatrix->m31), F(matrix.m_sharedMatrix->m32), F(matrix.m_sharedMatrix->m33), F(matrix.m_sharedMatrix->m34), F(matrix.m_sharedMatrix->m41), F(matrix.m_sharedMatrix->m42), F(matrix.m_sharedMatrix->m43), F(matrix.m_sharedMatrix->m44)); + + return *this; } template -void NzMatrix4::SetRotation(const NzQuaternion& rotation) +NzMatrix4& NzMatrix4::SetRotation(const NzQuaternion& rotation) { // http://www.flipcode.com/documents/matrfaq.html#Q54 EnsureOwnership(); @@ -439,20 +735,24 @@ void NzMatrix4::SetRotation(const NzQuaternion& rotation) m_sharedMatrix->m23 = F(2.0)*rotation.y*rotation.z - F(2.0)*rotation.x*rotation.w; m_sharedMatrix->m31 = F(2.0)*rotation.x*rotation.z - F(2.0)*rotation.y*rotation.w; m_sharedMatrix->m32 = F(2.0)*rotation.y*rotation.z + F(2.0)*rotation.x*rotation.w; + + return *this; } template -void NzMatrix4::SetScale(const NzVector3& scale) +NzMatrix4& NzMatrix4::SetScale(const NzVector3& scale) { EnsureOwnership(); m_sharedMatrix->m11 = scale.x; m_sharedMatrix->m22 = scale.y; m_sharedMatrix->m33 = scale.z; + + return *this; } template -void NzMatrix4::SetTranslation(const NzVector3& translation) +NzMatrix4& NzMatrix4::SetTranslation(const NzVector3& translation) { EnsureOwnership(); @@ -460,6 +760,8 @@ void NzMatrix4::SetTranslation(const NzVector3& translation) m_sharedMatrix->m42 = translation.y; m_sharedMatrix->m43 = translation.z; m_sharedMatrix->m44 = F(1.0); + + return *this; } template @@ -734,7 +1036,7 @@ bool NzMatrix4::operator==(const NzMatrix4& mat) const return false; for (unsigned int i = 0; i < 16; ++i) - if (!NzNumberEquals((&m_sharedMatrix->m11)[i])) + if (!NzNumberEquals((&m_sharedMatrix->m11)[i], (&mat.m_sharedMatrix->m11)[i])) return false; return true; @@ -904,6 +1206,15 @@ NzMatrix4 NzMatrix4::Translate(const NzVector3& translation) return mat; } +template +NzMatrix4 NzMatrix4::Transform(const NzVector3& translation, const NzVector3& scale, const NzQuaternion& rotation) +{ + NzMatrix4 mat; + mat.MakeTransform(translation, scale, rotation); + + return mat; +} + template NzMatrix4 NzMatrix4::Zero() { @@ -937,6 +1248,8 @@ void NzMatrix4::EnsureOwnership() SharedMatrix* sharedMatrix = new SharedMatrix; std::memcpy(&sharedMatrix->m11, &m_sharedMatrix->m11, 16*sizeof(T)); + + m_sharedMatrix = sharedMatrix; } } else