// Copyright (C) 2012 Jérôme Leclercq // This file is part of the "Nazara Engine". // For conditions of distribution and use, see copyright notice in Config.hpp #include #include #include #include #include #include #include #include #include #include #include #include #include #define NAZARA_CLASS_MATRIX4 #include #include template NzMatrix4::NzMatrix4() : m_sharedMatrix(nullptr) { } template NzMatrix4::NzMatrix4(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) : m_sharedMatrix(nullptr) { Set(r11, r12, r13, r14, r21, r22, r23, r24, r31, r32, r33, r34, r41, r42, r43, r44); } template NzMatrix4::NzMatrix4(T matrix[16]) : m_sharedMatrix(nullptr) { Set(matrix); } template template NzMatrix4::NzMatrix4(const NzMatrix4& matrix) : m_sharedMatrix(nullptr) { Set(matrix); } template NzMatrix4::NzMatrix4(const NzMatrix4& matrix) : m_sharedMatrix(nullptr) { Set(matrix); } template NzMatrix4::NzMatrix4(NzMatrix4&& matrix) : m_sharedMatrix(nullptr) { Set(matrix); } template NzMatrix4::~NzMatrix4() { ReleaseMatrix(); } template T NzMatrix4::GetDeterminant() const { #if NAZARA_MATH_SAFE if (!m_sharedMatrix) { NazaraError("Undefined matrix"); return 0.0; } #endif T A = m_sharedMatrix->m22 * (m_sharedMatrix->m33 * m_sharedMatrix->m44 - m_sharedMatrix->m43 * m_sharedMatrix->m34) - 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); T B = 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); T C = 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); T D = 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); return m_sharedMatrix->m11 * A - m_sharedMatrix->m21 * B + m_sharedMatrix->m31 * C - m_sharedMatrix->m41 * D; } template NzMatrix4 NzMatrix4::GetInverse() const { #if NAZARA_MATH_SAFE if (!m_sharedMatrix) { NazaraError("Undefined matrix"); return NzMatrix4(); } #endif NzMatrix4 matrix; T det = GetDeterminant(); if (!NzNumberEquals(det, static_cast(0.0))) { matrix(0, 0) = (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; matrix(0, 1) = -(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; matrix(0, 2) = (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; matrix(0, 3) = -(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; matrix(1, 0) = -(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; matrix(1, 1) = (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; matrix(1, 2) = -(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; matrix(1, 3) = (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; matrix(2, 0) = (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; matrix(2, 1) = -(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; matrix(2, 2) = (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; matrix(2, 3) = -(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; matrix(3, 0) = -(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; matrix(3, 1) = (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; matrix(3, 2) = -(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; matrix(3, 3) = (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; } return matrix; } template NzVector3 NzMatrix4::GetScale() const { #if NAZARA_MATH_SAFE if (!m_sharedMatrix) { NazaraError("Undefined matrix"); return NzVector3(); } #endif return NzVector3(std::sqrt(m_sharedMatrix->m11 * m_sharedMatrix->m11 + m_sharedMatrix->m21 * m_sharedMatrix->m21 + m_sharedMatrix->m31 * m_sharedMatrix->m31), std::sqrt(m_sharedMatrix->m12 * m_sharedMatrix->m12 + m_sharedMatrix->m22 * m_sharedMatrix->m22 + m_sharedMatrix->m32 * m_sharedMatrix->m32), std::sqrt(m_sharedMatrix->m13 * m_sharedMatrix->m13 + m_sharedMatrix->m23 * m_sharedMatrix->m23 + m_sharedMatrix->m33 * m_sharedMatrix->m33)); } template NzVector3 NzMatrix4::GetTranslation() const { #if NAZARA_MATH_SAFE if (!m_sharedMatrix) { NazaraError("Undefined matrix"); return NzVector3(); } #endif #if NAZARA_MATH_MATRIX_COLUMN_MAJOR return NzVector3(m_sharedMatrix->m41, m_sharedMatrix->m42, m_sharedMatrix->m43); #else return NzVector3(m_sharedMatrix->m14, m_sharedMatrix->m24, m_sharedMatrix->m34); #endif } template NzMatrix4 NzMatrix4::GetTransposed() const { #if NAZARA_MATH_SAFE if (!m_sharedMatrix) { NazaraError("Undefined matrix"); return NzMatrix4(); } #endif return NzMatrix4(m_sharedMatrix->m11, m_sharedMatrix->m21, m_sharedMatrix->m31, m_sharedMatrix->m41, m_sharedMatrix->m12, m_sharedMatrix->m22, m_sharedMatrix->m32, m_sharedMatrix->m42, m_sharedMatrix->m13, m_sharedMatrix->m23, m_sharedMatrix->m33, m_sharedMatrix->m43, m_sharedMatrix->m14, m_sharedMatrix->m24, m_sharedMatrix->m34, m_sharedMatrix->m44); } template bool NzMatrix4::HasNegativeScale() const { return GetDeterminant() < 0.f; } template bool NzMatrix4::HasScale() const { #if NAZARA_MATH_SAFE if (!m_sharedMatrix) { NazaraError("Undefined matrix"); return false; } #endif T t = m_sharedMatrix->m11 * m_sharedMatrix->m11 + m_sharedMatrix->m21 * m_sharedMatrix->m21 + m_sharedMatrix->m31 * m_sharedMatrix->m31; if (1.0 - t > std::numeric_limits::epsilon()) return true; t = m_sharedMatrix->m12 * m_sharedMatrix->m12 + m_sharedMatrix->m22 * m_sharedMatrix->m22 + m_sharedMatrix->m32 * m_sharedMatrix->m32; if (1.0 - t > std::numeric_limits::epsilon()) return true; t = m_sharedMatrix->m13 * m_sharedMatrix->m13 + m_sharedMatrix->m23 * m_sharedMatrix->m23 + m_sharedMatrix->m33 * m_sharedMatrix->m33; if (1.0 - t > std::numeric_limits::epsilon()) return true; return false; } template void 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(); m_sharedMatrix->m11 = r11; m_sharedMatrix->m12 = r12; m_sharedMatrix->m13 = r13; m_sharedMatrix->m14 = r14; m_sharedMatrix->m21 = r21; m_sharedMatrix->m22 = r22; m_sharedMatrix->m23 = r23; m_sharedMatrix->m24 = r24; m_sharedMatrix->m31 = r31; m_sharedMatrix->m32 = r32; m_sharedMatrix->m33 = r33; m_sharedMatrix->m34 = r34; m_sharedMatrix->m41 = r41; m_sharedMatrix->m42 = r42; m_sharedMatrix->m43 = r43; m_sharedMatrix->m44 = r44; } template void NzMatrix4::Set(T matrix[16]) { EnsureOwnership(); // Ici nous sommes certains de la continuité des éléments en mémoire std::memcpy(&m_sharedMatrix->m41, matrix, 16*sizeof(T)); } template void NzMatrix4::Set(const NzMatrix4& matrix) { ReleaseMatrix(); m_sharedMatrix = matrix.m_sharedMatrix; if (m_sharedMatrix) { NazaraMutexLock(m_sharedMatrix->mutex); m_sharedMatrix->refCount++; NazaraMutexUnlock(m_sharedMatrix->mutex); } } template void NzMatrix4::Set(NzMatrix4&& matrix) { std::swap(m_sharedMatrix, matrix.m_sharedMatrix); } template template void NzMatrix4::Set(const NzMatrix4& matrix) { Set(static_cast(matrix.m11), static_cast(matrix.m12), static_cast(matrix.m13), static_cast(matrix.m14), static_cast(matrix.m21), static_cast(matrix.m22), static_cast(matrix.m23), static_cast(matrix.m24), static_cast(matrix.m31), static_cast(matrix.m32), static_cast(matrix.m33), static_cast(matrix.m34), static_cast(matrix.m41), static_cast(matrix.m42), static_cast(matrix.m43), static_cast(matrix.m44)); } template void NzMatrix4::SetIdentity() { Set(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0); } template void NzMatrix4::SetOrtho(T left, T top, T width, T height, T zNear, T zFar) { #if NAZARA_MATH_MATRIX_COLUMN_MAJOR Set(2.0/(width-left), 0.0, 0.0, -(width+left)/(width-left), 0.0, 2.0/(top-height), 0.0, -(top+height)/(top-height), 0.0, 0.0, -2.0/(zFar-zNear), -(zFar+zNear)/(zFar-zNear), 0.0, 0.0, 0.0, 1.0); #else Set(2.0/(width-left), 0.0, 0.0, 0.0, 0.0, 2.0/(top-height), 0.0, 0.0, 0.0, 0.0, -2.0/(zFar-zNear), 0.0, -(width+left)/(width-left), -(top+height)/(top-height), -(zFar+zNear)/(zFar-zNear), 1.0); #endif } template void NzMatrix4::SetLookAt(const NzVector3& eye, const NzVector3& center, const NzVector3& up) { NzVector3 f = center - eye; f.Normalize(); NzVector3 u = up; u.Normalize(); NzVector3 s = f.CrossProduct(u); s.Normalize(); u = s.CrossProduct(f); Set(s.x, u.x, -f.x, 0.0, s.y, u.y, -f.y, 0.0, s.z, u.z, -f.z, 0.0, 0.0, 0.0, 0.0, 1.0); operator*=(Translate(-eye)); } template void NzMatrix4::SetPerspective(T angle, T ratio, T zNear, T zFar) { #if NAZARA_MATH_ANGLE_RADIAN angle /= 2; #else angle = NzDegreeToRadian(angle/2); #endif auto f = 1 / std::tan(angle); #if NAZARA_MATH_MATRIX_COLUMN_MAJOR Set(f / ratio, 0.0, 0.0, 0.0, 0.0, f, 0.0, 0.0, 0.0, 0.0, (zNear + zFar) / (zNear - zFar), -1.0, 0.0, 0.0, (2 * zNear * zFar) / (zNear - zFar), 1.0); #else Set(f / ratio, 0.0, 0.0, 0.0, 0.0, f, 0.0, 0.0, 0.0, 0.0, (zNear + zFar) / (zNear - zFar), (2 * zNear * zFar) / (zNear - zFar), 0.0, 0.0, -1.0, 1.0); #endif } template void NzMatrix4::SetRotation(const NzQuaternion& rotation) { // http://www.flipcode.com/documents/matrfaq.html#Q54 T xx = rotation.x * rotation.x; T xy = rotation.x * rotation.y; T xz = rotation.x * rotation.z; T xw = rotation.x * rotation.w; T yy = rotation.y * rotation.y; T yz = rotation.y * rotation.z; T yw = rotation.y * rotation.w; T zz = rotation.z * rotation.z; T zw = rotation.z * rotation.w; Set(1.0 - 2.0*(yy+zz), 2.0*(xy-zw), 2.0*(xz+yw), 0.0, 2.0*(xz+zw), 1.0 - 2.0*(xx+zz), 2.0*(yz-xw), 0.0, 2.0*(xz-yw), 2.0*(yz+xw), 1.0 - 2.0*(xx+yy), 0.0, 0.0, 0.0, 0.0, 1.0); } template void NzMatrix4::SetScale(const NzVector3& vector) { Set(vector.x, 0.0, 0.0, 0.0, 0.0, vector.y, 0.0, 0.0, 0.0, 0.0, vector.z, 0.0, 0.0, 0.0, 0.0, 1.0); } template void NzMatrix4::SetTranslation(const NzVector3& translation) { #if NAZARA_MATH_MATRIX_COLUMN_MAJOR Set(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, translation.x, translation.y, translation.z, 1.0); #else Set(1.0, 0.0, 0.0, translation.x, 0.0, 1.0, 0.0, translation.y, 0.0, 0.0, 1.0, translation.z, 0.0, 0.0, 0.0, 1.0); #endif } template void NzMatrix4::SetZero() { Set(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); } template NzString NzMatrix4::ToString() const { if (!m_sharedMatrix) return "Matrix4(undefined)"; NzStringStream ss; return ss << "Matrix4(" << m_sharedMatrix->m11 << ", " << m_sharedMatrix->m12 << ", " << m_sharedMatrix->m13 << ", " << m_sharedMatrix->m14 << ",\n" << " " << m_sharedMatrix->m21 << ", " << m_sharedMatrix->m22 << ", " << m_sharedMatrix->m23 << ", " << m_sharedMatrix->m24 << ",\n" << " " << m_sharedMatrix->m31 << ", " << m_sharedMatrix->m32 << ", " << m_sharedMatrix->m33 << ", " << m_sharedMatrix->m34 << ",\n" << " " << m_sharedMatrix->m41 << ", " << m_sharedMatrix->m42 << ", " << m_sharedMatrix->m43 << ", " << m_sharedMatrix->m44 << ')'; } template NzVector2 NzMatrix4::Transform(const NzVector2& vector, T z, T w) const { #if NAZARA_MATH_SAFE if (!m_sharedMatrix) { NazaraError("Undefined matrix"); return vector; } #endif return NzVector2(m_sharedMatrix->m11 * vector.x + m_sharedMatrix->m12 * vector.y + m_sharedMatrix->m13 * z + m_sharedMatrix->m14 * w, m_sharedMatrix->m21 * vector.x + m_sharedMatrix->m22 * vector.y + m_sharedMatrix->m23 * z + m_sharedMatrix->m24 * w); } template NzVector3 NzMatrix4::Transform(const NzVector3& vector, T w) const { #if NAZARA_MATH_SAFE if (!m_sharedMatrix) { NazaraError("Undefined matrix"); return vector; } #endif return NzVector3(m_sharedMatrix->m11 * vector.x + m_sharedMatrix->m12 * vector.y + m_sharedMatrix->m13 * vector.z + m_sharedMatrix->m14 * w, m_sharedMatrix->m21 * vector.x + m_sharedMatrix->m22 * vector.y + m_sharedMatrix->m23 * vector.z + m_sharedMatrix->m24 * w, m_sharedMatrix->m31 * vector.x + m_sharedMatrix->m32 * vector.y + m_sharedMatrix->m33 * vector.z + m_sharedMatrix->m34 * w); } template NzVector4 NzMatrix4::Transform(const NzVector4& vector) const { #if NAZARA_MATH_SAFE if (!m_sharedMatrix) { NazaraError("Undefined matrix"); return vector; } #endif return NzVector4(m_sharedMatrix->m11 * vector.x + m_sharedMatrix->m12 * vector.y + m_sharedMatrix->m13 * vector.z + m_sharedMatrix->m14 * vector.w, m_sharedMatrix->m21 * vector.x + m_sharedMatrix->m22 * vector.y + m_sharedMatrix->m23 * vector.z + m_sharedMatrix->m24 * vector.w, m_sharedMatrix->m31 * vector.x + m_sharedMatrix->m32 * vector.y + m_sharedMatrix->m33 * vector.z + m_sharedMatrix->m34 * vector.w, m_sharedMatrix->m41 * vector.x + m_sharedMatrix->m42 * vector.y + m_sharedMatrix->m43 * vector.z + m_sharedMatrix->m44 * vector.w); } template NzMatrix4& NzMatrix4::Transpose() { #if NAZARA_MATH_SAFE if (!m_sharedMatrix) { NazaraError("Undefined matrix"); return *this; } #endif std::swap(m_sharedMatrix->m12, m_sharedMatrix->m21); std::swap(m_sharedMatrix->m13, m_sharedMatrix->m31); std::swap(m_sharedMatrix->m14, m_sharedMatrix->m41); std::swap(m_sharedMatrix->m23, m_sharedMatrix->m32); std::swap(m_sharedMatrix->m24, m_sharedMatrix->m42); std::swap(m_sharedMatrix->m34, m_sharedMatrix->m43); return *this; } template NzMatrix4::operator T*() { #if NAZARA_MATH_SAFE if (!m_sharedMatrix) { NazaraError("Undefined matrix"); return nullptr; } #endif EnsureOwnership(); return &m_sharedMatrix->m11; } template NzMatrix4::operator const T*() const { #if NAZARA_MATH_SAFE if (!m_sharedMatrix) { NazaraError("Undefined matrix"); return nullptr; } #endif return &m_sharedMatrix->m11; } template T& NzMatrix4::operator()(unsigned int x, unsigned int y) { #if NAZARA_MATH_SAFE if (x > 3 || y > 3) { NzStringStream ss; ss << __FILE__ << ':' << __LINE__ << ": Index out of range: (" << x << ", " << y << ") > (3,3)"; throw std::out_of_range(ss.ToString()); } #endif EnsureOwnership(); return (&m_sharedMatrix->m11)[x*4+y]; } template const T& NzMatrix4::operator()(unsigned int x, unsigned int y) const { #if NAZARA_MATH_SAFE if (!m_sharedMatrix) { NazaraError("Undefined matrix"); throw std::runtime_error("Tried to access element of undefined matrix"); } if (x > 3 || y > 3) { NzStringStream ss; ss << __FILE__ << ':' << __LINE__ << ": Index out of range: (" << x << ", " << y << ") > (3,3)"; throw std::out_of_range(ss.ToString()); } #endif return (&m_sharedMatrix->m11)[x*4+y]; } template NzMatrix4& NzMatrix4::operator=(const NzMatrix4& matrix) { Set(matrix); return *this; } template NzMatrix4& NzMatrix4::operator=(NzMatrix4&& matrix) { Set(matrix); return *this; } template NzMatrix4 NzMatrix4::operator*(const NzMatrix4& matrix) const { #if NAZARA_MATH_SAFE if (!m_sharedMatrix) { NazaraError("Undefined matrix"); return matrix; } #endif NzMatrix4 mat; for(int k = 0; k < 4; k++) { for(int j = 0; j < 4; j++) { for(int i = 0; i < 4; i++) mat(j, k) += (*this)(j, i) * matrix(i, k); } } return mat; /*return NzMatrix4(m11 * matrix.m11 + m21 * matrix.m12 + m31 * matrix.m13 + m41 * matrix.m14, m12 * matrix.m11 + m22 * matrix.m12 + m32 * matrix.m13 + m42 * matrix.m14, m13 * matrix.m11 + m23 * matrix.m12 + m33 * matrix.m13 + m43 * matrix.m14, m14 * matrix.m11 + m24 * matrix.m12 + m34 * matrix.m13 + m44 * matrix.m14, m11 * matrix.m21 + m21 * matrix.m22 + m31 * matrix.m23 + m41 * matrix.m24, m12 * matrix.m21 + m22 * matrix.m22 + m32 * matrix.m23 + m42 * matrix.m24, m13 * matrix.m21 + m23 * matrix.m22 + m33 * matrix.m23 + m43 * matrix.m24, m14 * matrix.m21 + m24 * matrix.m22 + m34 * matrix.m23 + m44 * matrix.m24, m11 * matrix.m31 + m21 * matrix.m32 + m31 * matrix.m33 + m41 * matrix.m34, m12 * matrix.m31 + m22 * matrix.m32 + m32 * matrix.m33 + m42 * matrix.m34, m13 * matrix.m31 + m23 * matrix.m32 + m33 * matrix.m33 + m43 * matrix.m34, m14 * matrix.m31 + m24 * matrix.m32 + m34 * matrix.m33 + m44 * matrix.m34, m11 * matrix.m41 + m21 * matrix.m42 + m31 * matrix.m43 + m41 * matrix.m44, m12 * matrix.m41 + m22 * matrix.m42 + m32 * matrix.m43 + m42 * matrix.m44, m13 * matrix.m41 + m23 * matrix.m42 + m33 * matrix.m43 + m43 * matrix.m44, m14 * matrix.m41 + m24 * matrix.m42 + m34 * matrix.m43 + m44 * matrix.m44);*/ } template NzVector2 NzMatrix4::operator*(const NzVector2& vector) const { return Transform(vector); } template NzVector3 NzMatrix4::operator*(const NzVector3& vector) const { return Transform(vector); } template NzVector4 NzMatrix4::operator*(const NzVector4& vector) const { return Transform(vector); } template NzMatrix4 NzMatrix4::operator*(T scalar) const { #if NAZARA_MATH_SAFE if (!m_sharedMatrix) { NazaraError("Undefined matrix"); return *this; } #endif return NzMatrix4(m_sharedMatrix->m11 * scalar, m_sharedMatrix->m12 * scalar, m_sharedMatrix->m13 * scalar, m_sharedMatrix->m14 * scalar, m_sharedMatrix->m21 * scalar, m_sharedMatrix->m22 * scalar, m_sharedMatrix->m23 * scalar, m_sharedMatrix->m24 * scalar, m_sharedMatrix->m31 * scalar, m_sharedMatrix->m32 * scalar, m_sharedMatrix->m33 * scalar, m_sharedMatrix->m34 * scalar, m_sharedMatrix->m41 * scalar, m_sharedMatrix->m42 * scalar, m_sharedMatrix->m43 * scalar, m_sharedMatrix->m44 * scalar); } template NzMatrix4& NzMatrix4::operator*=(const NzMatrix4& matrix) { #if NAZARA_MATH_SAFE if (!m_sharedMatrix) { NazaraError("Undefined matrix"); return *this; } #endif // On calcule dans des variables temporaires T r11 = m_sharedMatrix->m11 * matrix.m_sharedMatrix->m11 + m_sharedMatrix->m21 * matrix.m_sharedMatrix->m12 + m_sharedMatrix->m31 * matrix.m_sharedMatrix->m13 + m_sharedMatrix->m41 * matrix.m_sharedMatrix->m14; T r12 = m_sharedMatrix->m12 * matrix.m_sharedMatrix->m11 + m_sharedMatrix->m22 * matrix.m_sharedMatrix->m12 + m_sharedMatrix->m32 * matrix.m_sharedMatrix->m13 + m_sharedMatrix->m42 * matrix.m_sharedMatrix->m14; T r13 = m_sharedMatrix->m13 * matrix.m_sharedMatrix->m11 + m_sharedMatrix->m23 * matrix.m_sharedMatrix->m12 + m_sharedMatrix->m33 * matrix.m_sharedMatrix->m13 + m_sharedMatrix->m43 * matrix.m_sharedMatrix->m14; T r14 = m_sharedMatrix->m14 * matrix.m_sharedMatrix->m11 + m_sharedMatrix->m24 * matrix.m_sharedMatrix->m12 + m_sharedMatrix->m34 * matrix.m_sharedMatrix->m13 + m_sharedMatrix->m44 * matrix.m_sharedMatrix->m14; T r21 = m_sharedMatrix->m11 * matrix.m_sharedMatrix->m21 + m_sharedMatrix->m21 * matrix.m_sharedMatrix->m22 + m_sharedMatrix->m31 * matrix.m_sharedMatrix->m23 + m_sharedMatrix->m41 * matrix.m_sharedMatrix->m24; T r22 = m_sharedMatrix->m12 * matrix.m_sharedMatrix->m21 + m_sharedMatrix->m22 * matrix.m_sharedMatrix->m22 + m_sharedMatrix->m32 * matrix.m_sharedMatrix->m23 + m_sharedMatrix->m42 * matrix.m_sharedMatrix->m24; T r23 = m_sharedMatrix->m13 * matrix.m_sharedMatrix->m21 + m_sharedMatrix->m23 * matrix.m_sharedMatrix->m22 + m_sharedMatrix->m33 * matrix.m_sharedMatrix->m23 + m_sharedMatrix->m43 * matrix.m_sharedMatrix->m24; T r24 = m_sharedMatrix->m14 * matrix.m_sharedMatrix->m21 + m_sharedMatrix->m24 * matrix.m_sharedMatrix->m22 + m_sharedMatrix->m34 * matrix.m_sharedMatrix->m23 + m_sharedMatrix->m44 * matrix.m_sharedMatrix->m24; T r31 = m_sharedMatrix->m11 * matrix.m_sharedMatrix->m31 + m_sharedMatrix->m21 * matrix.m_sharedMatrix->m32 + m_sharedMatrix->m31 * matrix.m_sharedMatrix->m33 + m_sharedMatrix->m41 * matrix.m_sharedMatrix->m34; T r32 = m_sharedMatrix->m12 * matrix.m_sharedMatrix->m31 + m_sharedMatrix->m22 * matrix.m_sharedMatrix->m32 + m_sharedMatrix->m32 * matrix.m_sharedMatrix->m33 + m_sharedMatrix->m42 * matrix.m_sharedMatrix->m34; T r33 = m_sharedMatrix->m13 * matrix.m_sharedMatrix->m31 + m_sharedMatrix->m23 * matrix.m_sharedMatrix->m32 + m_sharedMatrix->m33 * matrix.m_sharedMatrix->m33 + m_sharedMatrix->m43 * matrix.m_sharedMatrix->m34; T r34 = m_sharedMatrix->m14 * matrix.m_sharedMatrix->m31 + m_sharedMatrix->m24 * matrix.m_sharedMatrix->m32 + m_sharedMatrix->m34 * matrix.m_sharedMatrix->m33 + m_sharedMatrix->m44 * matrix.m_sharedMatrix->m34; T r41 = m_sharedMatrix->m11 * matrix.m_sharedMatrix->m41 + m_sharedMatrix->m21 * matrix.m_sharedMatrix->m42 + m_sharedMatrix->m31 * matrix.m_sharedMatrix->m43 + m_sharedMatrix->m41 * matrix.m_sharedMatrix->m44; T r42 = m_sharedMatrix->m12 * matrix.m_sharedMatrix->m41 + m_sharedMatrix->m22 * matrix.m_sharedMatrix->m42 + m_sharedMatrix->m32 * matrix.m_sharedMatrix->m43 + m_sharedMatrix->m42 * matrix.m_sharedMatrix->m44; T r43 = m_sharedMatrix->m13 * matrix.m_sharedMatrix->m41 + m_sharedMatrix->m23 * matrix.m_sharedMatrix->m42 + m_sharedMatrix->m33 * matrix.m_sharedMatrix->m43 + m_sharedMatrix->m43 * matrix.m_sharedMatrix->m44; T r44 = m_sharedMatrix->m14 * matrix.m_sharedMatrix->m41 + m_sharedMatrix->m24 * matrix.m_sharedMatrix->m42 + m_sharedMatrix->m34 * matrix.m_sharedMatrix->m43 + m_sharedMatrix->m44 * matrix.m_sharedMatrix->m44; // Et puis on affecte Set(r11, r12, r13, r14, r21, r22, r23, r24, r31, r32, r33, r34, r41, r42, r43, r44); return *this; } template NzMatrix4& NzMatrix4::operator*=(T scalar) { #if NAZARA_MATH_SAFE if (!m_sharedMatrix) { NazaraError("Undefined matrix"); return *this; } #endif m_sharedMatrix->m11 *= scalar; m_sharedMatrix->m12 *= scalar; m_sharedMatrix->m13 *= scalar; m_sharedMatrix->m14 *= scalar; m_sharedMatrix->m21 *= scalar; m_sharedMatrix->m22 *= scalar; m_sharedMatrix->m23 *= scalar; m_sharedMatrix->m24 *= scalar; m_sharedMatrix->m31 *= scalar; m_sharedMatrix->m32 *= scalar; m_sharedMatrix->m33 *= scalar; m_sharedMatrix->m34 *= scalar; m_sharedMatrix->m41 *= scalar; m_sharedMatrix->m42 *= scalar; m_sharedMatrix->m43 *= scalar; m_sharedMatrix->m44 *= scalar; return *this; } template NzMatrix4 NzMatrix4::LookAt(const NzVector3& eye, const NzVector3& center, const NzVector3& up) { NzMatrix4 matrix; matrix.SetLookAt(eye, center, up); return matrix; } template NzMatrix4 NzMatrix4::Ortho(T left, T top, T width, T height, T zNear, T zFar) { NzMatrix4 matrix; matrix.SetOrtho(left, top, width, height, zNear, zFar); return matrix; } template NzMatrix4 NzMatrix4::Perspective(T angle, T ratio, T zNear, T zFar) { NzMatrix4 matrix; matrix.SetPerspective(angle, ratio, zNear, zFar); return matrix; } template NzMatrix4 NzMatrix4::Rotate(const NzQuaternion& rotation) { NzMatrix4 matrix; matrix.SetRotation(rotation); return matrix; } template NzMatrix4 NzMatrix4::Scale(const NzVector3& scale) { NzMatrix4 matrix; matrix.SetScale(scale); return matrix; } template NzMatrix4 NzMatrix4::Translate(const NzVector3& translation) { NzMatrix4 mat; mat.SetTranslation(translation); return mat; } template std::ostream& operator<<(std::ostream& out, const NzMatrix4& matrix) { return out << matrix.ToString(); } template void NzMatrix4::EnsureOwnership() { if (m_sharedMatrix) { NazaraLock(m_sharedMatrix->mutex); if (m_sharedMatrix->refCount > 1) { m_sharedMatrix->refCount--; SharedMatrix* sharedMatrix = new SharedMatrix; std::memcpy(&sharedMatrix->m11, &m_sharedMatrix->m11, 16*sizeof(T)); } } else m_sharedMatrix = new SharedMatrix; } template void NzMatrix4::ReleaseMatrix() { if (!m_sharedMatrix) return; NazaraMutexLock(m_sharedMatrix->mutex); m_sharedMatrix->refCount--; NazaraMutexUnlock(m_sharedMatrix->mutex); if (m_sharedMatrix->refCount == 0) delete m_sharedMatrix; m_sharedMatrix = nullptr; } #undef NAZARA_MATRIX4_INL #include