00001 #include "matrix4.h"
00002
00007 #include <cmath>
00008 #include <cassert>
00009 #include <string>
00010 #include <iostream>
00011 #include <iomanip>
00012 using namespace std;
00013
00014 #include <glt/gl.h>
00015
00016 #include <misc/string.h>
00017 #include <math/umatrix.h>
00018
00019 double Matrix::_identity[16] =
00020 {
00021 1.0, 0.0, 0.0, 0.0,
00022 0.0, 1.0, 0.0, 0.0,
00023 0.0, 0.0, 1.0, 0.0,
00024 0.0, 0.0, 0.0, 1.0
00025 };
00026
00027 Matrix::Matrix()
00028 {
00029 reset();
00030 }
00031
00032 Matrix::Matrix(const Matrix &matrix)
00033 {
00034 (*this) = matrix;
00035 }
00036
00037 Matrix::Matrix(const float *matrix)
00038 {
00039 real *i = _matrix;
00040 const float *j = matrix;
00041 for (int k=0; k<16; i++,j++,k++)
00042 *i = *j;
00043 }
00044
00045 Matrix::Matrix(const double *matrix)
00046 {
00047 real *i = _matrix;
00048 const double *j = matrix;
00049 for (int k=0; k<16; i++,j++,k++)
00050 *i = *j;
00051 }
00052
00053 Matrix::Matrix(const unsigned int glMatrix)
00054 {
00055 switch (glMatrix)
00056 {
00057 case GL_MODELVIEW_MATRIX:
00058 glGetDoublev(GL_MODELVIEW_MATRIX,_matrix);
00059 break;
00060 case GL_PROJECTION_MATRIX:
00061 glGetDoublev(GL_PROJECTION_MATRIX,_matrix);
00062 break;
00063 default:
00064 break;
00065 }
00066 }
00067
00068 Matrix::Matrix(const string &str)
00069 {
00070 #ifndef NDEBUG
00071 const int n =
00072 #endif
00073 atoc(str,atof,"+-eE.0123456789",_matrix+0,_matrix+16);
00074
00075 assert(n==16);
00076 }
00077
00078 Matrix &
00079 Matrix::operator=(const Matrix &m)
00080 {
00081 memcpy(_matrix,m._matrix,sizeof(_matrix));
00082
00083 return *this;
00084 }
00085
00086 Matrix
00087 Matrix::operator *(const Matrix &m) const
00088 {
00089 Matrix prod;
00090
00091 for (int c=0;c<4;c++)
00092 for (int r=0;r<4;r++)
00093 prod.set(c,r,
00094 get(c,0)*m.get(0,r) +
00095 get(c,1)*m.get(1,r) +
00096 get(c,2)*m.get(2,r) +
00097 get(c,3)*m.get(3,r));
00098
00099 return prod;
00100 }
00101
00102 Matrix &
00103 Matrix::operator*=(const Matrix &m)
00104 {
00105
00106
00107
00108 return (*this) = (*this)*m;
00109 }
00110
00111 Vector
00112 Matrix::operator*(const Vector &v) const
00113 {
00114 double prod[4] = { 0,0,0,0 };
00115
00116 for (int r=0;r<4;r++)
00117 {
00118 for (int c=0;c<3;c++)
00119 prod[r] += v[c]*get(c,r);
00120
00121 prod[r] += get(3,r);
00122 }
00123
00124 double div = 1.0 / prod[3];
00125
00126 return Vector(prod[0]*div,prod[1]*div,prod[2]*div);
00127 }
00128
00129 void
00130 Matrix::reset()
00131 {
00132 memcpy(_matrix,_identity,16*sizeof(double));
00133 }
00134
00135 void
00136 Matrix::identity()
00137 {
00138 reset();
00139 }
00140
00141 bool
00142 Matrix::isIdentity() const
00143 {
00144 return !memcmp(_matrix,_identity,sizeof(_matrix));
00145 }
00146
00147 const double &
00148 Matrix::operator[](const int i) const
00149 {
00150 assert(i>=0 && i<16);
00151 return _matrix[i];
00152 }
00153
00154 double &
00155 Matrix::operator[](const int i)
00156 {
00157 assert(i>=0 && i<16);
00158 return _matrix[i];
00159 }
00160
00161 bool
00162 Matrix::operator==(const Matrix &m) const
00163 {
00164 return !memcmp(_matrix,m._matrix,sizeof(_matrix));
00165 }
00166
00167 bool
00168 Matrix::operator!=(const Matrix &m) const
00169 {
00170 return memcmp(_matrix,m._matrix,sizeof(_matrix))!=0;
00171 }
00172
00173 Matrix::operator double *()
00174 {
00175 return _matrix;
00176 }
00177
00178 Matrix::operator const double *() const
00179 {
00180 return _matrix;
00181 }
00182
00183 void
00184 Matrix::glMultMatrix() const
00185 {
00186 glMultMatrixd(_matrix);
00187 }
00188
00189 void
00190 Matrix::glLoadMatrix() const
00191 {
00192 glLoadMatrixd(_matrix);
00193 }
00194
00195
00196 #if 0
00197 double const *
00198 Matrix::row(const unsigned int row) const
00199 {
00200 static double r[4];
00201
00202 for (int c=0;c<4;c++)
00203 r[c] = _matrix[c*4+row];
00204
00205 return r;
00206 }
00207
00208 double const *
00209 Matrix::column(const unsigned int column) const
00210 {
00211 return _matrix+column*4;
00212 }
00213
00214 #endif
00215
00216 ostream &
00217 Matrix::writePov(ostream &os) const
00218 {
00219 UnMatrix um = unmatrix();
00220
00221 os << "scale < ";
00222 os << um[U_SCALEX] << ',';
00223 os << um[U_SCALEY] << ',';
00224 os << um[U_SCALEZ] << " > ";
00225
00226 os << "rotate < ";
00227 os << um[U_ROTATEX]/M_PI_DEG << ',';
00228 os << um[U_ROTATEY]/M_PI_DEG << ',';
00229 os << um[U_ROTATEZ]/M_PI_DEG << " > ";
00230
00231 os << "translate < ";
00232 os << um[U_TRANSX] << ',';
00233 os << um[U_TRANSY] << ',';
00234 os << um[U_TRANSZ] << " > ";
00235
00236 return os;
00237 }
00238
00244 Matrix matrixScale(const double sf)
00245 {
00246 Matrix scale;
00247
00248 scale.set(0,0,sf);
00249 scale.set(1,1,sf);
00250 scale.set(2,2,sf);
00251
00252 return scale;
00253 }
00254
00260 Matrix matrixScale(const Vector sf)
00261 {
00262 Matrix scale;
00263
00264 scale.set(0,0,sf[0]);
00265 scale.set(1,1,sf[1]);
00266 scale.set(2,2,sf[2]);
00267
00268 return scale;
00269 }
00270
00276 Matrix matrixTranslate(const Vector trans)
00277 {
00278 Matrix translate;
00279
00280 translate.set(3,0,trans[0]);
00281 translate.set(3,1,trans[1]);
00282 translate.set(3,2,trans[2]);
00283
00284 return translate;
00285 }
00286
00292 Matrix matrixTranslate(const real x,const real y,const real z)
00293 {
00294 Matrix translate;
00295
00296 translate.set(3,0,x);
00297 translate.set(3,1,y);
00298 translate.set(3,2,z);
00299
00300 return translate;
00301 }
00302
00310 Matrix matrixRotate(const Vector axis, const double angle)
00311 {
00312 Matrix rotate;
00313
00314
00315
00316 double s = sin(angle*M_PI_DEG);
00317 double c = cos(angle*M_PI_DEG);
00318 double t = 1 - c;
00319
00320 Vector ax = axis/sqrt(axis.norm());
00321
00322 double x = ax[0];
00323 double y = ax[1];
00324 double z = ax[2];
00325
00326 rotate.set(0,0,t*x*x+c);
00327 rotate.set(1,0,t*y*x+s*z);
00328 rotate.set(2,0,t*z*x-s*y);
00329
00330 rotate.set(0,1,t*x*y-s*z);
00331 rotate.set(1,1,t*y*y+c);
00332 rotate.set(2,1,t*z*y+s*x);
00333
00334 rotate.set(0,2,t*x*z+s*y);
00335 rotate.set(1,2,t*y*z-s*x);
00336 rotate.set(2,2,t*z*z+c);
00337
00338 return rotate;
00339 }
00340
00348 Matrix matrixRotate(const double azimuth, const double elevation)
00349 {
00350 Matrix rotate;
00351
00352 double ca = cos(azimuth*M_PI_DEG);
00353 double sa = sin(azimuth*M_PI_DEG);
00354 double cb = cos(elevation*M_PI_DEG);
00355 double sb = sin(elevation*M_PI_DEG);
00356
00357 rotate.set(0,0,cb);
00358 rotate.set(1,0,0);
00359 rotate.set(2,0,-sb);
00360
00361 rotate.set(0,1,-sa*sb);
00362 rotate.set(1,1,ca);
00363 rotate.set(2,1,-sa*cb);
00364
00365 rotate.set(0,2,ca*sb);
00366 rotate.set(1,2,sa);
00367 rotate.set(2,2,ca*cb);
00368
00369 return rotate;
00370 }
00371
00380 Matrix matrixOrient(const Vector &x,const Vector &y,const Vector &z)
00381 {
00382 Matrix orient;
00383
00384 orient.set(0,0,x.x());
00385 orient.set(0,1,x.y());
00386 orient.set(0,2,x.z());
00387
00388 orient.set(1,0,y.x());
00389 orient.set(1,1,y.y());
00390 orient.set(1,2,y.z());
00391
00392 orient.set(2,0,z.x());
00393 orient.set(2,1,z.y());
00394 orient.set(2,2,z.z());
00395
00396 return orient;
00397 }
00398
00406 Matrix matrixOrient(const Vector &direction,const Vector &up)
00407 {
00408 assert(direction.norm()>0.0);
00409 assert(up.norm()>0.0);
00410
00411 Vector d(direction);
00412 d.normalize();
00413
00414 Vector u(up);
00415 u.normalize();
00416
00417 return matrixOrient(xProduct(u,d),u,d);
00418 }
00419
00425 std::ostream &
00426 operator<<(std::ostream &os,const Matrix &m)
00427 {
00428 for (int r=0;r<4;r++)
00429 for (int c=0;c<4;c++)
00430 os << setw(10) << setfill(' ') << m.get(c,r) << ( c==3 ? '\n' : '\t');
00431
00432 return os;
00433 }
00434
00440 std::istream &
00441 operator>>(std::istream &is,Matrix &m)
00442 {
00443 for (int r=0;r<4;r++)
00444 for (int c=0;c<4;c++)
00445 {
00446 double tmp;
00447 is >> tmp;
00448 m.set(c,r,tmp);
00449 }
00450
00451 return is;
00452 }
00453
00454 Matrix
00455 Matrix::inverse() const
00456 {
00457 Matrix inv;
00458 invertMatrix(_matrix,inv._matrix);
00459 return inv;
00460 }
00461
00462 Matrix
00463 Matrix::transpose() const
00464 {
00465 Matrix tmp;
00466
00467 for (int i=0;i<4;i++)
00468 for (int j=0;j<4;j++)
00469 tmp.set(j,i,get(i,j));
00470
00471 return tmp;
00472 }
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482 void
00483 Matrix::invertMatrixGeneral( const double *m, double *out )
00484 {
00485
00486
00487 #define MAT(m,r,c) (m)[(c)*4+(r)]
00488
00489
00490 #define m11 MAT(m,0,0)
00491 #define m12 MAT(m,0,1)
00492 #define m13 MAT(m,0,2)
00493 #define m14 MAT(m,0,3)
00494 #define m21 MAT(m,1,0)
00495 #define m22 MAT(m,1,1)
00496 #define m23 MAT(m,1,2)
00497 #define m24 MAT(m,1,3)
00498 #define m31 MAT(m,2,0)
00499 #define m32 MAT(m,2,1)
00500 #define m33 MAT(m,2,2)
00501 #define m34 MAT(m,2,3)
00502 #define m41 MAT(m,3,0)
00503 #define m42 MAT(m,3,1)
00504 #define m43 MAT(m,3,2)
00505 #define m44 MAT(m,3,3)
00506
00507 double det;
00508 double d12, d13, d23, d24, d34, d41;
00509 double tmp[16];
00510
00511
00512
00513
00514
00515 d12 = (m31*m42-m41*m32);
00516 d13 = (m31*m43-m41*m33);
00517 d23 = (m32*m43-m42*m33);
00518 d24 = (m32*m44-m42*m34);
00519 d34 = (m33*m44-m43*m34);
00520 d41 = (m34*m41-m44*m31);
00521
00522 tmp[0] = (m22 * d34 - m23 * d24 + m24 * d23);
00523 tmp[1] = -(m21 * d34 + m23 * d41 + m24 * d13);
00524 tmp[2] = (m21 * d24 + m22 * d41 + m24 * d12);
00525 tmp[3] = -(m21 * d23 - m22 * d13 + m23 * d12);
00526
00527
00528 det = m11 * tmp[0] + m12 * tmp[1] + m13 * tmp[2] + m14 * tmp[3];
00529
00530
00531 if (det == 0.0) {
00532
00533 memcpy(out,_identity,16*sizeof(double));
00534 }
00535 else {
00536 double invDet = 1.0 / det;
00537
00538 tmp[0] *= invDet;
00539 tmp[1] *= invDet;
00540 tmp[2] *= invDet;
00541 tmp[3] *= invDet;
00542
00543 tmp[4] = -(m12 * d34 - m13 * d24 + m14 * d23) * invDet;
00544 tmp[5] = (m11 * d34 + m13 * d41 + m14 * d13) * invDet;
00545 tmp[6] = -(m11 * d24 + m12 * d41 + m14 * d12) * invDet;
00546 tmp[7] = (m11 * d23 - m12 * d13 + m13 * d12) * invDet;
00547
00548
00549
00550 d12 = m11*m22-m21*m12;
00551 d13 = m11*m23-m21*m13;
00552 d23 = m12*m23-m22*m13;
00553 d24 = m12*m24-m22*m14;
00554 d34 = m13*m24-m23*m14;
00555 d41 = m14*m21-m24*m11;
00556
00557 tmp[8] = (m42 * d34 - m43 * d24 + m44 * d23) * invDet;
00558 tmp[9] = -(m41 * d34 + m43 * d41 + m44 * d13) * invDet;
00559 tmp[10] = (m41 * d24 + m42 * d41 + m44 * d12) * invDet;
00560 tmp[11] = -(m41 * d23 - m42 * d13 + m43 * d12) * invDet;
00561 tmp[12] = -(m32 * d34 - m33 * d24 + m34 * d23) * invDet;
00562 tmp[13] = (m31 * d34 + m33 * d41 + m34 * d13) * invDet;
00563 tmp[14] = -(m31 * d24 + m32 * d41 + m34 * d12) * invDet;
00564 tmp[15] = (m31 * d23 - m32 * d13 + m33 * d12) * invDet;
00565
00566 memcpy(out, tmp, 16*sizeof(double));
00567 }
00568
00569 #undef m11
00570 #undef m12
00571 #undef m13
00572 #undef m14
00573 #undef m21
00574 #undef m22
00575 #undef m23
00576 #undef m24
00577 #undef m31
00578 #undef m32
00579 #undef m33
00580 #undef m34
00581 #undef m41
00582 #undef m42
00583 #undef m43
00584 #undef m44
00585 #undef MAT
00586 }
00587
00588
00589
00590
00591
00592
00593
00594 void
00595 Matrix::invertMatrix( const double *m, double *out )
00596 {
00597
00598 #define MAT(m,r,c) (m)[(c)*4+(r)]
00599
00600
00601 #define m11 MAT(m,0,0)
00602 #define m12 MAT(m,0,1)
00603 #define m13 MAT(m,0,2)
00604 #define m14 MAT(m,0,3)
00605 #define m21 MAT(m,1,0)
00606 #define m22 MAT(m,1,1)
00607 #define m23 MAT(m,1,2)
00608 #define m24 MAT(m,1,3)
00609 #define m31 MAT(m,2,0)
00610 #define m32 MAT(m,2,1)
00611 #define m33 MAT(m,2,2)
00612 #define m34 MAT(m,2,3)
00613 #define m41 MAT(m,3,0)
00614 #define m42 MAT(m,3,1)
00615 #define m43 MAT(m,3,2)
00616 #define m44 MAT(m,3,3)
00617
00618 register double det;
00619 double tmp[16];
00620
00621 if( m41 != 0. || m42 != 0. || m43 != 0. || m44 != 1. ) {
00622 invertMatrixGeneral(m, out);
00623 return;
00624 }
00625
00626
00627
00628 tmp[0]= m22 * m33 - m23 * m32;
00629 tmp[1]= m23 * m31 - m21 * m33;
00630 tmp[2]= m21 * m32 - m22 * m31;
00631
00632
00633 det= m11 * tmp[0] + m12 * tmp[1] + m13 * tmp[2];
00634
00635
00636 if (det == 0.0) {
00637
00638 memcpy( out, _identity, 16*sizeof(double) );
00639 }
00640 else {
00641 double d12, d13, d23, d24, d34, d41;
00642 register double im11, im12, im13, im14;
00643
00644 det= 1. / det;
00645
00646
00647 tmp[0] *= det;
00648 tmp[1] *= det;
00649 tmp[2] *= det;
00650 tmp[3] = 0.;
00651
00652 im11= m11 * det;
00653 im12= m12 * det;
00654 im13= m13 * det;
00655 im14= m14 * det;
00656 tmp[4] = im13 * m32 - im12 * m33;
00657 tmp[5] = im11 * m33 - im13 * m31;
00658 tmp[6] = im12 * m31 - im11 * m32;
00659 tmp[7] = 0.;
00660
00661
00662
00663 d12 = im11*m22 - m21*im12;
00664 d13 = im11*m23 - m21*im13;
00665 d23 = im12*m23 - m22*im13;
00666 d24 = im12*m24 - m22*im14;
00667 d34 = im13*m24 - m23*im14;
00668 d41 = im14*m21 - m24*im11;
00669
00670 tmp[8] = d23;
00671 tmp[9] = -d13;
00672 tmp[10] = d12;
00673 tmp[11] = 0.;
00674
00675 tmp[12] = -(m32 * d34 - m33 * d24 + m34 * d23);
00676 tmp[13] = (m31 * d34 + m33 * d41 + m34 * d13);
00677 tmp[14] = -(m31 * d24 + m32 * d41 + m34 * d12);
00678 tmp[15] = 1.;
00679
00680 memcpy(out, tmp, 16*sizeof(double));
00681 }
00682
00683 #undef m11
00684 #undef m12
00685 #undef m13
00686 #undef m14
00687 #undef m21
00688 #undef m22
00689 #undef m23
00690 #undef m24
00691 #undef m31
00692 #undef m32
00693 #undef m33
00694 #undef m34
00695 #undef m41
00696 #undef m42
00697 #undef m43
00698 #undef m44
00699 #undef MAT
00700 }