summaryrefslogtreecommitdiff
path: root/src/common/vector_math.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/vector_math.h')
-rw-r--r--src/common/vector_math.h279
1 files changed, 169 insertions, 110 deletions
diff --git a/src/common/vector_math.h b/src/common/vector_math.h
index 429485329..22dba3c2d 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,16 +78,22 @@ 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 using TV = decltype(T{} * V{});
91 using C = std::common_type_t<T, V>;
92
93 return {
94 static_cast<TV>(static_cast<C>(x) * static_cast<C>(f)),
95 static_cast<TV>(static_cast<C>(y) * static_cast<C>(f)),
96 };
91 } 97 }
92 98
93 template <typename V> 99 template <typename V>
@@ -97,8 +103,14 @@ public:
97 } 103 }
98 104
99 template <typename V> 105 template <typename V>
100 constexpr Vec2<decltype(T{} / V{})> operator/(const V& f) const { 106 [[nodiscard]] constexpr Vec2<decltype(T{} / V{})> operator/(const V& f) const {
101 return {x / f, y / f}; 107 using TV = decltype(T{} / V{});
108 using C = std::common_type_t<T, V>;
109
110 return {
111 static_cast<TV>(static_cast<C>(x) / static_cast<C>(f)),
112 static_cast<TV>(static_cast<C>(y) / static_cast<C>(f)),
113 };
102 } 114 }
103 115
104 template <typename V> 116 template <typename V>
@@ -107,18 +119,18 @@ public:
107 return *this; 119 return *this;
108 } 120 }
109 121
110 constexpr T Length2() const { 122 [[nodiscard]] constexpr T Length2() const {
111 return x * x + y * y; 123 return x * x + y * y;
112 } 124 }
113 125
114 // Only implemented for T=float 126 // Only implemented for T=float
115 float Length() const; 127 [[nodiscard]] float Length() const;
116 float Normalize(); // returns the previous length, which is often useful 128 [[nodiscard]] float Normalize(); // returns the previous length, which is often useful
117 129
118 constexpr T& operator[](std::size_t i) { 130 [[nodiscard]] constexpr T& operator[](std::size_t i) {
119 return *((&x) + i); 131 return *((&x) + i);
120 } 132 }
121 constexpr const T& operator[](std::size_t i) const { 133 [[nodiscard]] constexpr const T& operator[](std::size_t i) const {
122 return *((&x) + i); 134 return *((&x) + i);
123 } 135 }
124 136
@@ -128,47 +140,50 @@ public:
128 } 140 }
129 141
130 // Common aliases: UV (texel coordinates), ST (texture coordinates) 142 // Common aliases: UV (texel coordinates), ST (texture coordinates)
131 constexpr T& u() { 143 [[nodiscard]] constexpr T& u() {
132 return x; 144 return x;
133 } 145 }
134 constexpr T& v() { 146 [[nodiscard]] constexpr T& v() {
135 return y; 147 return y;
136 } 148 }
137 constexpr T& s() { 149 [[nodiscard]] constexpr T& s() {
138 return x; 150 return x;
139 } 151 }
140 constexpr T& t() { 152 [[nodiscard]] constexpr T& t() {
141 return y; 153 return y;
142 } 154 }
143 155
144 constexpr const T& u() const { 156 [[nodiscard]] constexpr const T& u() const {
145 return x; 157 return x;
146 } 158 }
147 constexpr const T& v() const { 159 [[nodiscard]] constexpr const T& v() const {
148 return y; 160 return y;
149 } 161 }
150 constexpr const T& s() const { 162 [[nodiscard]] constexpr const T& s() const {
151 return x; 163 return x;
152 } 164 }
153 constexpr const T& t() const { 165 [[nodiscard]] constexpr const T& t() const {
154 return y; 166 return y;
155 } 167 }
156 168
157 // swizzlers - create a subvector of specific components 169 // swizzlers - create a subvector of specific components
158 constexpr Vec2 yx() const { 170 [[nodiscard]] constexpr Vec2 yx() const {
159 return Vec2(y, x); 171 return Vec2(y, x);
160 } 172 }
161 constexpr Vec2 vu() const { 173 [[nodiscard]] constexpr Vec2 vu() const {
162 return Vec2(y, x); 174 return Vec2(y, x);
163 } 175 }
164 constexpr Vec2 ts() const { 176 [[nodiscard]] constexpr Vec2 ts() const {
165 return Vec2(y, x); 177 return Vec2(y, x);
166 } 178 }
167}; 179};
168 180
169template <typename T, typename V> 181template <typename T, typename V>
170constexpr Vec2<T> operator*(const V& f, const Vec2<T>& vec) { 182[[nodiscard]] constexpr Vec2<T> operator*(const V& f, const Vec2<T>& vec) {
171 return Vec2<T>(f * vec.x, f * vec.y); 183 using C = std::common_type_t<T, V>;
184
185 return Vec2<T>(static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.x)),
186 static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.y)));
172} 187}
173 188
174using Vec2f = Vec2<float>; 189using Vec2f = Vec2<float>;
@@ -196,15 +211,15 @@ public:
196 constexpr Vec3(const T& x_, const T& y_, const T& z_) : x(x_), y(y_), z(z_) {} 211 constexpr Vec3(const T& x_, const T& y_, const T& z_) : x(x_), y(y_), z(z_) {}
197 212
198 template <typename T2> 213 template <typename T2>
199 constexpr Vec3<T2> Cast() const { 214 [[nodiscard]] constexpr Vec3<T2> Cast() const {
200 return Vec3<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z)); 215 return Vec3<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z));
201 } 216 }
202 217
203 static constexpr Vec3 AssignToAll(const T& f) { 218 [[nodiscard]] static constexpr Vec3 AssignToAll(const T& f) {
204 return Vec3(f, f, f); 219 return Vec3(f, f, f);
205 } 220 }
206 221
207 constexpr Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const { 222 [[nodiscard]] constexpr Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const {
208 return {x + other.x, y + other.y, z + other.z}; 223 return {x + other.x, y + other.y, z + other.z};
209 } 224 }
210 225
@@ -215,7 +230,7 @@ public:
215 return *this; 230 return *this;
216 } 231 }
217 232
218 constexpr Vec3<decltype(T{} - T{})> operator-(const Vec3& other) const { 233 [[nodiscard]] constexpr Vec3<decltype(T{} - T{})> operator-(const Vec3& other) const {
219 return {x - other.x, y - other.y, z - other.z}; 234 return {x - other.x, y - other.y, z - other.z};
220 } 235 }
221 236
@@ -227,17 +242,24 @@ public:
227 } 242 }
228 243
229 template <typename U = T> 244 template <typename U = T>
230 constexpr Vec3<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const { 245 [[nodiscard]] constexpr Vec3<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const {
231 return {-x, -y, -z}; 246 return {-x, -y, -z};
232 } 247 }
233 248
234 constexpr Vec3<decltype(T{} * T{})> operator*(const Vec3& other) const { 249 [[nodiscard]] constexpr Vec3<decltype(T{} * T{})> operator*(const Vec3& other) const {
235 return {x * other.x, y * other.y, z * other.z}; 250 return {x * other.x, y * other.y, z * other.z};
236 } 251 }
237 252
238 template <typename V> 253 template <typename V>
239 constexpr Vec3<decltype(T{} * V{})> operator*(const V& f) const { 254 [[nodiscard]] constexpr Vec3<decltype(T{} * V{})> operator*(const V& f) const {
240 return {x * f, y * f, z * f}; 255 using TV = decltype(T{} * V{});
256 using C = std::common_type_t<T, V>;
257
258 return {
259 static_cast<TV>(static_cast<C>(x) * static_cast<C>(f)),
260 static_cast<TV>(static_cast<C>(y) * static_cast<C>(f)),
261 static_cast<TV>(static_cast<C>(z) * static_cast<C>(f)),
262 };
241 } 263 }
242 264
243 template <typename V> 265 template <typename V>
@@ -246,8 +268,15 @@ public:
246 return *this; 268 return *this;
247 } 269 }
248 template <typename V> 270 template <typename V>
249 constexpr Vec3<decltype(T{} / V{})> operator/(const V& f) const { 271 [[nodiscard]] constexpr Vec3<decltype(T{} / V{})> operator/(const V& f) const {
250 return {x / f, y / f, z / f}; 272 using TV = decltype(T{} / V{});
273 using C = std::common_type_t<T, V>;
274
275 return {
276 static_cast<TV>(static_cast<C>(x) / static_cast<C>(f)),
277 static_cast<TV>(static_cast<C>(y) / static_cast<C>(f)),
278 static_cast<TV>(static_cast<C>(z) / static_cast<C>(f)),
279 };
251 } 280 }
252 281
253 template <typename V> 282 template <typename V>
@@ -256,20 +285,20 @@ public:
256 return *this; 285 return *this;
257 } 286 }
258 287
259 constexpr T Length2() const { 288 [[nodiscard]] constexpr T Length2() const {
260 return x * x + y * y + z * z; 289 return x * x + y * y + z * z;
261 } 290 }
262 291
263 // Only implemented for T=float 292 // Only implemented for T=float
264 float Length() const; 293 [[nodiscard]] float Length() const;
265 Vec3 Normalized() const; 294 [[nodiscard]] Vec3 Normalized() const;
266 float Normalize(); // returns the previous length, which is often useful 295 [[nodiscard]] float Normalize(); // returns the previous length, which is often useful
267 296
268 constexpr T& operator[](std::size_t i) { 297 [[nodiscard]] constexpr T& operator[](std::size_t i) {
269 return *((&x) + i); 298 return *((&x) + i);
270 } 299 }
271 300
272 constexpr const T& operator[](std::size_t i) const { 301 [[nodiscard]] constexpr const T& operator[](std::size_t i) const {
273 return *((&x) + i); 302 return *((&x) + i);
274 } 303 }
275 304
@@ -280,63 +309,63 @@ public:
280 } 309 }
281 310
282 // Common aliases: UVW (texel coordinates), RGB (colors), STQ (texture coordinates) 311 // Common aliases: UVW (texel coordinates), RGB (colors), STQ (texture coordinates)
283 constexpr T& u() { 312 [[nodiscard]] constexpr T& u() {
284 return x; 313 return x;
285 } 314 }
286 constexpr T& v() { 315 [[nodiscard]] constexpr T& v() {
287 return y; 316 return y;
288 } 317 }
289 constexpr T& w() { 318 [[nodiscard]] constexpr T& w() {
290 return z; 319 return z;
291 } 320 }
292 321
293 constexpr T& r() { 322 [[nodiscard]] constexpr T& r() {
294 return x; 323 return x;
295 } 324 }
296 constexpr T& g() { 325 [[nodiscard]] constexpr T& g() {
297 return y; 326 return y;
298 } 327 }
299 constexpr T& b() { 328 [[nodiscard]] constexpr T& b() {
300 return z; 329 return z;
301 } 330 }
302 331
303 constexpr T& s() { 332 [[nodiscard]] constexpr T& s() {
304 return x; 333 return x;
305 } 334 }
306 constexpr T& t() { 335 [[nodiscard]] constexpr T& t() {
307 return y; 336 return y;
308 } 337 }
309 constexpr T& q() { 338 [[nodiscard]] constexpr T& q() {
310 return z; 339 return z;
311 } 340 }
312 341
313 constexpr const T& u() const { 342 [[nodiscard]] constexpr const T& u() const {
314 return x; 343 return x;
315 } 344 }
316 constexpr const T& v() const { 345 [[nodiscard]] constexpr const T& v() const {
317 return y; 346 return y;
318 } 347 }
319 constexpr const T& w() const { 348 [[nodiscard]] constexpr const T& w() const {
320 return z; 349 return z;
321 } 350 }
322 351
323 constexpr const T& r() const { 352 [[nodiscard]] constexpr const T& r() const {
324 return x; 353 return x;
325 } 354 }
326 constexpr const T& g() const { 355 [[nodiscard]] constexpr const T& g() const {
327 return y; 356 return y;
328 } 357 }
329 constexpr const T& b() const { 358 [[nodiscard]] constexpr const T& b() const {
330 return z; 359 return z;
331 } 360 }
332 361
333 constexpr const T& s() const { 362 [[nodiscard]] constexpr const T& s() const {
334 return x; 363 return x;
335 } 364 }
336 constexpr const T& t() const { 365 [[nodiscard]] constexpr const T& t() const {
337 return y; 366 return y;
338 } 367 }
339 constexpr const T& q() const { 368 [[nodiscard]] constexpr const T& q() const {
340 return z; 369 return z;
341 } 370 }
342 371
@@ -345,7 +374,7 @@ public:
345// _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all 374// _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all
346// component names (x<->r) and permutations (xy<->yx) 375// component names (x<->r) and permutations (xy<->yx)
347#define _DEFINE_SWIZZLER2(a, b, name) \ 376#define _DEFINE_SWIZZLER2(a, b, name) \
348 constexpr Vec2<T> name() const { \ 377 [[nodiscard]] constexpr Vec2<T> name() const { \
349 return Vec2<T>(a, b); \ 378 return Vec2<T>(a, b); \
350 } 379 }
351#define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \ 380#define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \
@@ -366,8 +395,12 @@ public:
366}; 395};
367 396
368template <typename T, typename V> 397template <typename T, typename V>
369constexpr Vec3<T> operator*(const V& f, const Vec3<T>& vec) { 398[[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); 399 using C = std::common_type_t<T, V>;
400
401 return Vec3<T>(static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.x)),
402 static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.y)),
403 static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.z)));
371} 404}
372 405
373template <> 406template <>
@@ -402,16 +435,16 @@ public:
402 : x(x_), y(y_), z(z_), w(w_) {} 435 : x(x_), y(y_), z(z_), w(w_) {}
403 436
404 template <typename T2> 437 template <typename T2>
405 constexpr Vec4<T2> Cast() const { 438 [[nodiscard]] constexpr Vec4<T2> Cast() const {
406 return Vec4<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z), 439 return Vec4<T2>(static_cast<T2>(x), static_cast<T2>(y), static_cast<T2>(z),
407 static_cast<T2>(w)); 440 static_cast<T2>(w));
408 } 441 }
409 442
410 static constexpr Vec4 AssignToAll(const T& f) { 443 [[nodiscard]] static constexpr Vec4 AssignToAll(const T& f) {
411 return Vec4(f, f, f, f); 444 return Vec4(f, f, f, f);
412 } 445 }
413 446
414 constexpr Vec4<decltype(T{} + T{})> operator+(const Vec4& other) const { 447 [[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}; 448 return {x + other.x, y + other.y, z + other.z, w + other.w};
416 } 449 }
417 450
@@ -423,7 +456,7 @@ public:
423 return *this; 456 return *this;
424 } 457 }
425 458
426 constexpr Vec4<decltype(T{} - T{})> operator-(const Vec4& other) const { 459 [[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}; 460 return {x - other.x, y - other.y, z - other.z, w - other.w};
428 } 461 }
429 462
@@ -436,17 +469,25 @@ public:
436 } 469 }
437 470
438 template <typename U = T> 471 template <typename U = T>
439 constexpr Vec4<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const { 472 [[nodiscard]] constexpr Vec4<std::enable_if_t<std::is_signed_v<U>, U>> operator-() const {
440 return {-x, -y, -z, -w}; 473 return {-x, -y, -z, -w};
441 } 474 }
442 475
443 constexpr Vec4<decltype(T{} * T{})> operator*(const Vec4& other) const { 476 [[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}; 477 return {x * other.x, y * other.y, z * other.z, w * other.w};
445 } 478 }
446 479
447 template <typename V> 480 template <typename V>
448 constexpr Vec4<decltype(T{} * V{})> operator*(const V& f) const { 481 [[nodiscard]] constexpr Vec4<decltype(T{} * V{})> operator*(const V& f) const {
449 return {x * f, y * f, z * f, w * f}; 482 using TV = decltype(T{} * V{});
483 using C = std::common_type_t<T, V>;
484
485 return {
486 static_cast<TV>(static_cast<C>(x) * static_cast<C>(f)),
487 static_cast<TV>(static_cast<C>(y) * static_cast<C>(f)),
488 static_cast<TV>(static_cast<C>(z) * static_cast<C>(f)),
489 static_cast<TV>(static_cast<C>(w) * static_cast<C>(f)),
490 };
450 } 491 }
451 492
452 template <typename V> 493 template <typename V>
@@ -456,8 +497,16 @@ public:
456 } 497 }
457 498
458 template <typename V> 499 template <typename V>
459 constexpr Vec4<decltype(T{} / V{})> operator/(const V& f) const { 500 [[nodiscard]] constexpr Vec4<decltype(T{} / V{})> operator/(const V& f) const {
460 return {x / f, y / f, z / f, w / f}; 501 using TV = decltype(T{} / V{});
502 using C = std::common_type_t<T, V>;
503
504 return {
505 static_cast<TV>(static_cast<C>(x) / static_cast<C>(f)),
506 static_cast<TV>(static_cast<C>(y) / static_cast<C>(f)),
507 static_cast<TV>(static_cast<C>(z) / static_cast<C>(f)),
508 static_cast<TV>(static_cast<C>(w) / static_cast<C>(f)),
509 };
461 } 510 }
462 511
463 template <typename V> 512 template <typename V>
@@ -466,15 +515,15 @@ public:
466 return *this; 515 return *this;
467 } 516 }
468 517
469 constexpr T Length2() const { 518 [[nodiscard]] constexpr T Length2() const {
470 return x * x + y * y + z * z + w * w; 519 return x * x + y * y + z * z + w * w;
471 } 520 }
472 521
473 constexpr T& operator[](std::size_t i) { 522 [[nodiscard]] constexpr T& operator[](std::size_t i) {
474 return *((&x) + i); 523 return *((&x) + i);
475 } 524 }
476 525
477 constexpr const T& operator[](std::size_t i) const { 526 [[nodiscard]] constexpr const T& operator[](std::size_t i) const {
478 return *((&x) + i); 527 return *((&x) + i);
479 } 528 }
480 529
@@ -486,29 +535,29 @@ public:
486 } 535 }
487 536
488 // Common alias: RGBA (colors) 537 // Common alias: RGBA (colors)
489 constexpr T& r() { 538 [[nodiscard]] constexpr T& r() {
490 return x; 539 return x;
491 } 540 }
492 constexpr T& g() { 541 [[nodiscard]] constexpr T& g() {
493 return y; 542 return y;
494 } 543 }
495 constexpr T& b() { 544 [[nodiscard]] constexpr T& b() {
496 return z; 545 return z;
497 } 546 }
498 constexpr T& a() { 547 [[nodiscard]] constexpr T& a() {
499 return w; 548 return w;
500 } 549 }
501 550
502 constexpr const T& r() const { 551 [[nodiscard]] constexpr const T& r() const {
503 return x; 552 return x;
504 } 553 }
505 constexpr const T& g() const { 554 [[nodiscard]] constexpr const T& g() const {
506 return y; 555 return y;
507 } 556 }
508 constexpr const T& b() const { 557 [[nodiscard]] constexpr const T& b() const {
509 return z; 558 return z;
510 } 559 }
511 constexpr const T& a() const { 560 [[nodiscard]] constexpr const T& a() const {
512 return w; 561 return w;
513 } 562 }
514 563
@@ -520,7 +569,7 @@ public:
520// DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and 569// DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and
521// permutations (xy<->yx) 570// permutations (xy<->yx)
522#define _DEFINE_SWIZZLER2(a, b, name) \ 571#define _DEFINE_SWIZZLER2(a, b, name) \
523 constexpr Vec2<T> name() const { \ 572 [[nodiscard]] constexpr Vec2<T> name() const { \
524 return Vec2<T>(a, b); \ 573 return Vec2<T>(a, b); \
525 } 574 }
526#define DEFINE_SWIZZLER2_COMP1(a, a2) \ 575#define DEFINE_SWIZZLER2_COMP1(a, a2) \
@@ -547,7 +596,7 @@ public:
547#undef _DEFINE_SWIZZLER2 596#undef _DEFINE_SWIZZLER2
548 597
549#define _DEFINE_SWIZZLER3(a, b, c, name) \ 598#define _DEFINE_SWIZZLER3(a, b, c, name) \
550 constexpr Vec3<T> name() const { \ 599 [[nodiscard]] constexpr Vec3<T> name() const { \
551 return Vec3<T>(a, b, c); \ 600 return Vec3<T>(a, b, c); \
552 } 601 }
553#define DEFINE_SWIZZLER3_COMP1(a, a2) \ 602#define DEFINE_SWIZZLER3_COMP1(a, a2) \
@@ -581,8 +630,16 @@ public:
581}; 630};
582 631
583template <typename T, typename V> 632template <typename T, typename V>
584constexpr Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) { 633[[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}; 634 using TV = decltype(V{} * T{});
635 using C = std::common_type_t<T, V>;
636
637 return {
638 static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.x)),
639 static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.y)),
640 static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.z)),
641 static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.w)),
642 };
586} 643}
587 644
588using Vec4f = Vec4<float>; 645using Vec4f = Vec4<float>;
@@ -593,39 +650,41 @@ constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec2<T>& a, const Vec2<T>& b
593} 650}
594 651
595template <typename T> 652template <typename T>
596constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec3<T>& a, const Vec3<T>& b) { 653[[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; 654 return a.x * b.x + a.y * b.y + a.z * b.z;
598} 655}
599 656
600template <typename T> 657template <typename T>
601constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec4<T>& a, const Vec4<T>& b) { 658[[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; 659 return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
603} 660}
604 661
605template <typename T> 662template <typename T>
606constexpr Vec3<decltype(T{} * T{} - T{} * T{})> Cross(const Vec3<T>& a, const Vec3<T>& b) { 663[[nodiscard]] constexpr Vec3<decltype(T{} * T{} - T{} * T{})> Cross(const Vec3<T>& a,
664 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}; 665 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} 666}
609 667
610// linear interpolation via float: 0.0=begin, 1.0=end 668// linear interpolation via float: 0.0=begin, 1.0=end
611template <typename X> 669template <typename X>
612constexpr decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end, 670[[nodiscard]] constexpr decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end,
613 const float t) { 671 const float t) {
614 return begin * (1.f - t) + end * t; 672 return begin * (1.f - t) + end * t;
615} 673}
616 674
617// linear interpolation via int: 0=begin, base=end 675// linear interpolation via int: 0=begin, base=end
618template <typename X, int base> 676template <typename X, int base>
619constexpr decltype((X{} * int{} + X{} * int{}) / base) LerpInt(const X& begin, const X& end, 677[[nodiscard]] constexpr decltype((X{} * int{} + X{} * int{}) / base) LerpInt(const X& begin,
620 const int t) { 678 const X& end,
679 const int t) {
621 return (begin * (base - t) + end * t) / base; 680 return (begin * (base - t) + end * t) / base;
622} 681}
623 682
624// bilinear interpolation. s is for interpolating x00-x01 and x10-x11, and t is for the second 683// bilinear interpolation. s is for interpolating x00-x01 and x10-x11, and t is for the second
625// interpolation. 684// interpolation.
626template <typename X> 685template <typename X>
627constexpr auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x11, const float s, 686[[nodiscard]] constexpr auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x11,
628 const float t) { 687 const float s, const float t) {
629 auto y0 = Lerp(x00, x01, s); 688 auto y0 = Lerp(x00, x01, s);
630 auto y1 = Lerp(x10, x11, s); 689 auto y1 = Lerp(x10, x11, s);
631 return Lerp(y0, y1, t); 690 return Lerp(y0, y1, t);
@@ -633,42 +692,42 @@ constexpr auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X&
633 692
634// Utility vector factories 693// Utility vector factories
635template <typename T> 694template <typename T>
636constexpr Vec2<T> MakeVec(const T& x, const T& y) { 695[[nodiscard]] constexpr Vec2<T> MakeVec(const T& x, const T& y) {
637 return Vec2<T>{x, y}; 696 return Vec2<T>{x, y};
638} 697}
639 698
640template <typename T> 699template <typename T>
641constexpr Vec3<T> MakeVec(const T& x, const T& y, const T& z) { 700[[nodiscard]] constexpr Vec3<T> MakeVec(const T& x, const T& y, const T& z) {
642 return Vec3<T>{x, y, z}; 701 return Vec3<T>{x, y, z};
643} 702}
644 703
645template <typename T> 704template <typename T>
646constexpr Vec4<T> MakeVec(const T& x, const T& y, const Vec2<T>& zw) { 705[[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const T& y, const Vec2<T>& zw) {
647 return MakeVec(x, y, zw[0], zw[1]); 706 return MakeVec(x, y, zw[0], zw[1]);
648} 707}
649 708
650template <typename T> 709template <typename T>
651constexpr Vec3<T> MakeVec(const Vec2<T>& xy, const T& z) { 710[[nodiscard]] constexpr Vec3<T> MakeVec(const Vec2<T>& xy, const T& z) {
652 return MakeVec(xy[0], xy[1], z); 711 return MakeVec(xy[0], xy[1], z);
653} 712}
654 713
655template <typename T> 714template <typename T>
656constexpr Vec3<T> MakeVec(const T& x, const Vec2<T>& yz) { 715[[nodiscard]] constexpr Vec3<T> MakeVec(const T& x, const Vec2<T>& yz) {
657 return MakeVec(x, yz[0], yz[1]); 716 return MakeVec(x, yz[0], yz[1]);
658} 717}
659 718
660template <typename T> 719template <typename T>
661constexpr Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w) { 720[[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}; 721 return Vec4<T>{x, y, z, w};
663} 722}
664 723
665template <typename T> 724template <typename T>
666constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const T& z, const T& w) { 725[[nodiscard]] constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const T& z, const T& w) {
667 return MakeVec(xy[0], xy[1], z, w); 726 return MakeVec(xy[0], xy[1], z, w);
668} 727}
669 728
670template <typename T> 729template <typename T>
671constexpr Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) { 730[[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) {
672 return MakeVec(x, yz[0], yz[1], w); 731 return MakeVec(x, yz[0], yz[1], w);
673} 732}
674 733
@@ -676,17 +735,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 735// 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. 736// out soon enough due to misuse of the returned structure.
678template <typename T> 737template <typename T>
679constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const Vec2<T>& zw) { 738[[nodiscard]] constexpr Vec4<T> MakeVec(const Vec2<T>& xy, const Vec2<T>& zw) {
680 return MakeVec(xy[0], xy[1], zw[0], zw[1]); 739 return MakeVec(xy[0], xy[1], zw[0], zw[1]);
681} 740}
682 741
683template <typename T> 742template <typename T>
684constexpr Vec4<T> MakeVec(const Vec3<T>& xyz, const T& w) { 743[[nodiscard]] constexpr Vec4<T> MakeVec(const Vec3<T>& xyz, const T& w) {
685 return MakeVec(xyz[0], xyz[1], xyz[2], w); 744 return MakeVec(xyz[0], xyz[1], xyz[2], w);
686} 745}
687 746
688template <typename T> 747template <typename T>
689constexpr Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw) { 748[[nodiscard]] constexpr Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw) {
690 return MakeVec(x, yzw[0], yzw[1], yzw[2]); 749 return MakeVec(x, yzw[0], yzw[1], yzw[2]);
691} 750}
692 751