LCOV - code coverage report
Current view: top level - libprimis-headers - geom.h (source / functions) Coverage Total Hit
Test: Libprimis Test Coverage Lines: 91.3 % 601 549
Test Date: 2025-12-16 06:27:13 Functions: 90.4 % 356 322

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

Generated by: LCOV version 2.0-1