#pragma once #include #include #include #include "Vector2.h" namespace SwanCommon { template struct Matrix3 { using Vec = Vector2; static constexpr std::array identity = {1, 0, 0, 0, 1, 0, 0, 0, 1}; std::array vals; constexpr Matrix3(): vals(identity) {} constexpr T *data() { return vals.data(); } constexpr const T *data() const { return vals.data(); } constexpr T &at(int x, int y) { return vals[y * 3 + x]; } constexpr const T &at(int x, int y) const { return vals[y * 3 + x]; } constexpr Matrix3 &set(std::initializer_list vals) { this->vals = vals; return *this; } constexpr Matrix3 &reset() { vals = identity; return *this; } constexpr Matrix3 &translate(Vec vec) { at(2, 0) += vec.x; at(2, 1) += vec.y; return *this; } constexpr Matrix3 &scale(Vec vec) { at(0, 0) *= vec.x; at(1, 1) *= vec.y; return *this; } constexpr Matrix3 &rotate(T rads) { T s = std::sin(rads); T c = std::cos(rads); at(0, 0) += c; at(1, 0) -= s; at(0, 1) += s; at(1, 1) += c; return *this; } static const Matrix3 IDENTITY; template friend std::ostream &operator<<(std::ostream &os, const Matrix3 &mat); }; template const Matrix3 Matrix3::IDENTITY = Matrix3(); template std::ostream &operator<<(std::ostream &os, const Matrix3 &mat) { os << '(' << '(' << mat.at(0, 0) << ", " << mat.at(1, 0) << ", " << mat.at(2, 0) << "), " << '(' << mat.at(0, 1) << ", " << mat.at(1, 1) << ", " << mat.at(2, 1) << "), " << '(' << mat.at(0, 2) << ", " << mat.at(1, 2) << ", " << mat.at(2, 2) << "))"; return os; } }