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 934 : vec2() {}
38 1087 : 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 59 : 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 15257 : vec() {}
211 2 : explicit vec(int a) : x(a), y(a), z(a) {}
212 1 : explicit vec(float a) : x(a), y(a), z(a) {}
213 17348 : 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 240 : 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 1315 : 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 52 : 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 1216 : 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 3689 : 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 941 : 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 1 : 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 5000 : vec &add(const vec &o) { x += o.x; y += o.y; z += o.z; return *this; }
376 4549 : vec &sub(const vec &o) { x -= o.x; y -= o.y; z -= o.z; return *this; }
377 14 : vec &min(const vec &o) { x = ::min(x, o.x); y = ::min(y, o.y); z = ::min(z, o.z); return *this; }
378 14 : 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 1541 : 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 2859 : 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 664 : vec &madd(const vec &a, const B &b) { return add(vec(a).mul(b)); }
500 :
501 : template<class B>
502 20 : 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 4 : void flip()
780 : {
781 4 : x ^= 0x80;
782 4 : y ^= 0x80;
783 4 : z ^= 0x80;
784 4 : }
785 :
786 3 : void scale(int k, int d)
787 : {
788 3 : x = static_cast<uchar>((x*k)/d);
789 3 : y = static_cast<uchar>((y*k)/d);
790 3 : z = static_cast<uchar>((z*k)/d);
791 3 : }
792 :
793 2 : bvec &shl(int n)
794 : {
795 2 : x <<= n;
796 2 : y <<= n;
797 2 : z <<= n;
798 2 : return *this;
799 : }
800 3 : bvec &shr(int n)
801 : {
802 3 : x >>= n;
803 3 : y >>= n;
804 3 : z >>= n;
805 3 : return *this;
806 : }
807 :
808 3 : static bvec fromcolor(const vec &v)
809 : {
810 3 : return bvec(static_cast<uchar>(v.x*255.0f), static_cast<uchar>(v.y*255.0f), static_cast<uchar>(v.z*255.0f));
811 : }
812 :
813 3 : vec tocolor() const
814 : {
815 3 : return vec(x*(1.0f/255.0f), y*(1.0f/255.0f), z*(1.0f/255.0f));
816 : }
817 :
818 5 : static bvec from565(ushort c)
819 : {
820 5 : return bvec((((c>>11)&0x1F)*527 + 15) >> 6, (((c>>5)&0x3F)*259 + 35) >> 6, ((c&0x1F)*527 + 15) >> 6);
821 : }
822 :
823 46 : static bvec hexcolor(int color)
824 : {
825 46 : return bvec((color>>16)&0xFF, (color>>8)&0xFF, color&0xFF);
826 : }
827 :
828 5 : int tohexcolor() const
829 : {
830 5 : return (static_cast<int>(x)<<16)|(static_cast<int>(y)<<8)|static_cast<int>(z);
831 : }
832 : };
833 :
834 : /**
835 : * @brief A four dimensional Cartesian-space vector template.
836 : *
837 : * This object defines a location in four dimensional Cartesian space, in whatever
838 : * arithmetic type it is specialized to be. All four values are of the type T
839 : * specialized, and all operators (unless explicitly specified, require types
840 : * trivially convertable to T (or preferably of type T).
841 : */
842 : template<typename T>
843 : struct vec4
844 : {
845 :
846 : T x, y, z, w; /** geometric space representation */
847 :
848 1034 : vec4() {}
849 30 : explicit vec4(const vec &p, T w = 0) : x(p.x), y(p.y), z(p.z), w(w) {}
850 2 : explicit vec4(const vec2 &p, T z = 0, T w = 0) : x(p.x), y(p.y), z(z), w(w) {}
851 1793 : vec4(T x, T y = 0, T z = 0, T w = 0) : x(x), y(y), z(z), w(w) {}
852 1 : vec4(bvec v, uchar c)
853 : {
854 1 : x = v.x;
855 1 : y = v.y;
856 1 : z = v.z;
857 1 : w = c;
858 1 : }
859 1 : vec4(bvec v)
860 : {
861 1 : x = v.x;
862 1 : y = v.y;
863 1 : z = v.z;
864 1 : w = 0;
865 1 : }
866 :
867 4 : explicit vec4(const T *v) : x(v[0]), y(v[1]), z(v[2]), w(v[3]) {}
868 :
869 : template<class U>
870 32 : vec4(const vec4<U> &p) : x(p.x), y(p.y), z(p.z), w(p.w) {}
871 :
872 : template<class U>
873 20 : operator vec4<U>()
874 : {
875 38 : return vec4<U>(static_cast<U>(this->x),
876 20 : static_cast<U>(this->y),
877 20 : static_cast<U>(this->z),
878 20 : static_cast<U>(this->w));
879 : }
880 :
881 : /**
882 : * @brief Returns the i-th dimension of this vec4.
883 : *
884 : * 0 = x
885 : * 1 = y
886 : * 2 = z
887 : * 3 = w
888 : *
889 : * All values other than these will return a reference to x.
890 : *
891 : * @param i the index to access
892 : *
893 : * @return reference to the value along the specified dimension
894 : */
895 4 : T &operator[](int i)
896 : {
897 4 : switch(i)
898 : {
899 1 : case 1:
900 : {
901 1 : return y;
902 : }
903 1 : case 2:
904 : {
905 1 : return z;
906 : }
907 1 : case 3:
908 : {
909 1 : return w;
910 : }
911 1 : default:
912 : {
913 1 : return x;
914 : }
915 : }
916 : }
917 :
918 : /**
919 : * @brief Returns the i-th dimension of this vec4.
920 : *
921 : * 0 = x
922 : * 1 = y
923 : * 2 = z
924 : * 3 = w
925 : *
926 : * All values other than these will return the value of x.
927 : *
928 : * @param i the index to access
929 : *
930 : * @return the value along the specified dimension
931 : */
932 4 : T operator[](int i) const
933 : {
934 4 : switch(i)
935 : {
936 1 : case 1:
937 : {
938 1 : return y;
939 : }
940 1 : case 2:
941 : {
942 1 : return z;
943 : }
944 1 : case 3:
945 : {
946 1 : return w;
947 : }
948 1 : default:
949 : {
950 1 : return x;
951 : }
952 : }
953 : }
954 :
955 :
956 : /**
957 : * @brief References the x coordinate of this vec4
958 : *
959 : * @return a reference to x
960 : */
961 3 : T &r() { return x; }
962 :
963 : /**
964 : * @brief References the y coordinate of this vec4
965 : *
966 : * @return a reference to y
967 : */
968 3 : T &g() { return y; }
969 :
970 : /**
971 : * @brief References the z coordinate of this vec4
972 : *
973 : * @return a reference to z
974 : */
975 3 : T &b() { return z; }
976 :
977 : /**
978 : * @brief References the w coordinate of this vec4
979 : *
980 : * @return a reference to w
981 : */
982 3 : T &a() { return w; }
983 :
984 : /**
985 : * @brief Returns the x coordinate of this vec4
986 : *
987 : * @return the value of x
988 : */
989 : T r() const { return x; }
990 :
991 : /**
992 : * @brief Returns the y coordinate of this vec4
993 : *
994 : * @return the value of y
995 : */
996 : T g() const { return y; }
997 :
998 : /**
999 : * @brief Returns the z coordinate of this vec4
1000 : *
1001 : * @return the value of z
1002 : */
1003 : T b() const { return z; }
1004 :
1005 : /**
1006 : * @brief Returns the w coordinate of this vec4
1007 : *
1008 : * @return the value of w
1009 : */
1010 : T a() const { return w; }
1011 :
1012 : /**
1013 : * @brief Returns a raw pointer to the data of this vec4.
1014 : *
1015 : * @return a pointer to the lowest dimension (x) of this object
1016 : */
1017 1 : const T *data() const { return &x; }
1018 :
1019 : /**
1020 : * @brief Returns a raw unsigned int pointer to the data in this vec4.
1021 : *
1022 : * @return a unsigned int pointer to the lowest dimension (x) of this object
1023 : */
1024 4 : uint *mask()
1025 : {
1026 4 : return reinterpret_cast<uint *>(&x);
1027 : }
1028 :
1029 : /**
1030 : * @brief Returns whether two vec objects exactly match
1031 : *
1032 : * The two values must be exactly equal (by floating point math rules), and
1033 : * no tolerance is provided.
1034 : *
1035 : * @param o the value to compare
1036 : *
1037 : * @return true if all values in the vec4s exactly match
1038 : * @return false if any value does not match
1039 : */
1040 247 : bool operator==(const vec4 &o) const { return x == o.x && y == o.y && z == o.z && w == o.w; }
1041 :
1042 : /**
1043 : * @brief Returns whether two vec objects do not match
1044 : *
1045 : * If any value compares not equal (by floating point math rules),
1046 : * then the vec4s are considered not equal
1047 : *
1048 : * @param o the value to compare
1049 : *
1050 : * @return true if any value does not match
1051 : * @return false if all values in the vec4s exactly match
1052 : */
1053 3 : bool operator!=(const vec4 &o) const { return x != o.x || y != o.y || z != o.z || w != o.w; }
1054 :
1055 : /**
1056 : * @brief Returns the 3 dimensional dot product between two 4-vecs.
1057 : *
1058 : * Returns the scalar (dot) product of two 4D vecs, `this` and the passed
1059 : * one, as if they are 3D vecs, by ignoring the fourth term in each vector.
1060 : *
1061 : * @param o the vec4 to multiply by
1062 : *
1063 : * @return the dot product of the first three elements of each vector
1064 : */
1065 287 : T dot3(const vec4 &o) const { return x*o.x + y*o.y + z*o.z; }
1066 :
1067 : /**
1068 : * @brief Returns the 3 dimensional dot product between `this` and a 3D vec.
1069 : *
1070 : * Returns the scalar (dot) product of a 3D and 4D vec, `this` and the passed
1071 : * 3D vec, by ignoring the fourth term in the 4D vec.
1072 : *
1073 : * @param o the vec3 to multiply by
1074 : *
1075 : * @return the dot product of the first three elements of each vector
1076 : */
1077 25 : T dot3(const vec &o) const { return x*o.x + y*o.y + z*o.z; }
1078 :
1079 : /**
1080 : * @brief Returns the scalar product with another vec4.
1081 : *
1082 : * Returns the scalar (dot) product of two 4D vecs, `this` and the passed
1083 : * vec4 `o`.
1084 : *
1085 : * @param o the vector to multiply with
1086 : *
1087 : * @return the dot product of the two vectors
1088 : */
1089 279 : T dot(const vec4 &o) const { return dot3(o) + w*o.w; }
1090 :
1091 : /**
1092 : * @brief Returns the dot product of `this` and a vec3, assuming o.w = 1.
1093 : *
1094 : * Calculates the dot product with a vec3, with `o.w` implied to equal 1.
1095 : *
1096 : * @param o the vec3 to multiply by
1097 : *
1098 : * @return the dot product of the two vectors
1099 : */
1100 4 : T dot(const vec &o) const { return x*o.x + y*o.y + z*o.z + w; }
1101 :
1102 : /**
1103 : * @brief Returns the square of the magnitude of the vector.
1104 : *
1105 : * Calculates the dot product of the vector with itself, yielding the
1106 : * square of the magnitude of the vec4.
1107 : *
1108 : * @return the magnitude of `this` squared
1109 : */
1110 253 : T squaredlen() const { return dot(*this); }
1111 :
1112 : /**
1113 : * @brief Returns the magnitude of the vector.
1114 : *
1115 : * Calculates the magnitude (length) of the vector, by taking the square
1116 : * root of the dot product of the vector with itself.
1117 : *
1118 : * @return the maginitude of `this`
1119 : */
1120 247 : T magnitude() const { return sqrtf(squaredlen()); }
1121 :
1122 : /**
1123 : * @brief Returns the magnitude of the vector, ignoring the w dimension.
1124 : *
1125 : * Calculates the #D magnitude (length) of the vector, by taking the square
1126 : * root of the 3D dot product of the vector with itself.
1127 : *
1128 : * @return the maginitude of `this`
1129 : */
1130 4 : T magnitude3() const { return sqrtf(dot3(*this)); }
1131 :
1132 : /**
1133 : * @brief Scales the vector to have a magnitude of 1
1134 : *
1135 : * Will cause a divide-by-zero if the vector is (0,0,0,0).
1136 : *
1137 : * @return a reference to `this` vector
1138 : */
1139 2 : vec4 &normalize() { mul(1/magnitude()); return *this; }
1140 :
1141 : /**
1142 : * @brief Scales the vector to have a magnitude of 1
1143 : *
1144 : * Will return (0,0,0,0) if the vector passed (0,0,0,0).
1145 : *
1146 : * @return a reference to `this` vector
1147 : */
1148 9 : vec4 &safenormalize() { T m = magnitude(); if(m) mul(1/m); return *this; }
1149 :
1150 2 : void lerp(const vec4<uchar> &a, const vec4<uchar> &b, float t)
1151 : {
1152 2 : x = static_cast<uchar>(a.x + (b.x-a.x)*t);
1153 2 : y = static_cast<uchar>(a.y + (b.y-a.y)*t);
1154 2 : z = static_cast<uchar>(a.z + (b.z-a.z)*t);
1155 2 : w = a.w;
1156 2 : }
1157 :
1158 : void lerp(const vec4<uchar> &a, const vec4<uchar> &b, int ka, int kb, int d)
1159 : {
1160 : x = static_cast<uchar>((a.x*ka + b.x*kb)/d);
1161 : y = static_cast<uchar>((a.y*ka + b.y*kb)/d);
1162 : z = static_cast<uchar>((a.z*ka + b.z*kb)/d);
1163 : w = a.w;
1164 : }
1165 :
1166 3 : void lerp(const vec4<uchar> &a, const vec4<uchar> &b, const vec4<uchar> &c, float ta, float tb, float tc)
1167 : {
1168 3 : x = static_cast<uchar>(a.x*ta + b.x*tb + c.x*tc);
1169 3 : y = static_cast<uchar>(a.y*ta + b.y*tb + c.y*tc);
1170 3 : z = static_cast<uchar>(a.z*ta + b.z*tb + c.z*tc);
1171 3 : w = static_cast<uchar>(a.w*ta + b.w*tb + c.w*tc);
1172 3 : }
1173 :
1174 : /**
1175 : * @brief Flips a vec4<uchar> by using the mask type pun.
1176 : *
1177 : * Not for use with non-char vec4<> objects.
1178 : */
1179 4 : void flip() { *mask() ^= 0x80808080; }
1180 :
1181 5 : vec4 &lerp(const vec4 &b, T t)
1182 : {
1183 5 : x += (b.x-x)*t;
1184 5 : y += (b.y-y)*t;
1185 5 : z += (b.z-z)*t;
1186 5 : w += (b.w-w)*t;
1187 5 : return *this;
1188 : }
1189 6 : vec4 &lerp(const vec4 &a, const vec4 &b, T t)
1190 : {
1191 6 : x = a.x+(b.x-a.x)*t;
1192 6 : y = a.y+(b.y-a.y)*t;
1193 6 : z = a.z+(b.z-a.z)*t;
1194 6 : w = a.w+(b.w-a.w)*t;
1195 6 : return *this;
1196 : }
1197 :
1198 : /**
1199 : * @brief Calculates the elementwise arithmetic mean.
1200 : *
1201 : * Sets `this` to the elementwise arithmetic mean of `this` object and the
1202 : * passed object. The original vector is not preserved, but the passed one
1203 : * is.
1204 : *
1205 : * @param b the vec4 to average with
1206 : *
1207 : * @return a reference to `this` object following the operation
1208 : */
1209 3 : vec4 &avg(const vec4 &b) { add(b); mul(0.5f); return *this; }
1210 :
1211 : /**
1212 : * @brief Sets this vec4 to the result of the multiply add of `this` with `a`,`b`
1213 : *
1214 : * Returns `a`*`b` (elementwise multiplication) added with `this` (elementwise addition).
1215 : *
1216 : * @param a value to multiply
1217 : * @param b value to multiply
1218 : *
1219 : * @return a reference to `this` following the operation
1220 : */
1221 : template<class B>
1222 117 : vec4 &madd(const vec4 &a, const B &b) { return add(vec4(a).mul(b)); }
1223 :
1224 : /**
1225 : * @brief Sets this vec4 to the result of the multiply subtract of `this` with `a`,`b`
1226 : *
1227 : * Returns `a`*`b` (elementwise multiplication) subtracted from `this` (elementwise subtraction).
1228 : *
1229 : * @param a value to multiply
1230 : * @param b value to multiply
1231 : *
1232 : * @return a reference to `this` following the operation
1233 : */
1234 : template<class B>
1235 9 : vec4 &msub(const vec4 &a, const B &b) { return sub(vec4(a).mul(b)); }
1236 :
1237 : /**
1238 : * @brief Calculates the elementwise product.
1239 : *
1240 : * Calculates the elementwise product of `f` with the first three entries
1241 : * in `this`. This means that the original vector is not preserved.
1242 : *
1243 : * @param f the value to multiply by
1244 : *
1245 : * @return a reference to `this` object following the operation
1246 : */
1247 254 : vec4 &mul3(T f) { x *= f; y *= f; z *= f; return *this; }
1248 :
1249 : /**
1250 : * @brief Calculates the elementwise product.
1251 : *
1252 : * Calculates the elementwise product of `f` with all four entries
1253 : * in `this`. This means that the original vector is not preserved.
1254 : *
1255 : * @param f the value to multiply by
1256 : *
1257 : * @return a reference to `this` object following the operation
1258 : */
1259 249 : vec4 &mul(T f) { mul3(f); w *= f; return *this; }
1260 :
1261 : /**
1262 : * @brief Calculates the elementwise product.
1263 : *
1264 : * Calculates the elementwise product of the four parameters in `this` with
1265 : * the four parameters in `o`. This measn that the original vector is not
1266 : * preserved.
1267 : *
1268 : * @param o the vec4 to multiply by
1269 : *
1270 : * @return a reference to `this` object following the operation
1271 : */
1272 13 : vec4 &mul(const vec4 &o) { x *= o.x; y *= o.y; z *= o.z; w *= o.w; return *this; }
1273 :
1274 : /**
1275 : * @brief Calculates the elementwise product.
1276 : *
1277 : * Calculates the elementwise product of the first three parameters in `this`
1278 : * with the three parameters in `o`. This means that the original vector is
1279 : * not preserved.
1280 : *
1281 : * @param o the vec3 to multiply by
1282 : *
1283 : * @return a reference to `this` object following the operation
1284 : */
1285 3 : vec4 &mul(const vec &o) { x *= o.x; y *= o.y; z *= o.z; return *this; }
1286 :
1287 : /**
1288 : * @brief Calculates the elementwise square.
1289 : *
1290 : * Calculates the elementwise product of `this` with itself. This means that
1291 : * the original vector is not preserved.
1292 : *
1293 : * @return a reference to `this` object following the operation
1294 : */
1295 3 : vec4 &square() { mul(*this); return *this; }
1296 :
1297 : /**
1298 : * @brief Calculates the elementwise quotient.
1299 : *
1300 : * Calculates the quotient of the first three values in `this` with the value
1301 : * passed to `f`. This means that the original vector is not preserved.
1302 : *
1303 : * @param f the value to divide by
1304 : *
1305 : * @return a reference to `this` object following the operation
1306 : *
1307 : */
1308 8 : vec4 &div3(T f) { x /= f; y /= f; z /= f; return *this; }
1309 :
1310 : /**
1311 : * @brief Calculates the elementwise quotient.
1312 : *
1313 : * Calculates the quotient of the four values in `this` with the value passed
1314 : * to `f`. This means that the original vector is not preserved.
1315 : *
1316 : * @param f the value to divide by
1317 : *
1318 : * @return a reference to `this` object following the operation
1319 : */
1320 4 : vec4 &div(T f) { div3(f); w /= f; return *this; }
1321 :
1322 : /**
1323 : * @brief Calculates the elementwise quotient.
1324 : *
1325 : * Calculates the quotient of the four values in `this` with the four values in
1326 : * `o`, element-by-element. This means that the original vector is not preserved.
1327 : *
1328 : * @param o the vector to divide by
1329 : *
1330 : * @return a reference to `this` object following the operation
1331 : */
1332 2 : vec4 &div(const vec4 &o) { x /= o.x; y /= o.y; z /= o.z; w /= o.w; return *this; }
1333 :
1334 : /**
1335 : * @brief Calculates the elementwise quotient.
1336 : *
1337 : * Calculates the quotient of the three values in `this` with the four values in
1338 : * `o`, element-by-element. This means that the original vector is not preserved.
1339 : *
1340 : * @param o the vector to divide by
1341 : *
1342 : * @return a reference to `this` object following the operation
1343 : */
1344 3 : vec4 &div(const vec &o) { x /= o.x; y /= o.y; z /= o.z; return *this; }
1345 :
1346 : /**
1347 : * @brief Calculates the elementwise reciprocal.
1348 : *
1349 : * Calculates the value 1/x for each of the four values in the vector, and assigns
1350 : * them to `this`. This means that the original vector is not preserved
1351 : *
1352 : * @return a reference to `this` object following the operation
1353 : */
1354 2 : vec4 &recip() { x = 1/x; y = 1/y; z = 1/z; w = 1/w; return *this; }
1355 :
1356 : /**
1357 : * @brief Calculates the elementwise sum.
1358 : *
1359 : * Calculates the sum of the four elements in `this` with the four values in
1360 : * `o`, element-by-element. This means that the original vector is not preserved.
1361 : *
1362 : * @param o the vector to add with
1363 : *
1364 : * @return a reference to `this` object following the operation
1365 : */
1366 164 : vec4 &add(const vec4 &o) { x += o.x; y += o.y; z += o.z; w += o.w; return *this; }
1367 :
1368 : /**
1369 : * @brief Calculates the elementwise sum.
1370 : *
1371 : * Calculates the sum of the first three elements in `this` with the first
1372 : * three values in `o`, element-by-element. This means that the original
1373 : * vector is not preserved.
1374 : *
1375 : * @param o the vector to add with
1376 : *
1377 : * @return a reference to `this` object following the operation
1378 : */
1379 3 : vec4 &add(const vec &o) { x += o.x; y += o.y; z += o.z; return *this; }
1380 :
1381 : /**
1382 : * @brief Calculates the elementwise sum.
1383 : *
1384 : * Calculates the sum of the first three elements in `this` with the value
1385 : * passed to `f`. This means that the original vector is not preserved.
1386 : *
1387 : * @param f the value to add with
1388 : *
1389 : * @return a reference to `this` object following the operation
1390 : */
1391 8 : vec4 &add3(T f) { x += f; y += f; z += f; return *this; }
1392 :
1393 : /**
1394 : * @brief Calculates the elementwise sum.
1395 : *
1396 : * Calculates the sum of the four elements in `this` with the four elements
1397 : * comprising `f`. This means that the original vector is not preserved.
1398 : *
1399 : * @param f the value to add with
1400 : *
1401 : * @return a reference to `this` object following the operation
1402 : */
1403 4 : vec4 &add(T f) { add3(f); w += f; return *this; }
1404 :
1405 : /**
1406 : * @brief Adds to the fourth value of the vector (w/a).
1407 : *
1408 : * Calculates the sum of the passed value and the fourth element of the vec4,
1409 : * modifying the original vector to equal this sum.
1410 : *
1411 : * @param f the value to add with
1412 : *
1413 : * @return a reference to `this` object following the operation
1414 : */
1415 4 : vec4 &addw(T f) { w += f; return *this; }
1416 :
1417 : /**
1418 : * @brief Subtracts from `this` the vec4 passed.
1419 : *
1420 : * Calculates the difference between the four elements in `this` and the
1421 : * four elements of `o`, modifying the original vector to equal this difference.
1422 : *
1423 : * @param o the vec4 to subtract
1424 : *
1425 : * @return a reference to `this` object following the operation
1426 : */
1427 248 : vec4 &sub(const vec4 &o) { x -= o.x; y -= o.y; z -= o.z; w -= o.w; return *this; }
1428 :
1429 : /**
1430 : * @brief Subtracts from `this` the vec passed.
1431 : *
1432 : * Calculates the difference between the four elements in `this` and the three
1433 : * elements of `o`, modifying the original vector to equal this difference.
1434 : *
1435 : * @param o the vec to subtract
1436 : *
1437 : * @return a reference to `this` object following the operation
1438 : */
1439 3 : vec4 &sub(const vec &o) { x -= o.x; y -= o.y; z -= o.z; return *this; }
1440 :
1441 : /**
1442 : * @brief Subtracts from the first three entries `this` the value passed.
1443 : *
1444 : * Calculates the difference between the first three elements in `this` and
1445 : * the value passed, modifying the original vector to equal this difference.
1446 : *
1447 : * @param f the value to subtract
1448 : *
1449 : * @return a reference to `this` object following the operation
1450 : */
1451 8 : vec4 &sub3(T f)
1452 : {
1453 8 : x -= f;
1454 8 : y -= f;
1455 8 : z -= f;
1456 8 : return *this;
1457 : }
1458 :
1459 : /**
1460 : * @brief Subtracts from the entries `this` the value passed.
1461 : *
1462 : * Calculates the difference between the elements in `this` and
1463 : * the value passed, modifying the original vector to equal this difference.
1464 : *
1465 : * @param f the value to subtract
1466 : *
1467 : * @return a reference to `this` object following the operation
1468 : */
1469 4 : vec4 &sub(T f)
1470 : {
1471 4 : sub3(f);
1472 4 : w -= f;
1473 4 : return *this;
1474 : }
1475 :
1476 : /**
1477 : * @brief Subtracts from the last element only.
1478 : *
1479 : * Calculates the difference between the last 'w' element in `this` and
1480 : * the value passed, modifying the original vector to equal this difference.
1481 : *
1482 : * @param f the value to subtract
1483 : *
1484 : * @return a reference to `this` object following the operation
1485 : */
1486 4 : vec4 &subw(T f)
1487 : {
1488 4 : w -= f;
1489 4 : return *this;
1490 : }
1491 :
1492 : /**
1493 : * @brief Negates the first three elements.
1494 : *
1495 : * `w` is left unchanged.
1496 : *
1497 : * @return a reference to `this`
1498 : */
1499 128 : vec4 &neg3()
1500 : {
1501 128 : x = -x;
1502 128 : y = -y;
1503 128 : z = -z;
1504 128 : return *this;
1505 : }
1506 :
1507 : /**
1508 : * @brief Negates all of the elements.
1509 : *
1510 : * @return a reference to `this`
1511 : */
1512 98 : vec4 &neg()
1513 : {
1514 98 : neg3();
1515 98 : w = -w;
1516 98 : return *this;
1517 : }
1518 :
1519 : /**
1520 : * @brief Clamps the elements individualy to the specified bounds.
1521 : *
1522 : * Clamps each element such that none of them exceeds the bounds specified.
1523 : *
1524 : * @param l the low value to clamp to
1525 : * @param h the high value to clamp to
1526 : */
1527 4 : vec4 &clamp(T l, T h)
1528 : {
1529 4 : x = ::std::clamp(x, l, h);
1530 4 : y = ::std::clamp(y, l, h);
1531 4 : z = ::std::clamp(z, l, h);
1532 4 : w = ::std::clamp(w, l, h);
1533 4 : return *this;
1534 : }
1535 :
1536 : /**
1537 : * @brief Returns a new vec4 object equal to the sum of the passed object and `this`
1538 : *
1539 : * @param v2 the other vec to add
1540 : *
1541 : * @return a new vec4 containing their sum
1542 : */
1543 4 : vec4 operator+(const vec4 &v2) const
1544 : {
1545 4 : return vec4(x+v2.x, y+v2.y, z+v2.z, w+v2.w);
1546 : }
1547 :
1548 : /**
1549 : * @brief Returns a new vec4 object equal to `this` minus the passed object.
1550 : *
1551 : * @param v2 the other vec to subtract with
1552 : *
1553 : * @return a new vec4 containing their difference
1554 : */
1555 4 : vec4 operator-(const vec4 &v2) const
1556 : {
1557 4 : return vec4(x-v2.x, y-v2.y, z-v2.z, w-v2.w);
1558 : }
1559 :
1560 : /**
1561 : * @brief Returns a new vec4 object equal to the arithmetic inverse of `this`
1562 : *
1563 : * @return a new vec4 equal to the arithmetic inverse
1564 : */
1565 4 : vec4 operator-() const
1566 : {
1567 4 : return vec4(-x, -y, -z, -w);
1568 : }
1569 :
1570 : /**
1571 : * @brief Returns a new vec4 object equal to the scalar multiplication by a value.
1572 : *
1573 : * @tparam u scalar type to multiply with
1574 : * @param n scalar value to multiply with
1575 : *
1576 : * @return a new vec4 equal to `this` * n
1577 : */
1578 : template<typename U>
1579 3 : vec4 operator*(const U &n) const
1580 : {
1581 3 : return vec4(n*x, n*y, n*z, n*w);
1582 : }
1583 :
1584 : /**
1585 : * @brief Returns a new vec4 equal to the elementwise product of `this` and the passed vec4.
1586 : *
1587 : * @param v2 the vec4 to multiply with
1588 : *
1589 : * @return a new vec4 equal to `this` * `v2`
1590 : */
1591 4 : vec4 operator*(const vec4 &v2) const
1592 : {
1593 4 : return vec4(x*v2.x, y*v2.y, z*v2.z, w*v2.w);
1594 : }
1595 :
1596 : /**
1597 : * @brief Returns a new vec4 object equal to the scalar division by a value.
1598 : *
1599 : * @tparam u scalar type to divide with
1600 : * @param n scalar value to divide with
1601 : *
1602 : * @return a new vec4 equal to `this` / `n`
1603 : */
1604 : template<typename U>
1605 3 : vec4 operator/(const U &n) const
1606 : {
1607 3 : return vec4(x/n, y/n, z/n, w/n);
1608 : }
1609 :
1610 :
1611 : /**
1612 : * @brief Returns a new vec4 equal to the elementwise division of `this` and the passed vec4.
1613 : *
1614 : * @param v2 the vec4 to divide with
1615 : *
1616 : * @return a new vec4 equal to `this` / `v2`
1617 : */
1618 4 : vec4 operator/(const vec4 &v2) const
1619 : {
1620 4 : return vec4(x/v2.x, y/v2.y, z/v2.z, w/v2.w);
1621 : }
1622 :
1623 :
1624 : /**
1625 : * @brief Sets this vec to the cross product of two passed objects
1626 : *
1627 : * The `w` field is unmodified.
1628 : * Only valid for vec-type objects with x,y,z scalar members.
1629 : *
1630 : * @tparam A the type of the first cross product operand
1631 : * @tparam B the type of the second cross product operand
1632 : * @param a the first cross product operand
1633 : * @param b the second cross product operand
1634 : *
1635 : */
1636 : template<class A, class B>
1637 9 : vec4 &cross(const A &a, const B &b)
1638 : {
1639 9 : x = a.y*b.z-a.z*b.y;
1640 9 : y = a.z*b.x-a.x*b.z;
1641 9 : z = a.x*b.y-a.y*b.x;
1642 9 : return *this;
1643 : }
1644 :
1645 : /**
1646 : * @brief Sets this vec4 to the cross product of a,b relative to an offset c
1647 : *
1648 : * The `w` field is unmodified.
1649 : *
1650 : * @param o the origin to calculate offsets from
1651 : * @param a the first vec to use
1652 : * @param b the second vec to use
1653 : */
1654 : vec4 &cross(const vec &o, const vec &a, const vec &b)
1655 : {
1656 : return cross(vec(a).sub(o), vec(b).sub(o));
1657 : }
1658 :
1659 : /**
1660 : * @brief Replaces the first three values of `this` with the passed vec
1661 : *
1662 : * @param v the vec to replace x,y,z of `this`with
1663 : */
1664 4 : void setxyz(const vec &v)
1665 : {
1666 4 : x = v.x;
1667 4 : y = v.y;
1668 4 : z = v.z;
1669 4 : }
1670 :
1671 : /**
1672 : * @brief Rotates the given 3-vector around the z-axis
1673 : *
1674 : * The w parameter is ignored.
1675 : * The positive direction of rotation is counterclockwise.
1676 : *
1677 : * @param c the raw cosine value to rotate by
1678 : * @param s the raw sine value to rotate by
1679 : */
1680 9 : vec4 &rotate_around_z(T c, T s)
1681 : {
1682 9 : T rx = x,
1683 9 : ry = y;
1684 9 : x = c*rx-s*ry;
1685 9 : y = c*ry+s*rx;
1686 9 : return *this;
1687 : }
1688 :
1689 : /**
1690 : * @brief Rotates the given 3-vector around the x-axis
1691 : *
1692 : * The w parameter is ignored.
1693 : * The positive direction of rotation is counterclockwise.
1694 : *
1695 : * @param c the raw cosine value to rotate by
1696 : * @param s the raw sine value to rotate by
1697 : */
1698 9 : vec4 &rotate_around_x(T c, T s)
1699 : {
1700 9 : T ry = y,
1701 9 : rz = z;
1702 9 : y = c*ry-s*rz;
1703 9 : z = c*rz+s*ry;
1704 9 : return *this;
1705 : }
1706 :
1707 : /**
1708 : * @brief Rotates the given 3-vector around the y-axis
1709 : *
1710 : * The w parameter is ignored.
1711 : * The positive direction of rotation is counterclockwise.
1712 : *
1713 : * @param c the raw cosine value to rotate by
1714 : * @param s the raw sine value to rotate by
1715 : */
1716 9 : vec4 &rotate_around_y(T c, T s)
1717 : {
1718 9 : T rx = x,
1719 9 : rz = z;
1720 9 : x = c*rx-s*rz;
1721 9 : z = c*rz+s*rx;
1722 9 : return *this;
1723 : }
1724 :
1725 : /**
1726 : * @brief Conducts a rotation around the z-axis
1727 : *
1728 : * The `w` parameter is ignored.
1729 : * The positive direction of rotation is counterclockwise.
1730 : *
1731 : * @param angle the angle (in radians) to rotate by
1732 : *
1733 : * @return a reference to `this` following the operation
1734 : */
1735 3 : vec4 &rotate_around_z(T angle)
1736 : {
1737 3 : return rotate_around_z(cosf(angle), std::sin(angle));
1738 : }
1739 :
1740 : /**
1741 : * @brief Conducts a rotation around the x-axis
1742 : *
1743 : * The `w` parameter is ignored.
1744 : * The positive direction of rotation is counterclockwise.
1745 : *
1746 : * @param angle the angle (in radians) to rotate by
1747 : *
1748 : * @return a reference to `this` following the operation
1749 : */
1750 3 : vec4 &rotate_around_x(T angle)
1751 : {
1752 3 : return rotate_around_x(cosf(angle), std::sin(angle));
1753 : }
1754 :
1755 : /**
1756 : * @brief Conducts a rotation around the y-axis
1757 : *
1758 : * The `w` parameter is ignored.
1759 : * The positive direction of rotation is counterclockwise.
1760 : *
1761 : * @param angle the angle (in radians) to rotate by
1762 : *
1763 : * @return a reference to `this` following the operation
1764 : */
1765 3 : vec4 &rotate_around_y(T angle)
1766 : {
1767 3 : return rotate_around_y(cosf(angle), std::sin(angle));
1768 : }
1769 :
1770 : /**
1771 : * @brief Conducts a rotation around the z-axis
1772 : *
1773 : * The `w` parameter is ignored.
1774 : * The positive direction of rotation is counterclockwise.
1775 : *
1776 : * @param sc a vec2 containing the {cosine, sine} values to rotate with
1777 : *
1778 : * @return a reference to `this` following the operation
1779 : */
1780 3 : vec4 &rotate_around_z(const vec2 &sc)
1781 : {
1782 3 : return rotate_around_z(sc.x, sc.y);
1783 : }
1784 :
1785 : /**
1786 : * @brief Conducts a rotation around the x-axis
1787 : *
1788 : * The `w` parameter is ignored.
1789 : * The positive direction of rotation is counterclockwise.
1790 : *
1791 : * @param sc a vec2 containing the {cosine, sine} values to rotate with
1792 : *
1793 : * @return a reference to `this` following the operation
1794 : */
1795 3 : vec4 &rotate_around_x(const vec2 &sc)
1796 : {
1797 3 : return rotate_around_x(sc.x, sc.y);
1798 : }
1799 :
1800 : /**
1801 : * @brief Conducts a rotation around the y-axis
1802 : *
1803 : * The `w` parameter is ignored.
1804 : * The positive direction of rotation is counterclockwise.
1805 : *
1806 : * @param sc a vec2 containing the {cosine, sine} values to rotate with
1807 : *
1808 : * @return a reference to `this` following the operation
1809 : */
1810 3 : vec4 &rotate_around_y(const vec2 &sc)
1811 : {
1812 3 : return rotate_around_y(sc.x, sc.y);
1813 : }
1814 :
1815 : /**
1816 : * @brief Returns a new vec containing values normalized to 0...255 (e.g. colors).
1817 : *
1818 : * `w` is not used in this calculation.
1819 : *
1820 : * @return a vec containing the normalized values of x,y,z
1821 : */
1822 0 : vec tonormal() const
1823 : {
1824 0 : return vec(x*(2.0f/255.0f)-1.0f, y*(2.0f/255.0f)-1.0f, z*(2.0f/255.0f)-1.0f);
1825 : }
1826 :
1827 : };
1828 :
1829 1 : inline vec2::vec2(const vec4<float> &v) : x(v.x), y(v.y) {}
1830 31 : inline vec::vec(const vec4<float> &v) : x(v.x), y(v.y), z(v.z) {}
1831 :
1832 : /**
1833 : * @brief matrix3: 3x3 matrix
1834 : * comprised of three vec3 vectors
1835 : * arranged as follows:
1836 : * [ a1 b1 c1
1837 : * a2 b2 c2
1838 : * a3 b3 c3 ]
1839 : *
1840 : * used largely in models/anims/ragdolls but also in stuff like bih
1841 : */
1842 : class matrix3
1843 : {
1844 : public:
1845 : /**
1846 : * @brief the three vectors making up the rows of the matrix
1847 : *
1848 : * a is the top vector
1849 : * b is the middle vector
1850 : * c is the bottom vector
1851 : */
1852 : vec a, b, c;
1853 :
1854 : /**
1855 : * @brief Creates an empty matrix.
1856 : */
1857 : matrix3();
1858 :
1859 : /**
1860 : * @brief Creates a new matrix with the given vectors.
1861 : *
1862 : * @param a the vector to assign to the top row
1863 : * @param b the vector to assign to the middle row
1864 : * @param c the vector to assign to the bottom row
1865 : */
1866 : matrix3(const vec &a, const vec &b, const vec &c);
1867 :
1868 : /**
1869 : * @brief Creates a new matrix as a rotation matrix.
1870 : *
1871 : * If the axis passed is not normalized, the resulting rotation matrix
1872 : * will not encode a pure rotation.
1873 : *
1874 : * @param angle the rotation amount the rotation matrix encodes
1875 : * @param axis the direction which is invariant under the rotation encoded by angle
1876 : */
1877 : explicit matrix3(float angle, const vec &axis);
1878 :
1879 : /**
1880 : * @brief Creates a 3d rotation matrix given a quaternion object.
1881 : *
1882 : * Note that quaternions are an engine-specific construct and not part of the
1883 : * game API beyond the prototype defined in this header.
1884 : *
1885 : * @param q the quaternion to use
1886 : */
1887 : explicit matrix3(const quat &q);
1888 :
1889 : /**
1890 : * @brief Creates a 3d matrix given a 4x3 matrix.
1891 : *
1892 : *
1893 : * @param m the matrix to use
1894 : */
1895 : explicit matrix3(const matrix4x3 &m);
1896 :
1897 : /**
1898 : * @brief Creates a 3x3 matrix given a 4x4 matrix.
1899 : *
1900 : * This truncates the 4th member in both dimensions of the matrix.
1901 : *
1902 : * @param m the matrix to use
1903 : */
1904 : explicit matrix3(const matrix4 &m);
1905 :
1906 : /**
1907 : * @brief Calculates the product of three matrices.
1908 : *
1909 : * @param m the first matrix to multiply by
1910 : * @param n the second matrix to multiply by
1911 : */
1912 : void mul(const matrix3 &m, const matrix3 &n);
1913 :
1914 : /**
1915 : * @brief Multiplies the matrix by another
1916 : *
1917 : * This operation changes the value of the matrix.
1918 : *
1919 : * @param n
1920 : */
1921 : void mul(const matrix3 &n);
1922 :
1923 : /**
1924 : * @brief Calculates the multiplication-transpose with another matrix.
1925 : *
1926 : * @param n the matrix to use
1927 : */
1928 : void multranspose(const matrix3 &n);
1929 :
1930 : /**
1931 : * @brief Calculates the transpose-multiplication with another two matrices.
1932 : *
1933 : * @param m the first matrix to use
1934 : * @param n the second matrix to use
1935 : */
1936 : void transposemul(const matrix3 &m, const matrix3 &n);
1937 :
1938 : /**
1939 : * @brief Calculates the transpose-multiplication with another matrix.
1940 : *
1941 : * @param n the matrix to multiply by
1942 : */
1943 : void transposemul(const matrix3 &n);
1944 :
1945 : /**
1946 : * @brief Transposes the matrix.
1947 : *
1948 : * ```
1949 : * a b c a d g
1950 : * d e f -> b e h
1951 : * g h i c f i
1952 : *```
1953 : */
1954 : void transpose();
1955 :
1956 : /**
1957 : * @brief Inverts the matrix using another matrix for the scale factor.
1958 : *
1959 : * This operation can be undone by calling invert() again using the same
1960 : * argument.
1961 : *
1962 : */
1963 : void invert(const matrix3 &o);
1964 :
1965 : /**
1966 : * @brief Inverts the matrix using itself for the scale factor.
1967 : *
1968 : * This operation can be undone by calling invert() again.
1969 : *
1970 : */
1971 : void invert();
1972 :
1973 : /**
1974 : * @brief Normalizes each of the three rows to a magnitude of 1.
1975 : *
1976 : * Calls normalize() for each of the three vec objects making up the matrix.
1977 : */
1978 : void normalize();
1979 :
1980 : /**
1981 : * @brief Multiplies each element of the matrix by the scale factor given.
1982 : *
1983 : * @param k the scale factor to multiply by
1984 : */
1985 : void scale(float k);
1986 :
1987 : /**
1988 : * @brief Rotates the matrix around the given axis by the given angle.
1989 : *
1990 : * @param angle the angle to rotate by (radians)
1991 : * @param axis the axis to rotate about
1992 : */
1993 : void rotate(float angle, const vec &axis);
1994 :
1995 : /**
1996 : * @brief Rotates the matrix around the given axis by the given angle
1997 : *
1998 : * @param ck the cosine term
1999 : * @param sk the sine term
2000 : * @param axis the axis to rotate about
2001 : */
2002 : void rotate(float ck, float sk, const vec &axis);
2003 :
2004 : /**
2005 : * @brief Sets the matrix to a 2D rotation matrix.
2006 : *
2007 : * The output matrix looks like this:
2008 : *
2009 : * ```
2010 : * cosf(angle) sinf(angle) 0
2011 : * -sinf(angle) cosf(angle) 0
2012 : * 0 0 1
2013 : * ```
2014 : * (This is a rotation matrix around the Z-axis.)
2015 : *
2016 : * @param angle the angle to rotate by (radians)
2017 : */
2018 : void setyaw(float angle);
2019 :
2020 : /**
2021 : * @brief Returns the trace of the matrix.
2022 : *
2023 : * The trace is equal to the sum of the diagonal values of the matrix.
2024 : *
2025 : * @return a float representing the trace of the matrix
2026 : */
2027 : float trace() const;
2028 :
2029 : /**
2030 : * @brief Calculates the axis and angle from a rotation matrix.
2031 : *
2032 : * Only used in certain ragdoll calculations.
2033 : *
2034 : * The axis vector represents the vector which is invariant under the
2035 : * rotation encoded in the rotation matrix.
2036 : *
2037 : * The angle represents the rotation magnitude around the axis vector.
2038 : *
2039 : * Both `angle` and `axis` are pure output parameters and their prior values
2040 : * are discarded.
2041 : *
2042 : * If the values encoding the axis result in a magnitude smaller than `threshhold`,
2043 : * returns false and does not set the angle nor the axis (except axis will
2044 : * be set if trace = 0..2); otherwise sets both angle and axis and returns true
2045 : *
2046 : * @param tr the trace of the matrix
2047 : * @param angle the angle to set
2048 : * @param axis the axis to set
2049 : * @param threshold the magnitude required not to reject the matrix
2050 : *
2051 : * @return whether the axis and angle were both set
2052 : */
2053 : bool calcangleaxis(float tr, float &angle, vec &axis, float threshold = 1e-16f) const;
2054 :
2055 : /**
2056 : * @brief Calculates the axis and angle from a rotation matrix.
2057 : *
2058 : * Ony used in certain ragdoll calculations.
2059 : *
2060 : * Same behavior as `calcangleaxis(float, float &, vec &, float)` except
2061 : * the `trace()` is automatically calculated.
2062 : *
2063 : * @param angle the angle to set
2064 : * @param axis the axis to set
2065 : * @param threshold the magnitude required not to reject the matrix
2066 : *
2067 : * @return whether the axis and angle were both set
2068 : */
2069 : bool calcangleaxis(float &angle, vec &axis, float threshold = 1e-16f) const;
2070 :
2071 : /**
2072 : * @brief Sets the matrix to the transform of the matrix.
2073 : *
2074 : * @param o the 3d vector to transform by
2075 : *
2076 : * @return whether the angle is within the allowable range
2077 : */
2078 : vec transform(const vec &o) const;
2079 :
2080 : /**
2081 : * @brief Sets the matrix to the transpose-transform.
2082 : *
2083 : * @param o the 3d vector to transform by
2084 : *
2085 : * @return the result of the transform
2086 : */
2087 : vec transposedtransform(const vec &o) const;
2088 :
2089 : /**
2090 : * @brief Sets the matrix to the absolute value of the transform
2091 : *
2092 : * @param o the 3d vector to transform by
2093 : *
2094 : * @return the dot products of the resulting matrix
2095 : */
2096 : vec abstransform(const vec &o) const;
2097 :
2098 : /**
2099 : * @brief Sets the matrix to the absolute value of the transpose-transform.
2100 : *
2101 : * @param o the 3d vector to transform by
2102 : *
2103 : * @return the result of the transform
2104 : */
2105 : vec abstransposedtransform(const vec &o) const;
2106 :
2107 : /**
2108 : * @brief Sets the matrix to be the identity matrix.
2109 : *
2110 : * ```
2111 : * 1 0 0
2112 : * 0 1 0
2113 : * 0 0 1
2114 : * ```
2115 : */
2116 : void identity();
2117 :
2118 : /**
2119 : * @brief Rotates the matrix values around the X axis.
2120 : *
2121 : * @param angle the angle by which to rotate about
2122 : */
2123 : void rotate_around_x(float angle);
2124 :
2125 : /**
2126 : * @brief Rotates the matrix values around the X axis.
2127 : *
2128 : * @param sc a vector containing the cosine + sine terms
2129 : */
2130 : void rotate_around_x(const vec2 &sc);
2131 :
2132 : /**
2133 : * @brief Rotates the matrix values around the Y axis.
2134 : *
2135 : * @param angle the angle by which to rotate about
2136 : */
2137 : void rotate_around_y(float angle);
2138 :
2139 : /**
2140 : * @brief Rotates the matrix values around the Y axis.
2141 : *
2142 : * @param sc a vector containing the cosine + sine terms
2143 : */
2144 : void rotate_around_y(const vec2 &sc);
2145 :
2146 : /**
2147 : * @brief Rotates the matrix values around the Z axis.
2148 : *
2149 : * @param angle by which to rotate
2150 : */
2151 : void rotate_around_z(float angle);
2152 :
2153 : /**
2154 : * @brief Rotates the matrix values around the Z axis.
2155 : *
2156 : * @param sc a vector containing the cosine + sine terms
2157 : */
2158 : void rotate_around_z(const vec2 &sc);
2159 :
2160 : /**
2161 : * @brief Returns the transform of the matrix.
2162 : *
2163 : * @param o the 2d vector to transform by
2164 : *
2165 : * @return the transform of the matrix
2166 : */
2167 : vec transform(const vec2 &o) const;
2168 :
2169 : /**
2170 : * @brief Returns the transposed transform of the matrix.
2171 : *
2172 : * @param o the vector to transform with
2173 : *
2174 : * @return the transposed transform of the matrix
2175 : */
2176 : vec transposedtransform(const vec2 &o) const;
2177 :
2178 : /**
2179 : * @brief Returns the first (top) row of the matrix.
2180 : *
2181 : * @return a 3d vector containing the first row of the matrix
2182 : */
2183 : vec rowx() const;
2184 :
2185 : /**
2186 : * @brief Returns the second (middle) row of the matrix.
2187 : *
2188 : * @return a 3d vector containing the second row of the matrix
2189 : */
2190 : vec rowy() const;
2191 :
2192 : /**
2193 : * @brief Returns the third (bottom) row of the matrix.
2194 : *
2195 : * @return a 3d fector containing the thrid row of the matrix
2196 : */
2197 : vec rowz() const;
2198 : private:
2199 :
2200 : /**
2201 : * @brief Calculates the multiplication-transpose of the three matrices
2202 : *
2203 : * @param m the first matrix to use
2204 : * @param n the second matrix to use
2205 : */
2206 : void multranspose(const matrix3 &m, const matrix3 &n);
2207 :
2208 : /**
2209 : * @brief Sets the matrix to a 2D rotation matrix.
2210 : *
2211 : * The output matrix looks like this:
2212 : * ```
2213 : * ck sk 0
2214 : * -sk ck 0
2215 : * 0 0 1
2216 : * ```
2217 : *
2218 : * @param ck the cosine term
2219 : * @param sk the sine term
2220 : */
2221 : void setyaw(float ck, float sk);
2222 :
2223 : /**
2224 : * @brief Rotates the matrix values around the X axis
2225 : *
2226 : * @param ck the cosine term
2227 : * @param sk the sine term
2228 : */
2229 : void rotate_around_x(float ck, float sk);
2230 :
2231 : /**
2232 : * @brief Rotates the matrix values around the Y axis.
2233 : *
2234 : * @param ck the cosine term
2235 : * @param sk the sine term
2236 : */
2237 : void rotate_around_y(float ck, float sk);
2238 :
2239 : /**
2240 : * @brief Rotates the matrix values around the Z axis.
2241 : *
2242 : * @param ck the cosine term
2243 : * @param sk the sine term
2244 : */
2245 : void rotate_around_z(float ck, float sk);
2246 :
2247 : /**
2248 : * @brief Sets the matrix to the transpose of the one given.
2249 : *
2250 : * @param m the matrix to use to set
2251 : */
2252 : void transpose(const matrix3 &m);
2253 : };
2254 :
2255 : /**
2256 : * @brief floating point 4x3 matrix object
2257 : * defined as four column vectors, a-d
2258 : * takes the form as follows:
2259 : * [ a1 b1 c1 d1 (x)
2260 : * a2 b2 c2 d2 (y)
2261 : * a3 b3 c3 d3 ] (z)
2262 : *
2263 : * used in animation along with dualquats
2264 : */
2265 : struct matrix4x3
2266 : {
2267 : vec a, b, c, d;
2268 :
2269 : /**
2270 : * @brief Creates an empty matrix4x3 object.
2271 : *
2272 : * Creates a matrix4x3 object, where all values within the matrix are set to
2273 : * zero.
2274 : */
2275 : matrix4x3();
2276 :
2277 : /**
2278 : * @brief Creates a matrix4x3 from four three-dimensional vec objects.
2279 : *
2280 : * The values of the passed vecs are copied to the new matrix4x3 object.
2281 : *
2282 : * @param a the vec to assign to `matrix4x3::a`
2283 : * @param b the vec to assign to `matrix4x3::b`
2284 : * @param c the vec to assign to `matrix4x3::c`
2285 : * @param d the vec to assign to `matrix4x3::d`
2286 : */
2287 : matrix4x3(const vec &a, const vec &b, const vec &c, const vec &d);
2288 :
2289 : /**
2290 : * @brief Creates a matrix4x3 from a rotation matrix and a translation vector.
2291 : *
2292 : * The rotation matrix is assigned to members `a` `b` `c` and the translation `d`.
2293 : * No transformations are made to the values of the passed parameters.
2294 : *
2295 : * @param rot the rotation matrix to assign to `a` `b` `c`
2296 : * @param trans the translation to assign to `d`
2297 : */
2298 : matrix4x3(const matrix3 &rot, const vec &trans);
2299 :
2300 : /**
2301 : * @brief Creates a matrix4x3 that represents a dual quaternion transformation.
2302 : *
2303 : * @param dq the dual quaternion to transform into a matrix4x3
2304 : */
2305 : matrix4x3(const dualquat &dq);
2306 :
2307 : /**
2308 : * @brief Creates a matrix4x3 by truncating `w` from a matrix4.
2309 : *
2310 : * The four vecs that make up the matrix4 are copied, omitting the `w` parameter.
2311 : *
2312 : * @param m the matrix4 to truncate into a matrix4x3
2313 : */
2314 : explicit matrix4x3(const matrix4 &m);
2315 :
2316 : /**
2317 : * @brief Multiplies all values inside the matrix by a scalar constant.
2318 : *
2319 : * @param k the scale factor to multiply by
2320 : */
2321 : void mul(float k);
2322 :
2323 : /**
2324 : * @brief Sets the diagonals a.x, b.y, c.z to the given values.
2325 : *
2326 : * Does not modify any of the values except for a.x, b.y, c.z.
2327 : *
2328 : * @param x the first value to set in the diagonal
2329 : * @param y the second value to set in the diagonal
2330 : * @param z the third value to set in the diagonal
2331 : */
2332 : void setscale(float x, float y, float z);
2333 :
2334 : /**
2335 : * @brief Sets the diagonals a.x, b.y, c.z to the given vector's x, y, z values.
2336 : *
2337 : * Does not modify any of the values except for a.x, b.y, c.z.
2338 : *
2339 : * @param v the vector to assign from
2340 : */
2341 : void setscale(const vec &v);
2342 :
2343 : /**
2344 : * @brief Sets the diagonals a.x, b.y, c.z identically to a given value.
2345 : *
2346 : * @parm n the value to set to
2347 : */
2348 : void setscale(float n);
2349 :
2350 : /**
2351 : * @brief Scales the first three vectors by x, y, and z respectively.
2352 : *
2353 : * Does not modify the fourth matrix element vector`d`.
2354 : *
2355 : * @param x the scale to multiply the first vector by
2356 : * @param y the scale to multiply the second vector by
2357 : * @param z the scale to multiply the third vector by
2358 : */
2359 : void scale(float x, float y, float z);
2360 :
2361 : /**
2362 : * @brief Multiplies the first three vectors by v.x, v.y, and v.z respectively.
2363 : *
2364 : * Does not modify the fourth matrix element vector`d`.
2365 : *
2366 : * @param v the vector to multiply by
2367 : */
2368 : void scale(const vec &v);
2369 :
2370 : /**
2371 : * @brief Scales the first three vector elements in the matrix by the specified amount.
2372 : *
2373 : * Does not modify the fourth matrix element vector`d`.
2374 : *
2375 : * @param n the scale factor to multiply by
2376 : */
2377 : void scale(float n);
2378 :
2379 : /**
2380 : * @brief Copies the `p` vector into the fourth column vector (`d`).
2381 : *
2382 : * @param p the vector to copy to the `d` vector.
2383 : */
2384 : void settranslation(const vec &p);
2385 :
2386 : /**
2387 : * @brief Copies x, y, z into the fourth column vector (`d`).
2388 : *
2389 : * @param x the first value to copy into d.x
2390 : * @param y the second value to copy into d.y
2391 : * @param z the third value to copy into d.z
2392 : */
2393 : void settranslation(float x, float y, float z);
2394 : void translate(const vec &p);
2395 : void translate(float x, float y, float z);
2396 : void translate(const vec &p, float scale);
2397 : void accumulate(const matrix4x3 &m, float k);
2398 :
2399 : /**
2400 : * @brief Normalizes the first three column vectors.
2401 : *
2402 : * Sets the three first vectors to have a magnitude of 1. That is,
2403 : * sqrt(x^2 + y^2 + z^2) = 1.
2404 : *
2405 : * Does not check for a divide-by-zero condition.
2406 : */
2407 : void normalize();
2408 :
2409 : /**
2410 : * @brief Linearly interpolates between the two matrices according to scale t
2411 : *
2412 : * If 0 < t < 1 then the matrix will be t% of the way between `this` and `to`.
2413 : * Values outside 0..1 imply a linear extrapolation.
2414 : *
2415 : * @param to the other matrix to interpolate between
2416 : * @param t the interpolation factor
2417 : */
2418 : void lerp(const matrix4x3 &to, float t);
2419 :
2420 : /**
2421 : * @brief Linearly interpolates between two other matrices according to scale t
2422 : *
2423 : * If 0 < t < 1 then the matrix will be t% of the way between `this` and `to`.
2424 : * Values outside 0..1 imply a linear extrapolation.
2425 : *
2426 : * @param from the first matrix to interpolate from
2427 : * @param to the other matrix to interpolate between
2428 : * @param t the interpolation factor
2429 : */
2430 : void lerp(const matrix4x3 &from, const matrix4x3 &to, float t);
2431 :
2432 : /**
2433 : * @brief Sets this matrix to the identity matrix.
2434 : *
2435 : * ```
2436 : * a b c d
2437 : * x 1 0 0 0
2438 : * y 0 1 0 0
2439 : * z 0 0 1 0
2440 : * ```
2441 : */
2442 : void identity();
2443 : void mul(const matrix4x3 &m, const matrix4x3 &n);
2444 : void mul(const matrix4x3 &n);
2445 :
2446 : void mul(const matrix3 &m, const matrix4x3 &n);
2447 :
2448 : void mul(const matrix3 &rot, const vec &trans, const matrix4x3 &n);
2449 :
2450 : void transpose();
2451 : void transpose(const matrix4x3 &o);
2452 :
2453 : void transposemul(const matrix4x3 &m, const matrix4x3 &n);
2454 :
2455 : void multranspose(const matrix4x3 &m, const matrix4x3 &n);
2456 :
2457 : void invert(const matrix4x3 &o);
2458 : void invert();
2459 : void rotate(float angle, const vec &d);
2460 :
2461 : void rotate(float ck, float sk, const vec &axis);
2462 :
2463 : void rotate_around_x(float ck, float sk);
2464 : void rotate_around_x(float angle);
2465 :
2466 : void rotate_around_x(const vec2 &sc);
2467 :
2468 : void rotate_around_y(float ck, float sk);
2469 : void rotate_around_y(float angle);
2470 : void rotate_around_y(const vec2 &sc);
2471 :
2472 : void rotate_around_z(float ck, float sk);
2473 : void rotate_around_z(float angle);
2474 : void rotate_around_z(const vec2 &sc);
2475 :
2476 : vec transposedtransform(const vec &o) const;
2477 : vec transformnormal(const vec &o) const;
2478 : vec transposedtransformnormal(const vec &o) const;
2479 : vec transform(const vec &o) const;
2480 : vec transform(const vec2 &o) const;
2481 :
2482 : /**
2483 : * @brief Returns the x values of the four vectors as a four-vector.
2484 : *
2485 : * @return a vector containing four x values
2486 : */
2487 : vec4<float> rowx() const;
2488 :
2489 : /**
2490 : * @brief Returns the y values of the four vectors as a four-vector.
2491 : *
2492 : * @return a vector containing four y values
2493 : */
2494 : vec4<float> rowy() const;
2495 :
2496 : /**
2497 : * @brief Returns the z values of the four vectors as a four-vector.
2498 : *
2499 : * @return a vector containing four z values
2500 : */
2501 : vec4<float> rowz() const;
2502 : };
2503 :
2504 : /*
2505 :
2506 : The engine uses 3 different linear coordinate systems
2507 : which are oriented around each of the axis dimensions.
2508 :
2509 : So any point within the game can be defined by four coordinates: (d, x, y, z)
2510 :
2511 : d is the reference axis dimension
2512 : x is the coordinate of the ROW dimension
2513 : y is the coordinate of the COL dimension
2514 : z is the coordinate of the reference dimension (DEPTH)
2515 :
2516 : typically, if d is not used, then it is implicitly the Z dimension.
2517 : ie: d=z => x=x, y=y, z=z
2518 :
2519 : */
2520 :
2521 : // DIM: X=0 Y=1 Z=2.
2522 : const int R[3] = {1, 2, 0}; /**< row */
2523 : const int C[3] = {2, 0, 1}; /**< col */
2524 : const int D[3] = {0, 1, 2}; /**< depth */
2525 :
2526 : struct ivec2;
2527 :
2528 : //integer vector3
2529 : struct ivec
2530 : {
2531 : int x, y, z;
2532 :
2533 1200 : ivec() {}
2534 2 : explicit ivec(const vec &v) : x(static_cast<int>(v.x)), y(static_cast<int>(v.y)), z(static_cast<int>(v.z)) {}
2535 800 : ivec(int a, int b, int c) : x(a), y(b), z(c) {}
2536 1 : ivec(int d, int row, int col, int depth)
2537 1 : {
2538 1 : (*this)[R[d]] = row;
2539 1 : (*this)[C[d]] = col;
2540 1 : (*this)[D[d]] = depth;
2541 1 : }
2542 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) {}
2543 : explicit ivec(const ivec2 &v, int z = 0);
2544 : explicit ivec(const svec &v);
2545 :
2546 699 : int &operator[](int i)
2547 : {
2548 699 : switch(i)
2549 : {
2550 234 : case 1:
2551 : {
2552 234 : return y;
2553 : }
2554 232 : case 2:
2555 : {
2556 232 : return z;
2557 : }
2558 233 : default:
2559 : {
2560 233 : return x;
2561 : }
2562 : }
2563 : }
2564 :
2565 418 : int operator[](int i) const
2566 : {
2567 418 : switch(i)
2568 : {
2569 139 : case 1:
2570 : {
2571 139 : return y;
2572 : }
2573 140 : case 2:
2574 : {
2575 140 : return z;
2576 : }
2577 139 : default:
2578 : {
2579 139 : return x;
2580 : }
2581 : }
2582 : }
2583 :
2584 : //int idx(int i) { return v[i]; }
2585 181 : bool operator==(const ivec &v) const { return x==v.x && y==v.y && z==v.z; }
2586 3 : bool operator!=(const ivec &v) const { return x!=v.x || y!=v.y || z!=v.z; }
2587 : ivec operator+(const ivec &v) const { return ivec(x+v.x, y+v.y, z+v.z); }
2588 : /**
2589 : * @brief Type conversion operator from ivec -> bool.
2590 : *
2591 : * If this ivec is identical to the origin (0,0,0), returns false; for any other
2592 : * values of (x,y,z) returns true. This is behavior analogous to int in three
2593 : * dimensions.
2594 : */
2595 182 : explicit operator bool() const { return !(x==0 && y==0 && z==0); }
2596 50 : ivec &shl(int n) { x<<= n; y<<= n; z<<= n; return *this; }
2597 3 : ivec &shr(int n) { x>>= n; y>>= n; z>>= n; return *this; }
2598 194 : ivec &mul(int n) { x *= n; y *= n; z *= n; return *this; }
2599 0 : ivec &div(int n) { x /= n; y /= n; z /= n; return *this; }
2600 12 : ivec &add(int n) { x += n; y += n; z += n; return *this; }
2601 1 : ivec &sub(int n) { x -= n; y -= n; z -= n; return *this; }
2602 2 : ivec &mul(const ivec &v) { x *= v.x; y *= v.y; z *= v.z; return *this; }
2603 : ivec &div(const ivec &v) { x /= v.x; y /= v.y; z /= v.z; return *this; }
2604 193 : ivec &add(const ivec &v) { x += v.x; y += v.y; z += v.z; return *this; }
2605 271 : ivec &sub(const ivec &v) { x -= v.x; y -= v.y; z -= v.z; return *this; }
2606 229 : ivec &mask(int n) { x &= n; y &= n; z &= n; return *this; }
2607 3 : ivec &neg() { x = -x; y = -y; z = -z; return *this; }
2608 6 : ivec &min(const ivec &o) { x = ::min(x, o.x); y = ::min(y, o.y); z = ::min(z, o.z); return *this; }
2609 6 : ivec &max(const ivec &o) { x = ::max(x, o.x); y = ::max(y, o.y); z = ::max(z, o.z); return *this; }
2610 2 : ivec &min(int n) { x = ::min(x, n); y = ::min(y, n); z = ::min(z, n); return *this; }
2611 2 : ivec &max(int n) { x = ::max(x, n); y = ::max(y, n); z = ::max(z, n); return *this; }
2612 3 : ivec &abs() { x = ::abs(x); y = ::abs(y); z = ::abs(z); return *this; }
2613 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; }
2614 186 : 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; }
2615 139 : int dot(const ivec &o) const { return x*o.x + y*o.y + z*o.z; }
2616 : float dist(const plane &p) const;
2617 :
2618 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))); }
2619 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))); }
2620 : };
2621 :
2622 0 : inline vec::vec(const ivec &v) : x(v.x), y(v.y), z(v.z) {}
2623 :
2624 : template<>
2625 : struct std::hash<ivec>
2626 : {
2627 48 : size_t operator()(const ivec &k) const
2628 : {
2629 48 : return k.x^k.y^k.z;
2630 : }
2631 : };
2632 :
2633 : /**
2634 : * @brief integer vector2
2635 : */
2636 : struct ivec2
2637 : {
2638 : union
2639 : {
2640 : struct { int x, y; } coord;
2641 : int v[2];
2642 : };
2643 :
2644 761 : ivec2() {}
2645 117 : ivec2(int x, int y)
2646 117 : {
2647 117 : coord.x = x;
2648 117 : coord.y = y;
2649 117 : }
2650 :
2651 : explicit ivec2(const vec2 &v)
2652 : {
2653 : coord.x = static_cast<int>(v.x);
2654 : coord.y = static_cast<int>(v.y);
2655 : }
2656 :
2657 : explicit ivec2(const ivec &v)
2658 : {
2659 : coord.x = v.x;
2660 : coord.y = v.y;
2661 : }
2662 :
2663 2 : int &operator[](int i) { return v[i]; }
2664 2 : int operator[](int i) const { return v[i]; }
2665 :
2666 30 : bool operator==(const ivec2 &o) const { return coord.x == o.coord.x && coord.y == o.coord.y; }
2667 3 : bool operator!=(const ivec2 &o) const { return coord.x != o.coord.x || coord.y != o.coord.y; }
2668 :
2669 3 : int &x() { return coord.x; }
2670 3 : int &y() { return coord.y; }
2671 0 : int x() const { return coord.x; }
2672 0 : int y() const { return coord.y; }
2673 :
2674 3 : bool iszero() const { return coord.x==0 && coord.y==0; }
2675 2 : ivec2 &shl(int n) { coord.x<<= n; coord.y<<= n; return *this; }
2676 3 : ivec2 &shr(int n) { coord.x>>= n; coord.y>>= n; return *this; }
2677 2 : ivec2 &mul(int n) { coord.x *= n; coord.y *= n; return *this; }
2678 : ivec2 &div(int n) { coord.x /= n; coord.y /= n; return *this; }
2679 2 : ivec2 &add(int n) { coord.x += n; coord.y += n; return *this; }
2680 2 : ivec2 &sub(int n) { coord.x -= n; coord.y -= n; return *this; }
2681 2 : ivec2 &mul(const ivec2 &v) { coord.x *= v.coord.x; coord.y *= v.coord.y; return *this; }
2682 : ivec2 &div(const ivec2 &v) { coord.x /= v.coord.x; coord.y /= v.coord.y; return *this; }
2683 2 : ivec2 &add(const ivec2 &v) { coord.x += v.coord.x; coord.y += v.coord.y; return *this; }
2684 2 : ivec2 &sub(const ivec2 &v) { coord.x -= v.coord.x; coord.y -= v.coord.y; return *this; }
2685 3 : ivec2 &mask(int n) { coord.x &= n; coord.y &= n; return *this; }
2686 3 : ivec2 &neg() { coord.x = -coord.x; coord.y = -coord.y; return *this; }
2687 1 : ivec2 &min(const ivec2 &o) { coord.x = ::min(coord.x, o.coord.x); coord.y = ::min(coord.y, o.coord.y); return *this; }
2688 1 : ivec2 &max(const ivec2 &o) { coord.x = ::max(coord.x, o.coord.x); coord.y = ::max(coord.y, o.coord.y); return *this; }
2689 1 : ivec2 &min(int n) { coord.x = ::min(coord.x, n); coord.y = ::min(coord.y, n); return *this; }
2690 1 : ivec2 &max(int n) { coord.x = ::max(coord.x, n); coord.y = ::max(coord.y, n); return *this; }
2691 3 : ivec2 &abs() { coord.x = ::abs(coord.x); coord.y = ::abs(coord.y); return *this; }
2692 1 : int dot(const ivec2 &o) const { return coord.x*o.coord.x + coord.y*o.coord.y; }
2693 2 : int cross(const ivec2 &o) const { return coord.x*o.coord.y - coord.y*o.coord.x; }
2694 : };
2695 :
2696 : inline ivec::ivec(const ivec2 &v, int z) : x(v.x()), y(v.y()), z(z) {}
2697 :
2698 : inline bvec::bvec(const vec4<uchar> &v) : x(v.x), y(v.y), z(v.z) {}
2699 :
2700 : /**
2701 : * @brief short integer three-vector object
2702 : */
2703 : struct svec
2704 : {
2705 : union
2706 : {
2707 : struct { short x, y, z; } coord;
2708 : short v[3];
2709 : };
2710 :
2711 0 : svec() {}
2712 : svec(short x, short y, short z)
2713 : {
2714 : coord.x = x;
2715 : coord.y = y;
2716 : coord.z = z;
2717 : }
2718 0 : explicit svec(const ivec &v)
2719 0 : {
2720 0 : coord.x = v.x;
2721 0 : coord.y = v.y;
2722 0 : coord.z = v.z;
2723 0 : }
2724 :
2725 : short &operator[](int i) { return v[i]; }
2726 : short operator[](int i) const { return v[i]; }
2727 : };
2728 :
2729 : inline vec::vec(const svec &v)
2730 : {
2731 : x = v.coord.x;
2732 : y = v.coord.y;
2733 : z = v.coord.z;
2734 : }
2735 :
2736 0 : inline ivec::ivec(const svec &v)
2737 : {
2738 0 : x = v.coord.x;
2739 0 : y = v.coord.y;
2740 0 : z = v.coord.z;
2741 0 : }
2742 :
2743 : /**
2744 : * @brief floating point 4x4 array object
2745 : */
2746 : struct matrix4
2747 : {
2748 : vec4<float> a, b, c, d;
2749 :
2750 : template<class T, class U>
2751 : T transformnormal(const U &in) const
2752 : {
2753 : T v;
2754 : transformnormal(in, v);
2755 : return v;
2756 : }
2757 :
2758 : template<class T, class U>
2759 : T transform(const U &in) const
2760 : {
2761 : T v;
2762 : transform(in, v);
2763 : return v;
2764 : }
2765 :
2766 : template<class T>
2767 0 : vec perspectivetransform(const T &in) const
2768 : {
2769 0 : vec4<float> v;
2770 0 : transform(in, v);
2771 0 : return vec(v).div(v.w);
2772 : }
2773 :
2774 : template<class T>
2775 4 : void mult(const matrix4 &x, const matrix4 &y)
2776 : {
2777 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);
2778 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);
2779 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);
2780 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);
2781 4 : }
2782 :
2783 : matrix4();
2784 : matrix4(const float *m);
2785 : matrix4(const vec &a, const vec &b, const vec &c = vec(0, 0, 1));
2786 : matrix4(const vec4<float> &a, const vec4<float> &b, const vec4<float> &c, const vec4<float> &d = vec4<float>(0, 0, 0, 1));
2787 : matrix4(const matrix4x3 &m);
2788 : matrix4(const matrix3 &rot, const vec &trans);
2789 : void mul(const matrix4 &x, const matrix3 &y);
2790 : void mul(const matrix3 &y);
2791 :
2792 : /**
2793 : * @brief Sets this matrix to the product of the two matrices provided
2794 : *
2795 : * The original contents of the matrix are disregarded.
2796 : * All calculations at single precision (float).
2797 : *
2798 : * @param x the first matrix to multiply
2799 : * @param y the second matrix to multiply
2800 : */
2801 : void mul(const matrix4 &x, const matrix4 &y);
2802 :
2803 : /**
2804 : * @brief Sets this matrix to the product of this and another matrix
2805 : *
2806 : * The original contents of the matrix are the left element in the product.
2807 : * All calculations at single precision (float).
2808 : *
2809 : * @param y the second matrix to multiply
2810 : */
2811 : void mul(const matrix4 &y);
2812 :
2813 : /**
2814 : * @brief Sets this matrix to the product of the two matrices provided
2815 : *
2816 : * The original contents of the matrix are disregarded.
2817 : * Uses double precision to perform calculations, and is narrowed at the end to float.
2818 : *
2819 : * @param x the first matrix to multiply
2820 : * @param y the second matrix to multiply
2821 : */
2822 : void muld(const matrix4 &x, const matrix4 &y);
2823 :
2824 : /**
2825 : * @brief Sets this matrix to the product of this and another matrix
2826 : *
2827 : * The original contents of the matrix are the left element in the product.
2828 : * Uses double precision to perform calculations, and is narrowed at the end to float.
2829 : *
2830 : * @param y the second matrix to multiply
2831 : */
2832 : void muld(const matrix4 &y);
2833 : void rotate_around_x(float ck, float sk);
2834 : void rotate_around_x(float angle);
2835 : void rotate_around_x(const vec2 &sc);
2836 : void rotate_around_y(float ck, float sk);
2837 : void rotate_around_y(float angle);
2838 : void rotate_around_y(const vec2 &sc);
2839 :
2840 : void rotate_around_z(float ck, float sk);
2841 : void rotate_around_z(float angle);
2842 : void rotate_around_z(const vec2 &sc);
2843 :
2844 : void rotate(float ck, float sk, const vec &axis);
2845 : void rotate(float angle, const vec &dir);
2846 : void rotate(const vec2 &sc, const vec &dir);
2847 :
2848 : /**
2849 : * @brief Sets the matrix to I, the identity matrix
2850 : *
2851 : * Sets the matrix to I, with the form as follows:
2852 : * ```
2853 : * a b c d
2854 : * x 1 0 0 0
2855 : * y 0 1 0 0
2856 : * z 0 0 1 0
2857 : * w 0 0 0 1
2858 : * ```
2859 : */
2860 : void identity();
2861 :
2862 : void settranslation(const vec &v);
2863 : void settranslation(float x, float y, float z);
2864 : void translate(const vec &p);
2865 : void translate(float x, float y, float z);
2866 : void translate(const vec &p, float scale);
2867 : void setscale(float x, float y, float z);
2868 : void setscale(const vec &v);
2869 : void setscale(float n);
2870 : void scale(float x, float y, float z);
2871 : void scale(const vec &v);
2872 : void scale(float n);
2873 :
2874 : void scalez(float k);
2875 :
2876 : void jitter(float x, float y);
2877 :
2878 : /**
2879 : * @brief Transposes the matrix along the diagonal.
2880 : *
2881 : * Transforms the matrix like so (letters are just arbitrary value placeholders)
2882 : * ```
2883 : * a b c d a e i m
2884 : * e f g h -> b f j n
2885 : * i j k l c g k o
2886 : * m n o p d h l p
2887 : * ```
2888 : */
2889 : void transpose();
2890 :
2891 : /**
2892 : * @brief Copies the transpose of the given matrix4 to `this`
2893 : *
2894 : * Copies the transform of the matrix passed like so (letters are just arbitrary
2895 : * value placeholders) to `this` object.
2896 : * ```
2897 : * a b c d a e i m
2898 : * e f g h -> b f j n
2899 : * i j k l c g k o
2900 : * m n o p d h l p
2901 : * ```
2902 : */
2903 : void transpose(const matrix4 &m);
2904 : void frustum(float left, float right, float bottom, float top, float znear, float zfar);
2905 : void perspective(float fovy, float aspect, float znear, float zfar);
2906 :
2907 : void ortho(float left, float right, float bottom, float top, float znear, float zfar);
2908 :
2909 : void transform(const vec &in, vec &out) const;
2910 : void transform(const vec4<float> &in, vec &out) const;
2911 :
2912 : void transform(const vec &in, vec4<float> &out) const;
2913 : void transform(const vec4<float> &in, vec4<float> &out) const;
2914 : void transformnormal(const vec &in, vec &out) const;
2915 : void transformnormal(const vec &in, vec4<float> &out) const;
2916 :
2917 : void transposedtransform(const vec &in, vec &out) const;
2918 : void transposedtransformnormal(const vec &in, vec &out) const;
2919 : void transposedtransform(const plane &in, plane &out) const;
2920 :
2921 : vec gettranslation() const;
2922 :
2923 : /**
2924 : * @brief Returns the first row of the matrix.
2925 : *
2926 : * Returns the first value of each column vector that makes up the matrix.
2927 : *
2928 : * @return a vec4 of the first row of the vector
2929 : */
2930 : vec4<float> rowx() const;
2931 :
2932 : /**
2933 : * @brief Returns the second row of the matrix.
2934 : *
2935 : * Returns the second value of each column vector that makes up the matrix.
2936 : *
2937 : * @return a vec4 of the second row of the vector
2938 : */
2939 : vec4<float> rowy() const;
2940 :
2941 : /**
2942 : * @brief Returns the third row of the matrix.
2943 : *
2944 : * Returns the third value of each column vector that makes up the matrix.
2945 : *
2946 : * @return a vec4 of the third row of the vector
2947 : */
2948 : vec4<float> rowz() const;
2949 :
2950 : /**
2951 : * @brief Returns the fourth row of the matrix.
2952 : *
2953 : * Returns the fourth value of each column vector that makes up the matrix.
2954 : *
2955 : * @return a vec4 of the last row of the vector
2956 : */
2957 : vec4<float> roww() const;
2958 :
2959 : /**
2960 : * @brief Sets this matrix to the inverse of the provided matrix.
2961 : *
2962 : * Sets the matrix values to the inverse of the provided matrix A*A^-1 = I
2963 : * returns false if singular (or nearly singular to within tolerance of mindet)
2964 : * or true if matrix was inverted successfully
2965 : *
2966 : * @param m a matrix4 object to be inverted and assigned to the object
2967 : * @param mindet the determinant value at which matrices are considered singular
2968 : *
2969 : * @return false if the matrix is singular, true otherwise
2970 : */
2971 : bool invert(const matrix4 &m, double mindet = 1.0e-12);
2972 :
2973 : /**
2974 : * @brief Returns the inverse of the matrix.
2975 : *
2976 : * Returns a zero matrix if the matrix is singular.
2977 : *
2978 : * @param mindet the determinant value at which matrices are considered singular
2979 : *
2980 : * @return a matrix4 containing the matrix inverse
2981 : */
2982 : matrix4 inverse(double mindet = 1.0e-12) const;
2983 :
2984 : vec2 lineardepthscale() const;
2985 : };
2986 :
2987 1 : inline matrix3::matrix3(const matrix4 &m)
2988 1 : : a(m.a), b(m.b), c(m.c)
2989 1 : {}
2990 :
2991 : inline matrix4x3::matrix4x3(const matrix4 &m)
2992 : : a(m.a), b(m.b), c(m.c), d(m.d)
2993 : {}
2994 :
2995 1 : inline matrix3::matrix3(const matrix4x3 &m) : a(m.a), b(m.b), c(m.c) {}
2996 :
2997 : //generic two dimensional vector
2998 : template<class T>
2999 : struct GenericVec2
3000 : {
3001 : T x,y;
3002 :
3003 8 : GenericVec2() {}
3004 : GenericVec2(T x, T y) : x(x), y(y) {}
3005 2 : GenericVec2(const vec2 &v) : x(v.x), y(v.y) {}
3006 :
3007 : bool operator==(const GenericVec2 &h) const { return x == h.x && y == h.y; }
3008 : bool operator!=(const GenericVec2 &h) const { return x != h.x || y != h.y; }
3009 : };
3010 :
3011 : //generic three dmensional vector
3012 : template<class T>
3013 : struct GenericVec3
3014 : {
3015 : T x,y,z;
3016 :
3017 : GenericVec3() {}
3018 : GenericVec3(T x, T y, T z) : x(x), y(y), z(z) {}
3019 : GenericVec3(const vec &v) : x(v.x), y(v.y), z(v.z) {}
3020 :
3021 : GenericVec3<T> operator+(const GenericVec3<T> &h) const { return GenericVec3<T>(x+h.x, y+h.y,z+h.z); }
3022 : GenericVec3<T> operator-(const GenericVec3<T> &h) const { return GenericVec3<T>(x-h.x, y-h.y, z-h.z); }
3023 :
3024 : //comparison
3025 : bool operator==(const GenericVec3<T> &h) const { return x == h.x && y == h.y && z == h.z; }
3026 : bool operator!=(const GenericVec3<T> &h) const { return x != h.x || y != h.y || z != h.z; }
3027 : bool operator>(const GenericVec3<T> &h) const { return x > h.x && y > h.y && z > h.z; }
3028 : bool operator<(const GenericVec3<T> &h) const { return x < h.x && y < h.y && z < h.z; }
3029 : bool operator>=(const GenericVec3<T> &h) const { return x >= h.x && y >= h.y && z >= h.z; }
3030 : bool operator<=(const GenericVec3<T> &h) const { return x <= h.x && y <= h.y && z <= h.z; }
3031 : };
3032 :
3033 : extern bool raysphereintersect(const vec ¢er, float radius, const vec &o, const vec &ray, float &dist);
3034 : extern bool rayboxintersect(const vec &b, const vec &s, const vec &o, const vec &ray, float &dist, int &orient);
3035 :
3036 : /**
3037 : * @brief Determines whether a line segment intersects a specified cylinder.
3038 : *
3039 : * Calculates whether a specified line segment intersects a cylinder, defined by
3040 : * a line segment and a radius around it. Segments which intersect along an edge,
3041 : * face, or tangent to the curved surface are considered to be intersecting. A
3042 : * successful intersection will cause the function to return `true`.
3043 : *
3044 : * Negative radii are handled the same as a positive radius of the same magnitude.
3045 : *
3046 : * If the line segment is entirely within the boundaries of the cylinder, the
3047 : * segment is considered to be intersecting, with the intersection starting
3048 : * at the `from` location.
3049 : *
3050 : * The distance along the line at which the segment intersects the cylinder is
3051 : * expressed as a value from 0 to 1 and returned through the reference parameter
3052 : * dist. If the segment is entirely within the cylinder, the segment's intersection
3053 : * distance is considered to be zero.
3054 : *
3055 : * If no intersection with the cylinder is found, the dist value will be returned
3056 : * unchanged, and the function will return false.
3057 : *
3058 : * @param from the start point of the intersecting line segment
3059 : * @param to the end point of the intersecting line segment
3060 : * @param start the start point of the cylinder's axial line segment
3061 : * @param end the endpoint of the cylinder's axial line segment
3062 : * @param radius the radius of the cylinder to be intersected
3063 : * @param dist the value to set to the distance along the segment where intersection occured
3064 : *
3065 : * @return true if the cylinder was intersected by the line segment
3066 : * @return false if the cylinder and line segment did not intersect
3067 : */
3068 : extern bool linecylinderintersect(const vec &from, const vec &to, const vec &start, const vec &end, float radius, float &dist);
3069 : extern int polyclip(const vec *in, int numin, const vec &dir, float below, float above, vec *out);
3070 :
3071 : extern const vec2 sincos360[]; /**< a 721 element table of cosines, sines given integral values */
3072 :
3073 : /**
3074 : * @brief Returns the angle passed to it, clamped to 0...360
3075 : *
3076 : * Normalizes negative/large angles passed to it to the range [0,360).
3077 : *
3078 : * @param angle the angle to parse
3079 : *
3080 : * @return the angle clamped to 0...360
3081 : */
3082 5 : inline int mod360(int angle)
3083 : {
3084 5 : if(angle < 0)
3085 : {
3086 1 : angle = 360 + (angle <= -360 ? angle%360 : angle);
3087 : }
3088 4 : else if(angle >= 360)
3089 : {
3090 3 : angle %= 360;
3091 : }
3092 5 : return angle;
3093 : }
3094 :
3095 : /**
3096 : * @brief Returns a vec2 containing (cos, sine) for a given integral angle.
3097 : *
3098 : * @param angle the angle to get the sine/cos value of
3099 : *
3100 : * @return a vec2 containing the cosine and sine of the given angle
3101 : */
3102 0 : inline const vec2 &sincosmod360(int angle) { return sincos360[mod360(angle)]; }
3103 :
3104 : /**
3105 : * @brief Returns the cosine for an angle (in degrees)
3106 : *
3107 : * Must be within the bounds of 0...720. Uses a lookup table for integral values in degrees.
3108 : *
3109 : * @param angle the angle to get the cosine of (in degrees)
3110 : *
3111 : * @return the cosine of that angle
3112 : */
3113 10 : inline float cos360(int angle) { return sincos360[angle].x; }
3114 :
3115 : /**
3116 : * @brief Returns the sine for an angle (in degrees)
3117 : *
3118 : * Must be within the bounds of 0...720. Uses a lookup table for integral values in degrees.
3119 : *
3120 : * @param angle the angle to get the sine of (in degrees)
3121 : *
3122 : * @return the sine of that angle
3123 : */
3124 10 : inline float sin360(int angle) { return sincos360[angle].y; }
3125 :
3126 : /**
3127 : * @brief Returns the tangent for an angle (in degrees)
3128 : *
3129 : * Must be within the bounds of 0...720. Uses a lookup table for integral values in degrees.
3130 : *
3131 : * @param angle the angle to get the tangent of (in degrees)
3132 : *
3133 : * @return the tangent of that angle
3134 : */
3135 0 : inline float tan360(int angle) { const vec2 &sc = sincos360[angle]; return sc.y/sc.x; }
3136 :
3137 : /**
3138 : * @brief Returns the cotangent for an angle (in degrees)
3139 : *
3140 : * Must be within the bounds of 0...720. Uses a lookup table for integral values in degrees.
3141 : *
3142 : * @param angle the angle to get the cotangent of (in degrees)
3143 : *
3144 : * @return the cotangent of that angle
3145 : */
3146 0 : inline float cotan360(int angle) { const vec2 &sc = sincos360[angle]; return sc.x/sc.y; }
3147 :
3148 : #endif /* GEOM_H_ */
|