Line data Source code
1 : /**
2 : * @file geom.h
3 : * @brief Physical geometry objects
4 : *
5 : * This file describes objects which represent concrete geometric constructions,
6 : * such as vectors that represent 2D, 3D, and 4D Cartesian coordinates, as well
7 : * as more complex geometric structures such as quaternions and matrices.
8 : */
9 :
10 : #ifndef GEOM_H_
11 : #define GEOM_H_
12 :
13 : struct vec;
14 :
15 : template<typename T>
16 : struct vec4;
17 :
18 : struct plane;
19 : struct quat;
20 : struct dualquat;
21 : class matrix3;
22 : struct matrix4x3;
23 : struct matrix4;
24 :
25 :
26 : /**
27 : * @brief two dimensional Cartesian vector object
28 : *
29 : * This object represents a two-dimensional location or vector in Cartesian space,
30 : * consisting of the `x` and `y` axes. Many operators and utility functions
31 : * corresponding to operations on the 2D plane are defined.
32 : */
33 : struct vec2
34 : {
35 : float x, y;
36 :
37 936 : vec2() {}
38 1092 : vec2(float x, float y) : x(x), y(y) {}
39 : explicit vec2(const vec &v);
40 : explicit vec2(const vec4<float> &v);
41 :
42 2 : float &operator[](int i)
43 : {
44 2 : switch(i)
45 : {
46 1 : case 1:
47 : {
48 1 : return y;
49 : }
50 1 : default:
51 : {
52 1 : return x;
53 : }
54 : }
55 : }
56 :
57 2 : float operator[](int i) const
58 : {
59 2 : switch(i)
60 : {
61 1 : case 1:
62 : {
63 1 : return y;
64 : }
65 1 : default:
66 : {
67 1 : return x;
68 : }
69 : }
70 : }
71 :
72 61 : bool operator==(const vec2 &o) const { return x == o.x && y == o.y; }
73 3 : bool operator!=(const vec2 &o) const { return x != o.x || y != o.y; }
74 :
75 1 : const float *data() const { return &x; }
76 :
77 2 : bool iszero() const { return x==0 && y==0; }
78 37 : float dot(const vec2 &o) const { return x*o.x + y*o.y; }
79 36 : float squaredlen() const { return dot(*this); }
80 27 : float magnitude() const { return sqrtf(squaredlen()); }
81 3 : vec2 &normalize() { mul(1/magnitude()); return *this; }
82 3 : vec2 &safenormalize() { float m = magnitude(); if(m) mul(1/m); return *this; }
83 3 : float cross(const vec2 &o) const { return x*o.y - y*o.x; }
84 6 : float squaredist(const vec2 &e) const { return vec2(*this).sub(e).squaredlen(); }
85 3 : float dist(const vec2 &e) const { return sqrtf(squaredist(e)); }
86 :
87 10 : vec2 &mul(float f) { x *= f; y *= f; return *this; }
88 4 : vec2 &mul(const vec2 &o) { x *= o.x; y *= o.y; return *this; }
89 2 : vec2 &square() { mul(*this); return *this; }
90 3 : vec2 &div(float f) { x /= f; y /= f; return *this; }
91 : vec2 &div(const vec2 &o) { x /= o.x; y /= o.y; return *this; }
92 : vec2 &recip() { x = 1/x; y = 1/y; return *this; }
93 2 : vec2 &add(float f) { x += f; y += f; return *this; }
94 5 : vec2 &add(const vec2 &o) { x += o.x; y += o.y; return *this; }
95 2 : vec2 &sub(float f) { x -= f; y -= f; return *this; }
96 20 : vec2 &sub(const vec2 &o) { x -= o.x; y -= o.y; return *this; }
97 3 : vec2 &neg() { x = -x; y = -y; return *this; }
98 1 : vec2 &min(const vec2 &o) { x = ::min(x, o.x); y = ::min(y, o.y); return *this; }
99 1 : vec2 &max(const vec2 &o) { x = ::max(x, o.x); y = ::max(y, o.y); return *this; }
100 1 : vec2 &min(float f) { x = ::min(x, f); y = ::min(y, f); return *this; }
101 1 : vec2 &max(float f) { x = ::max(x, f); y = ::max(y, f); return *this; }
102 3 : vec2 &abs() { x = fabs(x); y = fabs(y); return *this; }
103 2 : vec2 &clamp(float l, float h) { x = ::std::clamp(x, l, h); y = ::std::clamp(y, l, h); return *this; }
104 : vec2 &reflect(const vec2 &n) { float k = 2*dot(n); x -= k*n.x; y -= k*n.y; return *this; }
105 :
106 : /**
107 : * @brief Linearly interpolates between another vec2 according to scale t
108 : *
109 : * If 0 < t < 1 then the matrix will be t% of the way between `this` and `to`.
110 : * Values outside 0..1 imply a linear extrapolation.
111 : *
112 : * @param b the other vec2 to interpolate between
113 : * @param t the interpolation factor
114 : */
115 5 : vec2 &lerp(const vec2 &b, float t)
116 : {
117 5 : x += (b.x-x)*t;
118 5 : y += (b.y-y)*t;
119 5 : return *this;
120 : }
121 :
122 : /**
123 : * @brief Linearly interpolates between two other vec2s according to scale t
124 : *
125 : * If 0 < t < 1 then the matrix will be t% of the way between `this` and `to`.
126 : * Values outside 0..1 imply a linear extrapolation.
127 : *
128 : * @param a the first vec2 to interpolate from
129 : * @param b the other vec2 to interpolate between
130 : * @param t the interpolation factor
131 : */
132 3 : vec2 &lerp(const vec2 &a, const vec2 &b, float t)
133 : {
134 3 : x = a.x + (b.x-a.x)*t;
135 3 : y = a.y + (b.y-a.y)*t;
136 3 : return *this;
137 : }
138 :
139 3 : vec2 &avg(const vec2 &b) { add(b); mul(0.5f); return *this; }
140 :
141 3 : vec2 operator+(const vec2 &v2) const
142 : {
143 3 : return vec2(x+v2.x, y+v2.y);
144 : }
145 :
146 3 : vec2 operator-(const vec2 &v2) const
147 : {
148 3 : return vec2(x-v2.x, y-v2.y);
149 : }
150 :
151 2 : vec2 operator-() const
152 : {
153 2 : return vec2(-x, -y);
154 : }
155 :
156 : template<typename T>
157 3 : vec2 operator*(const T &n)
158 : {
159 3 : return vec2(n*x, n*y);
160 : }
161 :
162 3 : vec2 operator*(const vec2 &v2)
163 : {
164 3 : return vec2(x*v2.x, y*v2.y);
165 : }
166 :
167 : template<typename T>
168 3 : vec2 operator/(const T &n)
169 : {
170 3 : return vec2(x/n, y/n);
171 : }
172 :
173 3 : vec2 operator/(const vec2 &v2)
174 : {
175 3 : return vec2(x/v2.x, y/v2.y);
176 : }
177 :
178 : template<class B>
179 : vec2 &madd(const vec2 &a, const B &b) { return add(vec2(a).mul(b)); }
180 :
181 : template<class B>
182 : vec2 &msub(const vec2 &a, const B &b) { return sub(vec2(a).mul(b)); }
183 :
184 137 : vec2 &rotate_around_z(float c, float s) { float rx = x, ry = y; x = c*rx-s*ry; y = c*ry+s*rx; return *this; }
185 131 : vec2 &rotate_around_z(float angle) { return rotate_around_z(cosf(angle), std::sin(angle)); }
186 3 : vec2 &rotate_around_z(const vec2 &sc) { return rotate_around_z(sc.x, sc.y); }
187 : };
188 :
189 : struct ivec;
190 : struct svec;
191 :
192 : /**
193 : * @brief three dimensional Cartesian vector object
194 : *
195 : * This object represents a three-dimensional positiom or vector in Cartesian space,
196 : * represented by the axes `x`,`y`,`z` (`r`,`g`,`b`). Many operators and utility
197 : * functions corresponding to operations on the 2D plane are defined.
198 : *
199 : * The axis aliases `r``g``b` are provided for manipulation as a color,
200 : * in which case the values for each dimension should be no greater than `1.f` for
201 : * easy conversion to `bvec` byte representation.
202 : *
203 : * This object finds uses in nearly every part of the engine,
204 : * including world geometry, mapmodels, particles, projectiles, colors, etc.
205 : */
206 : struct vec
207 : {
208 : float x, y, z;
209 :
210 15410 : vec() {}
211 2 : explicit vec(int a) : x(a), y(a), z(a) {}
212 2 : explicit vec(float a) : x(a), y(a), z(a) {}
213 17820 : vec(float a, float b, float c) : x(a), y(b), z(c) {}
214 1 : explicit vec(int v[3]) : x(v[0]), y(v[1]), z(v[2]) {}
215 1 : explicit vec(const float *v) : x(v[0]), y(v[1]), z(v[2]) {}
216 1 : explicit vec(const vec2 &v, float z = 0) : x(v.x), y(v.y), z(z) {}
217 : explicit vec(const vec4<float> &v);
218 : explicit vec(const ivec &v);
219 : explicit vec(const svec &v);
220 :
221 48 : vec(float yaw, float pitch) : x(-std::sin(yaw)*cosf(pitch)), y(cosf(yaw)*cosf(pitch)), z(std::sin(pitch)) {}
222 3 : vec &set(int i, float f)
223 : {
224 3 : (*this)[i] = f; return *this;
225 : }
226 :
227 3 : float &r() {return x;}
228 3 : float &g() {return y;}
229 3 : float &b() {return z;}
230 0 : float r() const {return x;}
231 0 : float g() const {return y;}
232 0 : float b() const {return z;}
233 :
234 1 : const float *data() const {return &x;}
235 :
236 : //operator overloads
237 33 : float &operator[](int i)
238 : {
239 33 : switch(i)
240 : {
241 13 : case 1:
242 : {
243 13 : return y;
244 : }
245 11 : case 2:
246 : {
247 11 : return z;
248 : }
249 9 : default:
250 : {
251 9 : return x;
252 : }
253 : }
254 : }
255 :
256 118 : float operator[](int i) const
257 : {
258 118 : switch(i)
259 : {
260 41 : case 1:
261 : {
262 41 : return y;
263 : }
264 30 : case 2:
265 : {
266 30 : return z;
267 : }
268 47 : default:
269 : {
270 47 : return x;
271 : }
272 : }
273 : }
274 :
275 290 : bool operator==(const vec &o) const { return x == o.x && y == o.y && z == o.z; }
276 3 : bool operator!=(const vec &o) const { return x != o.x || y != o.y || z != o.z; }
277 :
278 3 : vec operator+(const vec &v2)
279 : {
280 3 : return vec(x+v2.x, y+v2.y, z+v2.z);
281 : }
282 :
283 3 : vec operator-(const vec &v2)
284 : {
285 3 : return vec(x-v2.x, y-v2.y, z-v2.z);
286 : }
287 :
288 2 : vec operator-()
289 : {
290 2 : return vec(-x, -y, -z);
291 : }
292 :
293 : template<typename T>
294 6 : vec operator*(const T &n)
295 : {
296 6 : return vec(n*x, n*y, n*z);
297 : }
298 :
299 6 : vec operator*(const vec &v2)
300 : {
301 6 : return vec(x*v2.x, y*v2.y, z*v2.z);
302 : }
303 :
304 : template<typename T>
305 : vec operator/(const T &n)
306 : {
307 : return vec(x/n, y/n, z/n);
308 : }
309 :
310 : vec operator/(const vec &v2)
311 : {
312 : return vec(x/v2.x, y/v2.y, z/v2.z);
313 : }
314 :
315 :
316 : //unary operators
317 : /**
318 : * @brief Returns whether this `vec` is exactly zero in all axes.
319 : *
320 : * The values are compared to zero under the IEEE 754 equality condition, meaning
321 : * that negative zero is treated as equal to positive zero.
322 : *
323 : * @return true if the vec is equal to (0,0,0)
324 : * @return false if the vec has any axis value that is not +/-0
325 : */
326 2 : bool iszero() const
327 : {
328 2 : return x==0 && y==0 && z==0;
329 : }
330 : /**
331 : * @brief Returns the square of this `vec`'s magnitude.
332 : *
333 : * This is equivalent to the dot product of this `vec` with itself.
334 : *
335 : * @return the square of the magnitude of the `vec`
336 : */
337 1323 : float squaredlen() const { return x*x + y*y + z*z; }
338 :
339 : /**
340 : * @brief Sets this `vec` to its elementwise square.
341 : *
342 : * Each axis is independently multiplied by itself and assigned to `this`.
343 : *
344 : * @return a reference to this vec
345 : */
346 3 : vec &square() { mul(*this); return *this; }
347 3 : vec &neg2() { x = -x; y = -y; return *this; } //unused
348 56 : vec &neg() { x = -x; y = -y; z = -z; return *this; } //overloaded by operator-()
349 15 : vec &abs() { x = fabs(x); y = fabs(y); z = fabs(z); return *this; }
350 1 : vec &recip() { x = 1/x; y = 1/y; z = 1/z; return *this; } //used twice
351 3 : float magnitude2() const { return sqrtf(dot2(*this)); }
352 1222 : float magnitude() const { return sqrtf(squaredlen()); }
353 911 : vec &normalize() { div(magnitude()); return *this; }
354 3 : vec &safenormalize() { float m = magnitude(); if(m) div(m); return *this; }
355 4 : bool isnormalized() const { float m = squaredlen(); return (m>0.99f && m<1.01f); }
356 :
357 : //elementwise float operators
358 3727 : vec &mul(float f) { x *= f; y *= f; z *= f; return *this; }
359 2 : vec &mul2(float f) { x *= f; y *= f; return *this; } //unused
360 943 : vec &div(float f) { x /= f; y /= f; z /= f; return *this; }
361 : vec &div2(float f) { x /= f; y /= f; return *this; } //unused
362 3 : vec &add(float f) { x += f; y += f; z += f; return *this; }
363 2 : vec &add2(float f) { x += f; y += f; return *this; } //used once
364 2 : vec &addz(float f) { z += f; return *this; } //unused
365 1 : vec &sub(float f) { x -= f; y -= f; z -= f; return *this; }
366 : vec &sub2(float f) { x -= f; y -= f; return *this; } //unused
367 : vec &subz(float f) { z -= f; return *this; } //unused
368 2 : vec &min(float f) { x = ::min(x, f); y = ::min(y, f); z = ::min(z, f); return *this; }
369 2 : vec &max(float f) { x = ::max(x, f); y = ::max(y, f); z = ::max(z, f); return *this; }
370 2 : vec &clamp(float l, float h) { x = ::std::clamp(x, l, h); y = ::std::clamp(y, l, h); z = ::std::clamp(z, l, h); return *this; }
371 :
372 : //elementwise vector operators
373 41 : vec &mul(const vec &o) { x *= o.x; y *= o.y; z *= o.z; return *this; }
374 0 : vec &div(const vec &o) { x /= o.x; y /= o.y; z /= o.z; return *this; }
375 5037 : vec &add(const vec &o) { x += o.x; y += o.y; z += o.z; return *this; }
376 4567 : vec &sub(const vec &o) { x -= o.x; y -= o.y; z -= o.z; return *this; }
377 35 : vec &min(const vec &o) { x = ::min(x, o.x); y = ::min(y, o.y); z = ::min(z, o.z); return *this; }
378 35 : vec &max(const vec &o) { x = ::max(x, o.x); y = ::max(y, o.y); z = ::max(z, o.z); return *this; }
379 :
380 : //dot products
381 10 : float dot2(const vec2 &o) const { return x*o.x + y*o.y; }
382 4 : float dot2(const vec &o) const { return x*o.x + y*o.y; }
383 1607 : float dot(const vec &o) const { return x*o.x + y*o.y + z*o.z; }
384 1 : float squaredot(const vec &o) const { float k = dot(o); return k*k; } //unused
385 13 : float absdot(const vec &o) const { return fabs(x*o.x) + fabs(y*o.y) + fabs(z*o.z); } //used once
386 : float zdot(const vec &o) const { return z*o.z; } //unused
387 :
388 : //distances
389 9 : float squaredist(const vec &e) const { return vec(*this).sub(e).squaredlen(); }
390 6 : float dist(const vec &e) const { return sqrtf(squaredist(e)); }
391 3 : float dist(const vec &e, vec &t) const { t = *this; t.sub(e); return t.magnitude(); }
392 3 : float dist2(const vec &o) const { float dx = x-o.x, dy = y-o.y; return sqrtf(dx*dx + dy*dy); }
393 :
394 : //cross products
395 :
396 : /**
397 : * @brief Checks whether the x,y dimensions are outside a distance from a vec
398 : *
399 : * If this vector's `x` or `y` coordinates are within `r` of the passed vec `o`,
400 : * the function returns false; otherwise return true. If the value is exactly
401 : * `r` away from the vec `o` in either direction, the function returns false
402 : *
403 : * @param o the vec to check nearness
404 : * @param r the distance at which to check
405 : *
406 : * @return true if `this` vec is close to `o`
407 : * @return false if `this` vec is far away from `o`
408 : */
409 5 : bool reject(const vec &o, float r) const
410 : {
411 5 : return x>o.x+r || x<o.x-r || y>o.y+r || y<o.y-r;
412 : }
413 :
414 : template<class A, class B>
415 2861 : vec &cross(const A &a, const B &b) { x = a.y*b.z-a.z*b.y; y = a.z*b.x-a.x*b.z; z = a.x*b.y-a.y*b.x; return *this; }
416 :
417 466 : vec &cross(const vec &o, const vec &a, const vec &b) { return cross(vec(a).sub(o), vec(b).sub(o)); }
418 :
419 : /**
420 : * @brief scalar triple product A*(BxC)
421 : */
422 2 : float scalartriple(const vec &a, const vec &b) const { return x*(a.y*b.z-a.z*b.y) + y*(a.z*b.x-a.x*b.z) + z*(a.x*b.y-a.y*b.x); }
423 :
424 : /**
425 : * @brief z component only of scalar triple product (A*(BxC))
426 : */
427 : float zscalartriple(const vec &a, const vec &b) const { return z*(a.x*b.y-a.y*b.x); } //unused
428 :
429 : //transformations
430 : vec &reflectz(float rz) { z = 2*rz - z; return *this; }
431 0 : vec &reflect(const vec &n) { float k = 2*dot(n); x -= k*n.x; y -= k*n.y; z -= k*n.z; return *this; }
432 438 : vec &project(const vec &n) { float k = dot(n); x -= k*n.x; y -= k*n.y; z -= k*n.z; return *this; }
433 : vec &projectxydir(const vec &n) { if(n.z) z = -(x*n.x/n.z + y*n.y/n.z); return *this; } //used once
434 : vec &projectxy(const vec &n)
435 : {
436 : float m = squaredlen(), k = dot(n);
437 : projectxydir(n);
438 : rescale(sqrtf(::max(m - k*k, 0.0f)));
439 : return *this;
440 : } //used once
441 : vec &projectxy(const vec &n, float threshold)
442 : {
443 : float m = squaredlen(), k = ::min(dot(n), threshold);
444 : projectxydir(n);
445 : rescale(sqrtf(::max(m - k*k, 0.0f)));
446 : return *this;
447 : } //used once
448 :
449 : /**
450 : * @brief Linearly interpolates between another vec2 according to scale t
451 : *
452 : * If 0 < t < 1 then the matrix will be t% of the way between `this` and `to`.
453 : * Values outside 0..1 imply a linear extrapolation.
454 : *
455 : * @param b the other vec2 to interpolate between
456 : * @param t the interpolation factor
457 : */
458 9 : vec &lerp(const vec &b, float t)
459 : {
460 9 : x += (b.x-x)*t;
461 9 : y += (b.y-y)*t;
462 9 : z += (b.z-z)*t;
463 9 : return *this;
464 : }
465 :
466 : /**
467 : * @brief Linearly interpolates between two other vecs according to scale t
468 : *
469 : * If 0 < t < 1 then the matrix will be t% of the way between `this` and `to`.
470 : * Values outside 0..1 imply a linear extrapolation.
471 : *
472 : * @param a the first vec to interpolate from
473 : * @param b the other vec to interpolate between
474 : * @param t the interpolation factor
475 : */
476 7 : vec &lerp(const vec &a, const vec &b, float t)
477 : {
478 7 : x = a.x + (b.x-a.x)*t;
479 7 : y = a.y + (b.y-a.y)*t;
480 7 : z = a.z + (b.z-a.z)*t;
481 7 : return *this;
482 : }
483 :
484 : /**
485 : * @brief Sets this `vec` to the arithmetic mean of itself and another `vec`.
486 : *
487 : * Each axis has its arithmetic mean (average) set independently.
488 : *
489 : * @param b the other `vec` to average with
490 : */
491 3 : vec &avg(const vec &b)
492 : {
493 3 : add(b);
494 3 : mul(0.5f);
495 3 : return *this;
496 : }
497 :
498 : template<class B>
499 667 : vec &madd(const vec &a, const B &b) { return add(vec(a).mul(b)); }
500 :
501 : template<class B>
502 21 : vec &msub(const vec &a, const B &b) { return sub(vec(a).mul(b)); }
503 :
504 3 : vec &rescale(float k)
505 : {
506 3 : float mag = magnitude();
507 3 : if(mag > 1e-6f) mul(k / mag);
508 3 : return *this;
509 : }
510 :
511 : //all rotate_around functions use RH coordinates (positive rotation in CCW direction)
512 9 : vec &rotate_around_z(float c, float s)
513 : {
514 9 : float rx = x,
515 9 : ry = y;
516 9 : x = c*rx-s*ry;
517 9 : y = c*ry+s*rx;
518 9 : return *this;
519 : }
520 :
521 9 : vec &rotate_around_x(float c, float s)
522 : {
523 9 : float ry = y,
524 9 : rz = z;
525 9 : y = c*ry-s*rz;
526 9 : z = c*rz+s*ry;
527 9 : return *this;
528 : }
529 :
530 9 : vec &rotate_around_y(float c, float s)
531 : {
532 9 : float rx = x,
533 9 : rz = z;
534 9 : x = c*rx-s*rz;
535 9 : z = c*rz+s*rx;
536 9 : return *this;
537 : }
538 :
539 3 : vec &rotate_around_z(float angle)
540 : {
541 3 : return rotate_around_z(cosf(angle), std::sin(angle));
542 : }
543 :
544 3 : vec &rotate_around_x(float angle)
545 : {
546 3 : return rotate_around_x(cosf(angle), std::sin(angle));
547 : }
548 :
549 3 : vec &rotate_around_y(float angle)
550 : {
551 3 : return rotate_around_y(cosf(angle), std::sin(angle));
552 : }
553 :
554 3 : vec &rotate_around_z(const vec2 &sc)
555 : {
556 3 : return rotate_around_z(sc.x, sc.y);
557 : }
558 :
559 3 : vec &rotate_around_x(const vec2 &sc)
560 : {
561 3 : return rotate_around_x(sc.x, sc.y);
562 : }
563 :
564 3 : vec &rotate_around_y(const vec2 &sc)
565 : {
566 3 : return rotate_around_y(sc.x, sc.y);
567 : }
568 :
569 0 : vec &rotate(float c, float s, const vec &d)
570 : {
571 0 : *this = vec(x*(d.x*d.x*(1-c)+c) + y*(d.x*d.y*(1-c)-d.z*s) + z*(d.x*d.z*(1-c)+d.y*s),
572 0 : x*(d.y*d.x*(1-c)+d.z*s) + y*(d.y*d.y*(1-c)+c) + z*(d.y*d.z*(1-c)-d.x*s),
573 0 : x*(d.x*d.z*(1-c)-d.y*s) + y*(d.y*d.z*(1-c)+d.x*s) + z*(d.z*d.z*(1-c)+c));
574 0 : return *this;
575 : }
576 : vec &rotate(float angle, const vec &d)
577 : {
578 : return rotate(cosf(angle), std::sin(angle), d);
579 : }
580 :
581 0 : vec &rotate(const vec2 &sc, const vec &d)
582 : {
583 0 : return rotate(sc.x, sc.y, d);
584 : }
585 :
586 4 : void orthogonal(const vec &d)
587 : {
588 4 : *this = fabs(d.x) > fabs(d.z) ? vec(-d.y, d.x, 0) : vec(0, -d.z, d.y);
589 4 : }
590 :
591 : void orthonormalize(vec &s, vec &t) const
592 : {
593 : s.project(*this);
594 : t.project(*this).project(s);
595 : } //unused
596 :
597 : template<class T>
598 : bool insidebb(const T &bbmin, const T &bbmax) const
599 : {
600 : return x >= bbmin.x && x <= bbmax.x && y >= bbmin.y && y <= bbmax.y && z >= bbmin.z && z <= bbmax.z;
601 : }
602 :
603 : template<class T, class U>
604 0 : bool insidebb(const T &bbmin, const T &bbmax, U margin) const
605 : {
606 0 : return x >= bbmin.x-margin && x <= bbmax.x+margin && y >= bbmin.y-margin && y <= bbmax.y+margin && z >= bbmin.z-margin && z <= bbmax.z+margin;
607 : }
608 :
609 : /**
610 : * @brief Determines whether this vec is within the boundaries {o, o+size}.
611 : *
612 : * The conditions cannot be met if `size` is negative (will always return
613 : * false). If `this` is on the boundary of the bounding box, returns true.
614 : *
615 : * @param o the position of the bounding box start
616 : * @param size the projection in +x,+y,+z for the bounding box to occupy
617 : *
618 : * @return true if `this` is inside the bounding box
619 : * @return false if size is negative, or `this` is not inside it
620 : */
621 : bool insidebb(const ivec &o, int size) const;
622 :
623 : /**
624 : * @brief Determines whether this vec is within the boundaries {o-margin, o+size+margin}.
625 : *
626 : * The conditions cannot be met if `size` is negative (will always return
627 : * false). If `this` is on the boundary of the bounding box (including margin),
628 : * returns true.
629 : *
630 : * @param o the position of the bounding box start
631 : * @param size the projection in +x,+y,+z for the bounding box to occupy
632 : * @param margin distance in every direction around bounding box
633 : *
634 : * @return true if `this` is inside the bounding box
635 : * @return false if size is negative, or `this` is not inside it
636 : */
637 : bool insidebb(const ivec &o, int size, int margin) const;
638 : float dist_to_bb(const ivec &min, const ivec &max) const;
639 :
640 : /**
641 : * @brief Returns the dot product of this and min/max, depending on sign.
642 : *
643 : * Returns the dot product between `this` and an ivec generated from `min`
644 : * and `max`. The generated vector to dot product is determined by `this`'s
645 : * sign for each dimension; if the dimension is negative then `max` is used,
646 : * and if it is zero or positive then `min` is used.
647 : *
648 : * @param min the `ivec` to use for positive/zero values
649 : * @param max the `ivec` to use for negative values
650 : *
651 : * @return the dot product between `this` and `min`/`max`
652 : */
653 : float project_bb(const ivec &min, const ivec &max) const;
654 :
655 0 : static vec hexcolor(int color)
656 : {
657 0 : return vec(((color>>16)&0xFF)*(1.0f/255.0f), ((color>>8)&0xFF)*(1.0f/255.0f), (color&0xFF)*(1.0f/255.0f));
658 : }
659 :
660 : int tohexcolor() const
661 : {
662 : return (static_cast<int>(::std::clamp(r(), 0.0f, 1.0f)*255)<<16) |
663 : (static_cast<int>(::std::clamp(g(), 0.0f, 1.0f)*255)<<8) |
664 : static_cast<int>(::std::clamp(b(), 0.0f, 1.0f)*255);
665 : }
666 : };
667 :
668 53 : inline vec2::vec2(const vec &v) : x(v.x), y(v.y) {}
669 :
670 : template<>
671 : struct std::hash<vec>
672 : {
673 0 : size_t operator()(const vec& k) const
674 : {
675 : union { uint i; float f; } x, y, z;
676 0 : x.f = k.x;
677 0 : y.f = k.y;
678 0 : z.f = k.z;
679 0 : uint v = x.i^y.i^z.i;
680 0 : return v + (v>>12);
681 : }
682 : };
683 :
684 : /**
685 : * @brief three dimensional Cartesian byte vector
686 : *
687 : * A three dimensional position in the Cartesian space consisting of values between
688 : * 0 and 255 in the `x`,`y`,`z` (`r`,`g`,`b`) axes. Generally the vector space represented by this object is the HTML
689 : * color space (0x000000 to 0xFFFFFF). This object contains several utility methods
690 : * and operations corresponding to useful color transformations in this space.
691 : *
692 : * For general purpose integral-valued positions in Cartesian space, `ivec` is
693 : * generally a more useful choice.
694 : */
695 : struct bvec
696 : {
697 : uchar x, y, z;
698 :
699 1 : bvec() {}
700 115 : bvec(uchar x, uchar y, uchar z) : x(x), y(y), z(z) {}
701 3 : explicit bvec(const vec &v) : x(static_cast<uchar>((v.x+1)*(255.0f/2.0f))), y(static_cast<uchar>((v.y+1)*(255.0f/2.0f))), z(static_cast<uchar>((v.z+1)*(255.0f/2.0f))) {}
702 : explicit bvec(const vec4<uchar> &v);
703 :
704 0 : uchar &r() {return x;}
705 0 : uchar &g() {return y;}
706 0 : uchar &b() {return z;}
707 1 : uchar r() const {return x;}
708 1 : uchar g() const {return y;}
709 1 : uchar b() const {return z;}
710 :
711 4 : uchar &operator[](int i)
712 : {
713 4 : switch(i)
714 : {
715 2 : case 1:
716 : {
717 2 : return y;
718 : }
719 0 : case 2:
720 : {
721 0 : return z;
722 : }
723 2 : default:
724 : {
725 2 : return x;
726 : }
727 : }
728 : }
729 2 : uchar operator[](int i) const
730 : {
731 2 : switch(i)
732 : {
733 0 : case 1:
734 : {
735 0 : return y;
736 : }
737 2 : case 2:
738 : {
739 2 : return z;
740 : }
741 0 : default:
742 : {
743 0 : return x;
744 : }
745 : }
746 : }
747 :
748 30 : bool operator==(const bvec &v) const { return x==v.x && y==v.y && z==v.z; }
749 3 : bool operator!=(const bvec &v) const { return x!=v.x || y!=v.y || z!=v.z; }
750 :
751 2 : bool iszero() const { return x==0 && y==0 && z==0; }
752 :
753 : vec tonormal() const { return vec(x*(2.0f/255.0f)-1.0f, y*(2.0f/255.0f)-1.0f, z*(2.0f/255.0f)-1.0f); }
754 :
755 : bvec &normalize()
756 : {
757 : vec n(x-127.5f, y-127.5f, z-127.5f);
758 : float mag = 127.5f/n.magnitude();
759 : x = static_cast<uchar>(n.x*mag+127.5f);
760 : y = static_cast<uchar>(n.y*mag+127.5f);
761 : z = static_cast<uchar>(n.z*mag+127.5f);
762 : return *this;
763 : }
764 :
765 : void lerp(const bvec &a, const bvec &b, float t)
766 : {
767 : x = static_cast<uchar>(a.x + (b.x-a.x)*t);
768 : y = static_cast<uchar>(a.y + (b.y-a.y)*t);
769 : z = static_cast<uchar>(a.z + (b.z-a.z)*t);
770 : }
771 :
772 : void lerp(const bvec &a, const bvec &b, int ka, int kb, int d)
773 : {
774 : x = static_cast<uchar>((a.x*ka + b.x*kb)/d);
775 : y = static_cast<uchar>((a.y*ka + b.y*kb)/d);
776 : z = static_cast<uchar>((a.z*ka + b.z*kb)/d);
777 : }
778 :
779 : /**
780 : * @brief Flips this byte vec by using the mask type pun.
781 : *
782 : * Adds 128 to the values in the vec4. If this causes the value to exceed 255,
783 : * underflows and assigns value modulo 255.
784 : */
785 4 : void flip()
786 : {
787 4 : x ^= 0x80;
788 4 : y ^= 0x80;
789 4 : z ^= 0x80;
790 4 : }
791 :
792 3 : void scale(int k, int d)
793 : {
794 3 : x = static_cast<uchar>((x*k)/d);
795 3 : y = static_cast<uchar>((y*k)/d);
796 3 : z = static_cast<uchar>((z*k)/d);
797 3 : }
798 :
799 2 : bvec &shl(int n)
800 : {
801 2 : x <<= n;
802 2 : y <<= n;
803 2 : z <<= n;
804 2 : return *this;
805 : }
806 3 : bvec &shr(int n)
807 : {
808 3 : x >>= n;
809 3 : y >>= n;
810 3 : z >>= n;
811 3 : return *this;
812 : }
813 :
814 3 : static bvec fromcolor(const vec &v)
815 : {
816 3 : return bvec(static_cast<uchar>(v.x*255.0f), static_cast<uchar>(v.y*255.0f), static_cast<uchar>(v.z*255.0f));
817 : }
818 :
819 3 : vec tocolor() const
820 : {
821 3 : return vec(x*(1.0f/255.0f), y*(1.0f/255.0f), z*(1.0f/255.0f));
822 : }
823 :
824 5 : static bvec from565(ushort c)
825 : {
826 5 : return bvec((((c>>11)&0x1F)*527 + 15) >> 6, (((c>>5)&0x3F)*259 + 35) >> 6, ((c&0x1F)*527 + 15) >> 6);
827 : }
828 :
829 46 : static bvec hexcolor(int color)
830 : {
831 46 : return bvec((color>>16)&0xFF, (color>>8)&0xFF, color&0xFF);
832 : }
833 :
834 5 : int tohexcolor() const
835 : {
836 5 : return (static_cast<int>(x)<<16)|(static_cast<int>(y)<<8)|static_cast<int>(z);
837 : }
838 : };
839 :
840 : /**
841 : * @brief A four dimensional Cartesian-space vector template.
842 : *
843 : * This object defines a location in four dimensional Cartesian space, in whatever
844 : * arithmetic type it is specialized to be. All four values are of the type T
845 : * specialized, and all operators (unless explicitly specified, require types
846 : * trivially convertable to T (or preferably of type T).
847 : */
848 : template<typename T>
849 : struct vec4
850 : {
851 :
852 : T x, y, z, w; /** geometric space representation */
853 :
854 1036 : vec4() {}
855 30 : explicit vec4(const vec &p, T w = 0) : x(p.x), y(p.y), z(p.z), w(w) {}
856 2 : explicit vec4(const vec2 &p, T z = 0, T w = 0) : x(p.x), y(p.y), z(z), w(w) {}
857 1827 : vec4(T x, T y = 0, T z = 0, T w = 0) : x(x), y(y), z(z), w(w) {}
858 1 : vec4(bvec v, uchar c)
859 : {
860 1 : x = v.x;
861 1 : y = v.y;
862 1 : z = v.z;
863 1 : w = c;
864 1 : }
865 1 : vec4(bvec v)
866 : {
867 1 : x = v.x;
868 1 : y = v.y;
869 1 : z = v.z;
870 1 : w = 0;
871 1 : }
872 :
873 4 : explicit vec4(const T *v) : x(v[0]), y(v[1]), z(v[2]), w(v[3]) {}
874 :
875 : template<class U>
876 32 : vec4(const vec4<U> &p) : x(p.x), y(p.y), z(p.z), w(p.w) {}
877 :
878 : template<class U>
879 20 : operator vec4<U>()
880 : {
881 38 : return vec4<U>(static_cast<U>(this->x),
882 20 : static_cast<U>(this->y),
883 20 : static_cast<U>(this->z),
884 20 : static_cast<U>(this->w));
885 : }
886 :
887 : /**
888 : * @brief Returns the i-th dimension of this vec4.
889 : *
890 : * 0 = x
891 : * 1 = y
892 : * 2 = z
893 : * 3 = w
894 : *
895 : * All values other than these will return a reference to x.
896 : *
897 : * @param i the index to access
898 : *
899 : * @return reference to the value along the specified dimension
900 : */
901 4 : T &operator[](int i)
902 : {
903 4 : switch(i)
904 : {
905 1 : case 1:
906 : {
907 1 : return y;
908 : }
909 1 : case 2:
910 : {
911 1 : return z;
912 : }
913 1 : case 3:
914 : {
915 1 : return w;
916 : }
917 1 : default:
918 : {
919 1 : return x;
920 : }
921 : }
922 : }
923 :
924 : /**
925 : * @brief Returns the i-th dimension of this vec4.
926 : *
927 : * 0 = x
928 : * 1 = y
929 : * 2 = z
930 : * 3 = w
931 : *
932 : * All values other than these will return the value of x.
933 : *
934 : * @param i the index to access
935 : *
936 : * @return the value along the specified dimension
937 : */
938 4 : T operator[](int i) const
939 : {
940 4 : switch(i)
941 : {
942 1 : case 1:
943 : {
944 1 : return y;
945 : }
946 1 : case 2:
947 : {
948 1 : return z;
949 : }
950 1 : case 3:
951 : {
952 1 : return w;
953 : }
954 1 : default:
955 : {
956 1 : return x;
957 : }
958 : }
959 : }
960 :
961 :
962 : /**
963 : * @brief References the x coordinate of this vec4
964 : *
965 : * @return a reference to x
966 : */
967 3 : T &r() { return x; }
968 :
969 : /**
970 : * @brief References the y coordinate of this vec4
971 : *
972 : * @return a reference to y
973 : */
974 3 : T &g() { return y; }
975 :
976 : /**
977 : * @brief References the z coordinate of this vec4
978 : *
979 : * @return a reference to z
980 : */
981 3 : T &b() { return z; }
982 :
983 : /**
984 : * @brief References the w coordinate of this vec4
985 : *
986 : * @return a reference to w
987 : */
988 3 : T &a() { return w; }
989 :
990 : /**
991 : * @brief Returns the x coordinate of this vec4
992 : *
993 : * @return the value of x
994 : */
995 : T r() const { return x; }
996 :
997 : /**
998 : * @brief Returns the y coordinate of this vec4
999 : *
1000 : * @return the value of y
1001 : */
1002 : T g() const { return y; }
1003 :
1004 : /**
1005 : * @brief Returns the z coordinate of this vec4
1006 : *
1007 : * @return the value of z
1008 : */
1009 : T b() const { return z; }
1010 :
1011 : /**
1012 : * @brief Returns the w coordinate of this vec4
1013 : *
1014 : * @return the value of w
1015 : */
1016 : T a() const { return w; }
1017 :
1018 : /**
1019 : * @brief Returns a raw pointer to the data of this vec4.
1020 : *
1021 : * @return a pointer to the lowest dimension (x) of this object
1022 : */
1023 1 : const T *data() const { return &x; }
1024 :
1025 : /**
1026 : * @brief Returns a raw unsigned int pointer to the data in this vec4.
1027 : *
1028 : * @return a unsigned int pointer to the lowest dimension (x) of this object
1029 : */
1030 6 : uint *mask()
1031 : {
1032 6 : return reinterpret_cast<uint *>(&x);
1033 : }
1034 :
1035 : /**
1036 : * @brief Returns whether two vec objects exactly match
1037 : *
1038 : * The two values must be exactly equal (by floating point math rules), and
1039 : * no tolerance is provided.
1040 : *
1041 : * @param o the value to compare
1042 : *
1043 : * @return true if all values in the vec4s exactly match
1044 : * @return false if any value does not match
1045 : */
1046 249 : bool operator==(const vec4 &o) const { return x == o.x && y == o.y && z == o.z && w == o.w; }
1047 :
1048 : /**
1049 : * @brief Returns whether two vec objects do not match
1050 : *
1051 : * If any value compares not equal (by floating point math rules),
1052 : * then the vec4s are considered not equal
1053 : *
1054 : * @param o the value to compare
1055 : *
1056 : * @return true if any value does not match
1057 : * @return false if all values in the vec4s exactly match
1058 : */
1059 3 : bool operator!=(const vec4 &o) const { return x != o.x || y != o.y || z != o.z || w != o.w; }
1060 :
1061 : /**
1062 : * @brief Returns the 3 dimensional dot product between two 4-vecs.
1063 : *
1064 : * Returns the scalar (dot) product of two 4D vecs, `this` and the passed
1065 : * one, as if they are 3D vecs, by ignoring the fourth term in each vector.
1066 : *
1067 : * @param o the vec4 to multiply by
1068 : *
1069 : * @return the dot product of the first three elements of each vector
1070 : */
1071 289 : T dot3(const vec4 &o) const { return x*o.x + y*o.y + z*o.z; }
1072 :
1073 : /**
1074 : * @brief Returns the 3 dimensional dot product between `this` and a 3D vec.
1075 : *
1076 : * Returns the scalar (dot) product of a 3D and 4D vec, `this` and the passed
1077 : * 3D vec, by ignoring the fourth term in the 4D vec.
1078 : *
1079 : * @param o the vec3 to multiply by
1080 : *
1081 : * @return the dot product of the first three elements of each vector
1082 : */
1083 25 : T dot3(const vec &o) const { return x*o.x + y*o.y + z*o.z; }
1084 :
1085 : /**
1086 : * @brief Returns the scalar product with another vec4.
1087 : *
1088 : * Returns the scalar (dot) product of two 4D vecs, `this` and the passed
1089 : * vec4 `o`.
1090 : *
1091 : * @param o the vector to multiply with
1092 : *
1093 : * @return the dot product of the two vectors
1094 : */
1095 281 : T dot(const vec4 &o) const { return dot3(o) + w*o.w; }
1096 :
1097 : /**
1098 : * @brief Returns the dot product of `this` and a vec3, assuming o.w = 1.
1099 : *
1100 : * Calculates the dot product with a vec3, with `o.w` implied to equal 1.
1101 : *
1102 : * @param o the vec3 to multiply by
1103 : *
1104 : * @return the dot product of the two vectors
1105 : */
1106 4 : T dot(const vec &o) const { return x*o.x + y*o.y + z*o.z + w; }
1107 :
1108 : /**
1109 : * @brief Returns the square of the magnitude of the vector.
1110 : *
1111 : * Calculates the dot product of the vector with itself, yielding the
1112 : * square of the magnitude of the vec4.
1113 : *
1114 : * @return the magnitude of `this` squared
1115 : */
1116 255 : T squaredlen() const { return dot(*this); }
1117 :
1118 : /**
1119 : * @brief Returns the magnitude of the vector.
1120 : *
1121 : * Calculates the magnitude (length) of the vector, by taking the square
1122 : * root of the dot product of the vector with itself.
1123 : *
1124 : * @return the maginitude of `this`
1125 : */
1126 249 : T magnitude() const { return sqrtf(squaredlen()); }
1127 :
1128 : /**
1129 : * @brief Returns the magnitude of the vector, ignoring the w dimension.
1130 : *
1131 : * Calculates the #D magnitude (length) of the vector, by taking the square
1132 : * root of the 3D dot product of the vector with itself.
1133 : *
1134 : * @return the maginitude of `this`
1135 : */
1136 4 : T magnitude3() const { return sqrtf(dot3(*this)); }
1137 :
1138 : /**
1139 : * @brief Scales the vector to have a magnitude of 1
1140 : *
1141 : * Will cause a divide-by-zero if the vector is (0,0,0,0).
1142 : *
1143 : * @return a reference to `this` vector
1144 : */
1145 2 : vec4 &normalize() { mul(1/magnitude()); return *this; }
1146 :
1147 : /**
1148 : * @brief Scales the vector to have a magnitude of 1
1149 : *
1150 : * Will return (0,0,0,0) if the vector passed (0,0,0,0).
1151 : *
1152 : * @return a reference to `this` vector
1153 : */
1154 9 : vec4 &safenormalize() { T m = magnitude(); if(m) mul(1/m); return *this; }
1155 :
1156 2 : void lerp(const vec4<uchar> &a, const vec4<uchar> &b, float t)
1157 : {
1158 2 : x = static_cast<uchar>(a.x + (b.x-a.x)*t);
1159 2 : y = static_cast<uchar>(a.y + (b.y-a.y)*t);
1160 2 : z = static_cast<uchar>(a.z + (b.z-a.z)*t);
1161 2 : w = a.w;
1162 2 : }
1163 :
1164 : void lerp(const vec4<uchar> &a, const vec4<uchar> &b, int ka, int kb, int d)
1165 : {
1166 : x = static_cast<uchar>((a.x*ka + b.x*kb)/d);
1167 : y = static_cast<uchar>((a.y*ka + b.y*kb)/d);
1168 : z = static_cast<uchar>((a.z*ka + b.z*kb)/d);
1169 : w = a.w;
1170 : }
1171 :
1172 3 : void lerp(const vec4<uchar> &a, const vec4<uchar> &b, const vec4<uchar> &c, float ta, float tb, float tc)
1173 : {
1174 3 : x = static_cast<uchar>(a.x*ta + b.x*tb + c.x*tc);
1175 3 : y = static_cast<uchar>(a.y*ta + b.y*tb + c.y*tc);
1176 3 : z = static_cast<uchar>(a.z*ta + b.z*tb + c.z*tc);
1177 3 : w = static_cast<uchar>(a.w*ta + b.w*tb + c.w*tc);
1178 3 : }
1179 :
1180 : /**
1181 : * @brief Flips a vec4<uchar> by using the mask type pun.
1182 : *
1183 : * Adds 128 to the values in the vec4. If this causes the value to exceed 255,
1184 : * underflows and assigns value modulo 255.
1185 : *
1186 : * Not for use with non-char vec4<> objects.
1187 : */
1188 6 : void flip() { *mask() ^= 0x80808080; }
1189 :
1190 5 : vec4 &lerp(const vec4 &b, T t)
1191 : {
1192 5 : x += (b.x-x)*t;
1193 5 : y += (b.y-y)*t;
1194 5 : z += (b.z-z)*t;
1195 5 : w += (b.w-w)*t;
1196 5 : return *this;
1197 : }
1198 6 : vec4 &lerp(const vec4 &a, const vec4 &b, T t)
1199 : {
1200 6 : x = a.x+(b.x-a.x)*t;
1201 6 : y = a.y+(b.y-a.y)*t;
1202 6 : z = a.z+(b.z-a.z)*t;
1203 6 : w = a.w+(b.w-a.w)*t;
1204 6 : return *this;
1205 : }
1206 :
1207 : /**
1208 : * @brief Calculates the elementwise arithmetic mean.
1209 : *
1210 : * Sets `this` to the elementwise arithmetic mean of `this` object and the
1211 : * passed object. The original vector is not preserved, but the passed one
1212 : * is.
1213 : *
1214 : * @param b the vec4 to average with
1215 : *
1216 : * @return a reference to `this` object following the operation
1217 : */
1218 3 : vec4 &avg(const vec4 &b) { add(b); mul(0.5f); return *this; }
1219 :
1220 : /**
1221 : * @brief Sets this vec4 to the result of the multiply add of `this` with `a`,`b`
1222 : *
1223 : * Returns `a`*`b` (elementwise multiplication) added with `this` (elementwise addition).
1224 : *
1225 : * @param a value to multiply
1226 : * @param b value to multiply
1227 : *
1228 : * @return a reference to `this` following the operation
1229 : */
1230 : template<class B>
1231 122 : vec4 &madd(const vec4 &a, const B &b) { return add(vec4(a).mul(b)); }
1232 :
1233 : /**
1234 : * @brief Sets this vec4 to the result of the multiply subtract of `this` with `a`,`b`
1235 : *
1236 : * Returns `a`*`b` (elementwise multiplication) subtracted from `this` (elementwise subtraction).
1237 : *
1238 : * @param a value to multiply
1239 : * @param b value to multiply
1240 : *
1241 : * @return a reference to `this` following the operation
1242 : */
1243 : template<class B>
1244 9 : vec4 &msub(const vec4 &a, const B &b) { return sub(vec4(a).mul(b)); }
1245 :
1246 : /**
1247 : * @brief Calculates the elementwise product.
1248 : *
1249 : * Calculates the elementwise product of `f` with the first three entries
1250 : * in `this`. This means that the original vector is not preserved.
1251 : *
1252 : * @param f the value to multiply by
1253 : *
1254 : * @return a reference to `this` object following the operation
1255 : */
1256 261 : vec4 &mul3(T f) { x *= f; y *= f; z *= f; return *this; }
1257 :
1258 : /**
1259 : * @brief Calculates the elementwise product.
1260 : *
1261 : * Calculates the elementwise product of `f` with all four entries
1262 : * in `this`. This means that the original vector is not preserved.
1263 : *
1264 : * @param f the value to multiply by
1265 : *
1266 : * @return a reference to `this` object following the operation
1267 : */
1268 256 : vec4 &mul(T f) { mul3(f); w *= f; return *this; }
1269 :
1270 : /**
1271 : * @brief Calculates the elementwise product.
1272 : *
1273 : * Calculates the elementwise product of the four parameters in `this` with
1274 : * the four parameters in `o`. This measn that the original vector is not
1275 : * preserved.
1276 : *
1277 : * @param o the vec4 to multiply by
1278 : *
1279 : * @return a reference to `this` object following the operation
1280 : */
1281 13 : vec4 &mul(const vec4 &o) { x *= o.x; y *= o.y; z *= o.z; w *= o.w; return *this; }
1282 :
1283 : /**
1284 : * @brief Calculates the elementwise product.
1285 : *
1286 : * Calculates the elementwise product of the first three parameters in `this`
1287 : * with the three parameters in `o`. This means that the original vector is
1288 : * not preserved.
1289 : *
1290 : * @param o the vec3 to multiply by
1291 : *
1292 : * @return a reference to `this` object following the operation
1293 : */
1294 3 : vec4 &mul(const vec &o) { x *= o.x; y *= o.y; z *= o.z; return *this; }
1295 :
1296 : /**
1297 : * @brief Calculates the elementwise square.
1298 : *
1299 : * Calculates the elementwise product of `this` with itself. This means that
1300 : * the original vector is not preserved.
1301 : *
1302 : * @return a reference to `this` object following the operation
1303 : */
1304 3 : vec4 &square() { mul(*this); return *this; }
1305 :
1306 : /**
1307 : * @brief Calculates the elementwise quotient.
1308 : *
1309 : * Calculates the quotient of the first three values in `this` with the value
1310 : * passed to `f`. This means that the original vector is not preserved.
1311 : *
1312 : * @param f the value to divide by
1313 : *
1314 : * @return a reference to `this` object following the operation
1315 : *
1316 : */
1317 8 : vec4 &div3(T f) { x /= f; y /= f; z /= f; return *this; }
1318 :
1319 : /**
1320 : * @brief Calculates the elementwise quotient.
1321 : *
1322 : * Calculates the quotient of the four values in `this` with the value passed
1323 : * to `f`. This means that the original vector is not preserved.
1324 : *
1325 : * @param f the value to divide by
1326 : *
1327 : * @return a reference to `this` object following the operation
1328 : */
1329 4 : vec4 &div(T f) { div3(f); w /= f; return *this; }
1330 :
1331 : /**
1332 : * @brief Calculates the elementwise quotient.
1333 : *
1334 : * Calculates the quotient of the four values in `this` with the four values in
1335 : * `o`, element-by-element. This means that the original vector is not preserved.
1336 : *
1337 : * @param o the vector to divide by
1338 : *
1339 : * @return a reference to `this` object following the operation
1340 : */
1341 2 : vec4 &div(const vec4 &o) { x /= o.x; y /= o.y; z /= o.z; w /= o.w; return *this; }
1342 :
1343 : /**
1344 : * @brief Calculates the elementwise quotient.
1345 : *
1346 : * Calculates the quotient of the three values in `this` with the four values in
1347 : * `o`, element-by-element. This means that the original vector is not preserved.
1348 : *
1349 : * @param o the vector to divide by
1350 : *
1351 : * @return a reference to `this` object following the operation
1352 : */
1353 3 : vec4 &div(const vec &o) { x /= o.x; y /= o.y; z /= o.z; return *this; }
1354 :
1355 : /**
1356 : * @brief Calculates the elementwise reciprocal.
1357 : *
1358 : * Calculates the value 1/x for each of the four values in the vector, and assigns
1359 : * them to `this`. This means that the original vector is not preserved
1360 : *
1361 : * @return a reference to `this` object following the operation
1362 : */
1363 2 : vec4 &recip() { x = 1/x; y = 1/y; z = 1/z; w = 1/w; return *this; }
1364 :
1365 : /**
1366 : * @brief Calculates the elementwise sum.
1367 : *
1368 : * Calculates the sum of the four elements in `this` with the four values in
1369 : * `o`, element-by-element. This means that the original vector is not preserved.
1370 : *
1371 : * @param o the vector to add with
1372 : *
1373 : * @return a reference to `this` object following the operation
1374 : */
1375 170 : vec4 &add(const vec4 &o) { x += o.x; y += o.y; z += o.z; w += o.w; return *this; }
1376 :
1377 : /**
1378 : * @brief Calculates the elementwise sum.
1379 : *
1380 : * Calculates the sum of the first three elements in `this` with the first
1381 : * three values in `o`, element-by-element. This means that the original
1382 : * vector is not preserved.
1383 : *
1384 : * @param o the vector to add with
1385 : *
1386 : * @return a reference to `this` object following the operation
1387 : */
1388 3 : vec4 &add(const vec &o) { x += o.x; y += o.y; z += o.z; return *this; }
1389 :
1390 : /**
1391 : * @brief Calculates the elementwise sum.
1392 : *
1393 : * Calculates the sum of the first three elements in `this` with the value
1394 : * passed to `f`. This means that the original vector is not preserved.
1395 : *
1396 : * @param f the value to add with
1397 : *
1398 : * @return a reference to `this` object following the operation
1399 : */
1400 8 : vec4 &add3(T f) { x += f; y += f; z += f; return *this; }
1401 :
1402 : /**
1403 : * @brief Calculates the elementwise sum.
1404 : *
1405 : * Calculates the sum of the four elements in `this` with the four elements
1406 : * comprising `f`. This means that the original vector is not preserved.
1407 : *
1408 : * @param f the value to add with
1409 : *
1410 : * @return a reference to `this` object following the operation
1411 : */
1412 4 : vec4 &add(T f) { add3(f); w += f; return *this; }
1413 :
1414 : /**
1415 : * @brief Adds to the fourth value of the vector (w/a).
1416 : *
1417 : * Calculates the sum of the passed value and the fourth element of the vec4,
1418 : * modifying the original vector to equal this sum.
1419 : *
1420 : * @param f the value to add with
1421 : *
1422 : * @return a reference to `this` object following the operation
1423 : */
1424 4 : vec4 &addw(T f) { w += f; return *this; }
1425 :
1426 : /**
1427 : * @brief Subtracts from `this` the vec4 passed.
1428 : *
1429 : * Calculates the difference between the four elements in `this` and the
1430 : * four elements of `o`, modifying the original vector to equal this difference.
1431 : *
1432 : * @param o the vec4 to subtract
1433 : *
1434 : * @return a reference to `this` object following the operation
1435 : */
1436 250 : vec4 &sub(const vec4 &o) { x -= o.x; y -= o.y; z -= o.z; w -= o.w; return *this; }
1437 :
1438 : /**
1439 : * @brief Subtracts from `this` the vec passed.
1440 : *
1441 : * Calculates the difference between the four elements in `this` and the three
1442 : * elements of `o`, modifying the original vector to equal this difference.
1443 : *
1444 : * @param o the vec to subtract
1445 : *
1446 : * @return a reference to `this` object following the operation
1447 : */
1448 3 : vec4 &sub(const vec &o) { x -= o.x; y -= o.y; z -= o.z; return *this; }
1449 :
1450 : /**
1451 : * @brief Subtracts from the first three entries `this` the value passed.
1452 : *
1453 : * Calculates the difference between the first three elements in `this` and
1454 : * the value passed, modifying the original vector to equal this difference.
1455 : *
1456 : * @param f the value to subtract
1457 : *
1458 : * @return a reference to `this` object following the operation
1459 : */
1460 8 : vec4 &sub3(T f)
1461 : {
1462 8 : x -= f;
1463 8 : y -= f;
1464 8 : z -= f;
1465 8 : return *this;
1466 : }
1467 :
1468 : /**
1469 : * @brief Subtracts from the entries `this` the value passed.
1470 : *
1471 : * Calculates the difference between the elements in `this` and
1472 : * the value passed, modifying the original vector to equal this difference.
1473 : *
1474 : * @param f the value to subtract
1475 : *
1476 : * @return a reference to `this` object following the operation
1477 : */
1478 4 : vec4 &sub(T f)
1479 : {
1480 4 : sub3(f);
1481 4 : w -= f;
1482 4 : return *this;
1483 : }
1484 :
1485 : /**
1486 : * @brief Subtracts from the last element only.
1487 : *
1488 : * Calculates the difference between the last 'w' element in `this` and
1489 : * the value passed, modifying the original vector to equal this difference.
1490 : *
1491 : * @param f the value to subtract
1492 : *
1493 : * @return a reference to `this` object following the operation
1494 : */
1495 4 : vec4 &subw(T f)
1496 : {
1497 4 : w -= f;
1498 4 : return *this;
1499 : }
1500 :
1501 : /**
1502 : * @brief Negates the first three elements.
1503 : *
1504 : * `w` is left unchanged.
1505 : *
1506 : * @return a reference to `this`
1507 : */
1508 128 : vec4 &neg3()
1509 : {
1510 128 : x = -x;
1511 128 : y = -y;
1512 128 : z = -z;
1513 128 : return *this;
1514 : }
1515 :
1516 : /**
1517 : * @brief Negates all of the elements.
1518 : *
1519 : * @return a reference to `this`
1520 : */
1521 98 : vec4 &neg()
1522 : {
1523 98 : neg3();
1524 98 : w = -w;
1525 98 : return *this;
1526 : }
1527 :
1528 : /**
1529 : * @brief Clamps the elements individualy to the specified bounds.
1530 : *
1531 : * Clamps each element such that none of them exceeds the bounds specified.
1532 : *
1533 : * @param l the low value to clamp to
1534 : * @param h the high value to clamp to
1535 : */
1536 4 : vec4 &clamp(T l, T h)
1537 : {
1538 4 : x = ::std::clamp(x, l, h);
1539 4 : y = ::std::clamp(y, l, h);
1540 4 : z = ::std::clamp(z, l, h);
1541 4 : w = ::std::clamp(w, l, h);
1542 4 : return *this;
1543 : }
1544 :
1545 : /**
1546 : * @brief Returns a new vec4 object equal to the sum of the passed object and `this`
1547 : *
1548 : * @param v2 the other vec to add
1549 : *
1550 : * @return a new vec4 containing their sum
1551 : */
1552 4 : vec4 operator+(const vec4 &v2) const
1553 : {
1554 4 : return vec4(x+v2.x, y+v2.y, z+v2.z, w+v2.w);
1555 : }
1556 :
1557 : /**
1558 : * @brief Returns a new vec4 object equal to `this` minus the passed object.
1559 : *
1560 : * @param v2 the other vec to subtract with
1561 : *
1562 : * @return a new vec4 containing their difference
1563 : */
1564 4 : vec4 operator-(const vec4 &v2) const
1565 : {
1566 4 : return vec4(x-v2.x, y-v2.y, z-v2.z, w-v2.w);
1567 : }
1568 :
1569 : /**
1570 : * @brief Returns a new vec4 object equal to the arithmetic inverse of `this`
1571 : *
1572 : * @return a new vec4 equal to the arithmetic inverse
1573 : */
1574 4 : vec4 operator-() const
1575 : {
1576 4 : return vec4(-x, -y, -z, -w);
1577 : }
1578 :
1579 : /**
1580 : * @brief Returns a new vec4 object equal to the scalar multiplication by a value.
1581 : *
1582 : * @tparam u scalar type to multiply with
1583 : * @param n scalar value to multiply with
1584 : *
1585 : * @return a new vec4 equal to `this` * n
1586 : */
1587 : template<typename U>
1588 3 : vec4 operator*(const U &n) const
1589 : {
1590 3 : return vec4(n*x, n*y, n*z, n*w);
1591 : }
1592 :
1593 : /**
1594 : * @brief Returns a new vec4 equal to the elementwise product of `this` and the passed vec4.
1595 : *
1596 : * @param v2 the vec4 to multiply with
1597 : *
1598 : * @return a new vec4 equal to `this` * `v2`
1599 : */
1600 4 : vec4 operator*(const vec4 &v2) const
1601 : {
1602 4 : return vec4(x*v2.x, y*v2.y, z*v2.z, w*v2.w);
1603 : }
1604 :
1605 : /**
1606 : * @brief Returns a new vec4 object equal to the scalar division by a value.
1607 : *
1608 : * @tparam u scalar type to divide with
1609 : * @param n scalar value to divide with
1610 : *
1611 : * @return a new vec4 equal to `this` / `n`
1612 : */
1613 : template<typename U>
1614 3 : vec4 operator/(const U &n) const
1615 : {
1616 3 : return vec4(x/n, y/n, z/n, w/n);
1617 : }
1618 :
1619 :
1620 : /**
1621 : * @brief Returns a new vec4 equal to the elementwise division of `this` and the passed vec4.
1622 : *
1623 : * @param v2 the vec4 to divide with
1624 : *
1625 : * @return a new vec4 equal to `this` / `v2`
1626 : */
1627 4 : vec4 operator/(const vec4 &v2) const
1628 : {
1629 4 : return vec4(x/v2.x, y/v2.y, z/v2.z, w/v2.w);
1630 : }
1631 :
1632 :
1633 : /**
1634 : * @brief Sets this vec to the cross product of two passed objects
1635 : *
1636 : * The `w` field is unmodified.
1637 : * Only valid for vec-type objects with x,y,z scalar members.
1638 : *
1639 : * @tparam A the type of the first cross product operand
1640 : * @tparam B the type of the second cross product operand
1641 : * @param a the first cross product operand
1642 : * @param b the second cross product operand
1643 : *
1644 : */
1645 : template<class A, class B>
1646 9 : vec4 &cross(const A &a, const B &b)
1647 : {
1648 9 : x = a.y*b.z-a.z*b.y;
1649 9 : y = a.z*b.x-a.x*b.z;
1650 9 : z = a.x*b.y-a.y*b.x;
1651 9 : return *this;
1652 : }
1653 :
1654 : /**
1655 : * @brief Sets this vec4 to the cross product of a,b relative to an offset c
1656 : *
1657 : * The `w` field is unmodified.
1658 : *
1659 : * @param o the origin to calculate offsets from
1660 : * @param a the first vec to use
1661 : * @param b the second vec to use
1662 : */
1663 : vec4 &cross(const vec &o, const vec &a, const vec &b)
1664 : {
1665 : return cross(vec(a).sub(o), vec(b).sub(o));
1666 : }
1667 :
1668 : /**
1669 : * @brief Replaces the first three values of `this` with the passed vec
1670 : *
1671 : * @param v the vec to replace x,y,z of `this`with
1672 : */
1673 4 : void setxyz(const vec &v)
1674 : {
1675 4 : x = v.x;
1676 4 : y = v.y;
1677 4 : z = v.z;
1678 4 : }
1679 :
1680 : /**
1681 : * @brief Rotates the given 3-vector around the z-axis
1682 : *
1683 : * The w parameter is ignored.
1684 : * The positive direction of rotation is counterclockwise.
1685 : *
1686 : * @param c the raw cosine value to rotate by
1687 : * @param s the raw sine value to rotate by
1688 : */
1689 9 : vec4 &rotate_around_z(T c, T s)
1690 : {
1691 9 : T rx = x,
1692 9 : ry = y;
1693 9 : x = c*rx-s*ry;
1694 9 : y = c*ry+s*rx;
1695 9 : return *this;
1696 : }
1697 :
1698 : /**
1699 : * @brief Rotates the given 3-vector around the x-axis
1700 : *
1701 : * The w parameter is ignored.
1702 : * The positive direction of rotation is counterclockwise.
1703 : *
1704 : * @param c the raw cosine value to rotate by
1705 : * @param s the raw sine value to rotate by
1706 : */
1707 9 : vec4 &rotate_around_x(T c, T s)
1708 : {
1709 9 : T ry = y,
1710 9 : rz = z;
1711 9 : y = c*ry-s*rz;
1712 9 : z = c*rz+s*ry;
1713 9 : return *this;
1714 : }
1715 :
1716 : /**
1717 : * @brief Rotates the given 3-vector around the y-axis
1718 : *
1719 : * The w parameter is ignored.
1720 : * The positive direction of rotation is counterclockwise.
1721 : *
1722 : * @param c the raw cosine value to rotate by
1723 : * @param s the raw sine value to rotate by
1724 : */
1725 9 : vec4 &rotate_around_y(T c, T s)
1726 : {
1727 9 : T rx = x,
1728 9 : rz = z;
1729 9 : x = c*rx-s*rz;
1730 9 : z = c*rz+s*rx;
1731 9 : return *this;
1732 : }
1733 :
1734 : /**
1735 : * @brief Conducts a rotation around the z-axis
1736 : *
1737 : * The `w` parameter is ignored.
1738 : * The positive direction of rotation is counterclockwise.
1739 : *
1740 : * @param angle the angle (in radians) to rotate by
1741 : *
1742 : * @return a reference to `this` following the operation
1743 : */
1744 3 : vec4 &rotate_around_z(T angle)
1745 : {
1746 3 : return rotate_around_z(cosf(angle), std::sin(angle));
1747 : }
1748 :
1749 : /**
1750 : * @brief Conducts a rotation around the x-axis
1751 : *
1752 : * The `w` parameter is ignored.
1753 : * The positive direction of rotation is counterclockwise.
1754 : *
1755 : * @param angle the angle (in radians) to rotate by
1756 : *
1757 : * @return a reference to `this` following the operation
1758 : */
1759 3 : vec4 &rotate_around_x(T angle)
1760 : {
1761 3 : return rotate_around_x(cosf(angle), std::sin(angle));
1762 : }
1763 :
1764 : /**
1765 : * @brief Conducts a rotation around the y-axis
1766 : *
1767 : * The `w` parameter is ignored.
1768 : * The positive direction of rotation is counterclockwise.
1769 : *
1770 : * @param angle the angle (in radians) to rotate by
1771 : *
1772 : * @return a reference to `this` following the operation
1773 : */
1774 3 : vec4 &rotate_around_y(T angle)
1775 : {
1776 3 : return rotate_around_y(cosf(angle), std::sin(angle));
1777 : }
1778 :
1779 : /**
1780 : * @brief Conducts a rotation around the z-axis
1781 : *
1782 : * The `w` parameter is ignored.
1783 : * The positive direction of rotation is counterclockwise.
1784 : *
1785 : * @param sc a vec2 containing the {cosine, sine} values to rotate with
1786 : *
1787 : * @return a reference to `this` following the operation
1788 : */
1789 3 : vec4 &rotate_around_z(const vec2 &sc)
1790 : {
1791 3 : return rotate_around_z(sc.x, sc.y);
1792 : }
1793 :
1794 : /**
1795 : * @brief Conducts a rotation around the x-axis
1796 : *
1797 : * The `w` parameter is ignored.
1798 : * The positive direction of rotation is counterclockwise.
1799 : *
1800 : * @param sc a vec2 containing the {cosine, sine} values to rotate with
1801 : *
1802 : * @return a reference to `this` following the operation
1803 : */
1804 3 : vec4 &rotate_around_x(const vec2 &sc)
1805 : {
1806 3 : return rotate_around_x(sc.x, sc.y);
1807 : }
1808 :
1809 : /**
1810 : * @brief Conducts a rotation around the y-axis
1811 : *
1812 : * The `w` parameter is ignored.
1813 : * The positive direction of rotation is counterclockwise.
1814 : *
1815 : * @param sc a vec2 containing the {cosine, sine} values to rotate with
1816 : *
1817 : * @return a reference to `this` following the operation
1818 : */
1819 3 : vec4 &rotate_around_y(const vec2 &sc)
1820 : {
1821 3 : return rotate_around_y(sc.x, sc.y);
1822 : }
1823 :
1824 : /**
1825 : * @brief Returns a new vec containing values normalized to 0...255 (e.g. colors).
1826 : *
1827 : * `w` is not used in this calculation.
1828 : *
1829 : * @return a vec containing the normalized values of x,y,z
1830 : */
1831 12 : vec tonormal() const
1832 : {
1833 12 : return vec(x*(2.0f/255.0f)-1.0f, y*(2.0f/255.0f)-1.0f, z*(2.0f/255.0f)-1.0f);
1834 : }
1835 :
1836 : };
1837 :
1838 1 : inline vec2::vec2(const vec4<float> &v) : x(v.x), y(v.y) {}
1839 35 : inline vec::vec(const vec4<float> &v) : x(v.x), y(v.y), z(v.z) {}
1840 :
1841 : /**
1842 : * @brief matrix3: 3x3 matrix
1843 : * comprised of three vec3 vectors
1844 : * arranged as follows:
1845 : * [ a1 b1 c1
1846 : * a2 b2 c2
1847 : * a3 b3 c3 ]
1848 : *
1849 : * used largely in models/anims/ragdolls but also in stuff like bih
1850 : */
1851 : class matrix3
1852 : {
1853 : public:
1854 : /**
1855 : * @brief the three vectors making up the rows of the matrix
1856 : *
1857 : * a is the top vector
1858 : * b is the middle vector
1859 : * c is the bottom vector
1860 : */
1861 : vec a, b, c;
1862 :
1863 : /**
1864 : * @brief Creates an empty matrix.
1865 : */
1866 : matrix3();
1867 :
1868 : /**
1869 : * @brief Creates a new matrix with the given vectors.
1870 : *
1871 : * @param a the vector to assign to the top row
1872 : * @param b the vector to assign to the middle row
1873 : * @param c the vector to assign to the bottom row
1874 : */
1875 : matrix3(const vec &a, const vec &b, const vec &c);
1876 :
1877 : /**
1878 : * @brief Creates a new matrix as a rotation matrix.
1879 : *
1880 : * If the axis passed is not normalized, the resulting rotation matrix
1881 : * will not encode a pure rotation.
1882 : *
1883 : * @param angle the rotation amount the rotation matrix encodes
1884 : * @param axis the direction which is invariant under the rotation encoded by angle
1885 : */
1886 : explicit matrix3(float angle, const vec &axis);
1887 :
1888 : /**
1889 : * @brief Creates a 3d rotation matrix given a quaternion object.
1890 : *
1891 : * Note that quaternions are an engine-specific construct and not part of the
1892 : * game API beyond the prototype defined in this header.
1893 : *
1894 : * @param q the quaternion to use
1895 : */
1896 : explicit matrix3(const quat &q);
1897 :
1898 : /**
1899 : * @brief Creates a 3d matrix given a 4x3 matrix.
1900 : *
1901 : *
1902 : * @param m the matrix to use
1903 : */
1904 : explicit matrix3(const matrix4x3 &m);
1905 :
1906 : /**
1907 : * @brief Creates a 3x3 matrix given a 4x4 matrix.
1908 : *
1909 : * This truncates the 4th member in both dimensions of the matrix.
1910 : *
1911 : * @param m the matrix to use
1912 : */
1913 : explicit matrix3(const matrix4 &m);
1914 :
1915 : /**
1916 : * @brief Calculates the product of three matrices.
1917 : *
1918 : * @param m the first matrix to multiply by
1919 : * @param n the second matrix to multiply by
1920 : */
1921 : void mul(const matrix3 &m, const matrix3 &n);
1922 :
1923 : /**
1924 : * @brief Multiplies the matrix by another
1925 : *
1926 : * This operation changes the value of the matrix.
1927 : *
1928 : * @param n
1929 : */
1930 : void mul(const matrix3 &n);
1931 :
1932 : /**
1933 : * @brief Calculates the multiplication-transpose with another matrix.
1934 : *
1935 : * @param n the matrix to use
1936 : */
1937 : void multranspose(const matrix3 &n);
1938 :
1939 : /**
1940 : * @brief Calculates the transpose-multiplication with another two matrices.
1941 : *
1942 : * @param m the first matrix to use
1943 : * @param n the second matrix to use
1944 : */
1945 : void transposemul(const matrix3 &m, const matrix3 &n);
1946 :
1947 : /**
1948 : * @brief Calculates the transpose-multiplication with another matrix.
1949 : *
1950 : * @param n the matrix to multiply by
1951 : */
1952 : void transposemul(const matrix3 &n);
1953 :
1954 : /**
1955 : * @brief Transposes the matrix.
1956 : *
1957 : * ```
1958 : * a b c a d g
1959 : * d e f -> b e h
1960 : * g h i c f i
1961 : *```
1962 : */
1963 : void transpose();
1964 :
1965 : /**
1966 : * @brief Inverts the matrix using another matrix for the scale factor.
1967 : *
1968 : * This operation can be undone by calling invert() again using the same
1969 : * argument.
1970 : *
1971 : */
1972 : void invert(const matrix3 &o);
1973 :
1974 : /**
1975 : * @brief Inverts the matrix using itself for the scale factor.
1976 : *
1977 : * This operation can be undone by calling invert() again.
1978 : *
1979 : */
1980 : void invert();
1981 :
1982 : /**
1983 : * @brief Normalizes each of the three rows to a magnitude of 1.
1984 : *
1985 : * Calls normalize() for each of the three vec objects making up the matrix.
1986 : */
1987 : void normalize();
1988 :
1989 : /**
1990 : * @brief Multiplies each element of the matrix by the scale factor given.
1991 : *
1992 : * @param k the scale factor to multiply by
1993 : */
1994 : void scale(float k);
1995 :
1996 : /**
1997 : * @brief Rotates the matrix around the given axis by the given angle.
1998 : *
1999 : * @param angle the angle to rotate by (radians)
2000 : * @param axis the axis to rotate about
2001 : */
2002 : void rotate(float angle, const vec &axis);
2003 :
2004 : /**
2005 : * @brief Rotates the matrix around the given axis by the given angle
2006 : *
2007 : * @param ck the cosine term
2008 : * @param sk the sine term
2009 : * @param axis the axis to rotate about
2010 : */
2011 : void rotate(float ck, float sk, const vec &axis);
2012 :
2013 : /**
2014 : * @brief Sets the matrix to a 2D rotation matrix.
2015 : *
2016 : * The output matrix looks like this:
2017 : *
2018 : * ```
2019 : * cosf(angle) sinf(angle) 0
2020 : * -sinf(angle) cosf(angle) 0
2021 : * 0 0 1
2022 : * ```
2023 : * (This is a rotation matrix around the Z-axis.)
2024 : *
2025 : * @param angle the angle to rotate by (radians)
2026 : */
2027 : void setyaw(float angle);
2028 :
2029 : /**
2030 : * @brief Returns the trace of the matrix.
2031 : *
2032 : * The trace is equal to the sum of the diagonal values of the matrix.
2033 : *
2034 : * @return a float representing the trace of the matrix
2035 : */
2036 : float trace() const;
2037 :
2038 : /**
2039 : * @brief Calculates the axis and angle from a rotation matrix.
2040 : *
2041 : * Only used in certain ragdoll calculations.
2042 : *
2043 : * The axis vector represents the vector which is invariant under the
2044 : * rotation encoded in the rotation matrix.
2045 : *
2046 : * The angle represents the rotation magnitude around the axis vector.
2047 : *
2048 : * Both `angle` and `axis` are pure output parameters and their prior values
2049 : * are discarded.
2050 : *
2051 : * If the values encoding the axis result in a magnitude smaller than `threshhold`,
2052 : * returns false and does not set the angle nor the axis (except axis will
2053 : * be set if trace = 0..2); otherwise sets both angle and axis and returns true
2054 : *
2055 : * @param tr the trace of the matrix
2056 : * @param angle the angle to set
2057 : * @param axis the axis to set
2058 : * @param threshold the magnitude required not to reject the matrix
2059 : *
2060 : * @return whether the axis and angle were both set
2061 : */
2062 : bool calcangleaxis(float tr, float &angle, vec &axis, float threshold = 1e-16f) const;
2063 :
2064 : /**
2065 : * @brief Calculates the axis and angle from a rotation matrix.
2066 : *
2067 : * Ony used in certain ragdoll calculations.
2068 : *
2069 : * Same behavior as `calcangleaxis(float, float &, vec &, float)` except
2070 : * the `trace()` is automatically calculated.
2071 : *
2072 : * @param angle the angle to set
2073 : * @param axis the axis to set
2074 : * @param threshold the magnitude required not to reject the matrix
2075 : *
2076 : * @return whether the axis and angle were both set
2077 : */
2078 : bool calcangleaxis(float &angle, vec &axis, float threshold = 1e-16f) const;
2079 :
2080 : /**
2081 : * @brief Sets the matrix to the transform of the matrix.
2082 : *
2083 : * @param o the 3d vector to transform by
2084 : *
2085 : * @return whether the angle is within the allowable range
2086 : */
2087 : vec transform(const vec &o) const;
2088 :
2089 : /**
2090 : * @brief Sets the matrix to the transpose-transform.
2091 : *
2092 : * @param o the 3d vector to transform by
2093 : *
2094 : * @return the result of the transform
2095 : */
2096 : vec transposedtransform(const vec &o) const;
2097 :
2098 : /**
2099 : * @brief Sets the matrix to the absolute value of the transform
2100 : *
2101 : * @param o the 3d vector to transform by
2102 : *
2103 : * @return the dot products of the resulting matrix
2104 : */
2105 : vec abstransform(const vec &o) const;
2106 :
2107 : /**
2108 : * @brief Sets the matrix to the absolute value of the transpose-transform.
2109 : *
2110 : * @param o the 3d vector to transform by
2111 : *
2112 : * @return the result of the transform
2113 : */
2114 : vec abstransposedtransform(const vec &o) const;
2115 :
2116 : /**
2117 : * @brief Sets the matrix to be the identity matrix.
2118 : *
2119 : * ```
2120 : * 1 0 0
2121 : * 0 1 0
2122 : * 0 0 1
2123 : * ```
2124 : */
2125 : void identity();
2126 :
2127 : /**
2128 : * @brief Rotates the matrix values around the X axis.
2129 : *
2130 : * @param angle the angle by which to rotate about
2131 : */
2132 : void rotate_around_x(float angle);
2133 :
2134 : /**
2135 : * @brief Rotates the matrix values around the X axis.
2136 : *
2137 : * @param sc a vector containing the cosine + sine terms
2138 : */
2139 : void rotate_around_x(const vec2 &sc);
2140 :
2141 : /**
2142 : * @brief Rotates the matrix values around the Y axis.
2143 : *
2144 : * @param angle the angle by which to rotate about
2145 : */
2146 : void rotate_around_y(float angle);
2147 :
2148 : /**
2149 : * @brief Rotates the matrix values around the Y axis.
2150 : *
2151 : * @param sc a vector containing the cosine + sine terms
2152 : */
2153 : void rotate_around_y(const vec2 &sc);
2154 :
2155 : /**
2156 : * @brief Rotates the matrix values around the Z axis.
2157 : *
2158 : * @param angle by which to rotate
2159 : */
2160 : void rotate_around_z(float angle);
2161 :
2162 : /**
2163 : * @brief Rotates the matrix values around the Z axis.
2164 : *
2165 : * @param sc a vector containing the cosine + sine terms
2166 : */
2167 : void rotate_around_z(const vec2 &sc);
2168 :
2169 : /**
2170 : * @brief Returns the transform of the matrix.
2171 : *
2172 : * @param o the 2d vector to transform by
2173 : *
2174 : * @return the transform of the matrix
2175 : */
2176 : vec transform(const vec2 &o) const;
2177 :
2178 : /**
2179 : * @brief Returns the transposed transform of the matrix.
2180 : *
2181 : * @param o the vector to transform with
2182 : *
2183 : * @return the transposed transform of the matrix
2184 : */
2185 : vec transposedtransform(const vec2 &o) const;
2186 :
2187 : /**
2188 : * @brief Returns the first (top) row of the matrix.
2189 : *
2190 : * @return a 3d vector containing the first row of the matrix
2191 : */
2192 : vec rowx() const;
2193 :
2194 : /**
2195 : * @brief Returns the second (middle) row of the matrix.
2196 : *
2197 : * @return a 3d vector containing the second row of the matrix
2198 : */
2199 : vec rowy() const;
2200 :
2201 : /**
2202 : * @brief Returns the third (bottom) row of the matrix.
2203 : *
2204 : * @return a 3d fector containing the thrid row of the matrix
2205 : */
2206 : vec rowz() const;
2207 : private:
2208 :
2209 : /**
2210 : * @brief Calculates the multiplication-transpose of the three matrices
2211 : *
2212 : * @param m the first matrix to use
2213 : * @param n the second matrix to use
2214 : */
2215 : void multranspose(const matrix3 &m, const matrix3 &n);
2216 :
2217 : /**
2218 : * @brief Sets the matrix to a 2D rotation matrix.
2219 : *
2220 : * The output matrix looks like this:
2221 : * ```
2222 : * ck sk 0
2223 : * -sk ck 0
2224 : * 0 0 1
2225 : * ```
2226 : *
2227 : * @param ck the cosine term
2228 : * @param sk the sine term
2229 : */
2230 : void setyaw(float ck, float sk);
2231 :
2232 : /**
2233 : * @brief Rotates the matrix values around the X axis
2234 : *
2235 : * @param ck the cosine term
2236 : * @param sk the sine term
2237 : */
2238 : void rotate_around_x(float ck, float sk);
2239 :
2240 : /**
2241 : * @brief Rotates the matrix values around the Y axis.
2242 : *
2243 : * @param ck the cosine term
2244 : * @param sk the sine term
2245 : */
2246 : void rotate_around_y(float ck, float sk);
2247 :
2248 : /**
2249 : * @brief Rotates the matrix values around the Z axis.
2250 : *
2251 : * @param ck the cosine term
2252 : * @param sk the sine term
2253 : */
2254 : void rotate_around_z(float ck, float sk);
2255 :
2256 : /**
2257 : * @brief Sets the matrix to the transpose of the one given.
2258 : *
2259 : * @param m the matrix to use to set
2260 : */
2261 : void transpose(const matrix3 &m);
2262 : };
2263 :
2264 : /**
2265 : * @brief floating point 4x3 matrix object
2266 : * defined as four column vectors, a-d
2267 : * takes the form as follows:
2268 : * [ a1 b1 c1 d1 (x)
2269 : * a2 b2 c2 d2 (y)
2270 : * a3 b3 c3 d3 ] (z)
2271 : *
2272 : * used in animation along with dualquats
2273 : */
2274 : struct matrix4x3
2275 : {
2276 : vec a, b, c, d;
2277 :
2278 : /**
2279 : * @brief Creates an empty matrix4x3 object.
2280 : *
2281 : * Creates a matrix4x3 object, where all values within the matrix are set to
2282 : * zero.
2283 : */
2284 : matrix4x3();
2285 :
2286 : /**
2287 : * @brief Creates a matrix4x3 from four three-dimensional vec objects.
2288 : *
2289 : * The values of the passed vecs are copied to the new matrix4x3 object.
2290 : *
2291 : * @param a the vec to assign to `matrix4x3::a`
2292 : * @param b the vec to assign to `matrix4x3::b`
2293 : * @param c the vec to assign to `matrix4x3::c`
2294 : * @param d the vec to assign to `matrix4x3::d`
2295 : */
2296 : matrix4x3(const vec &a, const vec &b, const vec &c, const vec &d);
2297 :
2298 : /**
2299 : * @brief Creates a matrix4x3 from a rotation matrix and a translation vector.
2300 : *
2301 : * The rotation matrix is assigned to members `a` `b` `c` and the translation `d`.
2302 : * No transformations are made to the values of the passed parameters.
2303 : *
2304 : * @param rot the rotation matrix to assign to `a` `b` `c`
2305 : * @param trans the translation to assign to `d`
2306 : */
2307 : matrix4x3(const matrix3 &rot, const vec &trans);
2308 :
2309 : /**
2310 : * @brief Creates a matrix4x3 that represents a dual quaternion transformation.
2311 : *
2312 : * @param dq the dual quaternion to transform into a matrix4x3
2313 : */
2314 : matrix4x3(const dualquat &dq);
2315 :
2316 : /**
2317 : * @brief Creates a matrix4x3 by truncating `w` from a matrix4.
2318 : *
2319 : * The four vecs that make up the matrix4 are copied, omitting the `w` parameter.
2320 : *
2321 : * @param m the matrix4 to truncate into a matrix4x3
2322 : */
2323 : explicit matrix4x3(const matrix4 &m);
2324 :
2325 : /**
2326 : * @brief Multiplies all values inside the matrix by a scalar constant.
2327 : *
2328 : * @param k the scale factor to multiply by
2329 : */
2330 : void mul(float k);
2331 :
2332 : /**
2333 : * @brief Sets the diagonals a.x, b.y, c.z to the given values.
2334 : *
2335 : * Does not modify any of the values except for a.x, b.y, c.z.
2336 : *
2337 : * @param x the first value to set in the diagonal
2338 : * @param y the second value to set in the diagonal
2339 : * @param z the third value to set in the diagonal
2340 : */
2341 : void setscale(float x, float y, float z);
2342 :
2343 : /**
2344 : * @brief Sets the diagonals a.x, b.y, c.z to the given vector's x, y, z values.
2345 : *
2346 : * Does not modify any of the values except for a.x, b.y, c.z.
2347 : *
2348 : * @param v the vector to assign from
2349 : */
2350 : void setscale(const vec &v);
2351 :
2352 : /**
2353 : * @brief Sets the diagonals a.x, b.y, c.z identically to a given value.
2354 : *
2355 : * @parm n the value to set to
2356 : */
2357 : void setscale(float n);
2358 :
2359 : /**
2360 : * @brief Scales the first three vectors by x, y, and z respectively.
2361 : *
2362 : * Does not modify the fourth matrix element vector`d`.
2363 : *
2364 : * @param x the scale to multiply the first vector by
2365 : * @param y the scale to multiply the second vector by
2366 : * @param z the scale to multiply the third vector by
2367 : */
2368 : void scale(float x, float y, float z);
2369 :
2370 : /**
2371 : * @brief Multiplies the first three vectors by v.x, v.y, and v.z respectively.
2372 : *
2373 : * Does not modify the fourth matrix element vector`d`.
2374 : *
2375 : * @param v the vector to multiply by
2376 : */
2377 : void scale(const vec &v);
2378 :
2379 : /**
2380 : * @brief Scales the first three vector elements in the matrix by the specified amount.
2381 : *
2382 : * Does not modify the fourth matrix element vector`d`.
2383 : *
2384 : * @param n the scale factor to multiply by
2385 : */
2386 : void scale(float n);
2387 :
2388 : /**
2389 : * @brief Copies the `p` vector into the fourth column vector (`d`).
2390 : *
2391 : * @param p the vector to copy to the `d` vector.
2392 : */
2393 : void settranslation(const vec &p);
2394 :
2395 : /**
2396 : * @brief Copies x, y, z into the fourth column vector (`d`).
2397 : *
2398 : * @param x the first value to copy into d.x
2399 : * @param y the second value to copy into d.y
2400 : * @param z the third value to copy into d.z
2401 : */
2402 : void settranslation(float x, float y, float z);
2403 : void translate(const vec &p);
2404 : void translate(float x, float y, float z);
2405 : void translate(const vec &p, float scale);
2406 : void accumulate(const matrix4x3 &m, float k);
2407 :
2408 : /**
2409 : * @brief Normalizes the first three column vectors.
2410 : *
2411 : * Sets the three first vectors to have a magnitude of 1. That is,
2412 : * sqrt(x^2 + y^2 + z^2) = 1.
2413 : *
2414 : * Does not check for a divide-by-zero condition.
2415 : */
2416 : void normalize();
2417 :
2418 : /**
2419 : * @brief Linearly interpolates between the two matrices according to scale t
2420 : *
2421 : * If 0 < t < 1 then the matrix will be t% of the way between `this` and `to`.
2422 : * Values outside 0..1 imply a linear extrapolation.
2423 : *
2424 : * @param to the other matrix to interpolate between
2425 : * @param t the interpolation factor
2426 : */
2427 : void lerp(const matrix4x3 &to, float t);
2428 :
2429 : /**
2430 : * @brief Linearly interpolates between two other matrices according to scale t
2431 : *
2432 : * If 0 < t < 1 then the matrix will be t% of the way between `this` and `to`.
2433 : * Values outside 0..1 imply a linear extrapolation.
2434 : *
2435 : * @param from the first matrix to interpolate from
2436 : * @param to the other matrix to interpolate between
2437 : * @param t the interpolation factor
2438 : */
2439 : void lerp(const matrix4x3 &from, const matrix4x3 &to, float t);
2440 :
2441 : /**
2442 : * @brief Sets this matrix to the identity matrix.
2443 : *
2444 : * ```
2445 : * a b c d
2446 : * x 1 0 0 0
2447 : * y 0 1 0 0
2448 : * z 0 0 1 0
2449 : * ```
2450 : */
2451 : void identity();
2452 : void mul(const matrix4x3 &m, const matrix4x3 &n);
2453 : void mul(const matrix4x3 &n);
2454 :
2455 : void mul(const matrix3 &m, const matrix4x3 &n);
2456 :
2457 : void mul(const matrix3 &rot, const vec &trans, const matrix4x3 &n);
2458 :
2459 : void transpose();
2460 : void transpose(const matrix4x3 &o);
2461 :
2462 : void transposemul(const matrix4x3 &m, const matrix4x3 &n);
2463 :
2464 : void multranspose(const matrix4x3 &m, const matrix4x3 &n);
2465 :
2466 : void invert(const matrix4x3 &o);
2467 : void invert();
2468 : void rotate(float angle, const vec &d);
2469 :
2470 : void rotate(float ck, float sk, const vec &axis);
2471 :
2472 : void rotate_around_x(float ck, float sk);
2473 : void rotate_around_x(float angle);
2474 :
2475 : void rotate_around_x(const vec2 &sc);
2476 :
2477 : void rotate_around_y(float ck, float sk);
2478 : void rotate_around_y(float angle);
2479 : void rotate_around_y(const vec2 &sc);
2480 :
2481 : void rotate_around_z(float ck, float sk);
2482 : void rotate_around_z(float angle);
2483 : void rotate_around_z(const vec2 &sc);
2484 :
2485 : vec transposedtransform(const vec &o) const;
2486 : vec transformnormal(const vec &o) const;
2487 : vec transposedtransformnormal(const vec &o) const;
2488 : vec transform(const vec &o) const;
2489 : vec transform(const vec2 &o) const;
2490 :
2491 : /**
2492 : * @brief Returns the x values of the four vectors as a four-vector.
2493 : *
2494 : * @return a vector containing four x values
2495 : */
2496 : vec4<float> rowx() const;
2497 :
2498 : /**
2499 : * @brief Returns the y values of the four vectors as a four-vector.
2500 : *
2501 : * @return a vector containing four y values
2502 : */
2503 : vec4<float> rowy() const;
2504 :
2505 : /**
2506 : * @brief Returns the z values of the four vectors as a four-vector.
2507 : *
2508 : * @return a vector containing four z values
2509 : */
2510 : vec4<float> rowz() const;
2511 : };
2512 :
2513 : /*
2514 :
2515 : The engine uses 3 different linear coordinate systems
2516 : which are oriented around each of the axis dimensions.
2517 :
2518 : So any point within the game can be defined by four coordinates: (d, x, y, z)
2519 :
2520 : d is the reference axis dimension
2521 : x is the coordinate of the ROW dimension
2522 : y is the coordinate of the COL dimension
2523 : z is the coordinate of the reference dimension (DEPTH)
2524 :
2525 : typically, if d is not used, then it is implicitly the Z dimension.
2526 : ie: d=z => x=x, y=y, z=z
2527 :
2528 : */
2529 :
2530 : // DIM: X=0 Y=1 Z=2.
2531 : const int R[3] = {1, 2, 0}; /**< row */
2532 : const int C[3] = {2, 0, 1}; /**< col */
2533 : const int D[3] = {0, 1, 2}; /**< depth */
2534 :
2535 : struct ivec2;
2536 :
2537 : //integer vector3
2538 : struct ivec
2539 : {
2540 : int x, y, z;
2541 :
2542 1228 : ivec() {}
2543 2 : explicit ivec(const vec &v) : x(static_cast<int>(v.x)), y(static_cast<int>(v.y)), z(static_cast<int>(v.z)) {}
2544 823 : ivec(int a, int b, int c) : x(a), y(b), z(c) {}
2545 1 : ivec(int d, int row, int col, int depth)
2546 1 : {
2547 1 : (*this)[R[d]] = row;
2548 1 : (*this)[C[d]] = col;
2549 1 : (*this)[D[d]] = depth;
2550 1 : }
2551 37 : ivec(int i, const ivec &co, int size) : x(co.x+((i&1)>>0)*size), y(co.y+((i&2)>>1)*size), z(co.z +((i&4)>>2)*size) {}
2552 : explicit ivec(const ivec2 &v, int z = 0);
2553 : explicit ivec(const svec &v);
2554 :
2555 707 : int &operator[](int i)
2556 : {
2557 707 : switch(i)
2558 : {
2559 238 : case 1:
2560 : {
2561 238 : return y;
2562 : }
2563 232 : case 2:
2564 : {
2565 232 : return z;
2566 : }
2567 237 : default:
2568 : {
2569 237 : return x;
2570 : }
2571 : }
2572 : }
2573 :
2574 418 : int operator[](int i) const
2575 : {
2576 418 : switch(i)
2577 : {
2578 139 : case 1:
2579 : {
2580 139 : return y;
2581 : }
2582 140 : case 2:
2583 : {
2584 140 : return z;
2585 : }
2586 139 : default:
2587 : {
2588 139 : return x;
2589 : }
2590 : }
2591 : }
2592 :
2593 : //int idx(int i) { return v[i]; }
2594 183 : bool operator==(const ivec &v) const { return x==v.x && y==v.y && z==v.z; }
2595 3 : bool operator!=(const ivec &v) const { return x!=v.x || y!=v.y || z!=v.z; }
2596 : ivec operator+(const ivec &v) const { return ivec(x+v.x, y+v.y, z+v.z); }
2597 : /**
2598 : * @brief Type conversion operator from ivec -> bool.
2599 : *
2600 : * If this ivec is identical to the origin (0,0,0), returns false; for any other
2601 : * values of (x,y,z) returns true. This is behavior analogous to int in three
2602 : * dimensions.
2603 : */
2604 186 : explicit operator bool() const { return !(x==0 && y==0 && z==0); }
2605 50 : ivec &shl(int n) { x<<= n; y<<= n; z<<= n; return *this; }
2606 3 : ivec &shr(int n) { x>>= n; y>>= n; z>>= n; return *this; }
2607 194 : ivec &mul(int n) { x *= n; y *= n; z *= n; return *this; }
2608 0 : ivec &div(int n) { x /= n; y /= n; z /= n; return *this; }
2609 12 : ivec &add(int n) { x += n; y += n; z += n; return *this; }
2610 1 : ivec &sub(int n) { x -= n; y -= n; z -= n; return *this; }
2611 2 : ivec &mul(const ivec &v) { x *= v.x; y *= v.y; z *= v.z; return *this; }
2612 : ivec &div(const ivec &v) { x /= v.x; y /= v.y; z /= v.z; return *this; }
2613 193 : ivec &add(const ivec &v) { x += v.x; y += v.y; z += v.z; return *this; }
2614 283 : ivec &sub(const ivec &v) { x -= v.x; y -= v.y; z -= v.z; return *this; }
2615 229 : ivec &mask(int n) { x &= n; y &= n; z &= n; return *this; }
2616 3 : ivec &neg() { x = -x; y = -y; z = -z; return *this; }
2617 6 : ivec &min(const ivec &o) { x = ::min(x, o.x); y = ::min(y, o.y); z = ::min(z, o.z); return *this; }
2618 6 : ivec &max(const ivec &o) { x = ::max(x, o.x); y = ::max(y, o.y); z = ::max(z, o.z); return *this; }
2619 2 : ivec &min(int n) { x = ::min(x, n); y = ::min(y, n); z = ::min(z, n); return *this; }
2620 2 : ivec &max(int n) { x = ::max(x, n); y = ::max(y, n); z = ::max(z, n); return *this; }
2621 3 : ivec &abs() { x = ::abs(x); y = ::abs(y); z = ::abs(z); return *this; }
2622 2 : ivec &clamp(int l, int h) { x = ::std::clamp(x, l, h); y = ::std::clamp(y, l, h); z = ::std::clamp(z, l, h); return *this; }
2623 192 : ivec &cross(const ivec &a, const ivec &b) { x = a.y*b.z-a.z*b.y; y = a.z*b.x-a.x*b.z; z = a.x*b.y-a.y*b.x; return *this; }
2624 143 : int dot(const ivec &o) const { return x*o.x + y*o.y + z*o.z; }
2625 : float dist(const plane &p) const;
2626 :
2627 2 : static inline ivec floor(const vec &o) { return ivec(static_cast<int>(::floor(o.x)), static_cast<int>(::floor(o.y)), static_cast<int>(::floor(o.z))); }
2628 2 : static inline ivec ceil(const vec &o) { return ivec(static_cast<int>(::ceil(o.x)), static_cast<int>(::ceil(o.y)), static_cast<int>(::ceil(o.z))); }
2629 : };
2630 :
2631 25 : inline vec::vec(const ivec &v) : x(v.x), y(v.y), z(v.z) {}
2632 :
2633 : template<>
2634 : struct std::hash<ivec>
2635 : {
2636 48 : size_t operator()(const ivec &k) const
2637 : {
2638 48 : return k.x^k.y^k.z;
2639 : }
2640 : };
2641 :
2642 : /**
2643 : * @brief integer vector2
2644 : */
2645 : struct ivec2
2646 : {
2647 : union
2648 : {
2649 : struct { int x, y; } coord;
2650 : int v[2];
2651 : };
2652 :
2653 763 : ivec2() {}
2654 122 : ivec2(int x, int y)
2655 122 : {
2656 122 : coord.x = x;
2657 122 : coord.y = y;
2658 122 : }
2659 :
2660 : explicit ivec2(const vec2 &v)
2661 : {
2662 : coord.x = static_cast<int>(v.x);
2663 : coord.y = static_cast<int>(v.y);
2664 : }
2665 :
2666 : explicit ivec2(const ivec &v)
2667 : {
2668 : coord.x = v.x;
2669 : coord.y = v.y;
2670 : }
2671 :
2672 2 : int &operator[](int i) { return v[i]; }
2673 2 : int operator[](int i) const { return v[i]; }
2674 :
2675 32 : bool operator==(const ivec2 &o) const { return coord.x == o.coord.x && coord.y == o.coord.y; }
2676 3 : bool operator!=(const ivec2 &o) const { return coord.x != o.coord.x || coord.y != o.coord.y; }
2677 :
2678 3 : int &x() { return coord.x; }
2679 3 : int &y() { return coord.y; }
2680 0 : int x() const { return coord.x; }
2681 0 : int y() const { return coord.y; }
2682 :
2683 3 : bool iszero() const { return coord.x==0 && coord.y==0; }
2684 2 : ivec2 &shl(int n) { coord.x<<= n; coord.y<<= n; return *this; }
2685 3 : ivec2 &shr(int n) { coord.x>>= n; coord.y>>= n; return *this; }
2686 2 : ivec2 &mul(int n) { coord.x *= n; coord.y *= n; return *this; }
2687 : ivec2 &div(int n) { coord.x /= n; coord.y /= n; return *this; }
2688 2 : ivec2 &add(int n) { coord.x += n; coord.y += n; return *this; }
2689 2 : ivec2 &sub(int n) { coord.x -= n; coord.y -= n; return *this; }
2690 2 : ivec2 &mul(const ivec2 &v) { coord.x *= v.coord.x; coord.y *= v.coord.y; return *this; }
2691 : ivec2 &div(const ivec2 &v) { coord.x /= v.coord.x; coord.y /= v.coord.y; return *this; }
2692 2 : ivec2 &add(const ivec2 &v) { coord.x += v.coord.x; coord.y += v.coord.y; return *this; }
2693 2 : ivec2 &sub(const ivec2 &v) { coord.x -= v.coord.x; coord.y -= v.coord.y; return *this; }
2694 3 : ivec2 &mask(int n) { coord.x &= n; coord.y &= n; return *this; }
2695 3 : ivec2 &neg() { coord.x = -coord.x; coord.y = -coord.y; return *this; }
2696 1 : ivec2 &min(const ivec2 &o) { coord.x = ::min(coord.x, o.coord.x); coord.y = ::min(coord.y, o.coord.y); return *this; }
2697 1 : ivec2 &max(const ivec2 &o) { coord.x = ::max(coord.x, o.coord.x); coord.y = ::max(coord.y, o.coord.y); return *this; }
2698 1 : ivec2 &min(int n) { coord.x = ::min(coord.x, n); coord.y = ::min(coord.y, n); return *this; }
2699 1 : ivec2 &max(int n) { coord.x = ::max(coord.x, n); coord.y = ::max(coord.y, n); return *this; }
2700 3 : ivec2 &abs() { coord.x = ::abs(coord.x); coord.y = ::abs(coord.y); return *this; }
2701 1 : int dot(const ivec2 &o) const { return coord.x*o.coord.x + coord.y*o.coord.y; }
2702 2 : int cross(const ivec2 &o) const { return coord.x*o.coord.y - coord.y*o.coord.x; }
2703 : };
2704 :
2705 : inline ivec::ivec(const ivec2 &v, int z) : x(v.x()), y(v.y()), z(z) {}
2706 :
2707 : inline bvec::bvec(const vec4<uchar> &v) : x(v.x), y(v.y), z(v.z) {}
2708 :
2709 : /**
2710 : * @brief short integer three-vector object
2711 : */
2712 : struct svec
2713 : {
2714 : union
2715 : {
2716 : struct { short x, y, z; } coord;
2717 : short v[3];
2718 : };
2719 :
2720 0 : svec() {}
2721 : svec(short x, short y, short z)
2722 : {
2723 : coord.x = x;
2724 : coord.y = y;
2725 : coord.z = z;
2726 : }
2727 0 : explicit svec(const ivec &v)
2728 0 : {
2729 0 : coord.x = v.x;
2730 0 : coord.y = v.y;
2731 0 : coord.z = v.z;
2732 0 : }
2733 :
2734 : short &operator[](int i) { return v[i]; }
2735 : short operator[](int i) const { return v[i]; }
2736 : };
2737 :
2738 : inline vec::vec(const svec &v)
2739 : {
2740 : x = v.coord.x;
2741 : y = v.coord.y;
2742 : z = v.coord.z;
2743 : }
2744 :
2745 0 : inline ivec::ivec(const svec &v)
2746 : {
2747 0 : x = v.coord.x;
2748 0 : y = v.coord.y;
2749 0 : z = v.coord.z;
2750 0 : }
2751 :
2752 : /**
2753 : * @brief floating point 4x4 array object
2754 : */
2755 : struct matrix4
2756 : {
2757 : vec4<float> a, b, c, d;
2758 :
2759 : template<class T, class U>
2760 : T transformnormal(const U &in) const
2761 : {
2762 : T v;
2763 : transformnormal(in, v);
2764 : return v;
2765 : }
2766 :
2767 : template<class T, class U>
2768 : T transform(const U &in) const
2769 : {
2770 : T v;
2771 : transform(in, v);
2772 : return v;
2773 : }
2774 :
2775 : template<class T>
2776 0 : vec perspectivetransform(const T &in) const
2777 : {
2778 0 : vec4<float> v;
2779 0 : transform(in, v);
2780 0 : return vec(v).div(v.w);
2781 : }
2782 :
2783 : template<class T>
2784 4 : void mult(const matrix4 &x, const matrix4 &y)
2785 : {
2786 4 : a = T(x.a).mul(y.a.x).madd(x.b, y.a.y).madd(x.c, y.a.z).madd(x.d, y.a.w);
2787 4 : b = T(x.a).mul(y.b.x).madd(x.b, y.b.y).madd(x.c, y.b.z).madd(x.d, y.b.w);
2788 4 : c = T(x.a).mul(y.c.x).madd(x.b, y.c.y).madd(x.c, y.c.z).madd(x.d, y.c.w);
2789 4 : d = T(x.a).mul(y.d.x).madd(x.b, y.d.y).madd(x.c, y.d.z).madd(x.d, y.d.w);
2790 4 : }
2791 :
2792 : matrix4();
2793 : matrix4(const float *m);
2794 : matrix4(const vec &a, const vec &b, const vec &c = vec(0, 0, 1));
2795 : matrix4(const vec4<float> &a, const vec4<float> &b, const vec4<float> &c, const vec4<float> &d = vec4<float>(0, 0, 0, 1));
2796 : matrix4(const matrix4x3 &m);
2797 : matrix4(const matrix3 &rot, const vec &trans);
2798 : void mul(const matrix4 &x, const matrix3 &y);
2799 : void mul(const matrix3 &y);
2800 :
2801 : /**
2802 : * @brief Sets this matrix to the product of the two matrices provided
2803 : *
2804 : * The original contents of the matrix are disregarded.
2805 : * All calculations at single precision (float).
2806 : *
2807 : * @param x the first matrix to multiply
2808 : * @param y the second matrix to multiply
2809 : */
2810 : void mul(const matrix4 &x, const matrix4 &y);
2811 :
2812 : /**
2813 : * @brief Sets this matrix to the product of this and another matrix
2814 : *
2815 : * The original contents of the matrix are the left element in the product.
2816 : * All calculations at single precision (float).
2817 : *
2818 : * @param y the second matrix to multiply
2819 : */
2820 : void mul(const matrix4 &y);
2821 :
2822 : /**
2823 : * @brief Sets this matrix to the product of the two matrices provided
2824 : *
2825 : * The original contents of the matrix are disregarded.
2826 : * Uses double precision to perform calculations, and is narrowed at the end to float.
2827 : *
2828 : * @param x the first matrix to multiply
2829 : * @param y the second matrix to multiply
2830 : */
2831 : void muld(const matrix4 &x, const matrix4 &y);
2832 :
2833 : /**
2834 : * @brief Sets this matrix to the product of this and another matrix
2835 : *
2836 : * The original contents of the matrix are the left element in the product.
2837 : * Uses double precision to perform calculations, and is narrowed at the end to float.
2838 : *
2839 : * @param y the second matrix to multiply
2840 : */
2841 : void muld(const matrix4 &y);
2842 : void rotate_around_x(float ck, float sk);
2843 : void rotate_around_x(float angle);
2844 : void rotate_around_x(const vec2 &sc);
2845 : void rotate_around_y(float ck, float sk);
2846 : void rotate_around_y(float angle);
2847 : void rotate_around_y(const vec2 &sc);
2848 :
2849 : void rotate_around_z(float ck, float sk);
2850 : void rotate_around_z(float angle);
2851 : void rotate_around_z(const vec2 &sc);
2852 :
2853 : void rotate(float ck, float sk, const vec &axis);
2854 : void rotate(float angle, const vec &dir);
2855 : void rotate(const vec2 &sc, const vec &dir);
2856 :
2857 : /**
2858 : * @brief Sets the matrix to I, the identity matrix
2859 : *
2860 : * Sets the matrix to I, with the form as follows:
2861 : * ```
2862 : * a b c d
2863 : * x 1 0 0 0
2864 : * y 0 1 0 0
2865 : * z 0 0 1 0
2866 : * w 0 0 0 1
2867 : * ```
2868 : */
2869 : void identity();
2870 :
2871 : void settranslation(const vec &v);
2872 : void settranslation(float x, float y, float z);
2873 : void translate(const vec &p);
2874 : void translate(float x, float y, float z);
2875 : void translate(const vec &p, float scale);
2876 : void setscale(float x, float y, float z);
2877 : void setscale(const vec &v);
2878 : void setscale(float n);
2879 : void scale(float x, float y, float z);
2880 : void scale(const vec &v);
2881 : void scale(float n);
2882 :
2883 : void scalez(float k);
2884 :
2885 : void jitter(float x, float y);
2886 :
2887 : /**
2888 : * @brief Transposes the matrix along the diagonal.
2889 : *
2890 : * Transforms the matrix like so (letters are just arbitrary value placeholders)
2891 : * ```
2892 : * a b c d a e i m
2893 : * e f g h -> b f j n
2894 : * i j k l c g k o
2895 : * m n o p d h l p
2896 : * ```
2897 : */
2898 : void transpose();
2899 :
2900 : /**
2901 : * @brief Copies the transpose of the given matrix4 to `this`
2902 : *
2903 : * Copies the transform of the matrix passed like so (letters are just arbitrary
2904 : * value placeholders) to `this` object.
2905 : * ```
2906 : * a b c d a e i m
2907 : * e f g h -> b f j n
2908 : * i j k l c g k o
2909 : * m n o p d h l p
2910 : * ```
2911 : */
2912 : void transpose(const matrix4 &m);
2913 : void frustum(float left, float right, float bottom, float top, float znear, float zfar);
2914 : void perspective(float fovy, float aspect, float znear, float zfar);
2915 :
2916 : void ortho(float left, float right, float bottom, float top, float znear, float zfar);
2917 :
2918 : void transform(const vec &in, vec &out) const;
2919 : void transform(const vec4<float> &in, vec &out) const;
2920 :
2921 : void transform(const vec &in, vec4<float> &out) const;
2922 : void transform(const vec4<float> &in, vec4<float> &out) const;
2923 : void transformnormal(const vec &in, vec &out) const;
2924 : void transformnormal(const vec &in, vec4<float> &out) const;
2925 :
2926 : void transposedtransform(const vec &in, vec &out) const;
2927 : void transposedtransformnormal(const vec &in, vec &out) const;
2928 : void transposedtransform(const plane &in, plane &out) const;
2929 :
2930 : vec gettranslation() const;
2931 :
2932 : /**
2933 : * @brief Returns the first row of the matrix.
2934 : *
2935 : * Returns the first value of each column vector that makes up the matrix.
2936 : *
2937 : * @return a vec4 of the first row of the vector
2938 : */
2939 : vec4<float> rowx() const;
2940 :
2941 : /**
2942 : * @brief Returns the second row of the matrix.
2943 : *
2944 : * Returns the second value of each column vector that makes up the matrix.
2945 : *
2946 : * @return a vec4 of the second row of the vector
2947 : */
2948 : vec4<float> rowy() const;
2949 :
2950 : /**
2951 : * @brief Returns the third row of the matrix.
2952 : *
2953 : * Returns the third value of each column vector that makes up the matrix.
2954 : *
2955 : * @return a vec4 of the third row of the vector
2956 : */
2957 : vec4<float> rowz() const;
2958 :
2959 : /**
2960 : * @brief Returns the fourth row of the matrix.
2961 : *
2962 : * Returns the fourth value of each column vector that makes up the matrix.
2963 : *
2964 : * @return a vec4 of the last row of the vector
2965 : */
2966 : vec4<float> roww() const;
2967 :
2968 : /**
2969 : * @brief Sets this matrix to the inverse of the provided matrix.
2970 : *
2971 : * Sets the matrix values to the inverse of the provided matrix A*A^-1 = I
2972 : * returns false if singular (or nearly singular to within tolerance of mindet)
2973 : * or true if matrix was inverted successfully
2974 : *
2975 : * @param m a matrix4 object to be inverted and assigned to the object
2976 : * @param mindet the determinant value at which matrices are considered singular
2977 : *
2978 : * @return false if the matrix is singular, true otherwise
2979 : */
2980 : bool invert(const matrix4 &m, double mindet = 1.0e-12);
2981 :
2982 : /**
2983 : * @brief Returns the inverse of the matrix.
2984 : *
2985 : * Returns a zero matrix if the matrix is singular.
2986 : *
2987 : * @param mindet the determinant value at which matrices are considered singular
2988 : *
2989 : * @return a matrix4 containing the matrix inverse
2990 : */
2991 : matrix4 inverse(double mindet = 1.0e-12) const;
2992 :
2993 : vec2 lineardepthscale() const;
2994 : };
2995 :
2996 1 : inline matrix3::matrix3(const matrix4 &m)
2997 1 : : a(m.a), b(m.b), c(m.c)
2998 1 : {}
2999 :
3000 : inline matrix4x3::matrix4x3(const matrix4 &m)
3001 : : a(m.a), b(m.b), c(m.c), d(m.d)
3002 : {}
3003 :
3004 1 : inline matrix3::matrix3(const matrix4x3 &m) : a(m.a), b(m.b), c(m.c) {}
3005 :
3006 : //generic two dimensional vector
3007 : template<class T>
3008 : struct GenericVec2
3009 : {
3010 : T x,y;
3011 :
3012 8 : GenericVec2() {}
3013 : GenericVec2(T x, T y) : x(x), y(y) {}
3014 2 : GenericVec2(const vec2 &v) : x(v.x), y(v.y) {}
3015 :
3016 : bool operator==(const GenericVec2 &h) const { return x == h.x && y == h.y; }
3017 : bool operator!=(const GenericVec2 &h) const { return x != h.x || y != h.y; }
3018 : };
3019 :
3020 : //generic three dmensional vector
3021 : template<class T>
3022 : struct GenericVec3
3023 : {
3024 : T x,y,z;
3025 :
3026 : GenericVec3() {}
3027 : GenericVec3(T x, T y, T z) : x(x), y(y), z(z) {}
3028 : GenericVec3(const vec &v) : x(v.x), y(v.y), z(v.z) {}
3029 :
3030 : GenericVec3<T> operator+(const GenericVec3<T> &h) const { return GenericVec3<T>(x+h.x, y+h.y,z+h.z); }
3031 : GenericVec3<T> operator-(const GenericVec3<T> &h) const { return GenericVec3<T>(x-h.x, y-h.y, z-h.z); }
3032 :
3033 : //comparison
3034 : bool operator==(const GenericVec3<T> &h) const { return x == h.x && y == h.y && z == h.z; }
3035 : bool operator!=(const GenericVec3<T> &h) const { return x != h.x || y != h.y || z != h.z; }
3036 : bool operator>(const GenericVec3<T> &h) const { return x > h.x && y > h.y && z > h.z; }
3037 : bool operator<(const GenericVec3<T> &h) const { return x < h.x && y < h.y && z < h.z; }
3038 : bool operator>=(const GenericVec3<T> &h) const { return x >= h.x && y >= h.y && z >= h.z; }
3039 : bool operator<=(const GenericVec3<T> &h) const { return x <= h.x && y <= h.y && z <= h.z; }
3040 : };
3041 :
3042 : extern bool raysphereintersect(const vec ¢er, float radius, const vec &o, const vec &ray, float &dist);
3043 : extern bool rayboxintersect(const vec &b, const vec &s, const vec &o, const vec &ray, float &dist, int &orient);
3044 :
3045 : /**
3046 : * @brief Determines whether a line segment intersects a specified cylinder.
3047 : *
3048 : * Calculates whether a specified line segment intersects a cylinder, defined by
3049 : * a line segment and a radius around it. Segments which intersect along an edge,
3050 : * face, or tangent to the curved surface are considered to be intersecting. A
3051 : * successful intersection will cause the function to return `true`.
3052 : *
3053 : * Negative radii are handled the same as a positive radius of the same magnitude.
3054 : *
3055 : * If the line segment is entirely within the boundaries of the cylinder, the
3056 : * segment is considered to be intersecting, with the intersection starting
3057 : * at the `from` location.
3058 : *
3059 : * The distance along the line at which the segment intersects the cylinder is
3060 : * expressed as a value from 0 to 1 and returned through the reference parameter
3061 : * dist. If the segment is entirely within the cylinder, the segment's intersection
3062 : * distance is considered to be zero.
3063 : *
3064 : * If no intersection with the cylinder is found, the dist value will be returned
3065 : * unchanged, and the function will return false.
3066 : *
3067 : * @param from the start point of the intersecting line segment
3068 : * @param to the end point of the intersecting line segment
3069 : * @param start the start point of the cylinder's axial line segment
3070 : * @param end the endpoint of the cylinder's axial line segment
3071 : * @param radius the radius of the cylinder to be intersected
3072 : * @param dist the value to set to the distance along the segment where intersection occured
3073 : *
3074 : * @return true if the cylinder was intersected by the line segment
3075 : * @return false if the cylinder and line segment did not intersect
3076 : */
3077 : extern bool linecylinderintersect(const vec &from, const vec &to, const vec &start, const vec &end, float radius, float &dist);
3078 : extern int polyclip(const vec *in, int numin, const vec &dir, float below, float above, vec *out);
3079 :
3080 : extern const vec2 sincos360[]; /**< a 721 element table of cosines, sines given integral values */
3081 :
3082 : /**
3083 : * @brief Returns the angle passed to it, clamped to 0...360
3084 : *
3085 : * Normalizes negative/large angles passed to it to the range [0,360).
3086 : *
3087 : * @param angle the angle to parse
3088 : *
3089 : * @return the angle clamped to 0...360
3090 : */
3091 6 : inline int mod360(int angle)
3092 : {
3093 6 : if(angle < 0)
3094 : {
3095 2 : angle = 360 + (angle <= -360 ? angle%360 : angle);
3096 : }
3097 4 : else if(angle >= 360)
3098 : {
3099 3 : angle %= 360;
3100 : }
3101 6 : return angle;
3102 : }
3103 :
3104 : /**
3105 : * @brief Returns a vec2 containing (cos, sine) for a given integral angle.
3106 : *
3107 : * @param angle the angle to get the sine/cos value of
3108 : *
3109 : * @return a vec2 containing the cosine and sine of the given angle
3110 : */
3111 1 : inline const vec2 &sincosmod360(int angle) { return sincos360[mod360(angle)]; }
3112 :
3113 : /**
3114 : * @brief Returns the cosine for an angle (in degrees)
3115 : *
3116 : * Must be within the bounds of 0...720. Uses a lookup table for integral values in degrees.
3117 : *
3118 : * @param angle the angle to get the cosine of (in degrees)
3119 : *
3120 : * @return the cosine of that angle
3121 : */
3122 10 : inline float cos360(int angle) { return sincos360[angle].x; }
3123 :
3124 : /**
3125 : * @brief Returns the sine for an angle (in degrees)
3126 : *
3127 : * Must be within the bounds of 0...720. Uses a lookup table for integral values in degrees.
3128 : *
3129 : * @param angle the angle to get the sine of (in degrees)
3130 : *
3131 : * @return the sine of that angle
3132 : */
3133 10 : inline float sin360(int angle) { return sincos360[angle].y; }
3134 :
3135 : /**
3136 : * @brief Returns the tangent for an angle (in degrees)
3137 : *
3138 : * Must be within the bounds of 0...720. Uses a lookup table for integral values in degrees.
3139 : *
3140 : * @param angle the angle to get the tangent of (in degrees)
3141 : *
3142 : * @return the tangent of that angle
3143 : */
3144 0 : inline float tan360(int angle) { const vec2 &sc = sincos360[angle]; return sc.y/sc.x; }
3145 :
3146 : /**
3147 : * @brief Returns the cotangent for an angle (in degrees)
3148 : *
3149 : * Must be within the bounds of 0...720. Uses a lookup table for integral values in degrees.
3150 : *
3151 : * @param angle the angle to get the cotangent of (in degrees)
3152 : *
3153 : * @return the cotangent of that angle
3154 : */
3155 0 : inline float cotan360(int angle) { const vec2 &sc = sincos360[angle]; return sc.x/sc.y; }
3156 :
3157 : #endif /* GEOM_H_ */
|