LCOV - code coverage report
Current view: top level - libprimis-headers - geom.h (source / functions) Coverage Total Hit
Test: Libprimis Test Coverage Lines: 90.7 % 601 545
Test Date: 2025-02-18 06:21:28 Functions: 89.9 % 355 319

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

Generated by: LCOV version 2.0-1