LCOV - code coverage report
Current view: top level - libprimis-headers - geom.h (source / functions) Hit Total Coverage
Test: Libprimis Test Coverage Lines: 459 492 93.3 %
Date: 2024-11-22 05:07:59 Functions: 303 328 92.4 %

          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 &center, 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_ */

Generated by: LCOV version 1.14