// 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 <https://www.gnu.org/licenses/>.
//
// For any other type of licensing, please contact me at [email protected]
#ifndef FLUXIONS_MATRIX4_HPP
#define FLUXIONS_MATRIX4_HPP
#include <type_traits>
#include <fluxions_gte_math.hpp>
#include <fluxions_gte_vector3.hpp>
#include <fluxions_gte_vector4.hpp>
namespace Fluxions
{
using namespace std;
template <typename T>
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<T> & 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<T> && 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<T> & 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 <typename U> constexpr auto operator = (const TMatrix4<U> & M) noexcept
{
m11 = static_cast<T>(M.m11); m12 = static_cast<T>(M.m12); m13 = static_cast<T>(M.m13); m14 = static_cast<T>(M.m14);
m21 = static_cast<T>(M.m21); m22 = static_cast<T>(M.m22); m23 = static_cast<T>(M.m23); m24 = static_cast<T>(M.m24);
m31 = static_cast<T>(M.m31); m32 = static_cast<T>(M.m32); m33 = static_cast<T>(M.m33); m34 = static_cast<T>(M.m34);
m41 = static_cast<T>(M.m41); m42 = static_cast<T>(M.m42); m43 = static_cast<T>(M.m43); m44 = static_cast<T>(M.m44);
return *this;
}
//template <typename U> constexpr TMatrix4<T> & operator = (const enable_if_t<is_arithmetic_v<U>, U> value) noexcept
template <typename U> constexpr TMatrix4<T> & operator = (const U value) noexcept
{
m11 = static_cast<T>(value); m12 = static_cast<T>(value); m13 = static_cast<T>(value); m14 = static_cast<T>(value);
m21 = static_cast<T>(value); m22 = static_cast<T>(value); m23 = static_cast<T>(value); m24 = static_cast<T>(value);
m31 = static_cast<T>(value); m32 = static_cast<T>(value); m33 = static_cast<T>(value); m34 = static_cast<T>(value);
m41 = static_cast<T>(value); m42 = static_cast<T>(value); m43 = static_cast<T>(value); m44 = static_cast<T>(value);
return *this;
}
template <typename U> constexpr operator TMatrix4<U>() const noexcept {
return TMatrix4<U>(
static_cast<U>(m11), static_cast<U>(m12), static_cast<U>(m13), static_cast<U>(m14),
static_cast<U>(m21), static_cast<U>(m22), static_cast<U>(m23), static_cast<U>(m24),
static_cast<U>(m31), static_cast<U>(m32), static_cast<U>(m33), static_cast<U>(m34),
static_cast<U>(m41), static_cast<U>(m42), static_cast<U>(m43), static_cast<U>(m44)
);
}
constexpr TVector4<T> row1() const noexcept { return TVector4<T>(m11, m12, m13, m14); }
constexpr TVector4<T> row2() const noexcept { return TVector4<T>(m21, m22, m23, m24); }
constexpr TVector4<T> row3() const noexcept { return TVector4<T>(m31, m32, m33, m34); }
constexpr TVector4<T> row4() const noexcept { return TVector4<T>(m41, m42, m43, m44); }
constexpr TVector4<T> col1() const noexcept { return TVector4<T>(m11, m21, m31, m41); }
constexpr TVector4<T> col2() const noexcept { return TVector4<T>(m12, m22, m32, m42); }
constexpr TVector4<T> col3() const noexcept { return TVector4<T>(m13, m23, m33, m43); }
constexpr TVector4<T> col4() const noexcept { return TVector4<T>(m14, m24, m34, m44); }
// col(i) returns the ith column of the matrix (i = 1 is column 1)
constexpr TVector4<T> 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<T>();
}
// row(i) returns the ith row of the matrix (i = 1 is row 1)
constexpr TVector4<T> 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<T>();
}
template <typename U> static constexpr auto compAdd(const TMatrix4<T> & m1, const TMatrix4<U> & m2) noexcept
{
return TMatrix4<common_type_t<T, U>>(
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 <typename U> static constexpr auto compSub(const TMatrix4<T> & m1, const TMatrix4<U> & m2) noexcept
{
return TMatrix4<common_type_t<T, U>>(
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 <typename U> static constexpr auto compMult(const TMatrix4<T> & m1, const TMatrix4<U> & m2) noexcept
{
return TMatrix4<common_type_t<T, U>>(
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 <typename U> static constexpr auto compDiv(const TMatrix4<T> & m1, const TMatrix4<U> & m2) noexcept
{
return TMatrix4<common_type_t<T, U>>(
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 <typename U> static constexpr auto multiply(const TMatrix4<T> & m1, const TMatrix4<U> & m2) noexcept
{
return TMatrix4<common_type_t<T, U>>(
(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<T>(
-m11, -m12, -m13, -m14,
-m21, -m22, -m23, -m24,
-m31, -m32, -m33, -m34,
-m41, -m42, -m43, -m44
);
}
template <typename U> constexpr auto operator()(std::function<U(T x)> Func) noexcept
{
return TMatrix4<common_type_t<T, U>>(
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 <typename U> constexpr auto MultMatrix(const TMatrix4<U> & M) noexcept
{
return *this = multiply(*this, M);
}
template <typename U> constexpr auto operator *= (const TMatrix4<U> & M) noexcept
{
return *this = multiply(*this, M);
}
template <typename U> constexpr auto operator += (const TMatrix4<U> & 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 <typename U> constexpr auto operator -= (const TMatrix4<U> & 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 <typename U> const TMatrix4<T> operator * (const TMatrix4<U> & M) const;
//template <typename U> const TMatrix4<T> operator + (const TMatrix4<U> & M) const;
//template <typename U> const TMatrix4<T> operator - (const TMatrix4<U> & M) const;
template <typename U> 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 <typename U> 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 <typename U> 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 <typename U> 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 <typename U> constexpr auto Rotate(U angleInDegrees, U x, U y, U z) noexcept
{
return *this *= MakeRotation((T)angleInDegrees, (T)x, (T)y, (T)z);
}
template <typename U> constexpr auto Scale(U x, U y, U z) noexcept
{
return *this *= MakeScaling((T)x, (T)y, (T)z);
}
template <typename U> constexpr auto Translate(U x, U y, U z) noexcept
{
return *this *= MakeTranslation((T)x, (T)y, (T)z);
}
template <typename U> 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 <typename U> constexpr auto Ortho2D(U left, U right, U bottom, U top) noexcept
{
return *this *= MakeOrtho2D((T)left, (T)right, (T)bottom, (T)top);
}
template <typename U> 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 <typename U> 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 <typename U> 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 <typename U> 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 <typename U> constexpr auto LookAt(TVector3<U> eye, TVector3<U> center, TVector3<U> up) noexcept
{
return *this *= MakeLookAt((TVector3<T>)eye, (TVector3<T>)center, (TVector3<T>)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<T> & position) noexcept
{
return *this *= MakeCubeMatrixPosition(face, position);
}
constexpr auto AsTranspose() const noexcept
{
return TMatrix4<T>(
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<T>(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<T>(
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<T>(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<T>(
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<T>(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
);
}
static constexpr auto MakeZero() noexcept
{
return TMatrix4<T>(
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<T>(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<T>(
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<T>(
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<T>(
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<double>(
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<T>(
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<T>(
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<T>(1.0 / std::tan(FX_DEGREES_TO_RADIANS * 0.5 * angleInDegrees));
return TMatrix4<T>(
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<T>(1.0 / std::tan(FX_DEGREES_TO_RADIANS * 0.5 * angleInDegrees));
return TMatrix4<T>(
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<T>(1.0 / std::tan(FX_DEGREES_TO_RADIANS * 0.5 * angleInDegrees));
return TMatrix4<T>(
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<T> eye, TVector3<T> center, TVector3<T> up) noexcept
{
TVector3<T> F = (center - eye).norm();
TVector3<T> S = F.cross(up).norm();
TVector3<T> U = S.cross(F).norm();
return TMatrix4<T>::multiply(TMatrix4<T>(
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<T>::MakeTranslation(-eye.x, -eye.y, -eye.z));
}
static constexpr auto MakeShadowBias() noexcept
{
return TMatrix4<T>(
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<T>::MakeRotation(90.0, 0.0, 1.0, 0.0);
break;
case 1: // GL_TEXTURE_CUBE_MAP_NEGATIVE_X
return TMatrix4<T>::MakeRotation(270.0, 0.0, 1.0, 0.0);
break;
case 2: // GL_TEXTURE_CUBE_MAP_POSITIVE_Y
return TMatrix4<T>::MakeRotation(270.0, 1.0, 0.0, 0.0);
break;
case 3: // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
return TMatrix4<T>::MakeRotation(90.0, 1.0, 0.0, 0.0);
break;
case 4: // GL_TEXTURE_CUBE_MAP_POSITIVE_Z
return TMatrix4<T>::MakeIdentity();
break;
case 5: // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
return TMatrix4<T>::MakeRotation(180.0, 0.0, 1.0, 0.0);
break;
}
return TMatrix4<T>::MakeIdentity();
}
static constexpr TMatrix4<T> MakeCubeMatrixPosition(int face, const TVector3<T> & 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<T>::MakeLookAt(position, position + TVector3<T>(1, 0, 0), TVector3<T>(0, -1, 0));
break;
case 1: // GL_TEXTURE_CUBE_MAP_NEGATIVE_X
return TMatrix4<T>::MakeLookAt(position, position + TVector3<T>(-1, 0, 0), TVector3<T>(0, -1, 0));
break;
case 2: // GL_TEXTURE_CUBE_MAP_POSITIVE_Y
return TMatrix4<T>::MakeLookAt(position, position + TVector3<T>(0, 1, 0), TVector3<T>(0, 0, 1));
break;
case 3: // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
return TMatrix4<T>::MakeLookAt(position, position + TVector3<T>(0, -1, 0), TVector3<T>(0, 0, -1));
break;
case 4: // GL_TEXTURE_CUBE_MAP_POSITIVE_Z
return TMatrix4<T>::MakeLookAt(position, position + TVector3<T>(0, 0, 1), TVector3<T>(0, -1, 0));
break;
case 5: // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
return TMatrix4<T>::MakeLookAt(position, position + TVector3<T>(0, 0, -1), TVector3<T>(0, -1, 0));
break;
}
return TMatrix4<T>::MakeIdentity();
}
};
//////////////////////////////////////////////////////////////////
// I M P L E M E N T A T I O N ///////////////////////////////////
//////////////////////////////////////////////////////////////////
//template <typename T>
//TMatrix4<T>::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 <typename T>
//TMatrix4<T>::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 <typename T>
//TMatrix4<T>::TMatrix4(const TMatrix4<T> & 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 <typename T>
//TMatrix4<T>::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 <typename T>
//TMatrix4<T>::TMatrix4(const T M[16])
//{
// for (int i = 0; i < 16; i++)
// {
// m[i] = M[i];
// }
//}
//
//template <typename T>
//template <typename U>
//const TMatrix4<T> & TMatrix4<T>::operator = (const TMatrix4<U> & 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 <typename T>
//const TMatrix4<T> & TMatrix4<T>::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 <typename T>
//template <typename U>
//const TMatrix4<T> TMatrix4<T>::multiply(const TMatrix4<U> &M) const
//{
// return TMatrix4<T>(
// (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 <typename T>
//template <typename U>
//const TMatrix4<T> TMatrix4<T>::compMult(const TMatrix4<U> &m) const
//{
// return TMatrix4<T>(
// 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<typename T>
//template<typename U>
//inline TMatrix4<T> TMatrix4<T>::multiply(TMatrix4<T> m1, TMatrix4<U> m2)
//{
// return TMatrix4<T>(
// (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 <typename T>
//template <typename U>
//const TMatrix4<T> & TMatrix4<T>::MultMatrix(const TMatrix4<U> & M)
//{
// return *this = multiply(M);
//}
//
//template <typename T>
//template <typename U>
//const TMatrix4<T> & TMatrix4<T>::operator *= (const TMatrix4<U> & M)
//{
// return *this = multiply(M);
//}
//
//template <typename T>
//template <typename U>
//const TMatrix4<T> & TMatrix4<T>::operator += (const TMatrix4<U> & 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 <typename T>
//template <typename U>
//const TMatrix4<T> & TMatrix4<T>::operator -= (const TMatrix4<U> & 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 <typename T>
//template <typename U>
//const TMatrix4<T> TMatrix4<T>::operator * (const TMatrix4<U> & M) const
//{
// return multiply(M);
//}
//
//template <typename T>
//template <typename U>
//const TMatrix4<T> TMatrix4<T>::operator + (const TMatrix4<U> & M) const
//{
// return TMatrix4<T>(
// 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 <typename T>
//template <typename U>
//const TMatrix4<T> TMatrix4<T>::operator - (const TMatrix4<U> & M) const
//{
// return TMatrix4<T>(
// 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 <typename T>
//template <typename U>
//const TMatrix4<T> & TMatrix4<T>::operator *= (const U X)
//{
// for (int i = 0; i < 16; i++)
// m[i] *= X;
// return *this;
//}
//
//template <typename T>
//template <typename U>
//const TMatrix4<T> & TMatrix4<T>::operator /= (const U X)
//{
// for (int i = 0; i < 16; i++)
// m[i] /= X;
// return *this;
//}
//template <typename T>
//const TMatrix4<T> & TMatrix4<T>::Rotate(double angleInDegrees, double X, double y, double z)
//{
// return MultMatrix(TMatrix4<double>::MakeRotation(angleInDegrees, X, y, z));
//}
//template <typename T>
//const TMatrix4<T> & TMatrix4<T>::Scale(double X, double y, double z)
//{
// return MultMatrix(TMatrix4<double>::MakeScaling(X, y, z));
//}
//
//template <typename T>
//const TMatrix4<T> & TMatrix4<T>::Translate(double X, double y, double z)
//{
// return MultMatrix(TMatrix4<double>::MakeTranslation(X, y, z));
//}
//
//template <typename T>
//const TMatrix4<T> & TMatrix4<T>::Ortho(double left, double right, double bottom, double top, double near_value, double far_value)
//{
// return MultMatrix(TMatrix4<double>::MakeOrtho(left, right, bottom, top, near_value, far_value));
//}
//
//template <typename T>
//const TMatrix4<T> & TMatrix4<T>::Ortho2D(double left, double right, double bottom, double top)
//{
// return MultMatrix(TMatrix4<double>::MakeOrtho2D(left, right, bottom, top));
//}
//
//template <typename T>
//const TMatrix4<T> & TMatrix4<T>::Frustum(double left, double right, double bottom, double top, double near_value, double far_value)
//{
// return MultMatrix(TMatrix4<double>::MakeFrustum(left, right, bottom, top, near_value, far_value));
//}
//
//template <typename T>
//const TMatrix4<T> & TMatrix4<T>::Perspective(double angleInDegrees, double aspect, double near_value, double far_value)
//{
// return MultMatrix(TMatrix4<double>::MakePerspective(angleInDegrees, aspect, near_value, far_value));
//}
//template <typename T>
//const TMatrix4<T> & TMatrix4<T>::PerspectiveX(double angleInDegrees, double aspect, double near_value, double far_value)
//{
// return MultMatrix(TMatrix4<double>::MakePerspectiveX(angleInDegrees, aspect, near_value, far_value));
//}
//template <typename T>
//const TMatrix4<T> & TMatrix4<T>::PerspectiveY(double angleInDegrees, double aspect, double near_value, double far_value)
//{
// return MultMatrix(TMatrix4<double>::MakePerspectiveY(angleInDegrees, aspect, near_value, far_value));
//}
//template <typename T>
//const TMatrix4<T> &TMatrix4<T>::LookAt(TVector3<double> eye, TVector3<double> center, TVector3<double> up)
//{
// return MultMatrix(TMatrix4<double>::MakeLookAt(eye, center, up));
//}
//template <typename T>
//const TMatrix4<T> & TMatrix4<T>::ShadowBias()
//{
// return MultMatrix(TMatrix4<double>::MakeShadowBias());
//}
//template <typename T>
//const TMatrix4<T> &TMatrix4<T>::CubeMatrix(int face)
//{
// return MultMatrix(TMatrix4<double>::MakeCubeMatrix(face));
//}
//template <typename T>
//inline TMatrix4<T> & TMatrix4<T>::Transpose()
//{
// return *this = AsTranspose();
//}
//template <typename T>
//TMatrix4<T> TMatrix4<T>::AsTranspose() const
//{
// return TMatrix4<T>(
// t11, t12, t13, t14,
// t21, t22, t23, t24,
// t31, t32, t33, t34,
// t41, t42, t43, t44
// );
//}
//template <typename T>
//T TMatrix4<T>::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 <typename T>
//TMatrix4<T> TMatrix4<T>::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<T>(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 <typename T>
//TMatrix4<T> & TMatrix4<T>::Adjugate()
//{
// return *this = AsAdjugate();
//}
//
//template <typename T>
//bool TMatrix4<T>::Invert()
//{
// T det;
//
// det = Determinant();
// if (det == 0)
// return false;
// *this = AsInverse();
// return true;
//}
////template <typename T>
////TMatrix4<T> TMatrix4<T>::QuickInverse() const
////{
//// return TMatrix4<T>(
//// t11, t12, t13, -m14,
//// t21, t22, t23, -m24,
//// t31, t32, t33, -m34,
//// T(0), T(0), T(0), T(1)
//// );
////}
////template <typename T>
////void TMatrix4<T>::QuickInvert()
////{
//// *this = QuickInverse();
////}
//template <typename T>
//TMatrix4<double> TMatrix4<T>::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<double>(
// 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 <typename T>
//TMatrix4<double> TMatrix4<T>::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<double>(
// 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 <typename T>
//TMatrix4<double> TMatrix4<T>::makeScale(double X, double y, double z)
//{
// return TMatrix4<double>(
// 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 <typename T>
//TMatrix4<double> TMatrix4<T>::makeTranslation(double X, double y, double z)
//{
// return TMatrix4<double>(
// 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 <typename T>
//inline TMatrix4<double> TMatrix4<T>::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<double>(
// 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 <typename T>
//inline TMatrix4<double> TMatrix4<T>::MakeScaling(double X, double y, double z)
//{
// return TMatrix4<double>(
// X, 0, 0, 0,
// 0, y, 0, 0,
// 0, 0, z, 0,
// 0, 0, 0, 1
// );
//}
//template <typename T>
//inline TMatrix4<double> TMatrix4<T>::MakeTranslation(double X, double y, double z)
//{
// return TMatrix4<double>(
// 1, 0, 0, X,
// 0, 1, 0, y,
// 0, 0, 1, z,
// 0, 0, 0, 1
// );
//}
//template <typename T>
//inline TMatrix4<double> TMatrix4<T>::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<double>(
// 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 <typename T>
//inline TMatrix4<double> TMatrix4<T>::MakeOrtho2D(double left, double right, double bottom, double top)
//{
// double tx = -(right + left) / (right - left);
// double ty = -(top + bottom) / (top - bottom);
// return TMatrix4<double>(
// 2 / (right - left), 0, 0, tx,
// 0, 2 / (top - bottom), 0, ty,
// 0, 0, -1, 0,
// 0, 0, 0, 1
// );
//}
//template <typename T>
//inline TMatrix4<double> TMatrix4<T>::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<double>(
// 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 <typename T>
//inline TMatrix4<double> TMatrix4<T>::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<double>(
// 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 <typename T>
//inline TMatrix4<double> TMatrix4<T>::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<double>(
// 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 <typename T>
//inline TMatrix4<double> TMatrix4<T>::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<double>(
// 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 <typename T>
//inline TMatrix4<double> TMatrix4<T>::MakeLookAt(TVector3<double> eye, TVector3<double> center, TVector3<double> up)
//{
// TVector3<double> F = (center - eye).norm();
// TVector3<double> S = F.cross(up).norm();
// TVector3<double> U = S.cross(F).norm();
// return TMatrix4<double>::multiply(TMatrix4<double>(
// 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<double>::MakeTranslation(-eye.X, -eye.y, -eye.z));
//}
//template <typename T>
//inline TMatrix4<double> TMatrix4<T>::MakeShadowBias()
//{
// return TMatrix4<double>(
// 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 <typename T>
//inline TMatrix4<double> TMatrix4<T>::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<double>::MakeRotation(90.0, 0.0, 1.0, 0.0);
// break;
// case 1: // GL_TEXTURE_CUBE_MAP_NEGATIVE_X
// return TMatrix4<double>::MakeRotation(270.0, 0.0, 1.0, 0.0);
// break;
// case 2: // GL_TEXTURE_CUBE_MAP_POSITIVE_Y
// return TMatrix4<double>::MakeRotation(270.0, 1.0, 0.0, 0.0);
// break;
// case 3: // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
// return TMatrix4<double>::MakeRotation(90.0, 1.0, 0.0, 0.0);
// break;
// case 4: // GL_TEXTURE_CUBE_MAP_POSITIVE_Z
// return TMatrix4<double>::MakeIdentity();
// break;
// case 5: // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
// return TMatrix4<double>::MakeRotation(180.0, 0.0, 1.0, 0.0);
// break;
// }
// return TMatrix4<double>::MakeIdentity();
//}
//template <typename T>
//inline TMatrix4<double> TMatrix4<T>::MakeIdentity()
//{
// return TMatrix4<double>(
// 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<float>;
extern template class TMatrix4<double>;
using Matrix4f = TMatrix4<float>;
using Matrix4d = TMatrix4<double>;
template <typename T, typename U>
constexpr auto operator * (const TMatrix4<T> & m1, const TMatrix4<U> & m2) noexcept
{
return TMatrix4<T>::multiply(m1, m2);
}
template <typename T, typename U>
constexpr auto operator * (const TMatrix4<T> & M, const TVector2<U> & V) noexcept
{
return TVector2<common_type_t<T, U>>(
M.m11 * V.x + M.m12 * V.y,
M.m21 * V.x + M.m22 * V.y
);
}
template <typename T, typename U>
constexpr auto operator * (const TMatrix4<T> & M, const TVector3<U> & V) noexcept
{
return TVector2<common_type_t<T, U>>(
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 <typename T, typename U>
constexpr auto operator * (const TMatrix4<T> & M, const TVector4<U> & V) noexcept
{
return TVector4<common_type_t<T, U>>(
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
Comments