1#pragma once
2#include <cmath>
3
4#include "renderer.hpp"
5
6typedef struct Vec2f {
7 union {
8 struct {
9 float x, y;
10 };
11 struct {
12 float u, v;
13 };
14 };
15
16 Vec2f() : x(0.0f), y(0.0f) {};
17
18 Vec2f(float x_, float y_) {
19 x = x_;
20 y = y_;
21 }
22
23 Vec2f operator+(const Vec2f &other) const {
24 return Vec2f(x + other.x, y + other.y);
25 }
26
27 Vec2f operator-(const Vec2f &other) const {
28 return Vec2f(x - other.x, y - other.y);
29 }
30
31 Vec2f operator*(float s) const {
32 return Vec2f(x * s, y * s);
33 }
34
35 Vec2f operator/(float s) const {
36 if (s != 0.0f) {
37 return Vec2f(x / s, y / s);
38 }
39 return Vec2f();
40 }
41
42 Vec2f normalized() const {
43 float len = length();
44 return (len > 0) ? (*this * (1.0f / len)) : Vec2f();
45 }
46
47 float dot(const Vec2f &other) const {
48 return x * other.x + y * other.y;
49 }
50
51 float length() const {
52 return sqrtf(x * x + y * y);
53 }
54
55} vec2f;
56
57typedef struct Vec3f {
58 union {
59 struct {
60 float x, y, z;
61 };
62 struct {
63 float r, g, b;
64 };
65 };
66
67 Vec3f() : x(0.0f), y(0.0f), z(0.0f) {};
68
69 Vec3f(float x_, float y_, float z_) {
70 x = x_;
71 y = y_;
72 z = z_;
73 }
74
75 Vec3f operator+(const Vec3f &o) const {
76 return Vec3f(x + o.x, y + o.y, z + o.z);
77 }
78
79 Vec3f operator-(const Vec3f &o) const {
80 return Vec3f(x - o.x, y - o.y, z - o.z);
81 }
82
83 Vec3f operator*(float s) const {
84 return Vec3f(x * s, y * s, z * s);
85 }
86
87 Vec3f operator/(float s) const {
88 if (s != 0.0f) {
89 return Vec3f(x / s, y / s, z / s);
90 }
91 return Vec3f();
92 }
93
94 Vec3f normalized() const {
95 float len = length();
96 if (len > 0.0f) {
97 return *this * (1.0f / len);
98 }
99 return Vec3f();
100 }
101
102 float length() const {
103 return sqrtf(x * x + y * y + z * z);
104 }
105
106 Vec3f cross(const Vec3f &o) const {
107 return Vec3f(y * o.z - z * o.y, z * o.x - x * o.z, x * o.y - y * o.x);
108 }
109
110 float dot(const Vec3f &o) const {
111 return x * o.x + y * o.y + z * o.z;
112 }
113
114} vec3f;
115
116inline vec3f operator*(float s, const vec3f &v) {
117 return {v.x * s, v.y * s, v.z * s};
118}
119
120typedef struct Vec4f {
121 float x = 0.0f;
122 float y = 0.0f;
123 float z = 0.0f;
124 float w = 0.0f;
125
126 Vec4f() = default;
127
128 Vec4f(float x_, float y_, float z_, float w_) {
129 x = x_;
130 y = y_;
131 z = z_;
132 w = w_;
133 }
134
135 // probably shouldn't be implicit? I like it though
136 Vec4f(const vec3f &v, float w_ = 1.0f) {
137 x = v.x;
138 y = v.y;
139 z = v.z;
140 w = w_;
141 }
142
143 Vec4f operator+(const Vec4f &o) const {
144 return Vec4f(x + o.x, y + o.y, z + o.z, w + o.w);
145 }
146
147 Vec4f operator*(float s) const {
148 return Vec4f(x * s, y * s, z * s, w * s);
149 }
150
151 Vec4f operator/(float s) const {
152 return Vec4f(x / s, y / s, z / s, w / s);
153 }
154
155 Vec4f operator-(const Vec4f &o) const {
156 return Vec4f(x - o.x, y - o.y, z - o.z, w - o.w);
157 }
158
159 inline Vec3f to_vec3() const {
160 return vec3f(x, y, z);
161 }
162} vec4f;
163
164typedef struct Mat4 {
165 // Row Major : m[row][col]
166 //
167 // Col0 Col1 Col2 Col3
168 // |-----------|-----------|-----------|-----------|
169 // Row0 | Xx | Xy | Xz | Xw |
170 // Row1 | Yx | Yy | Yz | Yw |
171 // Row2 | Zx | Zy | Zz | Zw |
172 // Row3 | Wx | Wy | Wy | Ww |
173 //
174 // Flat memory order (16 floats):
175 // Xx, Xy, Xz, Xw, Yx, Yy, Yz, Yw, Zx, Zy, Zz, Zw, Wx, Wy, Wz, Ww
176
177 float m[4][4];
178
179 static Mat4 zeroed() {
180 // 0 0 0 0
181 // 0 0 0 0
182 // 0 0 0 0
183 // 0 0 0 0
184 Mat4 result;
185 for (int i = 0; i < 4; ++i) {
186 for (int j = 0; j < 4; ++j) {
187 result.m[i][j] = 0.0f;
188 }
189 }
190 return result;
191 }
192
193 // 1 0 0 0
194 // 0 1 0 0
195 // 0 0 1 0
196 // 0 0 0 1
197 static Mat4 identity() {
198 Mat4 result = Mat4::zeroed();
199 for (int i = 0; i < 4; ++i) {
200 result.m[i][i] = 1.0f;
201 }
202 return result;
203 }
204
205 Mat4 operator*(const Mat4 &o) const {
206 Mat4 r;
207 for (int i = 0; i < 4; ++i) {
208 for (int j = 0; j < 4; ++j) {
209 float s = 0.0f;
210 for (int k = 0; k < 4; ++k) {
211 s += m[i][k] * o.m[k][j];
212 }
213 r.m[i][j] = s;
214 }
215 }
216 return r;
217 }
218
219 static Mat4 scale(float sx, float sy, float sz) {
220 Mat4 r = Mat4::identity();
221 // sx 0 0 0
222 // 0 sy 0 0
223 // 0 0 sz 0
224 // 0 0 0 1
225 r.m[0][0] = sx;
226 r.m[1][1] = sy;
227 r.m[2][2] = sz;
228 return r;
229 }
230
231 static Mat4 translate(float tx, float ty, float tz) {
232 Mat4 r = Mat4::identity();
233 // 1 0 0 0
234 // 0 1 0 0
235 // 0 0 1 0
236 // tx ty tz 1
237 r.m[3][0] = tx;
238 r.m[3][1] = ty;
239 r.m[3][2] = tz;
240 return r;
241 }
242
243 static Mat4 rotation_x(float a) {
244 Mat4 r = Mat4::identity();
245 // 0 0 0 0 // x axis
246 // 0 cosf(a) -sinf(a) 0 // y axis
247 // 0 cosf(a) cosf(a) 0 // z axis
248 // 0 0 0 1
249 r.m[1][1] = cosf(a);
250 r.m[1][2] = sinf(a);
251 r.m[2][1] = -sinf(a);
252 r.m[2][2] = cosf(a);
253 return r;
254 }
255
256 static Mat4 rotation_y(float a) {
257 Mat4 r = Mat4::identity();
258 // cosf(a) 0 -sinf(a) 0 // x axis
259 // 0 0 0 0 // y axis
260 // sinf(a) 0 cosf(a) 0 // z axis
261 // 0 0 0 1
262
263 r.m[0][0] = cosf(a);
264 r.m[0][2] = -sinf(a);
265 r.m[2][0] = sinf(a);
266 r.m[2][2] = cosf(a);
267 return r;
268 }
269
270 static Mat4 rotation_z(float a) {
271 // cosf(a) sinf(a) 0 0 // x axis
272 // -sinf(a) cosf(a) 0 0 // y axis
273 // 0 0 1 0 // z axis (lock)
274 // 0 0 0 1
275 Mat4 r = Mat4::identity();
276 r.m[0][0] = cosf(a);
277 r.m[0][1] = sinf(a);
278 r.m[1][0] = -sinf(a);
279 r.m[1][1] = cosf(a);
280 return r;
281 }
282
283 // Build a 4x4 rotation matrix around an arbitrary axis
284 static Mat4 rotation_axis(const vec3f &axis, float angle_rad) {
285 vec3f k = axis.normalized();
286 float c = cosf(angle_rad);
287 float s = sinf(angle_rad);
288 float t = 1.0f - c;
289
290 float kx = k.x, ky = k.y, kz = k.z;
291
292 Mat4 R;
293 R.m[0][0] = t * kx * kx + c;
294 R.m[0][1] = t * kx * ky - s * kz;
295 R.m[0][2] = t * kx * kz + s * ky;
296 R.m[0][3] = 0.0f;
297 // row 1
298 R.m[1][0] = t * kx * ky + s * kz;
299 R.m[1][1] = t * ky * ky + c;
300 R.m[1][2] = t * ky * kz - s * kx;
301 R.m[1][3] = 0.0f;
302 // row 2
303 R.m[2][0] = t * kx * kz - s * ky;
304 R.m[2][1] = t * ky * kz + s * kx;
305 R.m[2][2] = t * kz * kz + c;
306 R.m[2][3] = 0.0f;
307 // row 3
308 R.m[3][0] = 0.0f;
309 R.m[3][1] = 0.0f;
310 R.m[3][2] = 0.0f;
311 R.m[3][3] = 1.0f;
312 return R;
313 }
314
315 void transpose() {
316 for (int i = 0; i < 4; ++i)
317 for (int j = i + 1; j < 4; ++j) {
318 float tmp = m[i][j];
319 m[i][j] = m[j][i];
320 m[j][i] = tmp;
321 }
322 }
323} mat4;
324
325static inline vec4f operator*(const vec4f &v, const mat4 &m) {
326 return vec4f(
327 v.x * m.m[0][0] + v.y * m.m[1][0] + v.z * m.m[2][0] + v.w * m.m[3][0],
328 v.x * m.m[0][1] + v.y * m.m[1][1] + v.z * m.m[2][1] + v.w * m.m[3][1],
329 v.x * m.m[0][2] + v.y * m.m[1][2] + v.z * m.m[2][2] + v.w * m.m[3][2],
330 v.x * m.m[0][3] + v.y * m.m[1][3] + v.z * m.m[2][3] + v.w * m.m[3][3]
331 );
332}
333
334static inline vec2f vec2f_lerp(const vec2f &a, const vec2f &b, float t) {
335 return a * (1.0f - t) + b * t;
336}
337
338static inline vec3f vec3f_lerp(const vec3f &a, const vec3f &b, float t) {
339 return a * (1.0f - t) + b * t;
340}
341
342static inline vec4f vec4f_lerp(const vec4f &a, const vec4f &b, float t) {
343 return vec4f(
344 a.x + (b.x - a.x) * t,
345 a.y + (b.y - a.y) * t,
346 a.z + (b.z - a.z) * t,
347 a.w + (b.w - a.w) * t
348 );
349}