#pragma once #include namespace td { static constexpr float PI = 3.141592653f; template struct Vec2 { union { T x; T r; }; union { T y; T g; }; constexpr Vec2(T X = T(0), T Y = T(0)) : x(X), y(Y) {} }; template inline bool operator==(const Vec2& vec2, const Vec2& other) { return vec2.x == other.x && vec2.y == other.y; } template struct Vec3 { union { T x; T r; }; union { T y; T g; }; union { T z; T b; }; constexpr Vec3(T X = 0, T Y = 0, T Z = 0) : x(X), y(Y), z(Z) {} }; template inline bool operator==(const Vec3& vec3, const Vec3& other) { return vec3.x == other.x && vec3.y == other.y && vec3.z == other.z; } template struct Vec4 { union { T x; T r; }; union { T y; T g; }; union { T z; T b; }; union { T w; T a; }; constexpr Vec4(Vec3 vec, T W = 1) : x(vec.x), y(vec.y), z(vec.z), w(W) {} constexpr Vec4(T X = 0, T Y = 0, T Z = 0, T W = 0) : x(X), y(Y), z(Z), w(W) {} }; template inline bool operator==(const Vec4& vec4, const Vec4& other) { return vec4.x == other.x && vec4.y == other.y && vec4.z == other.z && vec4.w = other.w; } using Vec2i = Vec2; using Vec2u = Vec2; using Vec2f = Vec2; using Vec2d = Vec2; using Vec3i = Vec3; using Vec3u = Vec3; using Vec3f = Vec3; using Vec3d = Vec3; using Vec4i = Vec4; using Vec4u = Vec4; using Vec4f = Vec4; using Vec4d = Vec4; using Color = Vec3; template struct Mat4 { static const std::size_t MATRIX_SIZE = 4; T x0, x1, x2, x3; T y0, y1, y2, y3; T z0, z1, z2, z3; T w0, w1, w2, w3; T operator[](std::size_t offset) const { return reinterpret_cast(this)[offset]; } T& operator[](std::size_t offset) { return reinterpret_cast(this)[offset]; } T* data() { return reinterpret_cast(this); } const T* data() const { return reinterpret_cast(this); } T at(std::size_t row, std::size_t column) const { return operator[](row * MATRIX_SIZE + column); } T& at(std::size_t row, std::size_t column) { return operator[](row * MATRIX_SIZE + column); } }; typedef Mat4 Mat4f; typedef Mat4 Mat4i; typedef Mat4 Mat4d; template inline bool operator==(const Mat4& mat, const Mat4& other) { return mat.x0 == other.x0 && mat.y0 == other.y0 && mat.z0 == other.z0 && mat.w0 == other.w0 && mat.x1 == other.x1 && mat.y1 == other.y1 && mat.z1 == other.z1 && mat.w1 == other.w1 && mat.x2 == other.x2 && mat.y2 == other.y2 && mat.z2 == other.z2 && mat.w2 == other.w2 && mat.x3 == other.x3 && mat.y3 == other.y3 && mat.z3 == other.z3 && mat.w3 == other.w3; } namespace maths { template Mat4 Transpose(const Mat4& mat) { Mat4 result; result.x1 = mat.y0; result.x2 = mat.z0; result.x3 = mat.w0; result.y0 = mat.x1; result.y2 = mat.z1; result.y3 = mat.w1; result.z0 = mat.x2; result.z1 = mat.y2; result.z3 = mat.w2; result.w0 = mat.x3; result.w1 = mat.y3; result.w2 = mat.z3; result.x0 = mat.x0; result.y1 = mat.y1; result.z2 = mat.z2; result.w3 = mat.w3; return result; } Mat4f Perspective(float fovY, float aspectRatio, float zNear, float zFar); Mat4f Look(const Vec3f& eye, const Vec3f& center, const Vec3f& up); Mat4f Inverse(const Mat4f& mat); } // namespace maths } // namespace td