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