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

Generated by: LCOV version 2.0-1