summaryrefslogtreecommitdiff
path: root/src/common/vector_math.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/common/vector_math.h204
1 files changed, 103 insertions, 101 deletions
diff --git a/src/common/vector_math.h b/src/common/vector_math.h
index 429485329..2a0fcf541 100644
--- a/src/common/vector_math.h
+++ b/src/common/vector_math.h
@@ -52,15 +52,15 @@ public:
52 constexpr Vec2(const T& x_, const T& y_) : x(x_), y(y_) {} 52 constexpr Vec2(const T& x_, const T& y_) : x(x_), y(y_) {}
53 53
54 template <typename T2> 54 template <typename T2>
55 constexpr Vec2<T2> Cast() const { 55 [[nodiscard]] constexpr Vec2<T2> Cast() const {
56 return Vec2<T2>(static_cast<T2>(x), static_cast<T2>(y)); 56 return Vec2<T2>(static_cast<T2>(x), static_cast<T2>(y));
57 } 57 }
58 58
59 static constexpr Vec2 AssignToAll(const T& f) { 59 [[nodiscard]] static constexpr Vec2 AssignToAll(const T& f) {
60 return Vec2{f, f}; 60 return Vec2{f, f};
61 } 61 }
62 62
63 constexpr Vec2<decltype(T{} + T{})> operator+(const Vec2& other) const { 63 [[nodiscard]] constexpr Vec2<decltype(T{} + T{})> operator+(const Vec2& other) const {
64 return {x + other.x, y + other.y}; 64 return {x + other.x, y + other.y};
65 } 65 }
66 constexpr Vec2& operator+=(const Vec2& other) { 66 constexpr Vec2& operator+=(const Vec2& other) {
@@ -68,7 +68,7 @@ public:
68 y += other.y; 68 y += other.y;
69 return *this; 69 return *this;
70 } 70 }
71 constexpr Vec2<decltype(T{} - T{})> operator-(const Vec2& other) const { 71 [[nodiscard]] constexpr Vec2<decltype(T{} - T{})> operator-(const Vec2& other) const {
72 return {x - other.x, y - other.y}; 72 return {x - other.x, y - other.y};
73 } 73 }
74 constexpr Vec2& operator-=(const Vec2& other) { 74 constexpr Vec2& operator-=(const Vec2& other) {
@@ -78,15 +78,15 @@ public:
78 } 78 }
79 79
80 template <typename U = T> 80 template <typename U = T>
81 constexpr Vec2<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const { 81 [[nodiscard]] constexpr Vec2<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const {
82 return {-x, -y}; 82 return {-x, -y};
83 } 83 }
84 constexpr Vec2<decltype(T{} * T{})> operator*(const Vec2& other) const { 84 [[nodiscard]] constexpr Vec2<decltype(T{} * T{})> operator*(const Vec2& other) const {
85 return {x * other.x, y * other.y}; 85 return {x * other.x, y * other.y};
86 } 86 }
87 87
88 template <typename V> 88 template <typename V>
89 constexpr Vec2<decltype(T{} * V{})> operator*(const V& f) const { 89 [[nodiscard]] constexpr Vec2<decltype(T{} * V{})> operator*(const V& f) const {
90 return {x * f, y * f}; 90 return {x * f, y * f};
91 } 91 }
92 92
@@ -97,7 +97,7 @@ public:
97 } 97 }
98 98
99 template <typename V> 99 template <typename V>
100 constexpr Vec2<decltype(T{} / V{})> operator/(const V& f) const { 100 [[nodiscard]] constexpr Vec2<decltype(T{} / V{})> operator/(const V& f) const {
101 return {x / f, y / f}; 101 return {x / f, y / f};
102 } 102 }
103 103
@@ -107,18 +107,18 @@ public:
107 return *this; 107 return *this;
108 } 108 }
109 109
110 constexpr T Length2() const { 110 [[nodiscard]] constexpr T Length2() const {
111 return x * x + y * y; 111 return x * x + y * y;
112 } 112 }
113 113
114 // Only implemented for T=float 114 // Only implemented for T=float
115 float Length() const; 115 [[nodiscard]] float Length() const;
116 float Normalize(); // returns the previous length, which is often useful 116 [[nodiscard]] float Normalize(); // returns the previous length, which is often useful
117 117
118 constexpr T& operator[](std::size_t i) { 118 [[nodiscard]] constexpr T& operator[](std::size_t i) {
119 return *((&x) + i); 119 return *((&x) + i);
120 } 120 }
121 constexpr const T& operator[](std::size_t i) const { 121 [[nodiscard]] constexpr const T& operator[](std::size_t i) const {
122 return *((&x) + i); 122 return *((&x) + i);
123 } 123 }
124 124
@@ -128,46 +128,46 @@ public:
128 } 128 }
129 129
130 // Common aliases: UV (texel coordinates), ST (texture coordinates) 130 // Common aliases: UV (texel coordinates), ST (texture coordinates)
131 constexpr T& u() { 131 [[nodiscard]] constexpr T& u() {
132 return x; 132 return x;
133 } 133 }
134 constexpr T& v() { 134 [[nodiscard]] constexpr T& v() {
135 return y; 135 return y;
136 } 136 }
137 constexpr T& s() { 137 [[nodiscard]] constexpr T& s() {
138 return x; 138 return x;
139 } 139 }
140 constexpr T& t() { 140 [[nodiscard]] constexpr T& t() {
141 return y; 141 return y;
142 } 142 }
143 143
144 constexpr const T& u() const { 144 [[nodiscard]] constexpr const T& u() const {
145 return x; 145 return x;
146 } 146 }
147 constexpr const T& v() const { 147 [[nodiscard]] constexpr const T& v() const {
148 return y; 148 return y;
149 } 149 }
150 constexpr const T& s() const { 150 [[nodiscard]] constexpr const T& s() const {
151 return x; 151 return x;
152 } 152 }
153 constexpr const T& t() const { 153 [[nodiscard]] constexpr const T& t() const {
154 return y; 154 return y;
155 } 155 }
156 156
157 // swizzlers - create a subvector of specific components 157 // swizzlers - create a subvector of specific components
158 constexpr Vec2 yx() const { 158 [[nodiscard]] constexpr Vec2 yx() const {
159 return Vec2(y, x); 159 return Vec2(y, x);
160 } 160 }
161 constexpr Vec2 vu() const { 161 [[nodiscard]] constexpr Vec2 vu() const {
162 return Vec2(y, x); 162 return Vec2(y, x);
163 } 163 }
164 constexpr Vec2 ts() const { 164 [[nodiscard]] constexpr Vec2 ts() const {
165 return Vec2(y, x); 165 return Vec2(y, x);
166 } 166 }
167}; 167};
168 168
169template <typename T, typename V> 169template <typename T, typename V>
170constexpr Vec2<T> operator*(const V& f, const Vec2<T>& vec) { 170[[nodiscard]] constexpr Vec2<T> operator*(const V& f, const Vec2<T>& vec) {
171 return Vec2<T>(f * vec.x, f * vec.y); 171 return Vec2<T>(f * vec.x, f * vec.y);
172} 172}
173 173
@@ -196,15 +196,15 @@ public:
196 constexpr Vec3(const T& x_, const T& y_, const T& z_) : x(x_), y(y_), z(z_) {} 196 constexpr Vec3(const T& x_, const T& y_, const T& z_) : x(x_), y(y_), z(z_) {}
197 197
198 template <typename T2> 198 template <typename T2>
199 constexpr Vec3<T2> Cast() const { 199 [[nodiscard]] constexpr Vec3<T2> Cast() const {
200 return Vec3<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z)); 200 return Vec3<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z));
201 } 201 }
202 202
203 static constexpr Vec3 AssignToAll(const T& f) { 203 [[nodiscard]] static constexpr Vec3 AssignToAll(const T& f) {
204 return Vec3(f, f, f); 204 return Vec3(f, f, f);
205 } 205 }
206 206
207 constexpr Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const { 207 [[nodiscard]] constexpr Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const {
208 return {x + other.x, y + other.y, z + other.z}; 208 return {x + other.x, y + other.y, z + other.z};
209 } 209 }
210 210
@@ -215,7 +215,7 @@ public:
215 return *this; 215 return *this;
216 } 216 }
217 217
218 constexpr Vec3<decltype(T{} - T{})> operator-(const Vec3& other) const { 218 [[nodiscard]] constexpr Vec3<decltype(T{} - T{})> operator-(const Vec3& other) const {
219 return {x - other.x, y - other.y, z - other.z}; 219 return {x - other.x, y - other.y, z - other.z};
220 } 220 }
221 221
@@ -227,16 +227,16 @@ public:
227 } 227 }
228 228
229 template <typename U = T> 229 template <typename U = T>
230 constexpr Vec3<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const { 230 [[nodiscard]] constexpr Vec3<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const {
231 return {-x, -y, -z}; 231 return {-x, -y, -z};
232 } 232 }
233 233
234 constexpr Vec3<decltype(T{} * T{})> operator*(const Vec3& other) const { 234 [[nodiscard]] constexpr Vec3<decltype(T{} * T{})> operator*(const Vec3& other) const {
235 return {x * other.x, y * other.y, z * other.z}; 235 return {x * other.x, y * other.y, z * other.z};
236 } 236 }
237 237
238 template <typename V> 238 template <typename V>
239 constexpr Vec3<decltype(T{} * V{})> operator*(const V& f) const { 239 [[nodiscard]] constexpr Vec3<decltype(T{} * V{})> operator*(const V& f) const {
240 return {x * f, y * f, z * f}; 240 return {x * f, y * f, z * f};
241 } 241 }
242 242
@@ -246,7 +246,7 @@ public:
246 return *this; 246 return *this;
247 } 247 }
248 template <typename V> 248 template <typename V>
249 constexpr Vec3<decltype(T{} / V{})> operator/(const V& f) const { 249 [[nodiscard]] constexpr Vec3<decltype(T{} / V{})> operator/(const V& f) const {
250 return {x / f, y / f, z / f}; 250 return {x / f, y / f, z / f};
251 } 251 }
252 252
@@ -256,20 +256,20 @@ public:
256 return *this; 256 return *this;
257 } 257 }
258 258
259 constexpr T Length2() const { 259 [[nodiscard]] constexpr T Length2() const {
260 return x * x + y * y + z * z; 260 return x * x + y * y + z * z;
261 } 261 }
262 262
263 // Only implemented for T=float 263 // Only implemented for T=float
264 float Length() const; 264 [[nodiscard]] float Length() const;
265 Vec3 Normalized() const; 265 [[nodiscard]] Vec3 Normalized() const;
266 float Normalize(); // returns the previous length, which is often useful 266 [[nodiscard]] float Normalize(); // returns the previous length, which is often useful
267 267
268 constexpr T& operator[](std::size_t i) { 268 [[nodiscard]] constexpr T& operator[](std::size_t i) {
269 return *((&x) + i); 269 return *((&x) + i);
270 } 270 }
271 271
272 constexpr const T& operator[](std::size_t i) const { 272 [[nodiscard]] constexpr const T& operator[](std::size_t i) const {
273 return *((&x) + i); 273 return *((&x) + i);
274 } 274 }
275 275
@@ -280,63 +280,63 @@ public:
280 } 280 }
281 281
282 // Common aliases: UVW (texel coordinates), RGB (colors), STQ (texture coordinates) 282 // Common aliases: UVW (texel coordinates), RGB (colors), STQ (texture coordinates)
283 constexpr T& u() { 283 [[nodiscard]] constexpr T& u() {
284 return x; 284 return x;
285 } 285 }
286 constexpr T& v() { 286 [[nodiscard]] constexpr T& v() {
287 return y; 287 return y;
288 } 288 }
289 constexpr T& w() { 289 [[nodiscard]] constexpr T& w() {
290 return z; 290 return z;
291 } 291 }
292 292
293 constexpr T& r() { 293 [[nodiscard]] constexpr T& r() {
294 return x; 294 return x;
295 } 295 }
296 constexpr T& g() { 296 [[nodiscard]] constexpr T& g() {
297 return y; 297 return y;
298 } 298 }
299 constexpr T& b() { 299 [[nodiscard]] constexpr T& b() {
300 return z; 300 return z;
301 } 301 }
302 302
303 constexpr T& s() { 303 [[nodiscard]] constexpr T& s() {
304 return x; 304 return x;
305 } 305 }
306 constexpr T& t() { 306 [[nodiscard]] constexpr T& t() {
307 return y; 307 return y;
308 } 308 }
309 constexpr T& q() { 309 [[nodiscard]] constexpr T& q() {
310 return z; 310 return z;
311 } 311 }
312 312
313 constexpr const T& u() const { 313 [[nodiscard]] constexpr const T& u() const {
314 return x; 314 return x;
315 } 315 }
316 constexpr const T& v() const { 316 [[nodiscard]] constexpr const T& v() const {
317 return y; 317 return y;
318 } 318 }
319 constexpr const T& w() const { 319 [[nodiscard]] constexpr const T& w() const {
320 return z; 320 return z;
321 } 321 }
322 322
323 constexpr const T& r() const { 323 [[nodiscard]] constexpr const T& r() const {
324 return x; 324 return x;
325 } 325 }
326 constexpr const T& g() const { 326 [[nodiscard]] constexpr const T& g() const {
327 return y; 327 return y;
328 } 328 }
329 constexpr const T& b() const { 329 [[nodiscard]] constexpr const T& b() const {
330 return z; 330 return z;
331 } 331 }
332 332
333 constexpr const T& s() const { 333 [[nodiscard]] constexpr const T& s() const {
334 return x; 334 return x;
335 } 335 }
336 constexpr const T& t() const { 336 [[nodiscard]] constexpr const T& t() const {
337 return y; 337 return y;
338 } 338 }
339 constexpr const T& q() const { 339 [[nodiscard]] constexpr const T& q() const {
340 return z; 340 return z;
341 } 341 }
342 342
@@ -345,7 +345,7 @@ public:
345// _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all 345// _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all
346// component names (x<->r) and permutations (xy<->yx) 346// component names (x<->r) and permutations (xy<->yx)
347#define _DEFINE_SWIZZLER2(a, b, name) \ 347#define _DEFINE_SWIZZLER2(a, b, name) \
348 constexpr Vec2<T> name() const { \ 348 [[nodiscard]] constexpr Vec2<T> name() const { \
349 return Vec2<T>(a, b); \ 349 return Vec2<T>(a, b); \
350 } 350 }
351#define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \ 351#define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \
@@ -366,7 +366,7 @@ public:
366}; 366};
367 367
368template <typename T, typename V> 368template <typename T, typename V>
369constexpr Vec3<T> operator*(const V& f, const Vec3<T>& vec) { 369[[nodiscard]] constexpr Vec3<T> operator*(const V& f, const Vec3<T>& vec) {
370 return Vec3<T>(f * vec.x, f * vec.y, f * vec.z); 370 return Vec3<T>(f * vec.x, f * vec.y, f * vec.z);
371} 371}
372 372
@@ -402,16 +402,16 @@ public:
402 : x(x_), y(y_), z(z_), w(w_) {} 402 : x(x_), y(y_), z(z_), w(w_) {}
403 403
404 template <typename T2> 404 template <typename T2>
405 constexpr Vec4<T2> Cast() const { 405 [[nodiscard]] constexpr Vec4<T2> Cast() const {
406 return Vec4<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z), 406 return Vec4<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z),
407 static_cast<T2>(w)); 407 static_cast<T2>(w));
408 } 408 }
409 409
410 static constexpr Vec4 AssignToAll(const T& f) { 410 [[nodiscard]] static constexpr Vec4 AssignToAll(const T& f) {
411 return Vec4(f, f, f, f); 411 return Vec4(f, f, f, f);
412 } 412 }
413 413
414 constexpr Vec4<decltype(T{} + T{})> operator+(const Vec4& other) const { 414 [[nodiscard]] constexpr Vec4<decltype(T{} + T{})> operator+(const Vec4& other) const {
415 return {x + other.x, y + other.y, z + other.z, w + other.w}; 415 return {x + other.x, y + other.y, z + other.z, w + other.w};
416 } 416 }
417 417
@@ -423,7 +423,7 @@ public:
423 return *this; 423 return *this;
424 } 424 }
425 425
426 constexpr Vec4<decltype(T{} - T{})> operator-(const Vec4& other) const { 426 [[nodiscard]] constexpr Vec4<decltype(T{} - T{})> operator-(const Vec4& other) const {
427 return {x - other.x, y - other.y, z - other.z, w - other.w}; 427 return {x - other.x, y - other.y, z - other.z, w - other.w};
428 } 428 }
429 429
@@ -436,16 +436,16 @@ public:
436 } 436 }
437 437
438 template <typename U = T> 438 template <typename U = T>
439 constexpr Vec4<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const { 439 [[nodiscard]] constexpr Vec4<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const {
440 return {-x, -y, -z, -w}; 440 return {-x, -y, -z, -w};
441 } 441 }
442 442
443 constexpr Vec4<decltype(T{} * T{})> operator*(const Vec4& other) const { 443 [[nodiscard]] constexpr Vec4<decltype(T{} * T{})> operator*(const Vec4& other) const {
444 return {x * other.x, y * other.y, z * other.z, w * other.w}; 444 return {x * other.x, y * other.y, z * other.z, w * other.w};
445 } 445 }
446 446
447 template <typename V> 447 template <typename V>
448 constexpr Vec4<decltype(T{} * V{})> operator*(const V& f) const { 448 [[nodiscard]] constexpr Vec4<decltype(T{} * V{})> operator*(const V& f) const {
449 return {x * f, y * f, z * f, w * f}; 449 return {x * f, y * f, z * f, w * f};
450 } 450 }
451 451
@@ -456,7 +456,7 @@ public:
456 } 456 }
457 457
458 template <typename V> 458 template <typename V>
459 constexpr Vec4<decltype(T{} / V{})> operator/(const V& f) const { 459 [[nodiscard]] constexpr Vec4<decltype(T{} / V{})> operator/(const V& f) const {
460 return {x / f, y / f, z / f, w / f}; 460 return {x / f, y / f, z / f, w / f};
461 } 461 }
462 462
@@ -466,15 +466,15 @@ public:
466 return *this; 466 return *this;
467 } 467 }
468 468
469 constexpr T Length2() const { 469 [[nodiscard]] constexpr T Length2() const {
470 return x * x + y * y + z * z + w * w; 470 return x * x + y * y + z * z + w * w;
471 } 471 }
472 472
473 constexpr T& operator[](std::size_t i) { 473 [[nodiscard]] constexpr T& operator[](std::size_t i) {
474 return *((&x) + i); 474 return *((&x) + i);
475 } 475 }
476 476
477 constexpr const T& operator[](std::size_t i) const { 477 [[nodiscard]] constexpr const T& operator[](std::size_t i) const {
478 return *((&x) + i); 478 return *((&x) + i);
479 } 479 }
480 480
@@ -486,29 +486,29 @@ public:
486 } 486 }
487 487
488 // Common alias: RGBA (colors) 488 // Common alias: RGBA (colors)
489 constexpr T& r() { 489 [[nodiscard]] constexpr T& r() {
490 return x; 490 return x;
491 } 491 }
492 constexpr T& g() { 492 [[nodiscard]] constexpr T& g() {
493 return y; 493 return y;
494 } 494 }
495 constexpr T& b() { 495 [[nodiscard]] constexpr T& b() {
496 return z; 496 return z;
497 } 497 }
498 constexpr T& a() { 498 [[nodiscard]] constexpr T& a() {
499 return w; 499 return w;
500 } 500 }
501 501
502 constexpr const T& r() const { 502 [[nodiscard]] constexpr const T& r() const {
503 return x; 503 return x;
504 } 504 }
505 constexpr const T& g() const { 505 [[nodiscard]] constexpr const T& g() const {
506 return y; 506 return y;
507 } 507 }
508 constexpr const T& b() const { 508 [[nodiscard]] constexpr const T& b() const {
509 return z; 509 return z;
510 } 510 }
511 constexpr const T& a() const { 511 [[nodiscard]] constexpr const T& a() const {
512 return w; 512 return w;
513 } 513 }
514 514
@@ -520,7 +520,7 @@ public:
520// DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and 520// DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and
521// permutations (xy<->yx) 521// permutations (xy<->yx)
522#define _DEFINE_SWIZZLER2(a, b, name) \ 522#define _DEFINE_SWIZZLER2(a, b, name) \
523 constexpr Vec2<T> name() const { \ 523 [[nodiscard]] constexpr Vec2<T> name() const { \
524 return Vec2<T>(a, b); \ 524 return Vec2<T>(a, b); \
525 } 525 }
526#define DEFINE_SWIZZLER2_COMP1(a, a2) \ 526#define DEFINE_SWIZZLER2_COMP1(a, a2) \
@@ -547,7 +547,7 @@ public:
547#undef _DEFINE_SWIZZLER2 547#undef _DEFINE_SWIZZLER2
548 548
549#define _DEFINE_SWIZZLER3(a, b, c, name) \ 549#define _DEFINE_SWIZZLER3(a, b, c, name) \
550 constexpr Vec3<T> name() const { \ 550 [[nodiscard]] constexpr Vec3<T> name() const { \
551 return Vec3<T>(a, b, c); \ 551 return Vec3<T>(a, b, c); \
552 } 552 }
553#define DEFINE_SWIZZLER3_COMP1(a, a2) \ 553#define DEFINE_SWIZZLER3_COMP1(a, a2) \
@@ -581,7 +581,7 @@ public:
581}; 581};
582 582
583template <typename T, typename V> 583template <typename T, typename V>
584constexpr Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) { 584[[nodiscard]] constexpr Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) {
585 return {f * vec.x, f * vec.y, f * vec.z, f * vec.w}; 585 return {f * vec.x, f * vec.y, f * vec.z, f * vec.w};
586} 586}
587 587
@@ -593,39 +593,41 @@ constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec2<T>& a, const Vec2<T>& b
593} 593}
594 594
595template <typename T> 595template <typename T>
596constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec3<T>& a, const Vec3<T>& b) { 596[[nodiscard]] constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec3<T>& a, const Vec3<T>& b) {
597 return a.x * b.x + a.y * b.y + a.z * b.z; 597 return a.x * b.x + a.y * b.y + a.z * b.z;
598} 598}
599 599
600template <typename T> 600template <typename T>
601constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec4<T>& a, const Vec4<T>& b) { 601[[nodiscard]] constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec4<T>& a, const Vec4<T>& b) {
602 return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; 602 return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
603} 603}
604 604
605template <typename T> 605template <typename T>
606constexpr Vec3<decltype(T{} * T{} - T{} * T{})> Cross(const Vec3<T>& a, const Vec3<T>& b) { 606[[nodiscard]] constexpr Vec3<decltype(T{} * T{} - T{} * T{})> Cross(const Vec3<T>& a,
607 const Vec3<T>& b) {
607 return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x}; 608 return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x};
608} 609}
609 610
610// linear interpolation via float: 0.0=begin, 1.0=end 611// linear interpolation via float: 0.0=begin, 1.0=end
611template <typename X> 612template <typename X>
612constexpr decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end, 613[[nodiscard]] constexpr decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end,
613 const float t) { 614 const float t) {
614 return begin * (1.f - t) + end * t; 615 return begin * (1.f - t) + end * t;
615} 616}
616 617
617// linear interpolation via int: 0=begin, base=end 618// linear interpolation via int: 0=begin, base=end
618template <typename X, int base> 619template <typename X, int base>
619constexpr decltype((X{} * int{} + X{} * int{}) / base) LerpInt(const X& begin, const X& end, 620[[nodiscard]] constexpr decltype((X{} * int{} + X{} * int{}) / base) LerpInt(const X& begin,
620 const int t) { 621 const X& end,
622 const int t) {
621 return (begin * (base - t) + end * t) / base; 623 return (begin * (base - t) + end * t) / base;
622} 624}
623 625
624// bilinear interpolation. s is for interpolating x00-x01 and x10-x11, and t is for the second 626// bilinear interpolation. s is for interpolating x00-x01 and x10-x11, and t is for the second
625// interpolation. 627// interpolation.
626template <typename X> 628template <typename X>
627constexpr auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x11, const float s, 629[[nodiscard]] constexpr auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x11,
628 const float t) { 630 const float s, const float t) {
629 auto y0 = Lerp(x00, x01, s); 631 auto y0 = Lerp(x00, x01, s);
630 auto y1 = Lerp(x10, x11, s); 632 auto y1 = Lerp(x10, x11, s);
631 return Lerp(y0, y1, t); 633 return Lerp(y0, y1, t);
@@ -633,42 +635,42 @@ constexpr auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X&
633 635
634// Utility vector factories 636// Utility vector factories
635template <typename T> 637template <typename T>
636constexpr Vec2<T> MakeVec(const T& x, const T& y) { 638[[nodiscard]] constexpr Vec2<T> MakeVec(const T& x, const T& y) {
637 return Vec2<T>{x, y}; 639 return Vec2<T>{x, y};
638} 640}
639 641
640template <typename T> 642template <typename T>
641constexpr Vec3<T> MakeVec(const T& x, const T& y, const T& z) { 643[[nodiscard]] constexpr Vec3<T> MakeVec(const T& x, const T& y, const T& z) {
642 return Vec3<T>{x, y, z}; 644 return Vec3<T>{x, y, z};
643} 645}
644 646
645template <typename T> 647template <typename T>
646constexpr Vec4<T> MakeVec(const T& x, const T& y, const Vec2<T>& zw) { 648[[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const T& y, const Vec2<T>& zw) {
647 return MakeVec(x, y, zw[0], zw[1]); 649 return MakeVec(x, y, zw[0], zw[1]);
648} 650}
649 651
650template <typename T> 652template <typename T>
651constexpr Vec3<T> MakeVec(const Vec2<T>& xy, const T& z) { 653[[nodiscard]] constexpr Vec3<T> MakeVec(const Vec2<T>& xy, const T& z) {
652 return MakeVec(xy[0], xy[1], z); 654 return MakeVec(xy[0], xy[1], z);
653} 655}
654 656
655template <typename T> 657template <typename T>
656constexpr Vec3<T> MakeVec(const T& x, const Vec2<T>& yz) { 658[[nodiscard]] constexpr Vec3<T> MakeVec(const T& x, const Vec2<T>& yz) {
657 return MakeVec(x, yz[0], yz[1]); 659 return MakeVec(x, yz[0], yz[1]);
658} 660}
659 661
660template <typename T> 662template <typename T>
661constexpr Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w) { 663[[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w) {
662 return Vec4<T>{x, y, z, w}; 664 return Vec4<T>{x, y, z, w};
663} 665}
664 666
665template <typename T> 667template <typename T>
666constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const T& z, const T& w) { 668[[nodiscard]] constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const T& z, const T& w) {
667 return MakeVec(xy[0], xy[1], z, w); 669 return MakeVec(xy[0], xy[1], z, w);
668} 670}
669 671
670template <typename T> 672template <typename T>
671constexpr Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) { 673[[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) {
672 return MakeVec(x, yz[0], yz[1], w); 674 return MakeVec(x, yz[0], yz[1], w);
673} 675}
674 676
@@ -676,17 +678,17 @@ constexpr Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) {
676// Even if someone wanted to use an odd object like Vec2<Vec2<T>>, the compiler would error 678// Even if someone wanted to use an odd object like Vec2<Vec2<T>>, the compiler would error
677// out soon enough due to misuse of the returned structure. 679// out soon enough due to misuse of the returned structure.
678template <typename T> 680template <typename T>
679constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const Vec2<T>& zw) { 681[[nodiscard]] constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const Vec2<T>& zw) {
680 return MakeVec(xy[0], xy[1], zw[0], zw[1]); 682 return MakeVec(xy[0], xy[1], zw[0], zw[1]);
681} 683}
682 684
683template <typename T> 685template <typename T>
684constexpr Vec4<T> MakeVec(const Vec3<T>& xyz, const T& w) { 686[[nodiscard]] constexpr Vec4<T> MakeVec(const Vec3<T>& xyz, const T& w) {
685 return MakeVec(xyz[0], xyz[1], xyz[2], w); 687 return MakeVec(xyz[0], xyz[1], xyz[2], w);
686} 688}
687 689
688template <typename T> 690template <typename T>
689constexpr Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw) { 691[[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw) {
690 return MakeVec(x, yzw[0], yzw[1], yzw[2]); 692 return MakeVec(x, yzw[0], yzw[1], yzw[2]);
691} 693}
692 694