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