LCOV - code coverage report
Current view: top level - shared - matrix.cpp (source / functions) Hit Total Coverage
Test: Libprimis Test Coverage Lines: 605 663 91.3 %
Date: 2024-11-22 05:07:59 Functions: 144 154 93.5 %

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

Generated by: LCOV version 1.14