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

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

Generated by: LCOV version 1.14