// SSPHH/Fluxions/Unicornfish/Viperfish/Hatchetfish/Sunfish/KASL/GLUT Extensions // Copyright (C) 2017 Jonathan Metzgar // All rights reserved. // // This program is free software : you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program.If not, see . // // For any other type of licensing, please contact me at jmetzgar@outlook.com #ifndef FLUXIONS_MATRIX4_HPP #define FLUXIONS_MATRIX4_HPP #include #include #include #include namespace Fluxions { using namespace std; template class TMatrix4 { public: union { // normal access (column major) struct { T m11, m21, m31, m41; T m12, m22, m32, m42; T m13, m23, m33, m43; T m14, m24, m34, m44; }; // transposed access struct { T t11, t12, t13, t14; T t21, t22, t23, t24; T t31, t32, t33, t34; T t41, t42, t43, t44; }; // 2D array form T mm[4][4]; // array form T m[16]; T v[16]; }; static constexpr size_t size() { return 16; } static constexpr size_t numrows() { return 4; } static constexpr size_t numcols() { return 4; } TMatrix4() noexcept { m11 = 1; m12 = 0; m13 = 0; m14 = 0; m21 = 0; m22 = 1; m23 = 0; m24 = 0; m31 = 0; m32 = 0; m33 = 1; m34 = 0; m41 = 0; m42 = 0; m43 = 0; m44 = 1; } constexpr TMatrix4(const TMatrix4 & M) noexcept { m11 = M.m11; m12 = M.m12; m13 = M.m13; m14 = M.m14; m21 = M.m21; m22 = M.m22; m23 = M.m23; m24 = M.m24; m31 = M.m31; m32 = M.m32; m33 = M.m33; m34 = M.m34; m41 = M.m41; m42 = M.m42; m43 = M.m43; m44 = M.m44; } TMatrix4(TMatrix4 && M) noexcept { m11 = std::move(M.m11); m12 = std::move(M.m12); m13 = std::move(M.m13); m14 = std::move(M.m14); m21 = std::move(M.m21); m22 = std::move(M.m22); m23 = std::move(M.m23); m24 = std::move(M.m24); m31 = std::move(M.m31); m32 = std::move(M.m32); m33 = std::move(M.m33); m34 = std::move(M.m34); m41 = std::move(M.m41); m42 = std::move(M.m42); m43 = std::move(M.m43); m44 = std::move(M.m44); } TMatrix4(const T value) noexcept { m11 = value; m12 = value; m13 = value; m14 = value; m21 = value; m22 = value; m23 = value; m24 = value; m31 = value; m32 = value; m33 = value; m34 = value; m41 = value; m42 = value; m43 = value; m44 = value; } TMatrix4( const T a11, const T a12, const T a13, const T a14, const T a21, const T a22, const T a23, const T a24, const T a31, const T a32, const T a33, const T a34, const T a41, const T a42, const T a43, const T a44) noexcept { m11 = a11; m12 = a12; m13 = a13; m14 = a14; m21 = a21; m22 = a22; m23 = a23; m24 = a24; m31 = a31; m32 = a32; m33 = a33; m34 = a34; m41 = a41; m42 = a42; m43 = a43; m44 = a44; } TMatrix4(const T M[numrows()][numcols()]) noexcept { const T *_v = M[0]; for (auto i = 0; i < size(); i++) { v[i] = _v[i]; } } TMatrix4(const T M[size()]) noexcept { const T *_v = M; for (auto i = 0; i < size(); i++) { v[i] = _v[i]; } } constexpr auto operator = (const TMatrix4 & M) noexcept { m11 = M.m11; m12 = M.m12; m13 = M.m13; m14 = M.m14; m21 = M.m21; m22 = M.m22; m23 = M.m23; m24 = M.m24; m31 = M.m31; m32 = M.m32; m33 = M.m33; m34 = M.m34; m41 = M.m41; m42 = M.m42; m43 = M.m43; m44 = M.m44; return *this; } template constexpr auto operator = (const TMatrix4 & M) noexcept { m11 = static_cast(M.m11); m12 = static_cast(M.m12); m13 = static_cast(M.m13); m14 = static_cast(M.m14); m21 = static_cast(M.m21); m22 = static_cast(M.m22); m23 = static_cast(M.m23); m24 = static_cast(M.m24); m31 = static_cast(M.m31); m32 = static_cast(M.m32); m33 = static_cast(M.m33); m34 = static_cast(M.m34); m41 = static_cast(M.m41); m42 = static_cast(M.m42); m43 = static_cast(M.m43); m44 = static_cast(M.m44); return *this; } //template constexpr TMatrix4 & operator = (const enable_if_t, U> value) noexcept template constexpr TMatrix4 & operator = (const U value) noexcept { m11 = static_cast(value); m12 = static_cast(value); m13 = static_cast(value); m14 = static_cast(value); m21 = static_cast(value); m22 = static_cast(value); m23 = static_cast(value); m24 = static_cast(value); m31 = static_cast(value); m32 = static_cast(value); m33 = static_cast(value); m34 = static_cast(value); m41 = static_cast(value); m42 = static_cast(value); m43 = static_cast(value); m44 = static_cast(value); return *this; } template constexpr operator TMatrix4() const noexcept { return TMatrix4( static_cast(m11), static_cast(m12), static_cast(m13), static_cast(m14), static_cast(m21), static_cast(m22), static_cast(m23), static_cast(m24), static_cast(m31), static_cast(m32), static_cast(m33), static_cast(m34), static_cast(m41), static_cast(m42), static_cast(m43), static_cast(m44) ); } constexpr TVector4 row1() const noexcept { return TVector4(m11, m12, m13, m14); } constexpr TVector4 row2() const noexcept { return TVector4(m21, m22, m23, m24); } constexpr TVector4 row3() const noexcept { return TVector4(m31, m32, m33, m34); } constexpr TVector4 row4() const noexcept { return TVector4(m41, m42, m43, m44); } constexpr TVector4 col1() const noexcept { return TVector4(m11, m21, m31, m41); } constexpr TVector4 col2() const noexcept { return TVector4(m12, m22, m32, m42); } constexpr TVector4 col3() const noexcept { return TVector4(m13, m23, m33, m43); } constexpr TVector4 col4() const noexcept { return TVector4(m14, m24, m34, m44); } // col(i) returns the ith column of the matrix (i = 1 is column 1) constexpr TVector4 col(int i) const noexcept { switch (i) { case 1: return col1(); case 2: return col2(); case 3: return col3(); case 4: return col4(); } return TVector4(); } // row(i) returns the ith row of the matrix (i = 1 is row 1) constexpr TVector4 row(int i) const noexcept { switch (i) { case 1: return row1(); case 2: return row2(); case 3: return row3(); case 4: return row4(); } return TVector4(); } template static constexpr auto compAdd(const TMatrix4 & m1, const TMatrix4 & m2) noexcept { return TMatrix4>( m1.m11 + m2.m11, m1.m12 + m2.m12, m1.m13 + m2.m13, m1.m14 + m2.m14, m1.m21 + m2.m21, m1.m22 + m2.m22, m1.m23 + m2.m23, m1.m24 + m2.m24, m1.m31 + m2.m31, m1.m32 + m2.m32, m1.m33 + m2.m33, m1.m34 + m2.m34, m1.m41 + m2.m41, m1.m42 + m2.m42, m1.m43 + m2.m43, m1.m44 + m2.m44 ); } template static constexpr auto compSub(const TMatrix4 & m1, const TMatrix4 & m2) noexcept { return TMatrix4>( m1.m11 - m2.m11, m1.m12 - m2.m12, m1.m13 - m2.m13, m1.m14 - m2.m14, m1.m21 - m2.m21, m1.m22 - m2.m22, m1.m23 - m2.m23, m1.m24 - m2.m24, m1.m31 - m2.m31, m1.m32 - m2.m32, m1.m33 - m2.m33, m1.m34 - m2.m34, m1.m41 - m2.m41, m1.m42 - m2.m42, m1.m43 - m2.m43, m1.m44 - m2.m44 ); } template static constexpr auto compMult(const TMatrix4 & m1, const TMatrix4 & m2) noexcept { return TMatrix4>( m1.m11 * m2.m11, m1.m12 * m2.m12, m1.m13 * m2.m13, m1.m14 * m2.m14, m1.m21 * m2.m21, m1.m22 * m2.m22, m1.m23 * m2.m23, m1.m24 * m2.m24, m1.m31 * m2.m31, m1.m32 * m2.m32, m1.m33 * m2.m33, m1.m34 * m2.m34, m1.m41 * m2.m41, m1.m42 * m2.m42, m1.m43 * m2.m43, m1.m44 * m2.m44 ); } template static constexpr auto compDiv(const TMatrix4 & m1, const TMatrix4 & m2) noexcept { return TMatrix4>( m1.m11 / m2.m11, m1.m12 / m2.m12, m1.m13 / m2.m13, m1.m14 / m2.m14, m1.m21 / m2.m21, m1.m22 / m2.m22, m1.m23 / m2.m23, m1.m24 / m2.m24, m1.m31 / m2.m31, m1.m32 / m2.m32, m1.m33 / m2.m33, m1.m34 / m2.m34, m1.m41 / m2.m41, m1.m42 / m2.m42, m1.m43 / m2.m43, m1.m44 / m2.m44 ); } template static constexpr auto multiply(const TMatrix4 & m1, const TMatrix4 & m2) noexcept { return TMatrix4>( (m1.m14*m2.m41 + m1.m13*m2.m31 + m1.m12*m2.m21 + m1.m11*m2.m11), (m1.m14*m2.m42 + m1.m13*m2.m32 + m1.m12*m2.m22 + m1.m11*m2.m12), (m1.m14*m2.m43 + m1.m13*m2.m33 + m1.m12*m2.m23 + m1.m11*m2.m13), (m1.m14*m2.m44 + m1.m13*m2.m34 + m1.m12*m2.m24 + m1.m11*m2.m14), (m1.m24*m2.m41 + m1.m23*m2.m31 + m1.m22*m2.m21 + m1.m21*m2.m11), (m1.m24*m2.m42 + m1.m23*m2.m32 + m1.m22*m2.m22 + m1.m21*m2.m12), (m1.m24*m2.m43 + m1.m23*m2.m33 + m1.m22*m2.m23 + m1.m21*m2.m13), (m1.m24*m2.m44 + m1.m23*m2.m34 + m1.m22*m2.m24 + m1.m21*m2.m14), (m1.m34*m2.m41 + m1.m33*m2.m31 + m1.m32*m2.m21 + m1.m31*m2.m11), (m1.m34*m2.m42 + m1.m33*m2.m32 + m1.m32*m2.m22 + m1.m31*m2.m12), (m1.m34*m2.m43 + m1.m33*m2.m33 + m1.m32*m2.m23 + m1.m31*m2.m13), (m1.m34*m2.m44 + m1.m33*m2.m34 + m1.m32*m2.m24 + m1.m31*m2.m14), (m1.m44*m2.m41 + m1.m43*m2.m31 + m1.m42*m2.m21 + m1.m41*m2.m11), (m1.m44*m2.m42 + m1.m43*m2.m32 + m1.m42*m2.m22 + m1.m41*m2.m12), (m1.m44*m2.m43 + m1.m43*m2.m33 + m1.m42*m2.m23 + m1.m41*m2.m13), (m1.m44*m2.m44 + m1.m43*m2.m34 + m1.m42*m2.m24 + m1.m41*m2.m14)); } constexpr auto LoadIdentity() noexcept { return *this = MakeIdentity(); } constexpr auto operator - () noexcept { return TMatrix4( -m11, -m12, -m13, -m14, -m21, -m22, -m23, -m24, -m31, -m32, -m33, -m34, -m41, -m42, -m43, -m44 ); } template constexpr auto operator()(std::function Func) noexcept { return TMatrix4>( Func(m11), Func(m12), Func(m13), Func(m14), Func(m21), Func(m22), Func(m23), Func(m24), Func(m31), Func(m32), Func(m33), Func(m34), Func(m41), Func(m42), Func(m43), Func(m44) ); } template constexpr auto MultMatrix(const TMatrix4 & M) noexcept { return *this = multiply(*this, M); } template constexpr auto operator *= (const TMatrix4 & M) noexcept { return *this = multiply(*this, M); } template constexpr auto operator += (const TMatrix4 & M) noexcept { m11 += M.m11; m12 += M.m12; m13 += M.m13; m14 += M.m14; m21 += M.m21; m22 += M.m22; m23 += M.m23; m24 += M.m24; m31 += M.m31; m32 += M.m32; m33 += M.m33; m34 += M.m34; m41 += M.m41; m42 += M.m42; m43 += M.m43; m44 += M.m44; return *this; } template constexpr auto operator -= (const TMatrix4 & M) noexcept { m11 -= M.m11; m12 -= M.m12; m13 -= M.m13; m14 -= M.m14; m21 -= M.m21; m22 -= M.m22; m23 -= M.m23; m24 -= M.m24; m31 -= M.m31; m32 -= M.m32; m33 -= M.m33; m34 -= M.m34; m41 -= M.m41; m42 -= M.m42; m43 -= M.m43; m44 -= M.m44; return *this; } //template const TMatrix4 operator * (const TMatrix4 & M) const; //template const TMatrix4 operator + (const TMatrix4 & M) const; //template const TMatrix4 operator - (const TMatrix4 & M) const; template constexpr auto operator += (const U c) noexcept { m11 += c; m12 += c; m13 += c; m14 += c; m21 += c; m22 += c; m23 += c; m24 += c; m31 += c; m32 += c; m33 += c; m34 += c; m41 += c; m42 += c; m43 += c; m44 += c; return *this; } template constexpr auto operator -= (const U c) noexcept { m11 -= c; m12 -= c; m13 -= c; m14 -= c; m21 -= c; m22 -= c; m23 -= c; m24 -= c; m31 -= c; m32 -= c; m33 -= c; m34 -= c; m41 -= c; m42 -= c; m43 -= c; m44 -= c; return *this; } template constexpr auto operator *= (const U c) noexcept { m11 *= c; m12 *= c; m13 *= c; m14 *= c; m21 *= c; m22 *= c; m23 *= c; m24 *= c; m31 *= c; m32 *= c; m33 *= c; m34 *= c; m41 *= c; m42 *= c; m43 *= c; m44 *= c; return *this; } template constexpr auto operator /= (const U c) noexcept { m11 /= c; m12 /= c; m13 /= c; m14 /= c; m21 /= c; m22 /= c; m23 /= c; m24 /= c; m31 /= c; m32 /= c; m33 /= c; m34 /= c; m41 /= c; m42 /= c; m43 /= c; m44 /= c; return *this; } template constexpr auto Rotate(U angleInDegrees, U x, U y, U z) noexcept { return *this *= MakeRotation((T)angleInDegrees, (T)x, (T)y, (T)z); } template constexpr auto Scale(U x, U y, U z) noexcept { return *this *= MakeScaling((T)x, (T)y, (T)z); } template constexpr auto Translate(U x, U y, U z) noexcept { return *this *= MakeTranslation((T)x, (T)y, (T)z); } template constexpr auto Ortho(U left, U right, U bottom, U top, U near_value, U far_value) noexcept { return *this *= MakeOrtho((T)left, (T)right, (T)bottom, (T)top, (T)near_value, (T)far_value); } template constexpr auto Ortho2D(U left, U right, U bottom, U top) noexcept { return *this *= MakeOrtho2D((T)left, (T)right, (T)bottom, (T)top); } template constexpr auto Frustum(U left, U right, U bottom, U top, U near_value, U far_value) noexcept { return *this *= MakeFrustum((T)left, (T)right, (T)bottom, (T)top, (T)near_value, (T)far_value); } template constexpr auto Perspective(U angleInDegrees, U aspect, U near_value, U far_value) noexcept { return *this *= MakePerspective((T)angleInDegrees, (T)aspect, (T)near_value, (T)far_value); } template constexpr auto PerspectiveX(U angleInDegrees, U aspect, U near_value, U far_value) noexcept { return *this *= MakePerspectiveX((T)angleInDegrees, (T)aspect, (T)near_value, (T)far_value); } template constexpr auto PerspectiveY(U angleInDegrees, U aspect, U near_value, U far_value) noexcept { return *this *= MakePerspectiveY((T)angleInDegrees, (T)aspect, (T)near_value, (T)far_value); } template constexpr auto LookAt(TVector3 eye, TVector3 center, TVector3 up) noexcept { return *this *= MakeLookAt((TVector3)eye, (TVector3)center, (TVector3)up); } constexpr auto ShadowBias() noexcept { return *this *= MakeShadowBias(); } constexpr auto CubeMatrix(int face) noexcept { return *this *= MakeCubeMatrix(face); } constexpr auto CubeMatrixPosition(int face, const TVector3 & position) noexcept { return *this *= MakeCubeMatrixPosition(face, position); } constexpr auto AsTranspose() const noexcept { return TMatrix4( t11, t12, t13, t14, t21, t22, t23, t24, t31, t32, t33, t34, t41, t42, t43, t44 ); } constexpr auto Transpose() noexcept { return *this = AsTranspose(); } constexpr auto AsAdjugate() const noexcept { T t1 = m32 * m43 - m33 * m42; T t2 = m32 * m44 - m34 * m42; T t3 = m33 * m44 - m34 * m43; T t4 = m22 * m43 - m23 * m42; T t5 = m22 * m44 - m24 * m42; T t6 = m23 * m44 - m24 * m43; T t7 = m22 * m33 - m23 * m32; T t8 = m22 * m34 - m24 * m32; T t9 = m23 * m34 - m24 * m33; T t10 = m31 * m43 - m33 * m41; T t11 = m31 * m44 - m34 * m41; T t12 = m21 * m43 - m23 * m41; T t13 = m21 * m44 - m24 * m41; T t14 = m21 * m33 - m23 * m31; T t15 = m21 * m34 - m24 * m31; T t16 = m31 * m42 - m32 * m41; T t17 = m21 * m42 - m22 * m41; T t18 = m21 * m32 - m22 * m31; return TMatrix4(m22 * t3 - m23 * t2 + m24 * t1, -m12 * t3 + m13 * t2 - m14 * t1, m12 * t6 - m13 * t5 + m14 * t4, -m12 * t9 + m13 * t8 - m14 * t7, -m21 * t3 + m23 * t11 - m24 * t10, m11 * t3 - m13 * t11 + m14 * t10, -m11 * t6 + m13 * t13 - m14 * t12, m11 * t9 - m13 * t15 + m14 * t14, m21 * t2 - m22 * t11 + m24 * t16, -m11 * t2 + m12 * t11 - m14 * t16, m11 * t5 - m12 * t13 + m14 * t17, -m11 * t8 + m12 * t15 - m14 * t18, -m21 * t1 + m22 * t10 - m23 * t16, m11 * t1 - m12 * t10 + m13 * t16, -m11 * t4 + m12 * t12 - m13 * t17, m11 * t7 - m12 * t14 + m13 * t18); } constexpr auto Adjugate() noexcept { return *this = AsAdjugate(); } constexpr auto AsQuickInverse() const noexcept { return TMatrix4( t11, t12, t13, -m14, t21, t22, t23, -m24, t31, t32, t33, -m34, T(0), T(0), T(0), T(1) ); } constexpr auto QuickInvert() noexcept { if (Invertible()) return *this = AsQuickInverse(); return *this = MakeZero(); } constexpr auto AsInverse() const noexcept { T t1 = m32 * m43 - m33 * m42; T t2 = m32 * m44 - m34 * m42; T t3 = m33 * m44 - m34 * m43; T t4 = m22 * t3 - m23 * t2 + m24 * t1; T t5 = m31 * m42 - m32 * m41; T t6 = m31 * m43 - m33 * m41; T t7 = -m21 * t1 + m22 * t6 - m23 * t5; T t8 = m31 * m44 - m34 * m41; T t9 = m21 * t2 - m22 * t8 + m24 * t5; T t10 = -m21 * t3 + m23 * t8 - m24 * t6; T t11 = static_cast(1.0 / (m11 * t4 + m12 * t10 + m13 * t9 + m14 * t7)); T t12 = m22 * m43 - m23 * m42; T t13 = m22 * m44 - m24 * m42; T t14 = m23 * m44 - m24 * m43; T t15 = m22 * m33 - m23 * m32; T t16 = m22 * m34 - m24 * m32; T t17 = m23 * m34 - m24 * m33; T t18 = m21 * m43 - m23 * m41; T t19 = m21 * m44 - m24 * m41; T t20 = m21 * m33 - m23 * m31; T t21 = m21 * m34 - m24 * m31; T t22 = m21 * m42 - m22 * m41; T t23 = m21 * m32 - m22 * m31; return TMatrix4( t4 * t11, (-m12 * t3 + m13 * t2 - m14 * t1) * t11, (m12 * t14 - m13 * t13 + m14 * t12) * t11, (-m12 * t17 + m13 * t16 - m14 * t15) * t11, t10 * t11, (m11 * t3 - m13 * t8 + m14 * t6) * t11, (-m11 * t14 + m13 * t19 - m14 * t18) * t11, (m11 * t17 - m13 * t21 + m14 * t20) * t11, t9 * t11, (-m11 * t2 + m12 * t8 - m14 * t5) * t11, (m11 * t13 - m12 * t19 + m14 * t22) * t11, (-m11 * t16 + m12 * t21 - m14 * t23) * t11, t7 * t11, (m11 * t1 - m12 * t6 + m13 * t5) * t11, (-m11 * t12 + m12 * t18 - m13 * t22) * t11, (m11 * t15 - m12 * t20 + m13 * t23) * t11 ); } constexpr auto Invert() noexcept { if (Invertible()) return *this = AsInverse(); return *this = MakeZero(); } constexpr bool Invertible() const noexcept { return Determinant() != 0; } constexpr T Determinant() const noexcept { T t1 = m31 * m42 - m32 * m41; T t2 = m31 * m43 - m33 * m41; T t3 = m32 * m43 - m33 * m42; T t4 = m31 * m44 - m34 * m41; T t5 = m32 * m44 - m34 * m42; T t6 = m33 * m44 - m34 * m43; return m11 * (m22 * t6 - m23 * t5 + m24 * t3) - m12 * (m21 * t6 - m23 * t4 + m24 * t2) + m13 * (m21 * t5 - m22 * t4 + m24 * t1) - m14 * (m21 * t3 - m22 * t2 + m23 * t1); } /////////////////////////////////////////////////////////////// // S T A T I C M E M B E R S //////////////////////////////// /////////////////////////////////////////////////////////////// static constexpr auto MakeIdentity() noexcept { return TMatrix4( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ); } static constexpr auto MakeZero() noexcept { return TMatrix4( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); } static constexpr auto MakeRotation(T angleInDegrees, T x, T y, T z) noexcept { T angleInRadians = static_cast(angleInDegrees * FX_DEGREES_TO_RADIANS); T c = cos(angleInRadians); T s = sin(angleInRadians); T invLength = (T)(1.0 / sqrt(x*x + y*y + z*z)); x *= invLength; y *= invLength; z *= invLength; return TMatrix4( x * x * (1 - c) + c, x * y * (1 - c) - z * s, x * z * (1 - c) + y * s, 0.0, y * x * (1 - c) + z * s, y * y * (1 - c) + c, y * z * (1 - c) - x * s, 0.0, x * z * (1 - c) - y * s, y * z * (1 - c) + x * s, z * z * (1 - c) + c, 0.0, 0.0, 0.0, 0.0, 1.0 ); } static constexpr auto MakeScaling(T x, T y, T z) noexcept { return TMatrix4( x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1 ); } static constexpr auto MakeTranslation(T x, T y, T z) noexcept { return TMatrix4( 1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1 ); } static constexpr auto MakeOrtho(T left, T right, T bottom, T top, T near_value, T far_value) noexcept { T tx = -(right + left) / (right - left); T ty = -(top + bottom) / (top - bottom); T tz = -(far_value + near_value) / (far_value - near_value); return TMatrix4( 2 / (right - left), 0, 0, tx, 0, 2 / (top - bottom), 0, ty, 0, 0, -2 / (far_value - near_value), tz, 0, 0, 0, 1 ); } static constexpr auto MakeOrtho2D(T left, T right, T bottom, T top) noexcept { T tx = -(right + left) / (right - left); T ty = -(top + bottom) / (top - bottom); return TMatrix4( 2 / (right - left), 0, 0, tx, 0, 2 / (top - bottom), 0, ty, 0, 0, -1, 0, 0, 0, 0, 1 ); } static constexpr auto MakeFrustum(T left, T right, T bottom, T top, T near_value, T far_value) noexcept { T A = (right + left) / (right - left); T B = (top + bottom) / (top - bottom); T C = -(far_value + near_value) / (far_value - near_value); T D = -2 * far_value * near_value / (far_value - near_value); return TMatrix4( 2 * near_value / (right - left), 0, A, 0, 0, 2 * near_value / (top - bottom), B, 0, 0, 0, C, D, 0, 0, -1, 0 ); } static constexpr auto MakePerspective(T angleInDegrees, T aspect, T near_value, T far_value) noexcept { T f = static_cast(1.0 / std::tan(FX_DEGREES_TO_RADIANS * 0.5 * angleInDegrees)); return TMatrix4( f / aspect, 0, 0, 0, 0, f, 0, 0, 0, 0, (far_value + near_value) / (near_value - far_value), 2 * far_value * near_value / (near_value - far_value), 0, 0, -1, 0 ); } static constexpr auto MakePerspectiveX(T angleInDegrees, T aspect, T near_value, T far_value) noexcept { T f = static_cast(1.0 / std::tan(FX_DEGREES_TO_RADIANS * 0.5 * angleInDegrees)); return TMatrix4( f / aspect, 0, 0, 0, 0, f, 0, 0, 0, 0, (far_value + near_value) / (near_value - far_value), 2 * far_value * near_value / (near_value - far_value), 0, 0, -1, 0 ); } static constexpr auto MakePerspectiveY(T angleInDegrees, T aspect, T near_value, T far_value) noexcept { T f = static_cast(1.0 / std::tan(FX_DEGREES_TO_RADIANS * 0.5 * angleInDegrees)); return TMatrix4( f, 0, 0, 0, 0, f * aspect, 0, 0, 0, 0, (far_value + near_value) / (near_value - far_value), 2 * far_value * near_value / (near_value - far_value), 0, 0, -1, 0 ); } static constexpr auto MakeLookAt(TVector3 eye, TVector3 center, TVector3 up) noexcept { TVector3 F = (center - eye).norm(); TVector3 S = F.cross(up).norm(); TVector3 U = S.cross(F).norm(); return TMatrix4::multiply(TMatrix4( S.x, S.y, S.z, 0.0, U.x, U.y, U.z, 0.0, -F.x, -F.y, -F.z, 0.0, 0.0, 0.0, 0.0, 1.0), TMatrix4::MakeTranslation(-eye.x, -eye.y, -eye.z)); } static constexpr auto MakeShadowBias() noexcept { return TMatrix4( 0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0 ); } static constexpr auto MakeCubeMatrix(int face) noexcept { // support GL_TEXTURE_CUBE_MAP_POSITIVE_X, ... constants if (face >= 0x8515 && face <= 0x851A) face -= 0x8515; switch (face) { case 0: // GL_TEXTURE_CUBE_MAP_POSITIVE_X return TMatrix4::MakeRotation(90.0, 0.0, 1.0, 0.0); break; case 1: // GL_TEXTURE_CUBE_MAP_NEGATIVE_X return TMatrix4::MakeRotation(270.0, 0.0, 1.0, 0.0); break; case 2: // GL_TEXTURE_CUBE_MAP_POSITIVE_Y return TMatrix4::MakeRotation(270.0, 1.0, 0.0, 0.0); break; case 3: // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y return TMatrix4::MakeRotation(90.0, 1.0, 0.0, 0.0); break; case 4: // GL_TEXTURE_CUBE_MAP_POSITIVE_Z return TMatrix4::MakeIdentity(); break; case 5: // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z return TMatrix4::MakeRotation(180.0, 0.0, 1.0, 0.0); break; } return TMatrix4::MakeIdentity(); } static constexpr TMatrix4 MakeCubeMatrixPosition(int face, const TVector3 & position) noexcept { // support GL_TEXTURE_CUBE_MAP_POSITIVE_X, ... constants if (face >= 0x8515 && face <= 0x851A) face -= 0x8515; switch (face) { case 0: // GL_TEXTURE_CUBE_MAP_POSITIVE_X return TMatrix4::MakeLookAt(position, position + TVector3(1, 0, 0), TVector3(0, -1, 0)); break; case 1: // GL_TEXTURE_CUBE_MAP_NEGATIVE_X return TMatrix4::MakeLookAt(position, position + TVector3(-1, 0, 0), TVector3(0, -1, 0)); break; case 2: // GL_TEXTURE_CUBE_MAP_POSITIVE_Y return TMatrix4::MakeLookAt(position, position + TVector3(0, 1, 0), TVector3(0, 0, 1)); break; case 3: // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y return TMatrix4::MakeLookAt(position, position + TVector3(0, -1, 0), TVector3(0, 0, -1)); break; case 4: // GL_TEXTURE_CUBE_MAP_POSITIVE_Z return TMatrix4::MakeLookAt(position, position + TVector3(0, 0, 1), TVector3(0, -1, 0)); break; case 5: // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z return TMatrix4::MakeLookAt(position, position + TVector3(0, 0, -1), TVector3(0, -1, 0)); break; } return TMatrix4::MakeIdentity(); } }; ////////////////////////////////////////////////////////////////// // I M P L E M E N T A T I O N /////////////////////////////////// ////////////////////////////////////////////////////////////////// //template //TMatrix4::TMatrix4() //{ // m11 = 1; m12 = 0; m13 = 0; m14 = 0; // m21 = 0; m22 = 1; m23 = 0; m24 = 0; // m31 = 0; m32 = 0; m33 = 1; m34 = 0; // m41 = 0; m42 = 0; m43 = 0; m44 = 1; //} // //template //TMatrix4::TMatrix4( // const T a11, const T a12, const T a13, const T a14, // const T a21, const T a22, const T a23, const T a24, // const T a31, const T a32, const T a33, const T a34, // const T a41, const T a42, const T a43, const T a44 // ) //{ // m11 = a11; m12 = a12; m13 = a13; m14 = a14; // m21 = a21; m22 = a22; m23 = a23; m24 = a24; // m31 = a31; m32 = a32; m33 = a33; m34 = a34; // m41 = a41; m42 = a42; m43 = a43; m44 = a44; //} //template //TMatrix4::TMatrix4(const TMatrix4 & M) //{ // m11 = M.m11; m12 = M.m12; m13 = M.m13; m14 = M.m14; // m21 = M.m21; m22 = M.m22; m23 = M.m23; m24 = M.m24; // m31 = M.m31; m32 = M.m32; m33 = M.m33; m34 = M.m34; // m41 = M.m41; m42 = M.m42; m43 = M.m43; m44 = M.m44; //} // //template //TMatrix4::TMatrix4(const T M[4][4]) //{ // for (int i = 0; i < 4; i++) // { // for (int j = 0; j < 4; j++) // { // mm[i][j] = M[j][i]; // } // } //} // //template //TMatrix4::TMatrix4(const T M[16]) //{ // for (int i = 0; i < 16; i++) // { // m[i] = M[i]; // } //} // //template //template //const TMatrix4 & TMatrix4::operator = (const TMatrix4 & M) //{ // m11 = T(M.m11); m12 = T(M.m12); m13 = T(M.m13); m14 = T(M.m14); // m21 = T(M.m21); m22 = T(M.m22); m23 = T(M.m23); m24 = T(M.m24); // m31 = T(M.m31); m32 = T(M.m32); m33 = T(M.m33); m34 = T(M.m34); // m41 = T(M.m41); m42 = T(M.m42); m43 = T(M.m43); m44 = T(M.m44); // return *this; //} // //template //const TMatrix4 & TMatrix4::LoadIdentity() //{ // m11 = 1; m12 = 0; m13 = 0; m14 = 0; // m21 = 0; m22 = 1; m23 = 0; m24 = 0; // m31 = 0; m32 = 0; m33 = 1; m34 = 0; // m41 = 0; m42 = 0; m43 = 0; m44 = 1; // return *this; //} //template //template //const TMatrix4 TMatrix4::multiply(const TMatrix4 &M) const //{ // return TMatrix4( // (T)(m14*M.m41 + m13*M.m31 + m12*M.m21 + m11*M.m11), // (T)(m14*M.m42 + m13*M.m32 + m12*M.m22 + m11*M.m12), // (T)(m14*M.m43 + m13*M.m33 + m12*M.m23 + m11*M.m13), // (T)(m14*M.m44 + m13*M.m34 + m12*M.m24 + m11*M.m14), // (T)(m24*M.m41 + m23*M.m31 + m22*M.m21 + m21*M.m11), // (T)(m24*M.m42 + m23*M.m32 + m22*M.m22 + m21*M.m12), // (T)(m24*M.m43 + m23*M.m33 + m22*M.m23 + m21*M.m13), // (T)(m24*M.m44 + m23*M.m34 + m22*M.m24 + m21*M.m14), // (T)(m34*M.m41 + m33*M.m31 + m32*M.m21 + m31*M.m11), // (T)(m34*M.m42 + m33*M.m32 + m32*M.m22 + m31*M.m12), // (T)(m34*M.m43 + m33*M.m33 + m32*M.m23 + m31*M.m13), // (T)(m34*M.m44 + m33*M.m34 + m32*M.m24 + m31*M.m14), // (T)(m44*M.m41 + m43*M.m31 + m42*M.m21 + m41*M.m11), // (T)(m44*M.m42 + m43*M.m32 + m42*M.m22 + m41*M.m12), // (T)(m44*M.m43 + m43*M.m33 + m42*M.m23 + m41*M.m13), // (T)(m44*M.m44 + m43*M.m34 + m42*M.m24 + m41*M.m14)); //} //template //template //const TMatrix4 TMatrix4::compMult(const TMatrix4 &m) const //{ // return TMatrix4( // m11 * m.m11, m12 * m.m12, m13 * m.m13, m14 * m.m14, // m21 * m.m21, m22 * m.m22, m23 * m.m23, m24 * m.m24, // m31 * m.m31, m32 * m.m32, m33 * m.m33, m34 * m.m34, // m41 * m.m41, m42 * m.m42, m43 * m.m43, m44 * m.m44 // ); //} //template //template //inline TMatrix4 TMatrix4::multiply(TMatrix4 m1, TMatrix4 m2) //{ // return TMatrix4( // (T)(m1.m14*m2.m41 + m1.m13*m2.m31 + m1.m12*m2.m21 + m1.m11*m2.m11), // (T)(m1.m14*m2.m42 + m1.m13*m2.m32 + m1.m12*m2.m22 + m1.m11*m2.m12), // (T)(m1.m14*m2.m43 + m1.m13*m2.m33 + m1.m12*m2.m23 + m1.m11*m2.m13), // (T)(m1.m14*m2.m44 + m1.m13*m2.m34 + m1.m12*m2.m24 + m1.m11*m2.m14), // (T)(m1.m24*m2.m41 + m1.m23*m2.m31 + m1.m22*m2.m21 + m1.m21*m2.m11), // (T)(m1.m24*m2.m42 + m1.m23*m2.m32 + m1.m22*m2.m22 + m1.m21*m2.m12), // (T)(m1.m24*m2.m43 + m1.m23*m2.m33 + m1.m22*m2.m23 + m1.m21*m2.m13), // (T)(m1.m24*m2.m44 + m1.m23*m2.m34 + m1.m22*m2.m24 + m1.m21*m2.m14), // (T)(m1.m34*m2.m41 + m1.m33*m2.m31 + m1.m32*m2.m21 + m1.m31*m2.m11), // (T)(m1.m34*m2.m42 + m1.m33*m2.m32 + m1.m32*m2.m22 + m1.m31*m2.m12), // (T)(m1.m34*m2.m43 + m1.m33*m2.m33 + m1.m32*m2.m23 + m1.m31*m2.m13), // (T)(m1.m34*m2.m44 + m1.m33*m2.m34 + m1.m32*m2.m24 + m1.m31*m2.m14), // (T)(m1.m44*m2.m41 + m1.m43*m2.m31 + m1.m42*m2.m21 + m1.m41*m2.m11), // (T)(m1.m44*m2.m42 + m1.m43*m2.m32 + m1.m42*m2.m22 + m1.m41*m2.m12), // (T)(m1.m44*m2.m43 + m1.m43*m2.m33 + m1.m42*m2.m23 + m1.m41*m2.m13), // (T)(m1.m44*m2.m44 + m1.m43*m2.m34 + m1.m42*m2.m24 + m1.m41*m2.m14)); //} // //template //template //const TMatrix4 & TMatrix4::MultMatrix(const TMatrix4 & M) //{ // return *this = multiply(M); //} // //template //template //const TMatrix4 & TMatrix4::operator *= (const TMatrix4 & M) //{ // return *this = multiply(M); //} // //template //template //const TMatrix4 & TMatrix4::operator += (const TMatrix4 & M) //{ // m11 += M.m11; m12 += M.m12; m13 += M.m13; m14 += M.m14; // m21 += M.m21; m22 += M.m22; m23 += M.m23; m24 += M.m24; // m31 += M.m31; m32 += M.m32; m33 += M.m33; m34 += M.m34; // m41 += M.m41; m42 += M.m42; m43 += M.m43; m44 += M.m44; // return *this; //} // //template //template //const TMatrix4 & TMatrix4::operator -= (const TMatrix4 & M) //{ // m11 -= M.m11; m12 -= M.m12; m13 -= M.m13; m14 -= M.m14; // m21 -= M.m21; m22 -= M.m22; m23 -= M.m23; m24 -= M.m24; // m31 -= M.m31; m32 -= M.m32; m33 -= M.m33; m34 -= M.m34; // m41 -= M.m41; m42 -= M.m42; m43 -= M.m43; m44 -= M.m44; // return *this; //} //template //template //const TMatrix4 TMatrix4::operator * (const TMatrix4 & M) const //{ // return multiply(M); //} // //template //template //const TMatrix4 TMatrix4::operator + (const TMatrix4 & M) const //{ // return TMatrix4( // m11 + M.m11, m12 + M.m12, m13 + M.m13, m14 + M.m14, // m21 + M.m21, m22 + M.m22, m23 + M.m23, m24 + M.m24, // m31 + M.m31, m32 + M.m32, m33 + M.m33, m34 + M.m34, // m41 + M.m41, m42 + M.m42, m43 + M.m43, m44 + M.m44 // ); //} // //template //template //const TMatrix4 TMatrix4::operator - (const TMatrix4 & M) const //{ // return TMatrix4( // m11 - M.m11, m12 - M.m12, m13 - M.m13, m14 - M.m14, // m21 - M.m21, m22 - M.m22, m23 - M.m23, m24 - M.m24, // m31 - M.m31, m32 - M.m32, m33 - M.m33, m34 - M.m34, // m41 - M.m41, m42 - M.m42, m43 - M.m43, m44 - M.m44 // ); //} // //template //template //const TMatrix4 & TMatrix4::operator *= (const U X) //{ // for (int i = 0; i < 16; i++) // m[i] *= X; // return *this; //} // //template //template //const TMatrix4 & TMatrix4::operator /= (const U X) //{ // for (int i = 0; i < 16; i++) // m[i] /= X; // return *this; //} //template //const TMatrix4 & TMatrix4::Rotate(double angleInDegrees, double X, double y, double z) //{ // return MultMatrix(TMatrix4::MakeRotation(angleInDegrees, X, y, z)); //} //template //const TMatrix4 & TMatrix4::Scale(double X, double y, double z) //{ // return MultMatrix(TMatrix4::MakeScaling(X, y, z)); //} // //template //const TMatrix4 & TMatrix4::Translate(double X, double y, double z) //{ // return MultMatrix(TMatrix4::MakeTranslation(X, y, z)); //} // //template //const TMatrix4 & TMatrix4::Ortho(double left, double right, double bottom, double top, double near_value, double far_value) //{ // return MultMatrix(TMatrix4::MakeOrtho(left, right, bottom, top, near_value, far_value)); //} // //template //const TMatrix4 & TMatrix4::Ortho2D(double left, double right, double bottom, double top) //{ // return MultMatrix(TMatrix4::MakeOrtho2D(left, right, bottom, top)); //} // //template //const TMatrix4 & TMatrix4::Frustum(double left, double right, double bottom, double top, double near_value, double far_value) //{ // return MultMatrix(TMatrix4::MakeFrustum(left, right, bottom, top, near_value, far_value)); //} // //template //const TMatrix4 & TMatrix4::Perspective(double angleInDegrees, double aspect, double near_value, double far_value) //{ // return MultMatrix(TMatrix4::MakePerspective(angleInDegrees, aspect, near_value, far_value)); //} //template //const TMatrix4 & TMatrix4::PerspectiveX(double angleInDegrees, double aspect, double near_value, double far_value) //{ // return MultMatrix(TMatrix4::MakePerspectiveX(angleInDegrees, aspect, near_value, far_value)); //} //template //const TMatrix4 & TMatrix4::PerspectiveY(double angleInDegrees, double aspect, double near_value, double far_value) //{ // return MultMatrix(TMatrix4::MakePerspectiveY(angleInDegrees, aspect, near_value, far_value)); //} //template //const TMatrix4 &TMatrix4::LookAt(TVector3 eye, TVector3 center, TVector3 up) //{ // return MultMatrix(TMatrix4::MakeLookAt(eye, center, up)); //} //template //const TMatrix4 & TMatrix4::ShadowBias() //{ // return MultMatrix(TMatrix4::MakeShadowBias()); //} //template //const TMatrix4 &TMatrix4::CubeMatrix(int face) //{ // return MultMatrix(TMatrix4::MakeCubeMatrix(face)); //} //template //inline TMatrix4 & TMatrix4::Transpose() //{ // return *this = AsTranspose(); //} //template //TMatrix4 TMatrix4::AsTranspose() const //{ // return TMatrix4( // t11, t12, t13, t14, // t21, t22, t23, t24, // t31, t32, t33, t34, // t41, t42, t43, t44 // ); //} //template //T TMatrix4::Determinant() const //{ // T t1 = m31 * m42 - m32 * m41; // T t2 = m31 * m43 - m33 * m41; // T t3 = m32 * m43 - m33 * m42; // T t4 = m31 * m44 - m34 * m41; // T t5 = m32 * m44 - m34 * m42; // T t6 = m33 * m44 - m34 * m43; // return // m11 * (m22 * t6 - m23 * t5 + m24 * t3) - // m12 * (m21 * t6 - m23 * t4 + m24 * t2) + // m13 * (m21 * t5 - m22 * t4 + m24 * t1) - // m14 * (m21 * t3 - m22 * t2 + m23 * t1); //} //template //TMatrix4 TMatrix4::AsAdjugate() const //{ // T t1 = m32 * m43 - m33 * m42; // T t2 = m32 * m44 - m34 * m42; // T t3 = m33 * m44 - m34 * m43; // T t4 = m22 * m43 - m23 * m42; // T t5 = m22 * m44 - m24 * m42; // T t6 = m23 * m44 - m24 * m43; // T t7 = m22 * m33 - m23 * m32; // T t8 = m22 * m34 - m24 * m32; // T t9 = m23 * m34 - m24 * m33; // T t10 = m31 * m43 - m33 * m41; // T t11 = m31 * m44 - m34 * m41; // T t12 = m21 * m43 - m23 * m41; // T t13 = m21 * m44 - m24 * m41; // T t14 = m21 * m33 - m23 * m31; // T t15 = m21 * m34 - m24 * m31; // T t16 = m31 * m42 - m32 * m41; // T t17 = m21 * m42 - m22 * m41; // T t18 = m21 * m32 - m22 * m31; // return TMatrix4(m22 * t3 - m23 * t2 + m24 * t1, // -m12 * t3 + m13 * t2 - m14 * t1, // m12 * t6 - m13 * t5 + m14 * t4, // -m12 * t9 + m13 * t8 - m14 * t7, // -m21 * t3 + m23 * t11 - m24 * t10, // m11 * t3 - m13 * t11 + m14 * t10, // -m11 * t6 + m13 * t13 - m14 * t12, // m11 * t9 - m13 * t15 + m14 * t14, // m21 * t2 - m22 * t11 + m24 * t16, // -m11 * t2 + m12 * t11 - m14 * t16, // m11 * t5 - m12 * t13 + m14 * t17, // -m11 * t8 + m12 * t15 - m14 * t18, // -m21 * t1 + m22 * t10 - m23 * t16, // m11 * t1 - m12 * t10 + m13 * t16, // -m11 * t4 + m12 * t12 - m13 * t17, // m11 * t7 - m12 * t14 + m13 * t18); //} // //template //TMatrix4 & TMatrix4::Adjugate() //{ // return *this = AsAdjugate(); //} // //template //bool TMatrix4::Invert() //{ // T det; // // det = Determinant(); // if (det == 0) // return false; // *this = AsInverse(); // return true; //} ////template ////TMatrix4 TMatrix4::QuickInverse() const ////{ //// return TMatrix4( //// t11, t12, t13, -m14, //// t21, t22, t23, -m24, //// t31, t32, t33, -m34, //// T(0), T(0), T(0), T(1) //// ); ////} ////template ////void TMatrix4::QuickInvert() ////{ //// *this = QuickInverse(); ////} //template //TMatrix4 TMatrix4::AsInverse() const //{ // double t1 = m32 * m43 - m33 * m42; // double t2 = m32 * m44 - m34 * m42; // double t3 = m33 * m44 - m34 * m43; // double t4 = m22 * t3 - m23 * t2 + m24 * t1; // double t5 = m31 * m42 - m32 * m41; // double t6 = m31 * m43 - m33 * m41; // double t7 = -m21 * t1 + m22 * t6 - m23 * t5; // double t8 = m31 * m44 - m34 * m41; // double t9 = m21 * t2 - m22 * t8 + m24 * t5; // double t10 = -m21 * t3 + m23 * t8 - m24 * t6; // double t11 = 1.0 / (m11 * t4 + m12 * t10 + m13 * t9 + m14 * t7); // double t12 = m22 * m43 - m23 * m42; // double t13 = m22 * m44 - m24 * m42; // double t14 = m23 * m44 - m24 * m43; // double t15 = m22 * m33 - m23 * m32; // double t16 = m22 * m34 - m24 * m32; // double t17 = m23 * m34 - m24 * m33; // double t18 = m21 * m43 - m23 * m41; // double t19 = m21 * m44 - m24 * m41; // double t20 = m21 * m33 - m23 * m31; // double t21 = m21 * m34 - m24 * m31; // double t22 = m21 * m42 - m22 * m41; // double t23 = m21 * m32 - m22 * m31; // return TMatrix4( // t4 * t11, // (-m12 * t3 + m13 * t2 - m14 * t1) * t11, // (m12 * t14 - m13 * t13 + m14 * t12) * t11, // (-m12 * t17 + m13 * t16 - m14 * t15) * t11, // t10 * t11, // (m11 * t3 - m13 * t8 + m14 * t6) * t11, // (-m11 * t14 + m13 * t19 - m14 * t18) * t11, // (m11 * t17 - m13 * t21 + m14 * t20) * t11, // t9 * t11, // (-m11 * t2 + m12 * t8 - m14 * t5) * t11, // (m11 * t13 - m12 * t19 + m14 * t22) * t11, // (-m11 * t16 + m12 * t21 - m14 * t23) * t11, // t7 * t11, // (m11 * t1 - m12 * t6 + m13 * t5) * t11, // (-m11 * t12 + m12 * t18 - m13 * t22) * t11, // (m11 * t15 - m12 * t20 + m13 * t23) * t11 // ); //} //template //TMatrix4 TMatrix4::makeRotation(double angleInDegrees, double X, double y, double z) //{ // double angleInRadians = angleInDegrees * FX_DEGREES_TO_RADIANS; // double c = cos(angleInRadians); // double s = sin(angleInRadians); // double invLength = 1.0 / sqrt(X*X + y*y + z*z); // X *= invLength; // y *= invLength; // z *= invLength; // return TMatrix4( // X * X * (1 - c) + c, X * y * (1 - c) - z * s, X * z * (1 - c) + y * s, 0.0, // y * X * (1 - c) + z * s, y * y * (1 - c) + c, y * z * (1 - c) - X * s, 0.0, // X * z * (1 - c) - y * s, y * z * (1 - c) + X * s, z * z * (1 - c) + c, 0.0, // 0.0, 0.0, 0.0, 1.0 // ); //} //template //TMatrix4 TMatrix4::makeScale(double X, double y, double z) //{ // return TMatrix4( // X, 0.0, 0.0, 0.0, // 0.0, y, 1.0, 0.0, // 0.0, 0.0, z, 0.0, // 0.0, 0.0, 0.0, 1.0 // ); //} //template //TMatrix4 TMatrix4::makeTranslation(double X, double y, double z) //{ // return TMatrix4( // 0.0, 0.0, 0.0, X, // 0.0, 0.0, 1.0, y, // 0.0, 0.0, 0.0, z, // 0.0, 0.0, 0.0, 1.0 // ); //} //template //inline TMatrix4 TMatrix4::MakeRotation(double angleInDegrees, double X, double y, double z) //{ // double angleInRadians = angleInDegrees * FX_DEGREES_TO_RADIANS; // double c = cos(angleInRadians); // double s = sin(angleInRadians); // double invLength = 1.0 / sqrt(X*X + y*y + z*z); // X *= invLength; // y *= invLength; // z *= invLength; // return TMatrix4( // X * X * (1 - c) + c, X * y * (1 - c) - z * s, X * z * (1 - c) + y * s, 0.0, // y * X * (1 - c) + z * s, y * y * (1 - c) + c, y * z * (1 - c) - X * s, 0.0, // X * z * (1 - c) - y * s, y * z * (1 - c) + X * s, z * z * (1 - c) + c, 0.0, // 0.0, 0.0, 0.0, 1.0 // ); //} //template //inline TMatrix4 TMatrix4::MakeScaling(double X, double y, double z) //{ // return TMatrix4( // X, 0, 0, 0, // 0, y, 0, 0, // 0, 0, z, 0, // 0, 0, 0, 1 // ); //} //template //inline TMatrix4 TMatrix4::MakeTranslation(double X, double y, double z) //{ // return TMatrix4( // 1, 0, 0, X, // 0, 1, 0, y, // 0, 0, 1, z, // 0, 0, 0, 1 // ); //} //template //inline TMatrix4 TMatrix4::MakeOrtho(double left, double right, double bottom, double top, double near_value, double far_value) //{ // double tx = -(right + left) / (right - left); // double ty = -(top + bottom) / (top - bottom); // double tz = -(far_value + near_value) / (far_value - near_value); // return TMatrix4( // 2 / (right - left), 0, 0, tx, // 0, 2 / (top - bottom), 0, ty, // 0, 0, -2 / (far_value - near_value), tz, // 0, 0, 0, 1 // ); //} //template //inline TMatrix4 TMatrix4::MakeOrtho2D(double left, double right, double bottom, double top) //{ // double tx = -(right + left) / (right - left); // double ty = -(top + bottom) / (top - bottom); // return TMatrix4( // 2 / (right - left), 0, 0, tx, // 0, 2 / (top - bottom), 0, ty, // 0, 0, -1, 0, // 0, 0, 0, 1 // ); //} //template //inline TMatrix4 TMatrix4::MakeFrustum(double left, double right, double bottom, double top, double near_value, double far_value) //{ // double A = (right + left) / (right - left); // double B = (top + bottom) / (top - bottom); // double C = -(far_value + near_value) / (far_value - near_value); // double D = -2 * far_value * near_value / (far_value - near_value); // return TMatrix4( // 2 * near_value / (right - left), 0, A, 0, // 0, 2 * near_value / (top - bottom), B, 0, // 0, 0, C, D, // 0, 0, -1, 0 // ); //} //template //inline TMatrix4 TMatrix4::MakePerspective(double angleInDegrees, double aspect, double near_value, double far_value) //{ // double f = 1.0 / std::tan(FX_DEGREES_TO_RADIANS * 0.5 * angleInDegrees); // return TMatrix4( // f / aspect, 0, 0, 0, // 0, f, 0, 0, // 0, 0, (far_value + near_value) / (near_value - far_value), 2 * far_value * near_value / (near_value - far_value), // 0, 0, -1, 0 // ); //} //template //inline TMatrix4 TMatrix4::MakePerspectiveX(double angleInDegrees, double aspect, double near_value, double far_value) //{ // double f = 1.0 / std::tan(FX_DEGREES_TO_RADIANS * 0.5 * angleInDegrees); // return TMatrix4( // f / aspect, 0, 0, 0, // 0, f, 0, 0, // 0, 0, (far_value + near_value) / (near_value - far_value), 2 * far_value * near_value / (near_value - far_value), // 0, 0, -1, 0 // ); //} //template //inline TMatrix4 TMatrix4::MakePerspectiveY(double angleInDegrees, double aspect, double near_value, double far_value) //{ // double f = 1.0 / std::tan(FX_DEGREES_TO_RADIANS * 0.5 * angleInDegrees); // return TMatrix4( // f, 0, 0, 0, // 0, f * aspect, 0, 0, // 0, 0, (far_value + near_value) / (near_value - far_value), 2 * far_value * near_value / (near_value - far_value), // 0, 0, -1, 0 // ); //} //template //inline TMatrix4 TMatrix4::MakeLookAt(TVector3 eye, TVector3 center, TVector3 up) //{ // TVector3 F = (center - eye).norm(); // TVector3 S = F.cross(up).norm(); // TVector3 U = S.cross(F).norm(); // return TMatrix4::multiply(TMatrix4( // S.X, S.y, S.z, 0.0, // U.X, U.y, U.z, 0.0, // -F.X, -F.y, -F.z, 0.0, // 0.0, 0.0, 0.0, 1.0), // TMatrix4::MakeTranslation(-eye.X, -eye.y, -eye.z)); //} //template //inline TMatrix4 TMatrix4::MakeShadowBias() //{ // return TMatrix4( // 0.5, 0.0, 0.0, 0.5, // 0.0, 0.5, 0.0, 0.5, // 0.0, 0.0, 0.5, 0.5, // 0.0, 0.0, 0.0, 1.0); //} //template //inline TMatrix4 TMatrix4::MakeCubeMatrix(int face) //{ // // support GL_TEXTURE_CUBE_MAP_POSITIVE_X, ... constants // if (face >= 0x8515 && face <= 0x851A) face -= 0x8515; // switch (face) // { // case 0: // GL_TEXTURE_CUBE_MAP_POSITIVE_X // return TMatrix4::MakeRotation(90.0, 0.0, 1.0, 0.0); // break; // case 1: // GL_TEXTURE_CUBE_MAP_NEGATIVE_X // return TMatrix4::MakeRotation(270.0, 0.0, 1.0, 0.0); // break; // case 2: // GL_TEXTURE_CUBE_MAP_POSITIVE_Y // return TMatrix4::MakeRotation(270.0, 1.0, 0.0, 0.0); // break; // case 3: // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y // return TMatrix4::MakeRotation(90.0, 1.0, 0.0, 0.0); // break; // case 4: // GL_TEXTURE_CUBE_MAP_POSITIVE_Z // return TMatrix4::MakeIdentity(); // break; // case 5: // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z // return TMatrix4::MakeRotation(180.0, 0.0, 1.0, 0.0); // break; // } // return TMatrix4::MakeIdentity(); //} //template //inline TMatrix4 TMatrix4::MakeIdentity() //{ // return TMatrix4( // 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); //} extern template class TMatrix4; extern template class TMatrix4; using Matrix4f = TMatrix4; using Matrix4d = TMatrix4; template constexpr auto operator * (const TMatrix4 & m1, const TMatrix4 & m2) noexcept { return TMatrix4::multiply(m1, m2); } template constexpr auto operator * (const TMatrix4 & M, const TVector2 & V) noexcept { return TVector2>( M.m11 * V.x + M.m12 * V.y, M.m21 * V.x + M.m22 * V.y ); } template constexpr auto operator * (const TMatrix4 & M, const TVector3 & V) noexcept { return TVector2>( M.m11 * V.x + M.m12 * V.y + M.m13 * V.z, M.m21 * V.x + M.m22 * V.y + M.m23 * V.z, M.m31 * V.x + M.m32 * V.y + M.m33 * V.z ); } template constexpr auto operator * (const TMatrix4 & M, const TVector4 & V) noexcept { return TVector4>( M.m11 * V.x + M.m12 * V.y + M.m13 * V.z + M.m14 * V.w, M.m21 * V.x + M.m22 * V.y + M.m23 * V.z + M.m24 * V.w, M.m31 * V.x + M.m32 * V.y + M.m33 * V.z + M.m34 * V.w, M.m41 * V.x + M.m42 * V.y + M.m43 * V.z + M.m44 * V.w ); } } #endif