lxgui
Loading...
Searching...
No Matches
gui_matrix4.cpp
1#include "lxgui/gui_matrix4.hpp"
2
3#include <cmath>
4#include <iostream>
5
6namespace lxgui::gui {
7
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
18const matrix4f matrix4f::identity = build_identity();
19
20matrix4f::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
25matrix4f::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
34matrix4f 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
39matrix4f 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
46matrix4f 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
53matrix4f 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
58matrix4f matrix4f::view(const vector2f& window, const vector2f& center) noexcept {
59 return translation(vector2f(window.x / 2, window.y / 2) - center) * view(window);
60}
61
62void 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
69void matrix4f::invert() noexcept {
70 *this = invert(*this);
71}
72
74 matrix4f n = m;
75 n.transpose();
76 return n;
77}
78
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
136matrix4f 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
145matrix4f 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
154matrix4f 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
180vector2f 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
191vector2f 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
202std::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)
matrix4f build_identity() noexcept
color operator+(const color &c1, const color &c2) noexcept
color operator*(const color &c1, const color &c2) noexcept
color operator-(const color &c1, const color &c2) noexcept
A 4x4 matrix, used for coordinate transformations.
static matrix4f scaling(const vector2f &scale) noexcept
void invert() noexcept
static const matrix4f identity
element_type data[16]
void transpose() noexcept
matrix4f() noexcept=default
static matrix4f translation(const vector2f &dx) noexcept
static matrix4f transformation(const vector2f &dx, const vector2f &scale, float rot) noexcept
static matrix4f view(const vector2f &window) noexcept
static matrix4f rotation(float rot) noexcept