A 2D tile-based sandbox game.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Matrix3.h 2.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #pragma once
  2. #include <ostream>
  3. #include <cmath>
  4. #include <array>
  5. #include "Vector2.h"
  6. namespace SwanCommon {
  7. // 3D transformation matrix.
  8. // All the operations assume that the last row remains {0, 0, 1}.
  9. // If the last row is modified, methods like .scale, .translate and .rotate won't work.
  10. template<typename T>
  11. struct Matrix3 {
  12. using Vec = Vector2<T>;
  13. static constexpr std::array<T, 9> identity = {1, 0, 0, 0, 1, 0, 0, 0, 1};
  14. std::array<T, 9> vals;
  15. constexpr Matrix3(): vals(identity) {}
  16. constexpr Matrix3(const Matrix3 &mat): vals(mat.vals) {}
  17. constexpr Matrix3 &operator=(const Matrix3 &mat) { vals = mat.vals; }
  18. constexpr T *data() {
  19. return vals.data();
  20. }
  21. constexpr const T *data() const {
  22. return vals.data();
  23. }
  24. constexpr T &at(int x, int y) {
  25. return vals[y * 3 + x];
  26. }
  27. constexpr const T &at(int x, int y) const {
  28. return vals[y * 3 + x];
  29. }
  30. constexpr Matrix3<T> &set(std::initializer_list<T> vals) {
  31. this->vals = vals;
  32. return *this;
  33. }
  34. constexpr Matrix3<T> &reset() {
  35. vals = identity;
  36. return *this;
  37. }
  38. constexpr Matrix3<T> &translate(Vec vec) {
  39. at(2, 0) += vec.x;
  40. at(2, 1) += vec.y;
  41. return *this;
  42. }
  43. constexpr Matrix3<T> &scale(Vec vec) {
  44. at(0, 0) *= vec.x;
  45. at(1, 0) *= vec.x;
  46. at(2, 0) *= vec.x;
  47. at(0, 1) *= vec.y;
  48. at(1, 1) *= vec.y;
  49. at(2, 1) *= vec.y;
  50. return *this;
  51. }
  52. constexpr Matrix3<T> &rotate(T rads) {
  53. T s = std::sin(rads);
  54. T c = std::cos(rads);
  55. T old00 = at(0, 0), old10 = at(1, 0), old20 = at(2, 0);
  56. at(0, 0) = c * old00 + -s * at(0, 1);
  57. at(1, 0) = c * old10 + -s * at(1, 1);
  58. at(2, 0) = c * old20 + -s * at(2, 1);
  59. at(0, 1) = s * old00 + c * at(0, 1);
  60. at(1, 1) = s * old10 + c * at(1, 1);
  61. at(2, 1) = s * old20 + c * at(2, 1);
  62. return *this;
  63. }
  64. static const Matrix3<T> IDENTITY;
  65. template<typename U>
  66. friend std::ostream &operator<<(std::ostream &os, const Matrix3<U> &mat);
  67. };
  68. template<typename T>
  69. const Matrix3<T> Matrix3<T>::IDENTITY = Matrix3<T>();
  70. template<typename T>
  71. std::ostream &operator<<(std::ostream &os, const Matrix3<T> &mat) {
  72. os << '('
  73. << '(' << mat.at(0, 0) << ", " << mat.at(1, 0) << ", " << mat.at(2, 0) << "), "
  74. << '(' << mat.at(0, 1) << ", " << mat.at(1, 1) << ", " << mat.at(2, 1) << "), "
  75. << '(' << mat.at(0, 2) << ", " << mat.at(1, 2) << ", " << mat.at(2, 2) << "))";
  76. return os;
  77. }
  78. }