lxgui
gui_matrix4.cpp
1 #include "lxgui/gui_matrix4.hpp"
2 
3 #include <cmath>
4 #include <iostream>
5 
6 namespace lxgui::gui {
7 
8 matrix4f build_identity() noexcept {
9  matrix4f id;
10  for (std::size_t row = 0u; row < 4u; ++row) {
11  for (std::size_t col = 0u; col < 4u; ++col)
12  id(row, col) = (row == col ? 1.0f : 0.0f);
13  }
14 
15  return id;
16 }
17 
18 const matrix4f matrix4f::identity = build_identity();
19 
20 matrix4f::matrix4f(std::initializer_list<element_type> list) noexcept {
21  const std::size_t length = std::min<std::size_t>(list.size(), 16u);
22  std::copy(list.begin(), list.begin() + length, data);
23 }
24 
25 matrix4f::matrix4f(const element_type* mat) noexcept {
26  std::copy(mat, mat + 16u, data);
27 }
28 
30  return {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
31  0.0f, 0.0f, 1.0f, 0.0f, dx.x, dx.y, 0.0f, 1.0f};
32 }
33 
34 matrix4f matrix4f::scaling(const vector2f& scale) noexcept {
35  return {scale.x, 0.0f, 0.0f, 0.0f, 0.0f, scale.y, 0.0f, 0.0f,
36  0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
37 }
38 
39 matrix4f matrix4f::rotation(float rot) noexcept {
40  float co = std::cos(rot), si = std::sin(rot);
41 
42  return {co, si, 0.0f, 0.0f, -si, co, 0.0f, 0.0f,
43  0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
44 }
45 
46 matrix4f matrix4f::transformation(const vector2f& dx, const vector2f& scale, float rot) noexcept {
47  float co = std::cos(rot), si = std::sin(rot);
48 
49  return {scale.x * co, scale.y * si, 0.0f, 0.0f, -scale.x * si, scale.y * co, 0.0f, 0.0f,
50  0.0f, 0.0f, 1.0f, 0.0f, scale.x * dx.x, scale.y * dx.y, 0.0f, 1.0f};
51 }
52 
53 matrix4f matrix4f::view(const vector2f& window) noexcept {
54  return {2.0f / window.x, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f / window.y, 0.0f, 0.0f,
55  -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 1.0f};
56 }
57 
58 matrix4f matrix4f::view(const vector2f& window, const vector2f& center) noexcept {
59  return translation(vector2f(window.x / 2, window.y / 2) - center) * view(window);
60 }
61 
62 void matrix4f::transpose() noexcept {
63  for (std::size_t row = 0; row < 4; ++row) {
64  for (std::size_t col = 0; col < 4; ++col)
65  std::swap((*this)(row, col), (*this)(col, row));
66  }
67 }
68 
69 void matrix4f::invert() noexcept {
70  *this = invert(*this);
71 }
72 
74  matrix4f n = m;
75  n.transpose();
76  return n;
77 }
78 
79 matrix4f matrix4f::invert(const matrix4f& m) noexcept {
80  element_type m00 = m(0, 0), m01 = m(0, 1), m02 = m(0, 2), m03 = m(0, 3);
81  element_type m10 = m(1, 0), m11 = m(1, 1), m12 = m(1, 2), m13 = m(1, 3);
82  element_type m20 = m(2, 0), m21 = m(2, 1), m22 = m(2, 2), m23 = m(2, 3);
83  element_type m30 = m(3, 0), m31 = m(3, 1), m32 = m(3, 2), m33 = m(3, 3);
84 
85  element_type v0 = m20 * m31 - m21 * m30;
86  element_type v1 = m20 * m32 - m22 * m30;
87  element_type v2 = m20 * m33 - m23 * m30;
88  element_type v3 = m21 * m32 - m22 * m31;
89  element_type v4 = m21 * m33 - m23 * m31;
90  element_type v5 = m22 * m33 - m23 * m32;
91 
92  element_type t00 = (v5 * m11 - v4 * m12 + v3 * m13);
93  element_type t10 = -(v5 * m10 - v2 * m12 + v1 * m13);
94  element_type t20 = (v4 * m10 - v2 * m11 + v0 * m13);
95  element_type t30 = -(v3 * m10 - v1 * m11 + v0 * m12);
96 
97  element_type inv_det = 1.0f / (t00 * m00 + t10 * m01 + t20 * m02 + t30 * m03);
98 
99  element_type d00 = t00 * inv_det;
100  element_type d10 = t10 * inv_det;
101  element_type d20 = t20 * inv_det;
102  element_type d30 = t30 * inv_det;
103 
104  element_type d01 = -(v5 * m01 - v4 * m02 + v3 * m03) * inv_det;
105  element_type d11 = (v5 * m00 - v2 * m02 + v1 * m03) * inv_det;
106  element_type d21 = -(v4 * m00 - v2 * m01 + v0 * m03) * inv_det;
107  element_type d31 = (v3 * m00 - v1 * m01 + v0 * m02) * inv_det;
108 
109  v0 = m10 * m31 - m11 * m30;
110  v1 = m10 * m32 - m12 * m30;
111  v2 = m10 * m33 - m13 * m30;
112  v3 = m11 * m32 - m12 * m31;
113  v4 = m11 * m33 - m13 * m31;
114  v5 = m12 * m33 - m13 * m32;
115 
116  element_type d02 = (v5 * m01 - v4 * m02 + v3 * m03) * inv_det;
117  element_type d12 = -(v5 * m00 - v2 * m02 + v1 * m03) * inv_det;
118  element_type d22 = (v4 * m00 - v2 * m01 + v0 * m03) * inv_det;
119  element_type d32 = -(v3 * m00 - v1 * m01 + v0 * m02) * inv_det;
120 
121  v0 = m21 * m10 - m20 * m11;
122  v1 = m22 * m10 - m20 * m12;
123  v2 = m23 * m10 - m20 * m13;
124  v3 = m22 * m11 - m21 * m12;
125  v4 = m23 * m11 - m21 * m13;
126  v5 = m23 * m12 - m22 * m13;
127 
128  element_type d03 = -(v5 * m01 - v4 * m02 + v3 * m03) * inv_det;
129  element_type d13 = (v5 * m00 - v2 * m02 + v1 * m03) * inv_det;
130  element_type d23 = -(v4 * m00 - v2 * m01 + v0 * m03) * inv_det;
131  element_type d33 = (v3 * m00 - v1 * m01 + v0 * m02) * inv_det;
132 
133  return {d00, d01, d02, d03, d10, d11, d12, d13, d20, d21, d22, d23, d30, d31, d32, d33};
134 }
135 
136 matrix4f operator+(const matrix4f& m1, const matrix4f& m2) noexcept {
137  matrix4f r;
138 
139  for (std::size_t i = 0; i < 16; ++i)
140  r.data[i] = m1.data[i] + m2.data[i];
141 
142  return r;
143 }
144 
145 matrix4f operator-(const matrix4f& m1, const matrix4f& m2) noexcept {
146  matrix4f r;
147 
148  for (std::size_t i = 0; i < 16; ++i)
149  r.data[i] = m1.data[i] - m2.data[i];
150 
151  return r;
152 }
153 
154 matrix4f operator*(const matrix4f& m1, const matrix4f& m2) noexcept {
155  matrix4f r;
156 
157  r(0, 0) = m1(0, 0) * m2(0, 0) + m1(0, 1) * m2(1, 0) + m1(0, 2) * m2(2, 0) + m1(0, 3) * m2(3, 0);
158  r(0, 1) = m1(0, 0) * m2(0, 1) + m1(0, 1) * m2(1, 1) + m1(0, 2) * m2(2, 1) + m1(0, 3) * m2(3, 1);
159  r(0, 2) = m1(0, 0) * m2(0, 2) + m1(0, 1) * m2(1, 2) + m1(0, 2) * m2(2, 2) + m1(0, 3) * m2(3, 2);
160  r(0, 3) = m1(0, 0) * m2(0, 3) + m1(0, 1) * m2(1, 3) + m1(0, 2) * m2(2, 3) + m1(0, 3) * m2(3, 3);
161 
162  r(1, 0) = m1(1, 0) * m2(0, 0) + m1(1, 1) * m2(1, 0) + m1(1, 2) * m2(2, 0) + m1(1, 3) * m2(3, 0);
163  r(1, 1) = m1(1, 0) * m2(0, 1) + m1(1, 1) * m2(1, 1) + m1(1, 2) * m2(2, 1) + m1(1, 3) * m2(3, 1);
164  r(1, 2) = m1(1, 0) * m2(0, 2) + m1(1, 1) * m2(1, 2) + m1(1, 2) * m2(2, 2) + m1(1, 3) * m2(3, 2);
165  r(1, 3) = m1(1, 0) * m2(0, 3) + m1(1, 1) * m2(1, 3) + m1(1, 2) * m2(2, 3) + m1(1, 3) * m2(3, 3);
166 
167  r(2, 0) = m1(2, 0) * m2(0, 0) + m1(2, 1) * m2(1, 0) + m1(2, 2) * m2(2, 0) + m1(2, 3) * m2(3, 0);
168  r(2, 1) = m1(2, 0) * m2(0, 1) + m1(2, 1) * m2(1, 1) + m1(2, 2) * m2(2, 1) + m1(2, 3) * m2(3, 1);
169  r(2, 2) = m1(2, 0) * m2(0, 2) + m1(2, 1) * m2(1, 2) + m1(2, 2) * m2(2, 2) + m1(2, 3) * m2(3, 2);
170  r(2, 3) = m1(2, 0) * m2(0, 3) + m1(2, 1) * m2(1, 3) + m1(2, 2) * m2(2, 3) + m1(2, 3) * m2(3, 3);
171 
172  r(3, 0) = m1(3, 0) * m2(0, 0) + m1(3, 1) * m2(1, 0) + m1(3, 2) * m2(2, 0) + m1(3, 3) * m2(3, 0);
173  r(3, 1) = m1(3, 0) * m2(0, 1) + m1(3, 1) * m2(1, 1) + m1(3, 2) * m2(2, 1) + m1(3, 3) * m2(3, 1);
174  r(3, 2) = m1(3, 0) * m2(0, 2) + m1(3, 1) * m2(1, 2) + m1(3, 2) * m2(2, 2) + m1(3, 3) * m2(3, 2);
175  r(3, 3) = m1(3, 0) * m2(0, 3) + m1(3, 1) * m2(1, 3) + m1(3, 2) * m2(2, 3) + m1(3, 3) * m2(3, 3);
176 
177  return r;
178 }
179 
180 vector2f operator*(const matrix4f& m, const vector2f& v) noexcept {
181  vector2f r;
182 
183  const float inv_w = 1.0f / (m(3, 0) * v.x + m(3, 1) * v.y + m(3, 3));
184 
185  r.x = (m(0, 0) * v.x + m(0, 1) * v.y + m(0, 3)) * inv_w;
186  r.y = (m(1, 0) * v.x + m(1, 1) * v.y + m(1, 3)) * inv_w;
187 
188  return r;
189 }
190 
191 vector2f operator*(const vector2f& v, const matrix4f& m) noexcept {
192  vector2f r;
193 
194  const float inv_w = 1.0f / (m(0, 3) * v.x + m(1, 3) * v.y + m(3, 3));
195 
196  r.x = (m(0, 0) * v.x + m(1, 0) * v.y + m(3, 0)) * inv_w;
197  r.y = (m(0, 1) * v.x + m(1, 1) * v.y + m(3, 1)) * inv_w;
198 
199  return r;
200 }
201 
202 std::ostream& operator<<(std::ostream& o, const matrix4f& m) {
203  return o << "(" << m(0, 0) << ", " << m(0, 1) << ", " << m(0, 2) << ", " << m(0, 3) << ")\n"
204  << "(" << m(1, 0) << ", " << m(1, 1) << ", " << m(1, 2) << ", " << m(1, 3) << ")\n"
205  << "(" << m(2, 0) << ", " << m(2, 1) << ", " << m(2, 2) << ", " << m(2, 3) << ")\n"
206  << "(" << m(3, 0) << ", " << m(3, 1) << ", " << m(3, 2) << ", " << m(3, 3) << ")\n";
207 }
208 
209 } // namespace lxgui::gui
vector2< float > vector2f
Holds 2D coordinates (as floats)
std::ostream & operator<<(std::ostream &stream, const color &c)
Definition: gui_color.cpp:212
matrix4f build_identity() noexcept
Definition: gui_matrix4.cpp:8
color operator+(const color &c1, const color &c2) noexcept
Definition: gui_color.cpp:192
color operator*(const color &c1, const color &c2) noexcept
Definition: gui_color.cpp:200
color operator-(const color &c1, const color &c2) noexcept
Definition: gui_color.cpp:196
A 4x4 matrix, used for coordinate transformations.
Definition: gui_matrix4.hpp:13
static matrix4f scaling(const vector2f &scale) noexcept
Definition: gui_matrix4.cpp:34
void invert() noexcept
Definition: gui_matrix4.cpp:69
static const matrix4f identity
Definition: gui_matrix4.hpp:51
element_type data[16]
Definition: gui_matrix4.hpp:49
void transpose() noexcept
Definition: gui_matrix4.cpp:62
matrix4f() noexcept=default
static matrix4f translation(const vector2f &dx) noexcept
Definition: gui_matrix4.cpp:29
static matrix4f transformation(const vector2f &dx, const vector2f &scale, float rot) noexcept
Definition: gui_matrix4.cpp:46
static matrix4f view(const vector2f &window) noexcept
Definition: gui_matrix4.cpp:53
static matrix4f rotation(float rot) noexcept
Definition: gui_matrix4.cpp:39