LCOV - code coverage report
Current view: top level - shared - matrix.cpp (source / functions) Coverage Total Hit
Test: Libprimis Test Coverage Lines: 95.2 % 663 631
Test Date: 2026-07-09 06:56:18 Functions: 97.4 % 154 150

            Line data    Source code
       1              : #include <cstring>
       2              : #include <functional>
       3              : #include <stdexcept>
       4              : #include <algorithm>
       5              : 
       6              : #include <SDL.h>
       7              : #include <zlib.h>
       8              : 
       9              : #include "../libprimis-headers/tools.h"
      10              : #include "../libprimis-headers/geom.h"
      11              : 
      12              : #include "geomexts.h"
      13              : 
      14              : /**
      15              :  * @file matrix.cpp
      16              :  * @brief Matrix math functions
      17              :  *
      18              :  * This file defines matrix3, matrix4, and matrix4x3's member functions.
      19              :  * The definitions of the classes themselves are in geom.h (one of the shared
      20              :  * header files)
      21              :  *
      22              :  */
      23              : 
      24              : //needed for det3
      25              : 
      26              : /**
      27              :  * @brief 2x2 matrix determinant
      28              :  *
      29              :  * Returns the determinant of a 2x2 matrix, provided a set of four doubles
      30              :  * (rather than as a matrix2 object).
      31              :  *
      32              :  * @param a top left element
      33              :  * @param b top right element
      34              :  * @param c bottom left element
      35              :  * @param d bottom right element
      36              :  *
      37              :  * @return determinant of the matrix
      38              :  */
      39          120 : static double det2x2(double a, double b, double c, double d)
      40              : {
      41          120 :     return a*d - b*c;
      42              : }
      43              : 
      44              : //needed to invert matrix below
      45              : /**
      46              :  * @brief 3x3 matrix determinant
      47              :  *
      48              :  * Returns the determinant of a 3x3 matrix, provided a set of nine doubles
      49              :  * (rather than as a matrix3 object).
      50              :  *
      51              :  * @param a1 top left element
      52              :  * @param a2 top center element
      53              :  * @param a3 top right element
      54              :  * @param b1 middle left element
      55              :  * @param b2 middle center element
      56              :  * @param b3 middle right element
      57              :  * @param c1 bottom left element
      58              :  * @param c2 bottom center element
      59              :  * @param c3 bottom right element
      60              :  *
      61              :  * @return determinant of the matrix
      62              :  */
      63           40 : static double det3x3(double a1, double a2, double a3,
      64              :                             double b1, double b2, double b3,
      65              :                             double c1, double c2, double c3)
      66              : {
      67           40 :     return a1 * det2x2(b2, b3, c2, c3)
      68           40 :          - b1 * det2x2(a2, a3, c2, c3)
      69           40 :          + c1 * det2x2(a2, a3, b2, b3);
      70              : }
      71              : 
      72              : // =============================================================================
      73              : //  matrix3 (3x3) object
      74              : // =============================================================================
      75              : 
      76          519 : matrix3::matrix3() : a(0,0,0), b(0,0,0), c(0,0,0)
      77              : {
      78          519 : }
      79              : 
      80           22 : matrix3::matrix3(const vec &a, const vec &b, const vec &c) : a(a), b(b), c(c)
      81              : {
      82           22 : }
      83              : 
      84            4 : matrix3::matrix3(const quat &q)
      85              : {
      86            4 :     float x   = q.x,   y  = q.y,    z = q.z, w = q.w,
      87            4 :           tx  = 2*x,   ty = 2*y,   tz = 2*z,
      88            4 :           txx = tx*x, tyy = ty*y, tzz = tz*z,
      89            4 :           txy = tx*y, txz = tx*z, tyz = ty*z,
      90            4 :           twx = w*tx, twy = w*ty, twz = w*tz;
      91            4 :     a = vec(1 - (tyy + tzz), txy + twz, txz - twy);
      92            4 :     b = vec(txy - twz, 1 - (txx + tzz), tyz + twx);
      93            4 :     c = vec(txz + twy, tyz - twx, 1 - (txx + tyy));
      94            4 : }
      95              : 
      96            9 : matrix3::matrix3(float angle, const vec &axis)
      97              : {
      98            9 :     rotate(angle, axis);
      99            9 : }
     100              : 
     101            4 : void matrix3::mul(const matrix3 &m, const matrix3 &n)
     102              : {
     103            4 :     a = vec(m.a).mul(n.a.x).madd(m.b, n.a.y).madd(m.c, n.a.z);
     104            4 :     b = vec(m.a).mul(n.b.x).madd(m.b, n.b.y).madd(m.c, n.b.z);
     105            4 :     c = vec(m.a).mul(n.c.x).madd(m.b, n.c.y).madd(m.c, n.c.z);
     106            4 : }
     107              : 
     108            2 : void matrix3::mul(const matrix3 &n)
     109              : {
     110            2 :     mul(matrix3(*this), n);
     111            2 : }
     112              : 
     113            2 : void matrix3::multranspose(const matrix3 &m, const matrix3 &n)
     114              : {
     115            2 :     a = vec(m.a).mul(n.a.x).madd(m.b, n.b.x).madd(m.c, n.c.x);
     116            2 :     b = vec(m.a).mul(n.a.y).madd(m.b, m.b.y).madd(m.c, n.c.y);
     117            2 :     c = vec(m.a).mul(n.a.z).madd(m.b, n.b.z).madd(m.c, n.c.z);
     118            2 : }
     119            2 : void matrix3::multranspose(const matrix3 &n)
     120              : {
     121            2 :     multranspose(matrix3(*this), n);
     122            2 : }
     123              : 
     124            2 : void matrix3::transposemul(const matrix3 &m, const matrix3 &n)
     125              : {
     126            2 :     a = vec(m.a.dot(n.a), m.b.dot(n.a), m.c.dot(n.a));
     127            2 :     b = vec(m.a.dot(n.b), m.b.dot(n.b), m.c.dot(n.b));
     128            2 :     c = vec(m.a.dot(n.c), m.b.dot(n.c), m.c.dot(n.c));
     129            2 : }
     130              : 
     131            2 : void matrix3::transposemul(const matrix3 &n)
     132              : {
     133            2 :     transposemul(matrix3(*this), n);
     134            2 : }
     135              : 
     136            1 : void matrix3::transpose()
     137              : {
     138            1 :     std::swap(a.y, b.x); std::swap(a.z, c.x);
     139            1 :     std::swap(b.z, c.y);
     140            1 : }
     141              : 
     142            4 : void matrix3::transpose(const matrix3 &m)
     143              : {
     144            4 :     a = vec(m.a.x, m.b.x, m.c.x);
     145            4 :     b = vec(m.a.y, m.b.y, m.c.y);
     146            4 :     c = vec(m.a.z, m.b.z, m.c.z);
     147            4 : }
     148              : 
     149            4 : void matrix3::invert(const matrix3 &o)
     150              : {
     151            4 :     vec unscale(1/o.a.squaredlen(), 1/o.b.squaredlen(), 1/o.c.squaredlen());
     152            4 :     transpose(o);
     153            4 :     a.mul(unscale);
     154            4 :     b.mul(unscale);
     155            4 :     c.mul(unscale);
     156            4 : }
     157              : 
     158            2 : void matrix3::invert()
     159              : {
     160            2 :     invert(matrix3(*this));
     161            2 : }
     162              : 
     163            2 : void matrix3::normalize()
     164              : {
     165            2 :     a.normalize();
     166            2 :     b.normalize();
     167            2 :     c.normalize();
     168            2 : }
     169              : 
     170            1 : void matrix3::scale(float k)
     171              : {
     172            1 :     a.mul(k);
     173            1 :     b.mul(k);
     174            1 :     c.mul(k);
     175            1 : }
     176              : 
     177            9 : void matrix3::rotate(float angle, const vec &axis)
     178              : {
     179            9 :     rotate(cosf(angle), std::sin(angle), axis);
     180            9 : }
     181              : 
     182           24 : void matrix3::rotate(float ck, float sk, const vec &axis)
     183              : {
     184           24 :     a = vec(axis.x*axis.x*(1-ck)+ck, axis.x*axis.y*(1-ck)+axis.z*sk, axis.x*axis.z*(1-ck)-axis.y*sk);
     185           24 :     b = vec(axis.x*axis.y*(1-ck)-axis.z*sk, axis.y*axis.y*(1-ck)+ck, axis.y*axis.z*(1-ck)+axis.x*sk);
     186           24 :     c = vec(axis.x*axis.z*(1-ck)+axis.y*sk, axis.y*axis.z*(1-ck)-axis.x*sk, axis.z*axis.z*(1-ck)+ck);
     187           24 : }
     188              : 
     189            9 : void matrix3::setyaw(float ck, float sk)
     190              : {
     191            9 :     a = vec(ck, sk, 0);
     192            9 :     b = vec(-sk, ck, 0);
     193            9 :     c = vec(0, 0, 1);
     194            9 : }
     195              : 
     196            9 : void matrix3::setyaw(float angle)
     197              : {
     198            9 :     setyaw(cosf(angle), std::sin(angle));
     199            9 : }
     200              : 
     201           10 : float matrix3::trace() const
     202              : {
     203           10 :     return a.x + b.y + c.z;
     204              : }
     205              : 
     206            7 : bool matrix3::calcangleaxis(float tr, float &angle, vec &axis, float threshold) const
     207              : {
     208            7 :     if(tr <= -1)
     209              :     {
     210            2 :         if(a.x >= b.y && a.x >= c.z)
     211              :         {
     212            2 :             float r = 1 + a.x - b.y - c.z;
     213            2 :             if(r <= threshold)
     214              :             {
     215            0 :                 return false;
     216              :             }
     217            2 :             r = sqrtf(r);
     218            2 :             axis.x = 0.5f*r;
     219            2 :             axis.y = b.x/r;
     220            2 :             axis.z = c.x/r;
     221            2 :         }
     222            0 :         else if(b.y >= c.z)
     223              :         {
     224            0 :             float r = 1 + b.y - a.x - c.z;
     225            0 :             if(r <= threshold)
     226              :             {
     227            0 :                 return false;
     228              :             }
     229            0 :             r = sqrtf(r);
     230            0 :             axis.y = 0.5f*r;
     231            0 :             axis.x = b.x/r;
     232            0 :             axis.z = c.y/r;
     233              :         }
     234              :         else
     235              :         {
     236            0 :             float r = 1 + b.y - a.x - c.z;
     237            0 :             if(r <= threshold)
     238              :             {
     239            0 :                 return false;
     240              :             }
     241            0 :             r = sqrtf(r);
     242            0 :             axis.z = 0.5f*r;
     243            0 :             axis.x = c.x/r;
     244            0 :             axis.y = c.y/r;
     245              :         }
     246            2 :         angle = M_PI;
     247              :     }
     248            5 :     else if(tr >= 3)
     249              :     {
     250            2 :         axis = vec(0, 0, 1);
     251            2 :         angle = 0;
     252              :     }
     253              :     else
     254              :     {
     255            3 :         axis = vec(b.z - c.y, c.x - a.z, a.y - b.x);
     256            3 :         float r = axis.squaredlen();
     257            3 :         if(r <= threshold)
     258              :         {
     259            0 :             return false;
     260              :         }
     261            3 :         axis.mul(1/sqrtf(r));
     262            3 :         angle = acosf(0.5f*(tr - 1));
     263              :     }
     264            7 :     return true;
     265              : }
     266              : 
     267            1 : bool matrix3::calcangleaxis(float &angle, vec &axis, float threshold) const
     268              : {
     269            1 :     return calcangleaxis(trace(), angle, axis, threshold);
     270              : }
     271              : 
     272            6 : vec matrix3::transform(const vec &o) const
     273              : {
     274            6 :     return vec(a).mul(o.x).madd(b, o.y).madd(c, o.z);
     275              : }
     276              : 
     277            9 : vec matrix3::transposedtransform(const vec &o) const
     278              : {
     279            9 :     return vec(a.dot(o), b.dot(o), c.dot(o));
     280              : }
     281              : 
     282            4 : vec matrix3::abstransform(const vec &o) const
     283              : {
     284            4 :     return vec(a).mul(o.x).abs().add(vec(b).mul(o.y).abs()).add(vec(c).mul(o.z).abs());
     285              : }
     286              : 
     287            4 : vec matrix3::abstransposedtransform(const vec &o) const
     288              : {
     289            4 :     return vec(a.absdot(o), b.absdot(o), c.absdot(o));
     290              : }
     291              : 
     292           59 : void matrix3::identity()
     293              : {
     294           59 :     a = vec(1, 0, 0);
     295           59 :     b = vec(0, 1, 0);
     296           59 :     c = vec(0, 0, 1);
     297           59 : }
     298              : 
     299            2 : void matrix3::rotate_around_x(float ck, float sk)
     300              : {
     301            2 :     vec rb = vec(b).mul(ck).madd(c, sk),
     302            2 :         rc = vec(c).mul(ck).msub(b, sk);
     303            2 :     b = rb;
     304            2 :     c = rc;
     305            2 : }
     306              : 
     307            1 : void matrix3::rotate_around_x(float angle)
     308              : {
     309            1 :     rotate_around_x(cosf(angle), std::sin(angle));
     310            1 : }
     311              : 
     312            1 : void matrix3::rotate_around_x(const vec2 &sc)
     313              : {
     314            1 :     rotate_around_x(sc.x, sc.y);
     315            1 : }
     316              : 
     317            2 : void matrix3::rotate_around_y(float ck, float sk)
     318              : {
     319            2 :     vec rc = vec(c).mul(ck).madd(a, sk),
     320            2 :         ra = vec(a).mul(ck).msub(c, sk);
     321            2 :     c = rc;
     322            2 :     a = ra;
     323            2 : }
     324              : 
     325            1 : void matrix3::rotate_around_y(float angle)
     326              : {
     327            1 :     rotate_around_y(cosf(angle), std::sin(angle));
     328            1 : }
     329              : 
     330            1 : void matrix3::rotate_around_y(const vec2 &sc)
     331              : {
     332            1 :     rotate_around_y(sc.x, sc.y);
     333            1 : }
     334              : 
     335            3 : void matrix3::rotate_around_z(float ck, float sk)
     336              : {
     337            3 :     vec ra = vec(a).mul(ck).madd(b, sk),
     338            3 :         rb = vec(b).mul(ck).msub(a, sk);
     339            3 :     a = ra;
     340            3 :     b = rb;
     341            3 : }
     342              : 
     343            1 : void matrix3::rotate_around_z(float angle)
     344              : {
     345            1 :     rotate_around_z(cosf(angle), std::sin(angle));
     346            1 : }
     347              : 
     348            2 : void matrix3::rotate_around_z(const vec2 &sc)
     349              : {
     350            2 :     rotate_around_z(sc.x, sc.y);
     351            2 : }
     352              : 
     353            3 : vec matrix3::transform(const vec2 &o) const
     354              : {
     355            3 :     return vec(a).mul(o.x).madd(b, o.y);
     356              : }
     357              : 
     358            3 : vec matrix3::transposedtransform(const vec2 &o) const
     359              : {
     360            3 :     return vec(a.dot2(o), b.dot2(o), c.dot2(o));
     361              : }
     362              : 
     363            1 : vec matrix3::rowx() const
     364              : {
     365            1 :     return vec(a.x, b.x, c.x);
     366              : }
     367              : 
     368            1 : vec matrix3::rowy() const
     369              : {
     370            1 :     return vec(a.y, b.y, c.y);
     371              : }
     372              : 
     373            1 : vec matrix3::rowz() const
     374              : {
     375            1 :     return vec(a.z, b.z, c.z);
     376              : }
     377              : 
     378              : // =============================================================================
     379              : //  matrix4 (4x4) object
     380              : // =============================================================================
     381              : 
     382              : /**
     383              :  * @brief Sets the matrix to its inverse
     384              :  *
     385              :  * sets the matrix values to the inverse of the provided matrix A*A^-1 = I
     386              :  * returns false if singular (or nearly singular to within tolerance of mindet)
     387              :  * or true if matrix was inverted successfully
     388              :  *
     389              :  * @param m a matrix4 object to be inverted and assigned to the object
     390              :  * @param mindet the minimum value at which matrices are considered
     391              :  *
     392              :  * @return true if the matrix was invertable
     393              :  */
     394            4 : bool matrix4::invert(const matrix4 &m, double mindet)
     395              : {
     396            4 :     double a1 = m.a.x, a2 = m.a.y, a3 = m.a.z, a4 = m.a.w,
     397            4 :            b1 = m.b.x, b2 = m.b.y, b3 = m.b.z, b4 = m.b.w,
     398            4 :            c1 = m.c.x, c2 = m.c.y, c3 = m.c.z, c4 = m.c.w,
     399            4 :            d1 = m.d.x, d2 = m.d.y, d3 = m.d.z, d4 = m.d.w,
     400            4 :            det1 =  det3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4),
     401            4 :            det2 = -det3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4),
     402            4 :            det3 =  det3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4),
     403            4 :            det4 = -det3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4),
     404            4 :            det = a1*det1 + b1*det2 + c1*det3 + d1*det4;
     405              : 
     406            4 :     if(std::fabs(det) < mindet)
     407              :     {
     408            2 :         return false;
     409              :     }
     410              : 
     411            2 :     double invdet = 1/det;
     412              : 
     413            2 :     a.x = det1 * invdet;
     414            2 :     a.y = det2 * invdet;
     415            2 :     a.z = det3 * invdet;
     416            2 :     a.w = det4 * invdet;
     417              : 
     418            2 :     b.x = -det3x3(b1, b3, b4, c1, c3, c4, d1, d3, d4) * invdet;
     419            2 :     b.y =  det3x3(a1, a3, a4, c1, c3, c4, d1, d3, d4) * invdet;
     420            2 :     b.z = -det3x3(a1, a3, a4, b1, b3, b4, d1, d3, d4) * invdet;
     421            2 :     b.w =  det3x3(a1, a3, a4, b1, b3, b4, c1, c3, c4) * invdet;
     422              : 
     423            2 :     c.x =  det3x3(b1, b2, b4, c1, c2, c4, d1, d2, d4) * invdet;
     424            2 :     c.y = -det3x3(a1, a2, a4, c1, c2, c4, d1, d2, d4) * invdet;
     425            2 :     c.z =  det3x3(a1, a2, a4, b1, b2, b4, d1, d2, d4) * invdet;
     426            2 :     c.w = -det3x3(a1, a2, a4, b1, b2, b4, c1, c2, c4) * invdet;
     427              : 
     428            2 :     d.x = -det3x3(b1, b2, b3, c1, c2, c3, d1, d2, d3) * invdet;
     429            2 :     d.y =  det3x3(a1, a2, a3, c1, c2, c3, d1, d2, d3) * invdet;
     430            2 :     d.z = -det3x3(a1, a2, a3, b1, b2, b3, d1, d2, d3) * invdet;
     431            2 :     d.w =  det3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3) * invdet;
     432              : 
     433            2 :     return true;
     434              : }
     435              : 
     436            2 : matrix4 matrix4::inverse(double mindet) const
     437              : {
     438            2 :     matrix4 ret;
     439            2 :     if(ret.invert(*this, mindet))
     440              :     {
     441            1 :         return ret;
     442              :     }
     443              :     else
     444              :     {
     445            1 :         return { vec4<float>(0,0,0,0), vec4<float>(0,0,0,0), vec4<float>(0,0,0,0), vec4<float>(0,0,0,0) };
     446              :     }
     447              : }
     448              : 
     449          140 : matrix4::matrix4() : a(0,0,0,0), b(0,0,0,0), c(0,0,0,0), d(0,0,0,0)
     450              : {
     451          140 : }
     452              : 
     453            1 : matrix4::matrix4(const float *m) : a(m), b(m+4), c(m+8), d(m+12)
     454              : {
     455            1 : }
     456              : 
     457            8 : matrix4::matrix4(const vec &a, const vec &b, const vec &c)
     458            8 :     : a(a.x, b.x, c.x, 0), b(a.y, b.y, c.y, 0), c(a.z, b.z, c.z, 0), d(0, 0, 0, 1)
     459              : {
     460            8 : }
     461              : 
     462           31 : matrix4::matrix4(const vec4<float> &a, const vec4<float> &b, const vec4<float> &c, const vec4<float> &d)
     463           31 :     : a(a), b(b), c(c), d(d)
     464              : {
     465           31 : }
     466              : 
     467            1 : matrix4::matrix4(const matrix4x3 &m)
     468            1 :     : a(m.a, 0), b(m.b, 0), c(m.c, 0), d(m.d, 1)
     469              : {
     470            1 : }
     471              : 
     472            1 : matrix4::matrix4(const matrix3 &rot, const vec &trans)
     473            1 :     : a(rot.a, 0), b(rot.b, 0), c(rot.c, 0), d(trans, 1)
     474              : {
     475            1 : }
     476              : 
     477            0 : void matrix4::transposedtransform(const plane &in, plane &out) const
     478              : {
     479            0 :     out.x = in.dist(a);
     480            0 :     out.y = in.dist(b);
     481            0 :     out.z = in.dist(c);
     482            0 :     out.offset = in.dist(d);
     483            0 : }
     484              : 
     485            9 : void matrix4::mul(const matrix4 &x, const matrix3 &y)
     486              : {
     487            9 :     a = vec4<float>(x.a).mul(y.a.x).madd(x.b, y.a.y).madd(x.c, y.a.z);
     488            9 :     b = vec4<float>(x.a).mul(y.b.x).madd(x.b, y.b.y).madd(x.c, y.b.z);
     489            9 :     c = vec4<float>(x.a).mul(y.c.x).madd(x.b, y.c.y).madd(x.c, y.c.z);
     490            9 :     d = x.d;
     491            9 : }
     492              : 
     493            9 : void matrix4::mul(const matrix3 &y)
     494              : {
     495            9 :     mul(matrix4(*this), y);
     496            9 : }
     497              : 
     498            1 : void matrix4::mul(const matrix4 &x, const matrix4 &y)
     499              : {
     500            1 :     mult<vec4<float>>(x, y);
     501            1 : }
     502              : 
     503            1 : void matrix4::mul(const matrix4 &y)
     504              : {
     505            1 :     mult<vec4<float>>(matrix4(*this), y);
     506            1 : }
     507              : 
     508            1 : void matrix4::muld(const matrix4 &x, const matrix4 &y)
     509              : {
     510            1 :     mult<vec4<double>>(x, y);
     511            1 : }
     512              : 
     513            1 : void matrix4::muld(const matrix4 &y)
     514              : {
     515            1 :     mult<vec4<double>>(matrix4(*this), y);
     516            1 : }
     517              : 
     518            2 : void matrix4::rotate_around_x(float ck, float sk)
     519              : {
     520            2 :     vec4<float> rb = vec4<float>(b).mul(ck).madd(c, sk),
     521            2 :                 rc = vec4<float>(c).mul(ck).msub(b, sk);
     522            2 :     b = rb;
     523            2 :     c = rc;
     524            2 : }
     525              : 
     526            1 : void matrix4::rotate_around_x(float angle)
     527              : {
     528            1 :     rotate_around_x(cosf(angle), std::sin(angle));
     529            1 : }
     530              : 
     531            1 : void matrix4::rotate_around_x(const vec2 &sc)
     532              : {
     533            1 :     rotate_around_x(sc.x, sc.y);
     534            1 : }
     535              : 
     536            2 : void matrix4::rotate_around_y(float ck, float sk)
     537              : {
     538            2 :     vec4<float> rc = vec4<float>(c).mul(ck).madd(a, sk),
     539            2 :                 ra = vec4<float>(a).mul(ck).msub(c, sk);
     540            2 :     c = rc;
     541            2 :     a = ra;
     542            2 : }
     543              : 
     544            1 : void matrix4::rotate_around_y(float angle)
     545              : {
     546            1 :     rotate_around_y(cosf(angle), std::sin(angle));
     547            1 : }
     548              : 
     549            1 : void matrix4::rotate_around_y(const vec2 &sc)
     550              : {
     551            1 :     rotate_around_y(sc.x, sc.y);
     552            1 : }
     553              : 
     554            2 : void matrix4::rotate_around_z(float ck, float sk)
     555              : {
     556            2 :     vec4<float> ra = vec4<float>(a).mul(ck).madd(b, sk),
     557            2 :                 rb = vec4<float>(b).mul(ck).msub(a, sk);
     558            2 :     a = ra;
     559            2 :     b = rb;
     560            2 : }
     561              : 
     562            1 : void matrix4::rotate_around_z(float angle)
     563              : {
     564            1 :     rotate_around_z(cosf(angle), std::sin(angle));
     565            1 : }
     566              : 
     567            1 : void matrix4::rotate_around_z(const vec2 &sc)
     568              : {
     569            1 :     rotate_around_z(sc.x, sc.y);
     570            1 : }
     571              : 
     572            9 : void matrix4::rotate(float ck, float sk, const vec &axis)
     573              : {
     574            9 :     matrix3 m;
     575            9 :     m.rotate(ck, sk, axis);
     576            9 :     mul(m);
     577            9 : }
     578              : 
     579            3 : void matrix4::rotate(float angle, const vec &dir)
     580              : {
     581            3 :     rotate(cosf(angle), std::sin(angle), dir);
     582            3 : }
     583              : 
     584            3 : void matrix4::rotate(const vec2 &sc, const vec &dir)
     585              : {
     586            3 :     rotate(sc.x, sc.y, dir);
     587            3 : }
     588              : 
     589           36 : void matrix4::identity()
     590              : {
     591           36 :     a = vec4<float>(1, 0, 0, 0);
     592           36 :     b = vec4<float>(0, 1, 0, 0);
     593           36 :     c = vec4<float>(0, 0, 1, 0);
     594           36 :     d = vec4<float>(0, 0, 0, 1);
     595           36 : }
     596              : 
     597            1 : void matrix4::settranslation(const vec &v)
     598              : {
     599            1 :     d.setxyz(v);
     600            1 : }
     601              : 
     602            1 : void matrix4::settranslation(float x, float y, float z)
     603              : {
     604            1 :     d.x = x;
     605            1 :     d.y = y;
     606            1 :     d.z = z;
     607            1 : }
     608              : 
     609            0 : void matrix4::translate(const vec &p)
     610              : {
     611            0 :     d.madd(a, p.x).madd(b, p.y).madd(c, p.z);
     612            0 : }
     613              : 
     614            0 : void matrix4::translate(float x, float y, float z)
     615              : {
     616            0 :     translate(vec(x, y, z));
     617            0 : }
     618              : 
     619            0 : void matrix4::translate(const vec &p, float scale)
     620              : {
     621            0 :     translate(vec(p).mul(scale));
     622            0 : }
     623              : 
     624            3 : void matrix4::setscale(float x, float y, float z)
     625              : {
     626            3 :     a.x = x;
     627            3 :     b.y = y;
     628            3 :     c.z = z;
     629            3 : }
     630              : 
     631            1 : void matrix4::setscale(const vec &v)
     632              : {
     633            1 :     setscale(v.x, v.y, v.z);
     634            1 : }
     635              : 
     636            1 : void matrix4::setscale(float n)
     637              : {
     638            1 :     setscale(n, n, n);
     639            1 : }
     640              : 
     641            3 : void matrix4::scale(float x, float y, float z)
     642              : {
     643            3 :     a.mul(x);
     644            3 :     b.mul(y);
     645            3 :     c.mul(z);
     646            3 : }
     647              : 
     648            1 : void matrix4::scale(const vec &v)
     649              : {
     650            1 :     scale(v.x, v.y, v.z);
     651            1 : }
     652              : 
     653            1 : void matrix4::scale(float n)
     654              : {
     655            1 :     scale(n, n, n);
     656            1 : }
     657              : 
     658            2 : void matrix4::scalez(float k)
     659              : {
     660            2 :     a.z *= k;
     661            2 :     b.z *= k;
     662            2 :     c.z *= k;
     663            2 :     d.z *= k;
     664            2 : }
     665              : 
     666            2 : void matrix4::jitter(float x, float y)
     667              : {
     668            2 :     a.x += x * a.w;
     669            2 :     a.y += y * a.w;
     670            2 :     b.x += x * b.w;
     671            2 :     b.y += y * b.w;
     672            2 :     c.x += x * c.w;
     673            2 :     c.y += y * c.w;
     674            2 :     d.x += x * d.w;
     675            2 :     d.y += y * d.w;
     676            2 : }
     677              : 
     678            1 : void matrix4::transpose()
     679              : {
     680              :     //swap upper triangular elements of row 'a'
     681            1 :     std::swap(a.y, b.x);
     682            1 :     std::swap(a.z, c.x);
     683            1 :     std::swap(a.w, d.x);
     684              :     //swap upper triangular elements of row 'b'
     685            1 :     std::swap(b.z, c.y);
     686            1 :     std::swap(b.w, d.y);
     687              :     //swap upper triangular element of row 'c'
     688            1 :     std::swap(c.w, d.z);
     689              :     //no upper triangular elements on row 'd'
     690            1 : }
     691              : 
     692            1 : void matrix4::transpose(const matrix4 &m)
     693              : {
     694            1 :     a = vec4<float>(m.a.x, m.b.x, m.c.x, m.d.x);
     695            1 :     b = vec4<float>(m.a.y, m.b.y, m.c.y, m.d.y);
     696            1 :     c = vec4<float>(m.a.z, m.b.z, m.c.z, m.d.z);
     697            1 :     d = vec4<float>(m.a.w, m.b.w, m.c.w, m.d.w);
     698            1 : }
     699              : 
     700            2 : void matrix4::frustum(float left, float right, float bottom, float top, float znear, float zfar)
     701              : {
     702            2 :     float width = right - left,
     703            2 :           height = top - bottom,
     704            2 :           zrange = znear - zfar;
     705            2 :     a = vec4<float>(2*znear/width, 0, 0, 0); //depth to width ratio
     706            2 :     b = vec4<float>(0, 2*znear/height, 0, 0); //depth to height ratio
     707            2 :     c = vec4<float>((right + left)/width, (top + bottom)/height, (zfar + znear)/zrange, -1); //offset from centered
     708            2 :     d = vec4<float>(0, 0, 2*znear*zfar/zrange, 0); //depth scale
     709            2 : }
     710              : 
     711            1 : void matrix4::perspective(float fovy, float aspect, float znear, float zfar)
     712              : {
     713            1 :     float ydist = znear * std::tan(fovy/(2*RAD)),
     714            1 :           xdist = ydist * aspect;
     715            1 :     frustum(-xdist, xdist, -ydist, ydist, znear, zfar);
     716            1 : }
     717              : 
     718            3 : void matrix4::ortho(float left, float right, float bottom, float top, float znear, float zfar)
     719              : {
     720            3 :     float width = right - left,
     721            3 :           height = top - bottom,
     722            3 :           zrange = znear - zfar;
     723            3 :     a = vec4<float>(2/width, 0, 0, 0);
     724            3 :     b = vec4<float>(0, 2/height, 0, 0);
     725            3 :     c = vec4<float>(0, 0, 2/zrange, 0);
     726            3 :     d = vec4<float>(-(right+left)/width, -(top+bottom)/height, (zfar+znear)/zrange, 1);
     727            3 : }
     728              : 
     729            1 : void matrix4::transform(const vec &in, vec &out) const
     730              : {
     731            1 :     out = vec(a).mul(in.x).add(vec(b).mul(in.y)).add(vec(c).mul(in.z)).add(vec(d));
     732            1 : }
     733              : 
     734            1 : void matrix4::transform(const vec4<float> &in, vec &out) const
     735              : {
     736            1 :     out = vec(a).mul(in.x).add(vec(b).mul(in.y)).add(vec(c).mul(in.z)).add(vec(d).mul(in.w));
     737            1 : }
     738              : 
     739            1 : void matrix4::transform(const vec &in, vec4<float> &out) const
     740              : {
     741            1 :     out = vec4<float>(a).mul(in.x).madd(b, in.y).madd(c, in.z).add(d);
     742            1 : }
     743              : 
     744            1 : void matrix4::transform(const vec4<float> &in, vec4<float> &out) const
     745              : {
     746            1 :     out = vec4<float>(a).mul(in.x).madd(b, in.y).madd(c, in.z).madd(d, in.w);
     747            1 : }
     748              : 
     749            4 : void matrix4::transformnormal(const vec &in, vec &out) const
     750              : {
     751            4 :     out = vec(a).mul(in.x).add(vec(b).mul(in.y)).add(vec(c).mul(in.z));
     752            4 : }
     753              : 
     754            3 : void matrix4::transformnormal(const vec &in, vec4<float> &out) const
     755              : {
     756            3 :     out = vec4<float>(a).mul(in.x).madd(b, in.y).madd(c, in.z);
     757            3 : }
     758              : 
     759            3 : void matrix4::transposedtransform(const vec &in, vec &out) const
     760              : {
     761            3 :     vec p = vec(in).sub(vec(d));
     762            3 :     out.x = a.dot3(p);
     763            3 :     out.y = b.dot3(p);
     764            3 :     out.z = c.dot3(p);
     765            3 : }
     766              : 
     767            3 : void matrix4::transposedtransformnormal(const vec &in, vec &out) const
     768              : {
     769            3 :     out.x = a.dot3(in);
     770            3 :     out.y = b.dot3(in);
     771            3 :     out.z = c.dot3(in);
     772            3 : }
     773              : 
     774            1 : vec matrix4::gettranslation() const
     775              : {
     776            1 :     return vec(d);
     777              : }
     778              : 
     779            2 : vec4<float> matrix4::rowx() const
     780              : {
     781            2 :     return vec4<float>(a.x, b.x, c.x, d.x);
     782              : }
     783              : 
     784            2 : vec4<float> matrix4::rowy() const
     785              : {
     786            2 :     return vec4<float>(a.y, b.y, c.y, d.y);
     787              : }
     788              : 
     789            2 : vec4<float> matrix4::rowz() const
     790              : {
     791            2 :     return vec4<float>(a.z, b.z, c.z, d.z);
     792              : }
     793              : 
     794            2 : vec4<float> matrix4::roww() const
     795              : {
     796            2 :     return vec4<float>(a.w, b.w, c.w, d.w);
     797              : }
     798              : 
     799            3 : vec2 matrix4::lineardepthscale() const
     800              : {
     801            3 :     return vec2(d.w, -d.z).div(c.z*d.w - d.z*c.w);
     802              : }
     803              : 
     804              : // =============================================================================
     805              : //  matrix4x3 object
     806              : // =============================================================================
     807              : 
     808           67 : matrix4x3::matrix4x3() : a(0,0,0), b(0,0,0), c(0,0,0), d(0,0,0)
     809              : {
     810           67 : }
     811              : 
     812           34 : matrix4x3::matrix4x3(const vec &a, const vec &b, const vec &c, const vec &d) : a(a), b(b), c(c), d(d)
     813              : {
     814           34 : }
     815              : 
     816            9 : matrix4x3::matrix4x3(const matrix3 &rot, const vec &trans) : a(rot.a), b(rot.b), c(rot.c), d(trans)
     817              : {
     818            9 : }
     819              : 
     820            2 : matrix4x3::matrix4x3(const dualquat &dq)
     821              : {
     822            2 :     vec4<float> r = vec4<float>(dq.real).mul(1/dq.real.squaredlen()), rr = vec4<float>(r).mul(dq.real);
     823            2 :     r.mul(2);
     824            2 :     float xy = r.x*dq.real.y, xz = r.x*dq.real.z, yz = r.y*dq.real.z,
     825            2 :           wx = r.w*dq.real.x, wy = r.w*dq.real.y, wz = r.w*dq.real.z;
     826            2 :     a = vec(rr.w + rr.x - rr.y - rr.z, xy + wz, xz - wy);
     827            2 :     b = vec(xy - wz, rr.w + rr.y - rr.x - rr.z, yz + wx);
     828            2 :     c = vec(xz + wy, yz - wx, rr.w + rr.z - rr.x - rr.y);
     829            4 :     d = vec(-(dq.dual.w*r.x - dq.dual.x*r.w + dq.dual.y*r.z - dq.dual.z*r.y),
     830            2 :             -(dq.dual.w*r.y - dq.dual.x*r.z - dq.dual.y*r.w + dq.dual.z*r.x),
     831            2 :             -(dq.dual.w*r.z + dq.dual.x*r.y - dq.dual.y*r.x - dq.dual.z*r.w));
     832            2 : }
     833              : 
     834            4 : void matrix4x3::mul(float k)
     835              : {
     836            4 :     a.mul(k);
     837            4 :     b.mul(k);
     838            4 :     c.mul(k);
     839            4 :     d.mul(k);
     840            4 : }
     841              : 
     842            3 : void matrix4x3::setscale(float x, float y, float z)
     843              : {
     844            3 :     a.x = x;
     845            3 :     b.y = y;
     846            3 :     c.z = z;
     847            3 : }
     848              : 
     849            1 : void matrix4x3::setscale(const vec &v)
     850              : {
     851            1 :     setscale(v.x, v.y, v.z);
     852            1 : }
     853              : 
     854            1 : void matrix4x3::setscale(float n)
     855              : {
     856            1 :     setscale(n, n, n);
     857            1 : }
     858              : 
     859            3 : void matrix4x3::scale(float x, float y, float z)
     860              : {
     861            3 :     a.mul(x);
     862            3 :     b.mul(y);
     863            3 :     c.mul(z);
     864            3 : }
     865              : 
     866            1 : void matrix4x3::scale(const vec &v)
     867              : {
     868            1 :     scale(v.x, v.y, v.z);
     869            1 : }
     870              : 
     871            1 : void matrix4x3::scale(float n)
     872              : {
     873            1 :     scale(n, n, n);
     874            1 : }
     875              : 
     876            1 : void matrix4x3::settranslation(const vec &p)
     877              : {
     878            1 :     d = p;
     879            1 : }
     880              : 
     881            1 : void matrix4x3::settranslation(float x, float y, float z)
     882              : {
     883            1 :     d = vec(x, y, z);
     884            1 : }
     885              : 
     886            4 : void matrix4x3::translate(const vec &p)
     887              : {
     888            4 :     d.madd(a, p.x).madd(b, p.y).madd(c, p.z);
     889            4 : }
     890              : 
     891            1 : void matrix4x3::translate(float x, float y, float z)
     892              : {
     893            1 :     translate(vec(x, y, z));
     894            1 : }
     895              : 
     896            3 : void matrix4x3::translate(const vec &p, float scale)
     897              : {
     898            3 :     translate(vec(p).mul(scale));
     899            3 : }
     900              : 
     901            1 : void matrix4x3::accumulate(const matrix4x3 &m, float k)
     902              : {
     903            1 :     a.madd(m.a, k);
     904            1 :     b.madd(m.b, k);
     905            1 :     c.madd(m.c, k);
     906            1 :     d.madd(m.d, k);
     907            1 : }
     908              : 
     909            4 : void matrix4x3::normalize()
     910              : {
     911            4 :     a.normalize();
     912            4 :     b.normalize();
     913            4 :     c.normalize();
     914            4 : }
     915              : 
     916            1 : void matrix4x3::lerp(const matrix4x3 &to, float t)
     917              : {
     918            1 :     a.lerp(to.a, t);
     919            1 :     b.lerp(to.b, t);
     920            1 :     c.lerp(to.c, t);
     921            1 :     d.lerp(to.d, t);
     922            1 : }
     923            1 : void matrix4x3::lerp(const matrix4x3 &from, const matrix4x3 &to, float t)
     924              : {
     925            1 :     a.lerp(from.a, to.a, t);
     926            1 :     b.lerp(from.b, to.b, t);
     927            1 :     c.lerp(from.c, to.c, t);
     928            1 :     d.lerp(from.d, to.d, t);
     929            1 : }
     930              : 
     931           47 : void matrix4x3::identity()
     932              : {
     933           47 :     a = vec(1, 0, 0);
     934           47 :     b = vec(0, 1, 0);
     935           47 :     c = vec(0, 0, 1);
     936           47 :     d = vec(0, 0, 0);
     937           47 : }
     938              : 
     939            2 : void matrix4x3::mul(const matrix4x3 &m, const matrix4x3 &n)
     940              : {
     941            2 :     a = vec(m.a).mul(n.a.x).madd(m.b, n.a.y).madd(m.c, n.a.z);
     942            2 :     b = vec(m.a).mul(n.b.x).madd(m.b, n.b.y).madd(m.c, n.b.z);
     943            2 :     c = vec(m.a).mul(n.c.x).madd(m.b, n.c.y).madd(m.c, n.c.z);
     944            2 :     d = vec(m.d).madd(m.a, n.d.x).madd(m.b, n.d.y).madd(m.c, n.d.z);
     945            2 : }
     946              : 
     947            1 : void matrix4x3::mul(const matrix4x3 &n)
     948              : {
     949            1 :     mul(matrix4x3(*this), n);
     950            1 : }
     951              : 
     952            1 : void matrix4x3::mul(const matrix3 &m, const matrix4x3 &n)
     953              : {
     954            1 :     a = vec(m.a).mul(n.a.x).madd(m.b, n.a.y).madd(m.c, n.a.z);
     955            1 :     b = vec(m.a).mul(n.b.x).madd(m.b, n.b.y).madd(m.c, n.b.z);
     956            1 :     c = vec(m.a).mul(n.c.x).madd(m.b, n.c.y).madd(m.c, n.c.z);
     957            1 :     d = vec(m.a).mul(n.d.x).madd(m.b, n.d.y).madd(m.c, n.d.z);
     958            1 : }
     959              : 
     960            1 : void matrix4x3::mul(const matrix3 &rot, const vec &trans, const matrix4x3 &n)
     961              : {
     962            1 :     mul(rot, n);
     963            1 :     d.add(trans);
     964            1 : }
     965              : 
     966            3 : void matrix4x3::transpose()
     967              : {
     968            3 :     d = vec(a.dot(d), b.dot(d), c.dot(d)).neg();
     969            3 :     std::swap(a.y, b.x);
     970            3 :     std::swap(a.z, c.x);
     971            3 :     std::swap(b.z, c.y);
     972            3 : }
     973              : 
     974            8 : void matrix4x3::transpose(const matrix4x3 &o)
     975              : {
     976            8 :     a = vec(o.a.x, o.b.x, o.c.x);
     977            8 :     b = vec(o.a.y, o.b.y, o.c.y);
     978            8 :     c = vec(o.a.z, o.b.z, o.c.z);
     979            8 :     d = vec(o.a.dot(o.d), o.b.dot(o.d), o.c.dot(o.d)).neg();
     980            8 : }
     981              : 
     982            2 : void matrix4x3::transposemul(const matrix4x3 &m, const matrix4x3 &n)
     983              : {
     984            2 :     vec t(m.a.dot(m.d), m.b.dot(m.d), m.c.dot(m.d));
     985            2 :     a = vec(m.a.dot(n.a), m.b.dot(n.a), m.c.dot(n.a));
     986            2 :     b = vec(m.a.dot(n.b), m.b.dot(n.b), m.c.dot(n.b));
     987            2 :     c = vec(m.a.dot(n.c), m.b.dot(n.c), m.c.dot(n.c));
     988            2 :     d = vec(m.a.dot(n.d), m.b.dot(n.d), m.c.dot(n.d)).sub(t);
     989            2 : }
     990              : 
     991            1 : void matrix4x3::multranspose(const matrix4x3 &m, const matrix4x3 &n)
     992              : {
     993            1 :     vec t(n.a.dot(n.d), n.b.dot(n.d), n.c.dot(n.d));
     994            1 :     a = vec(m.a).mul(n.a.x).madd(m.b, n.b.x).madd(m.c, n.c.x);
     995            1 :     b = vec(m.a).mul(n.a.y).madd(m.b, m.b.y).madd(m.c, n.c.y);
     996            1 :     c = vec(m.a).mul(n.a.z).madd(m.b, n.b.z).madd(m.c, n.c.z);
     997            1 :     d = vec(m.d).msub(m.a, t.x).msub(m.b, t.y).msub(m.c, t.z);
     998            1 : }
     999              : 
    1000            8 : void matrix4x3::invert(const matrix4x3 &o)
    1001              : {
    1002            8 :     vec unscale(1/o.a.squaredlen(), 1/o.b.squaredlen(), 1/o.c.squaredlen());
    1003            8 :     transpose(o);
    1004            8 :     a.mul(unscale);
    1005            8 :     b.mul(unscale);
    1006            8 :     c.mul(unscale);
    1007            8 :     d.mul(unscale);
    1008            8 : }
    1009              : 
    1010            6 : void matrix4x3::invert()
    1011              : {
    1012            6 :     invert(matrix4x3(*this));
    1013            6 : }
    1014              : 
    1015            3 : void matrix4x3::rotate(float angle, const vec &d)
    1016              : {
    1017            3 :     rotate(cosf(angle), std::sin(angle), d);
    1018            3 : }
    1019              : 
    1020            6 : void matrix4x3::rotate(float ck, float sk, const vec &axis)
    1021              : {
    1022            6 :     matrix3 m;
    1023            6 :     m.rotate(ck, sk, axis);
    1024            6 :     *this = matrix4x3(m, vec(0, 0, 0));
    1025            6 : }
    1026              : 
    1027            2 : void matrix4x3::rotate_around_x(float ck, float sk)
    1028              : {
    1029            2 :     vec rb = vec(b).mul(ck).madd(c, sk),
    1030            2 :         rc = vec(c).mul(ck).msub(b, sk);
    1031            2 :     b = rb;
    1032            2 :     c = rc;
    1033            2 : }
    1034            1 : void matrix4x3::rotate_around_x(float angle)
    1035              : {
    1036            1 :     rotate_around_x(cosf(angle), std::sin(angle));
    1037            1 : }
    1038              : 
    1039            1 : void matrix4x3::rotate_around_x(const vec2 &sc)
    1040              : {
    1041            1 :     rotate_around_x(sc.x, sc.y);
    1042            1 : }
    1043              : 
    1044            2 : void matrix4x3::rotate_around_y(float ck, float sk)
    1045              : {
    1046            2 :     vec rc = vec(c).mul(ck).madd(a, sk),
    1047            2 :         ra = vec(a).mul(ck).msub(c, sk);
    1048            2 :     c = rc;
    1049            2 :     a = ra;
    1050            2 : }
    1051            1 : void matrix4x3::rotate_around_y(float angle)
    1052              : {
    1053            1 :     rotate_around_y(cosf(angle), std::sin(angle));
    1054            1 : }
    1055              : 
    1056            1 : void matrix4x3::rotate_around_y(const vec2 &sc)
    1057              : {
    1058            1 :     rotate_around_y(sc.x, sc.y);
    1059            1 : }
    1060              : 
    1061            2 : void matrix4x3::rotate_around_z(float ck, float sk)
    1062              : {
    1063            2 :     vec ra = vec(a).mul(ck).madd(b, sk),
    1064            2 :         rb = vec(b).mul(ck).msub(a, sk);
    1065            2 :     a = ra;
    1066            2 :     b = rb;
    1067            2 : }
    1068              : 
    1069            1 : void matrix4x3::rotate_around_z(float angle)
    1070              : {
    1071            1 :     rotate_around_z(cosf(angle), std::sin(angle));
    1072            1 : }
    1073              : 
    1074            1 : void matrix4x3::rotate_around_z(const vec2 &sc)
    1075              : {
    1076            1 :     rotate_around_z(sc.x, sc.y);
    1077            1 : }
    1078              : 
    1079            3 : vec matrix4x3::transposedtransform(const vec &o) const
    1080              : {
    1081            3 :     vec p = vec(o).sub(d);
    1082            3 :     return vec(a.dot(p), b.dot(p), c.dot(p));
    1083              : }
    1084              : 
    1085            3 : vec matrix4x3::transformnormal(const vec &o) const
    1086              : {
    1087            3 :     return vec(a).mul(o.x).madd(b, o.y).madd(c, o.z);
    1088              : }
    1089              : 
    1090            3 : vec matrix4x3::transposedtransformnormal(const vec &o) const
    1091              : {
    1092            3 :     return vec(a.dot(o), b.dot(o), c.dot(o));
    1093              : }
    1094              : 
    1095           12 : vec matrix4x3::transform(const vec &o) const
    1096              : {
    1097           12 :     return vec(d).madd(a, o.x).madd(b, o.y).madd(c, o.z);
    1098              : }
    1099              : 
    1100            3 : vec matrix4x3::transform(const vec2 &o) const
    1101              : {
    1102            3 :     return vec(d).madd(a, o.x).madd(b, o.y);
    1103              : }
    1104              : 
    1105            1 : vec4<float> matrix4x3::rowx() const
    1106              : {
    1107            1 :     return vec4<float>(a.x, b.x, c.x, d.x);
    1108              : }
    1109              : 
    1110            1 : vec4<float> matrix4x3::rowy() const
    1111              : {
    1112            1 :     return vec4<float>(a.y, b.y, c.y, d.y);
    1113              : }
    1114              : 
    1115            1 : vec4<float> matrix4x3::rowz() const
    1116              : {
    1117            1 :     return vec4<float>(a.z, b.z, c.z, d.z);
    1118              : }
    1119              : 
    1120              : //end matrix4x3
        

Generated by: LCOV version 2.0-1