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