00001 #ifndef PTMATRIX_TMATRIXUTILITY
00002 #define PTMATRIX_TMATRIXUTILITY
00003 #include "TVector.h"
00004 #include "TMatrix.h"
00005
00006
00007
00008 namespace PTM {
00009
00010 inline void getAxisMap2D(int& x, int& y, int axis){
00011 switch(axis){
00012 case 'x': case 'X': case '0':
00013 x = 0; y = 1;
00014 break;
00015 case 'y': case 'Y': case '1':
00016 x = 1; y = 0;
00017 break;
00018 default:
00019 x = 0; y = 1;
00020 break;
00021 }
00022 }
00023
00024 template <class MD, class AD>
00025 void init_rot(TMatrixBase<DIMENC(2), DIMENC(2), MD>& m,
00026 const TVectorBase<DIMENC(2), AD>& a,
00027 char axis){
00028 int x, y;
00029 getAxisMap2D(x, y, axis);
00030 m.col(x) = a.unit();
00031 m.col(y)[0] = -m.col(x)[1];
00032 m.col(y)[1] = m.col(x)[0];
00033 }
00034
00035
00036 template <class D>
00037 void init_rot(TMatrixBase<DIMENC(2), DIMENC(2), D>& m, TYPENAME D::element_type th){
00038 TYPENAME D::element_type c = cos(th);
00039 TYPENAME D::element_type s = sin(th);
00040 m[0][0] = c; m[0][1] = -s;
00041 m[1][0] = s; m[1][1] = c;
00042 }
00043
00044 inline void getAxisMap3D(int& x, int& y, int& z, int axis){
00045 switch(axis){
00046 case 'x': case 'X': case '0':
00047 x = 0; y = 1; z = 2;
00048 break;
00049 case 'y': case 'Y': case '1':
00050 x = 1; y = 2; z = 0;
00051 break;
00052 case 'z': case 'Z': case '2':
00053 x = 2; y = 0; z = 1;
00054 break;
00055 default:
00056 x = 0; y = 1; z = 2;
00057 break;
00058 }
00059 }
00060
00061 template <class MD, class AD, class BD>
00062 void init_rot(TMatrixBase<DIMENC(3), DIMENC(3), MD>& m,
00063 const TVectorBase<DIMENC(3), AD>& a,
00064 const TVectorBase<DIMENC(3), BD>& b,
00065 char axis){
00066 int x,y,z;
00067 getAxisMap3D(x, y, z, axis);
00068 m.col(x) = a.unit();
00069 m.col(y) = (b - (b*m.col(x))*m.col(x)).unit();
00070 m.col(z) = m.col(x) % m.col(y);
00071 }
00072
00073 template <class MD>
00074 void init_rot(TMatrixBase<DIMENC(3), DIMENC(3), MD>& m, TYPENAME MD::element_type th, char axis){
00075 int x,y,z;
00076 getAxisMap3D(x, y, z, axis);
00077 TYPENAME MD::element_type c = (TYPENAME MD::element_type)cos(th);
00078 TYPENAME MD::element_type s = (TYPENAME MD::element_type)sin(th);
00079 m.item(x,x) = 1; m.item(x, y) = 0; m.item(x, z) = 0;
00080 m.item(y,x) = 0; m.item(y, y) = c; m.item(y, z) = -s;
00081 m.item(z,x) = 0; m.item(z, y) = s; m.item(z, z) = c;
00082 }
00083
00084
00085
00086
00087
00088
00089 template <class MD, class AD>
00090 void init_rot(TMatrixBase<DIMENC(3), DIMENC(3), MD>& m, TYPENAME MD::element_type th,
00091 const TVectorBase<DIMENC(3), AD>& axis){
00092 TYPENAME MD::element_type s = (TYPENAME MD::element_type) sin(th), c = (TYPENAME MD::element_type) cos(th);
00093 TYPENAME MD::element_type u = axis[0], v = axis[1], w = axis[2];
00094 m.item(0,0) = u*u + (1-u*u)*c;
00095 m.item(1,0) = u*v*(1-c) + w*s;
00096 m.item(2,0) = w*u*(1-c) - v*s;
00097
00098 m.item(0,1) = u*v*(1-c) - w*s;
00099 m.item(1,1) = v*v + (1-v*v)*c;
00100 m.item(2,1) = v*w*(1-c) + u*s;
00101
00102 m.item(0,2) = w*u*(1-c) + v*s;
00103 m.item(1,2) = v*w*(1-c) - u*s;
00104 m.item(2,2) = w*w + (1-w*w)*c;
00105 }
00106
00107
00108 template <class MD, class QD>
00109 void init_rot(TMatrixBase<DIMENC(3), DIMENC(3), MD>& m, const TVectorBase<DIMENC(4), QD>& q){
00110 typedef TMatrixBase<DIMENC(3), DIMENC(3), MD> MAT;
00111 const int W = 0;
00112 const int X = 1;
00113 const int Y = 2;
00114 const int Z = 3;
00115 TYPENAME MAT::element_type d = q*q;
00116 assert(d);
00117 TYPENAME MAT::element_type s = 2 / d;
00118 TYPENAME MAT::element_type xs = q[X] * s, ys = q[Y] * s, zs = q[Z] * s;
00119 TYPENAME MAT::element_type wx = q[W] * xs, wy = q[W] * ys, wz = q[W] * zs;
00120 TYPENAME MAT::element_type xx = q[X] * xs, xy = q[X] * ys, xz = q[X] * zs;
00121 TYPENAME MAT::element_type yy = q[Y] * ys, yz = q[Y] * zs, zz = q[Z] * zs;
00122 m.item(0,0) = 1 - (yy + zz); m.item(0,1) = xy - wz; m.item(0,2) = xz + wy;
00123 m.item(1,0) = xy + wz; m.item(1,1) = 1 - (xx + zz); m.item(1,2) = yz - wx;
00124 m.item(2,0) = xz - wy; m.item(2,1) = yz + wx; m.item(2,2) = 1 - (xx + yy);
00125 }
00126
00127
00128 template <class D>
00129 void init_unitize(TMatrixBase<DIMENC(2),DIMENC(2),D>& m){
00130 TYPENAME D::element_type z = D::zero(0);
00131 TYPENAME D::element_type u = D::unit(1);
00132 m.item(0,0)=u; m.item(0,1)=z;
00133 m.item(1,0)=z; m.item(1,1)=u;
00134 }
00135
00136 template <class D>
00137 void init_unitize(TMatrixBase<DIMENC(3),DIMENC(3),D>& m){
00138 TYPENAME D::element_type z = D::zero(0);
00139 TYPENAME D::element_type u = D::unit(1);
00140 m.item(0,0)=u; m.item(0,1)=z; m.item(0,2)=z;
00141 m.item(1,0)=z; m.item(1,1)=u; m.item(1,2)=z;
00142 m.item(2,0)=z; m.item(2,1)=z; m.item(2,2)=u;
00143 }
00144
00145 template <class D>
00146 void init_unitize(TMatrixBase<DIMENC(4),DIMENC(4),D>& m){
00147 typedef TYPENAME D::zero zero;
00148 typedef TYPENAME D::unit unit;
00149 TYPENAME D::element_type z = zero(0);
00150 TYPENAME D::element_type u = unit(1);
00151 m.item(0,0)=u; m.item(0,1)=z; m.item(0,2)=z; m.item(0,3)=z;
00152 m.item(1,0)=z; m.item(1,1)=u; m.item(1,2)=z; m.item(1,3)=z;
00153 m.item(2,0)=z; m.item(2,1)=z; m.item(2,2)=u; m.item(2,3)=z;
00154 m.item(3,0)=z; m.item(3,1)=z; m.item(3,2)=z; m.item(3,3)=u;
00155 }
00156
00157 template <class M>
00158 void init_unitize(MatrixImp<M>& m){
00159 assert(m.width() == m.height());
00160 typedef TYPENAME M::zero zero;
00161 TYPENAME M::element_type z = zero();
00162 m.clear(z);
00163 for(size_t i=0; i<m.width(); i++) m.item(i,i) = 1;
00164 }
00165
00166 template <class MD, class D>
00167 void init_cross(TMatrixBase<DIMENC(3), DIMENC(3), MD>& m, const TVectorBase<DIMENC(3), D>& v){
00168 m.item(0,0) = 0; m.item(0,1) = -v[2]; m.item(0,2) = v[1];
00169 m.item(1,0) = v[2]; m.item(1,1) = 0; m.item(1,2) = -v[0];
00170 m.item(2,0) = -v[1]; m.item(2,1) = v[0]; m.item(2,2) = 0;
00171 }
00172
00173
00174 template <class D, class BP>
00175 void init_look_at(TMatrixBase<DIMENC(4), DIMENC(4), D>& a, const TVectorBase<DIMENC(3), BP>& posi){
00176
00177 typedef TMatrixCol<4,4, TYPENAME D::element_type> TAf;
00178 typedef TVector<3, TYPENAME BP::element_type> TVec;
00179
00180 TVec relv = posi - a.col(3).sub_vector(TSubVectorDim<0,3>());
00181
00182 TVector<3, TYPENAME D::element_type> tmp = a.col(0).sub_vector(TSubVectorDim<0,3>());
00183 TYPENAME D::element_type sx = tmp.norm();
00184 tmp = a.col(1).sub_vector(TSubVectorDim<0,3>());
00185 TYPENAME D::element_type sy = tmp.norm();
00186 tmp = a.col(2).sub_vector(TSubVectorDim<0,3>());
00187 TYPENAME D::element_type sz = tmp.norm();
00188
00189
00190 TVec tv;
00191 tv[0] = relv[0];
00192 tv[1] = 0;
00193 tv[2] = relv[2];
00194 TVec ey;
00195 ey[0] = 0;
00196 ey[1] = 1;
00197 ey[2] = 0;
00198 a.col(0).sub_vector(TSubVectorDim<0,3>()) = (ey % tv.unit()).unit();
00199 a.col(2).sub_vector(TSubVectorDim<0,3>()) = relv.unit();
00200 TVec a1 = a.col(2).sub_vector(TSubVectorDim<0,3>()) % a.col(0).sub_vector(TSubVectorDim<0,3>());
00201 a.col(1).sub_vector(TSubVectorDim<0,3>()) = a1;
00202 if (a.item(1,1) < 0){
00203 TAf rot;
00204 init_rot(rot.sub_matrix(TSubMatrixDim<0,0,3,3>()), (TYPENAME TAf::element_type)M_PI, 'z');
00205 a = a * rot;
00206 }
00207 a.col(0).sub_vector(TSubVectorDim<0,3>()) *= sx;
00208 a.col(1).sub_vector(TSubVectorDim<0,3>()) *= sy;
00209 a.col(2).sub_vector(TSubVectorDim<0,3>()) *= sz;
00210 }
00211 template <class D, class BP, class BT>
00212 void init_look_at(TMatrixBase<DIMENC(4),DIMENC(4),D>& a,
00213 const TVectorBase<DIMENC(3), BP>& posz,
00214 const TVectorBase<DIMENC(3), BT>& posy){
00215 typedef TYPENAME D::ret_type TAf;
00216 typedef TYPENAME BP::ret_type TVec;
00217 TYPENAME D::element_type sx = a.col(0).sub_vector(TSubVectorDim<0,3>()).norm();
00218 TYPENAME D::element_type sy = a.col(1).sub_vector(TSubVectorDim<0,3>()).norm();
00219 TYPENAME D::element_type sz = a.col(2).sub_vector(TSubVectorDim<0,3>()).norm();
00220
00221 TVec relvz = posz - a.col(3).sub_vector(TSubVectorDim<0,3>());
00222 TVec relvy = posy - a.col(3).sub_vector(TSubVectorDim<0,3>());
00223
00224 a.col(2).sub_vector(TSubVectorDim<0,3>()) = relvz.unit();
00225 relvy = relvy - (relvy * a.col(2).sub_vector(TSubVectorDim<0,3>())) * a.col(2).sub_vector(TSubVectorDim<0,3>());
00226 a.col(1).sub_vector(TSubVectorDim<0,3>()) = relvy.unit();
00227 a.col(0).sub_vector(TSubVectorDim<0,3>()) = a.col(1).sub_vector(TSubVectorDim<0,3>()) % a.col(2).sub_vector(TSubVectorDim<0,3>());
00228
00229 a.col(0).sub_vector(TSubVectorDim<0,3>()) *= sx;
00230 a.col(1).sub_vector(TSubVectorDim<0,3>()) *= sy;
00231 a.col(2).sub_vector(TSubVectorDim<0,3>()) *= sz;
00232 }
00233
00234 template <class D, class BP>
00235 void init_look_at_gl(TMatrixBase<DIMENC(4),DIMENC(4),D>& a, const TVectorBase<DIMENC(3), BP>& posi){
00236 TYPENAME BP::ret_type posi_ = posi - 2 * (posi - a.col(3).sub_vector(TSubVectorDim<0,3>()));
00237 init_look_at(a, posi_);
00238 }
00239 template <class D, class BZ, class BY>
00240 void init_look_at_gl(TMatrixBase<DIMENC(4),DIMENC(4),D>& a,
00241 const TVectorBase<DIMENC(3), BZ>& posi,
00242 const TVectorBase<DIMENC(3), BY>& posy){
00243 TYPENAME BZ::ret_type workAroundForBCB6 = a.col(3).sub_vector(TSubVectorDim<0,3>());
00244 TYPENAME BZ::ret_type posi_ = posi - 2 * (posi - workAroundForBCB6);
00245 init_look_at(a, posi_, posy);
00246 }
00247
00248 template <class D, class SD, class ZD>
00249 void init_projection_gl(TMatrixBase<DIMENC(4),DIMENC(4),D>& a,
00250 const TVectorBase<DIMENC(3), SD>& screen_,
00251 const TVectorBase<DIMENC(2), ZD>& size_,
00252 TYPENAME D::element_type front=1.0f, TYPENAME D::element_type back=10000.0f){
00253 TYPENAME SD::ret_type screen(screen_);
00254 TYPENAME ZD::ret_type size(size_);
00255 if (screen[2] <= 0) screen[2] = size[0];
00256 assert(screen[2] > 0);
00257 assert(front > 0);
00258 assert(back > front);
00259
00260 typedef TYPENAME D::element_type ET;
00261 TVector<2,float> center = screen.sub_vector(TSubVectorDim<0,2>());
00262
00263 center *= front / screen[2];
00264 size *= front / screen[2];
00265
00266 TYPENAME D::element_type Q = back/(back-front);
00267 a.item(0,0) = 2*front/size[0]; a.item(1,0) = 0; a.item(2,0) = 0; a.item(3,0) = 0;
00268 a.item(0,1) = 0; a.item(1,1) = 2*front/size[1]; a.item(2,1) = 0; a.item(3,1) = 0;
00269 a.item(0,2) = 2*center[0]/size[0]; a.item(1,2) = 2*center[1]/size[1]; a.item(2,2) = -Q; a.item(3,2) = -1;
00270 a.item(0,3) = 0; a.item(1,3) = 0; a.item(2,3) = -Q*front; a.item(3,3) = 0;
00271 }
00272 template <class D, class SD, class ZD>
00273 void init_projection_d3d(TMatrixBase<DIMENC(4), DIMENC(4), D>& a,
00274 const TVectorBase<DIMENC(3), SD>& screen_,
00275 const TVectorBase<DIMENC(2), ZD>& size_,
00276 TYPENAME D::element_type front=1.0f, TYPENAME D::element_type back=10000.0f){
00277 TYPENAME SD::ret_type screen(screen_);
00278 TYPENAME ZD::ret_type size(size_);
00279 if (screen[2] <= 0) screen[2] = size[0];
00280 assert(screen[2] > 0);
00281 assert(front > 0);
00282 assert(back > front);
00283
00284 typedef TYPENAME D::element_type ET;
00285 TSubVector<2, TYPENAME TVectorBase<DIMENC(3), SD>::desc > center = screen.sub_vector(TSubVectorDim<0,2>());
00286
00287 center *= front / screen[2];
00288 size *= front / screen[2];
00289
00290 TYPENAME D::element_type Q = back/(back-front);
00291 a.item(0,0) = 2*front/size[0]; a.item(1,0) = 0; a.item(2,0) = 0; a.item(3,0) = 0;
00292 a.item(0,1) = 0; a.item(1,1) = 2*front/size[1]; a.item(2,1) = 0; a.item(3,1) = 0;
00293 a.item(0,2) = 2*center[0]/size[0]; a.item(1,2) = 2*center[1]/size[1]; a.item(2,2) = Q; a.item(3,2) = 1;
00294 a.item(0,3) = 0; a.item(1,3) = 0; a.item(2,3) = -Q*front; a.item(3,3) = 0;
00295 }
00296
00297
00298
00299 template <class QD, class T, class AD>
00300 void init_quaternion(TVectorBase<DIMENC(4), QD>& q, T angle, const TVectorBase<DIMENC(3),AD>& axis){
00301 TYPENAME QD::element_type d = axis.norm();
00302 assert(d);
00303 TYPENAME QD::element_type s = (TYPENAME QD::element_type)(sin(angle / 2) / d);
00304 q[0] = TVectorBase<DIMENC(4), QD>::element_type( cos(angle / 2) );
00305 q.sub_vector(TSubVectorDim<1,3>()) = s * axis;
00306 }
00307
00308
00309 template <class QD, class AD>
00310 void init_quaternion(TVectorBase<DIMENC(4), QD>& q, const TVectorBase<DIMENC(3),AD>& rot){
00311 typedef TYPENAME QD::element_type ET;
00312 ET angle = rot.norm();
00313 ET s = (ET)(sin(angle / 2));
00314 q[0] = (ET)( cos(angle / 2) );
00315 if (angle > 1e-10f){
00316 q.sub_vector(TSubVectorDim<1,3>()) = s/angle * rot;
00317 }else{
00318 q[1] = (ET)0;
00319 q[2] = (ET)0;
00320 q[3] = (ET)0;
00321 }
00322 }
00323
00324
00325 template <class QD, class T>
00326 void init_quaternion(TVectorBase<DIMENC(4), QD>& q, T angle, char axis){
00327 q[0] = (TYPENAME QD::element_type) cos(angle / 2);
00328 int x,y,z;
00329 getAxisMap3D(x,y,z, axis);
00330 q[x+1] = (TYPENAME QD::element_type) sin(angle / 2);
00331 q[y+1] = 0;
00332 q[z+1] = 0;
00333 }
00334
00335
00336 template <class QD, class MD>
00337 void init_quaternion(TVectorBase<DIMENC(4), QD>& q, TMatrixBase<DIMENC(3), DIMENC(3), MD>& m){
00338
00339 double tr = m[0][0] + m[1][1] + m[2][2];
00340 if (tr > 0){
00341 double s = sqrt(tr+1);
00342 typedef TYPENAME QD::element_type QET;
00343 W() = QET(s/2);
00344 s = QET(0.5/s);
00345 X() = QET((m[1][2] - m[2][1]) * s);
00346 Y() = QET((m[2][0] - m[0][2]) * s);
00347 Z() = QET((m[0][1] - m[1][0]) * s);
00348 }else{
00349 double q[4];
00350 int i, j, k;
00351 int nxt[3] = {1, 2, 0};
00352 i = 0;
00353 if (m[1][1] > m[0][0]) i = 1;
00354 if (m[2][2] > m[i][i]) i = 2;
00355 j = nxt[i];
00356 k = nxt[j];
00357 s = sqrt((m[i][i] - (m[j][j] + m[k][k])) + 1.0f);
00358 q[i] = s * 0.5f;
00359 if (s){
00360 s = 0.5 / s;
00361 q[3] = (m[j][k] - m[k][j]) * s;
00362 q[j] = (m[i][j] + m[j][i]) * s;
00363 q[k] = (m[i][k] + m[k][i]) * s;
00364 W() = q[0];
00365 X() = q[1];
00366 Y() = q[2];
00367 Z() = q[3];
00368 }else{
00369 W() = 0;
00370 X() = 1;
00371 Y() = 0;
00372 Z() = 0;
00373 }
00374 }
00375 }
00376
00377 }
00378 #endif