#pragma once #include #include #include #include "Rotation.hpp" template struct Matrix { public: Matrix() : elements{} {}; Matrix(T scalar) { std::fill(elements, elements + R * C, scalar); }; template Matrix(Args... args): elements{ args... } {}; Matrix(T values[R * C]) { std::copy(values, values + R * C, elements); }; static Matrix identity() { Matrix result{}; for (int i = 0; i < R; i++) { result(i, i) = 1; } return result; } static Matrix<4, 4> transformation(Vector<3> position) { return { 1.0f, 0.0f, 0.0f, position.x(), 0.0f, 1.0f, 0.0f, position.y(), 0.0f, 0.0f, 1.0f, position.z(), 0.0f, 0.0f, 0.0f, 1.0f }; } static Matrix<4, 4> rotation(Rotation angles) { auto c = angles.vector.map([](auto a) { return cos(a); }); auto s = angles.vector.map([](auto a) { return sin(a); }); Matrix<4, 4> rotation_x{ 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, c.x(), -s.x(), 0.0f, 0.0f, s.x(), c.x(), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, }; Matrix<4, 4> rotation_y{ c.y(), 0.0f, s.y(), 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, -s.y(), 0.0f, c.y(), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, }; Matrix<4, 4> rotation_z{ c.z(), -s.z(), 0.0f, 0.0f, s.z(), c.z(), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, }; return rotation_x * rotation_y * rotation_z; } Vector row(size_t index) { return { &elements[index * C] }; } Vector col(size_t index) { Vector result{}; for (int i = 0; i < R; i++) { result[i] = this->operator()(index, i); } return result; } Matrix operator+(Matrix other) { Matrix result{}; for (int i = 0; i < R * C; i++) { result.elements[i] = elements[i] + other.elements[i]; } return result; } Matrix operator*(float scalar) { Matrix result{}; for (int i = 0; i < R * C; i++) { result.elements[i] = elements[i] * scalar; } return result; } template Matrix operator*(Matrix other) { Matrix result{}; for (int y = 0; y < R; y++) { for (int x = 0; x < N; x++) { auto r = row(y); auto c = other.col(x); auto dot = r * c; result(x, y) = dot; } } return result; } Vector operator*(Vector vector) { Matrix matrix(vector.elements); matrix = this->operator*(matrix); return { matrix.elements }; } auto& operator()(size_t x, size_t y) { return elements[y * C + x]; } std::string string() { std::stringstream str{}; for (int x = 0; x < R; x++) { for (int y = 0; y < C; y++) { str << this->operator()(x, y) << " "; } str << "\n"; } return str.str(); } T elements[R * C]; };