#pragma once #include "EHS.h" #include "Vec3.h" #include "Mat2.h" namespace ehs { template class Mat3 { private: T data[9]; public: Mat3() { for (UInt_8 i = 0; i < 9; ++i) data[i] = 0; } template Mat3(const Mat2& mat) { for (UInt_8 i = 0; i < 4; ++i) data[i / 2 * 4 + i % 2] = mat.data[i]; } template Mat3(const Mat3& mat) { for (UInt_8 i = 0; i < 9; ++i) data[i] = mat.data[i]; } template Mat3& operator=(const Mat3& mat) { if (this == &mat) return *this; for (UInt_8 i = 0; i < 9; ++i) data[i] = mat.data[i]; return *this; } operator Mat2() const { Mat2 result; for (UInt_8 i = 0; i < 4; ++i) result.data[i] = data[i / 2 * 4 + i % 2]; return result; } operator const T*() const { return data; } operator T*() { return data; } Vec3 operator*(Vec3 vec) const { Vec3 result; result.x = vec.x * data[0] + vec.y * data[3] + vec.z * data[6]; result.y = vec.x * data[1] + vec.y * data[4] + vec.z * data[7]; result.z = vec.x * data[2] + vec.y * data[5] + vec.z * data[8]; return result; } Mat3& operator*=(const T scalar) { for (UInt_8 i = 0; i < 9; ++i) data[i] *= scalar; return *this; } Mat3 operator*(const T scalar) const { Mat3 result; for (UInt_8 i = 0; i < 9; ++i) result.data[i] = data[i] * scalar; return result; } Mat3& operator*=(const Mat3& mat) { Mat3 old = *this; for (UInt_8 i = 0; i < 9; ++i) { UInt_8 row = i / 3; UInt_8 column = i % 3; data[i] = 0; data[i] += old.data[0 * 3 + column] * mat.data[row * 3 + 0]; data[i] += old.data[1 * 3 + column] * mat.data[row * 3 + 1]; data[i] += old.data[2 * 3 + column] * mat.data[row * 3 + 2]; } return *this; } Mat3 operator*(const Mat3& mat) const { Mat3 result; for (UInt_8 i = 0; i < 9; ++i) { UInt_8 row = i / 3; UInt_8 column = i % 3; result.data[i] += data[0 * 3 + column] * mat.data[row * 3 + 0]; result.data[i] += data[1 * 3 + column] * mat.data[row * 3 + 1]; result.data[i] += data[2 * 3 + column] * mat.data[row * 3 + 2]; } return result; } Mat3 GetTranspose() const { Mat3 result; for (UInt_8 i = 0; i < 9; ++i) result.data[i] = data[3 * (i % 3) + i / 3]; return result; } void Transpose() { Mat3 old = *this; for (UInt_8 i = 0; i < 9; ++i) data[i] = old.data[3 * (i % 3) + i / 3]; } Mat3 GetMinor() const { Mat3 result; for (UInt_8 r = 0; r < 3; ++r) for (UInt_8 c = 0; c < 3; ++c) result[3 * r + c] = Cut(r, c).GetDeterminant(); return result; } void Minor() { Mat3 old = *this; for (UInt_8 r = 0; r < 3; ++r) for (UInt_8 c = 0; c < 3; ++c) data[3 * r + c] = old.Cut(r, c).GetDeterminant(); } Mat2 Cut(const UInt_8 row, const UInt_8 column) const { Mat2 result; UInt_8 index = 0; for (UInt_8 r = 0; r < 3; ++r) { for (UInt_8 c = 0; c < 3; ++c) { if (r == row || c == column) continue; result[index++] = data[3 * r + c]; } } return result; } T GetDeterminant() const { Mat3 cofactor = GetCofactor(); T result = 0; for (UInt_8 c = 0; c < 3; ++c) result += data[c] * cofactor[c]; return result; } Mat3 GetCofactor() const { Mat3 minor = GetMinor(); Mat3 result; for (UInt_8 r = 0; r < 3; ++r) { for (UInt_8 c = 0; c < 3; ++c) { UInt_8 i = 3 * c + r; result.data[i] = minor.data[i] * Math::Pow(-1, r + c); } } return result; } void Cofactor() { Mat3 minor = GetMinor(); for (UInt_8 r = 0; r < 3; ++r) { for (UInt_8 c = 0; c < 3; ++c) { UInt_8 i = 3 * c + r; data[i] = minor.data[i] * Math::Pow(-1, r + c); } } } Mat3 GetAdjugate() const { return GetCofactor().GetTranspose(); } void Adjugate() { Cofactor(); Transpose(); } Mat3 GetInverse() const { T det = GetDeterminant(); if (Math::ComCmp(det, 0.0f)) return {}; return GetAdjugate() * (1 / det); } void Inverse() { T det = GetDeterminant(); if (Math::ComCmp(det, 0.0f)) return; Adjugate(); operator*=(1 / det); } static Mat3 Identity() { Mat3 result; result.data[0] = 1; result.data[4] = 1; result.data[8] = 1; return result; } static Mat3 Scale(const Vec3& scale) { Mat3 result; result.data[0] = scale.x; result.data[4] = scale.y; result.data[8] = scale.z; return result; } static Mat3 PitchRotate(const T angle) { T radians = Math::Rads(angle); Mat3 result; result.data[0] = 1; result.data[4] = Math::Cos(radians); result.data[5] = Math::Sin(radians); result.data[7] = -Math::Sin(radians); result.data[8] = Math::Cos(radians); return result; } static Mat3 YawRotate(const T angle) { T radians = Math::Rads(angle); Mat3 result; result.data[0] = Math::Cos(radians); result.data[2] = -Math::Sin(radians); result.data[4] = 1; result.data[6] = Math::Sin(radians); result.data[8] = Math::Cos(radians); return result; } static Mat3 RollRotate(const T angle) { T radians = Math::Rads(angle); Mat3 result; result.data[0] = Math::Cos(radians); result.data[1] = Math::Sin(radians); result.data[3] = -Math::Sin(radians); result.data[4] = Math::Cos(radians); result.data[8] = 1; return result; } static Mat3 Rotate(const Vec3& vec) { return YawRotate(vec.y) * RollRotate(vec.z) * PitchRotate(vec.x); } }; typedef Mat3 Mat3_f; typedef Mat3 Mat3_d; }