#ifndef MATH_MAT4_H #define MATH_MAT4_H #include #include #include "math/vector.hpp" namespace engine::math { // values are represented in memory as column first, meaning values[1] is the first column, 2nd row struct Matrix4 { static constexpr Matrix4 idty() { return { 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, }; } static constexpr Matrix4 translate(const Vector3& v) { return { 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, v.x, v.y, v.z, 1.f, }; } static constexpr Matrix4 scale(float fac) { return { fac, 0.f, 0.f, 0.f, 0.f, fac, 0.f, 0.f, 0.f, 0.f, fac, 0.f, 0.f, 0.f, 0.f, 1.f, }; } static constexpr Matrix4 scale(const Vector3& facs) { return { facs.x, 0.f, 0.f, 0.f, 0.f, facs.y, 0.f, 0.f, 0.f, 0.f, facs.z, 0.f, 0.f, 0.f, 0.f, 1.f, }; } static constexpr Matrix4 rot_x(float a) { float c = std::cos(a); float s = std::sin(a); return { 1.f, 0.f, 0.f, 0.f, 0.f, c, s, 0.f, 0.f, -s, c, 0.f, 0.f, 0.f, 0.f, 1.f, }; } static constexpr Matrix4 rot_y(float a) { float c = std::cos(a); float s = std::sin(a); return { c, 0.f, -s, 0.f, 0.f, 1.f, 0.f, 0.f, s, 0.f, c, 0.f, 0.f, 0.f, 0.f, 1.f, }; } static constexpr Matrix4 rot_z(float a) { float c = std::cos(a); float s = std::sin(a); return { c, s, 0.f, 0.f, -s, c, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, }; } static constexpr Matrix4 perspective(float fov, float aspect_ratio, float min_z, float max_z) { float inv_tan = 1.f / std::tan(fov / 2.f); return { inv_tan / aspect_ratio, 0.f, 0.f, 0.f, 0.f, -inv_tan, 0.f, 0.f, 0.f, 0.f, -1.f / (max_z - min_z), -1.f, 0.f, 0.f, -min_z / (max_z - min_z), 0.f, }; } static constexpr Matrix4 look_at(const Vector3& eye, const Vector3& center, const Vector3& up) { Vector3 new_z = (eye - center).normalize(); Vector3 new_x = up.cross(eye - center).normalize(); Vector3 new_y = new_z.cross(new_x); return { new_x.x, new_y.x, new_z.x, 0.f, new_x.y, new_y.y, new_z.y, 0.f, new_x.z, new_y.z, new_z.z, 0.f, -new_x.dot(eye), -new_y.dot(eye), -new_z.dot(eye), 1.f, }; } // TODO: should be Quaternion::to_mat4 static constexpr Matrix4 from_quaternion(const Quaternion& q) { return { 2.f * (q.w * q.w + q.x * q.x) - 1.f, 2.f * (q.x * q.y + q.w * q.z) , 2.f * (q.x * q.z - q.w * q.y) , 0.f, 2.f * (q.x * q.y - q.w * q.z) , 2.f * (q.w * q.w + q.y * q.y) - 1.f, 2.f * (q.y * q.z + q.w * q.x) , 0.f, 2.f * (q.x * q.z + q.w * q.y) , 2.f * (q.y * q.z - q.w * q.x) , 2.f * (q.w * q.w + q.z * q.z) - 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, }; } std::array values; constexpr Matrix4 operator+() const & { return *this; } constexpr Matrix4 operator-() const & { return { -values[ 0], -values[ 1], -values[ 2], -values[ 3], -values[ 4], -values[ 5], -values[ 6], -values[ 7], -values[ 8], -values[ 9], -values[10], -values[11], -values[12], -values[13], -values[14], -values[15], }; } constexpr Matrix4 operator+(const Matrix4& m) const & { return { values[ 0] + m.values[ 0], values[ 1] + m.values[ 1], values[ 2] + m.values[ 2], values[ 3] + m.values[ 3], values[ 4] + m.values[ 4], values[ 5] + m.values[ 5], values[ 6] + m.values[ 6], values[ 7] + m.values[ 7], values[ 8] + m.values[ 8], values[ 9] + m.values[ 9], values[10] + m.values[10], values[11] + m.values[11], values[12] + m.values[12], values[13] + m.values[13], values[14] + m.values[14], values[15] + m.values[15], }; } constexpr Matrix4 operator-(const Matrix4& m) const & { return *this + (-m); } constexpr Matrix4 operator*(const Matrix4& m) const & { Matrix4 ret; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { ret.values[i + j * 4] = 0.f; for (int k = 0; k < 4; k++) ret.values[i + j * 4] += values[i + k * 4] * m.values[k + j * 4]; } } return ret; } constexpr Vector4 operator*(const Vector4& v) const & { return { values[ 0] * v.x + values[ 4] * v.y + values[ 8] * v.z + values[12] * v.w, values[ 1] * v.x + values[ 5] * v.y + values[ 9] * v.z + values[13] * v.w, values[ 2] * v.x + values[ 6] * v.y + values[10] * v.z + values[14] * v.w, values[ 3] * v.x + values[ 7] * v.y + values[11] * v.z + values[15] * v.w, }; } constexpr std::array to_vecs() const & { return {{ { values[ 0], values[ 1], values[ 2], values[ 3] }, { values[ 4], values[ 5], values[ 6], values[ 7] }, { values[ 8], values[ 9], values[10], values[11] }, { values[12], values[13], values[14], values[15] }, }}; } constexpr Matrix4 transpose() const & { return { values[ 0], values[ 4], values[ 8], values[12], values[ 1], values[ 5], values[ 9], values[13], values[ 2], values[ 6], values[10], values[14], values[ 3], values[ 7], values[11], values[15], }; } }; constexpr Matrix4 operator*(float fac, const Matrix4& m) { return { fac * m.values[ 0], fac * m.values[ 1], fac * m.values[ 2], fac * m.values[ 3], fac * m.values[ 4], fac * m.values[ 5], fac * m.values[ 6], fac * m.values[ 7], fac * m.values[ 8], fac * m.values[ 9], fac * m.values[10], fac * m.values[11], fac * m.values[12], fac * m.values[13], fac * m.values[14], fac * m.values[15], }; } } #endif // MATH_MAT4_H