00001
00002 #ifndef INCLUDED_fmatSpatial_h_
00003 #define INCLUDED_fmatSpatial_h_
00004
00005 #include "fmatCore.h"
00006
00007 namespace fmat {
00008
00009 template<typename R> class TransformT;
00010
00011
00012
00013
00014 template<typename R>
00015 inline Matrix<2,2,R> rotation2DT(R rad) {
00016 R s = std::sin(rad), c = std::cos(rad);
00017 R dat[4] = { c, s, -s, c };
00018 return Matrix<2,2,R>(dat);
00019 }
00020
00021 inline Matrix<2,2,fmatReal> rotation2D(fmatReal rad) { return rotation2DT<fmatReal>(rad); }
00022
00023
00024 template<size_t N, typename R>
00025 inline Matrix<N,N,R> rotationXN(R rad) {
00026 (void)sizeof(fmat_internal::CompileTimeAssert<Rotation_requires_larger_dimensions,N>=3>);
00027 Matrix<N,N,R> ans = Matrix<N,N,R>::identity();
00028 ans(1,1) = ans(2,2) = std::cos(rad);
00029 ans(1,2) = -(ans(2,1) = std::sin(rad));
00030 return ans;
00031 }
00032
00033 inline Matrix<3,3,fmatReal> rotationX(fmatReal rad) { return rotationXN<3,fmatReal>(rad); }
00034
00035
00036 template<size_t N, typename R>
00037 inline Matrix<N,N,R> rotationYN(R rad) {
00038 (void)sizeof(fmat_internal::CompileTimeAssert<Rotation_requires_larger_dimensions,N>=3>);
00039 Matrix<N,N,R> ans = Matrix<N,N,R>::identity();
00040 ans(0,0) = ans(2,2) = std::cos(rad);
00041 ans(2,0) = -(ans(0,2) = std::sin(rad));
00042 return ans;
00043 }
00044
00045 inline Matrix<3,3,fmatReal> rotationY(fmatReal rad) { return rotationYN<3,fmatReal>(rad); }
00046
00047
00048 template<size_t N, typename R>
00049 inline Matrix<N,N,R> rotationZN(R rad) {
00050 (void)sizeof(fmat_internal::CompileTimeAssert<Rotation_requires_larger_dimensions,N>=2>);
00051 if(N==2) {
00052 R s = std::sin(rad), c = std::cos(rad);
00053 R dat[4] = { c, s, -s, c };
00054 return Matrix<N,N,R>(dat);
00055 } else {
00056 Matrix<N,N,R> ans = Matrix<N,N,R>::identity();
00057 ans(0,0) = ans(1,1) = std::cos(rad);
00058 ans(0,1) = -(ans(1,0) = std::sin(rad));
00059 return ans;
00060 }
00061 }
00062
00063 inline Matrix<3,3,fmatReal> rotationZ(fmatReal rad) { return rotationZN<3,fmatReal>(rad); }
00064
00065
00066
00067
00068
00069
00070 template<class R=fmatReal>
00071 class QuaternionT {
00072 public:
00073
00074 QuaternionT() : w(1), x(0), y(0), z(0) {}
00075
00076
00077 QuaternionT(R w_, R x_, R y_, R z_) : w(w_), x(x_), y(y_), z(z_) {}
00078
00079
00080 template<typename T> static QuaternionT from(const T& q) { return QuaternionT(q[0],q[1],q[2],q[3]); }
00081
00082 template<typename T> QuaternionT& importFrom(const T& q) { w=q[0]; x=q[1]; y=q[2]; z=q[3]; return *this; }
00083
00084 template<typename T> T exportTo() const { T q; q[0]=w; q[1]=x; q[2]=y; q[3]=z; return q; }
00085
00086 template<typename T> T& exportTo(T& q) const { q[0]=w; q[1]=x; q[2]=y; q[3]=z; return q; }
00087
00088 template<typename T> void exportTo(T& w_, T& x_, T& y_, T& z_) const { w_=w; x_=x; y_=y; z_=z; }
00089
00090 template<typename T> void exportTo(T& x_, T& y_, T& z_) const { if(w<0) { x_=-x; y_=-y; z_=-z; } else { x_=x; y_=y; z_=z; } }
00091
00092 R getW() const { return w; }
00093 R getX() const { return x; }
00094 R getY() const { return y; }
00095 R getZ() const { return z; }
00096
00097
00098 static const QuaternionT& identity() { return IDENTITY; }
00099 static const QuaternionT IDENTITY;
00100
00101
00102 static QuaternionT<R> aboutX(R rad) { return fmat::QuaternionT<R>(std::cos(rad/2),std::sin(rad/2),0,0); }
00103
00104 static QuaternionT<R> aboutY(R rad) { return fmat::QuaternionT<R>(std::cos(rad/2),0,std::sin(rad/2),0); }
00105
00106 static QuaternionT<R> aboutZ(R rad) { return fmat::QuaternionT<R>(std::cos(rad/2),0,0,std::sin(rad/2)); }
00107
00108
00109
00110 template<class T>
00111 static QuaternionT fromAxisAngle(const T& axis, R angle) {
00112 if(std::abs(angle) <= std::numeric_limits<R>::epsilon())
00113 return QuaternionT();
00114 R n = axis.sumSq();
00115 if(n <= std::numeric_limits<R>::epsilon())
00116 return QuaternionT();
00117 R s = std::sin(angle/2)/std::sqrt(n);
00118 return QuaternionT(std::cos(angle/2), axis[0]*s, axis[1]*s, axis[2]*s);
00119 }
00120
00121
00122
00123 template<class T>
00124 static QuaternionT fromAxis(const T& axis) {
00125 R n2 = static_cast<R>(axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]);
00126 if(n2>1) {
00127 if(n2>1+std::numeric_limits<R>::epsilon()*10) {
00128 R n = std::sqrt(n2);
00129 std::cerr << "Warning: fmat::Quaternion axis constructor passed non-normalized |" << axis[0] << ',' << axis[1] << ',' << axis[2] << "| = " << n << " (err " << (n-1) << ')' << std::endl;
00130 R s = 1/n;
00131 return QuaternionT(0, axis[0]*s, axis[1]*s, axis[2]*s);
00132 } else {
00133
00134 R s = 1/n2;
00135 return QuaternionT(0, axis[0]*s, axis[1]*s, axis[2]*s);
00136 }
00137 } else {
00138 return QuaternionT(std::sqrt(1-n2),axis[0],axis[1],axis[2]);
00139 }
00140 }
00141
00142
00143
00144
00145
00146
00147
00148 template<class T>
00149 static QuaternionT fromMatrix(const T& rot) {
00150 QuaternionT quat = fmat_internal::NoInit();
00151 R tracem1 = rot(0,0) + rot(1,1) + rot(2,2);
00152 if( tracem1 >= 0 ) {
00153 const R r = std::sqrt(tracem1 + 1);
00154 quat.w = (R)0.5 * r;
00155 const R s = (R)0.5 / r;
00156 quat.x = ( rot(2,1) - rot(1,2) ) * s;
00157 quat.y = ( rot(0,2) - rot(2,0) ) * s;
00158 quat.z = ( rot(1,0) - rot(0,1) ) * s;
00159 } else {
00160 if ( rot(0,0) > rot(1,1) && rot(0,0) > rot(2,2) ) {
00161 const R r = std::sqrt( 1.0f + rot(0,0) - rot(1,1) - rot(2,2));
00162 quat.x = (R)0.5 * r;
00163 const R s = (R)0.5 / r;
00164 quat.w = (rot(2,1) - rot(1,2) ) * s;
00165 quat.y = (rot(0,1) + rot(1,0) ) * s;
00166 quat.z = (rot(0,2) + rot(2,0) ) * s;
00167 } else if (rot(1,1) > rot(2,2)) {
00168 const R r = std::sqrt( 1.0f + rot(1,1) - rot(0,0) - rot(2,2));
00169 quat.y = (R)0.5 * r;
00170 const R s = (R)0.5 / r;
00171 quat.w = (rot(0,2) - rot(2,0) ) * s;
00172 quat.x = (rot(0,1) + rot(1,0) ) * s;
00173 quat.z = (rot(1,2) + rot(2,1) ) * s;
00174 } else {
00175 const R r = std::sqrt( 1.0f + rot(2,2) - rot(0,0) - rot(1,1) );
00176 quat.z = (R)0.5 * r;
00177 const R s = (R)0.5 / r;
00178 quat.w = (rot(1,0) - rot(0,1) ) * s;
00179 quat.x = (rot(0,2) + rot(2,0) ) * s;
00180 quat.y = (rot(1,2) + rot(2,1) ) * s;
00181 }
00182 }
00183 return quat;
00184 }
00185
00186
00187
00188 Matrix<3,3,R> toMatrix() const {
00189 const R t2 = w*x;
00190 const R t3 = w*y;
00191 const R t4 = w*z;
00192 const R t5 = -x*x;
00193 const R t6 = x*y;
00194 const R t7 = x*z;
00195 const R t8 = -y*y;
00196 const R t9 = y*z;
00197 const R t10 = -z*z;
00198 const R values[9] = {
00199 2*(t8 + t10) + 1,
00200 2*(t4 + t6),
00201 2*(t7 - t3),
00202 2*(t6 - t4),
00203 2*(t5 + t10) + 1,
00204 2*(t2 + t9),
00205 2*(t3 + t7),
00206 2*(t9 - t2),
00207 2*(t5 + t8) + 1
00208 };
00209 return Matrix<3,3,R>(values);
00210 }
00211
00212 operator Matrix<3,3,R>() const { return toMatrix(); }
00213
00214
00215 Column<3,R> axis() const {
00216 R n2 = (x*x + y*y + z*z);
00217 if(n2 < std::numeric_limits<R>::epsilon())
00218 return fmat::packT<R>(0,0,1);
00219 R sc = 1/std::sqrt(n2);
00220 return fmat::packT<R>(x*sc, y*sc, z*sc);
00221 }
00222
00223
00224
00225 R angle() const {
00226 R n = std::sqrt(x*x + y*y + z*z);
00227 R ang = 2*std::atan2(n,w);
00228 if(ang>static_cast<R>(M_PI))
00229 ang-=2*static_cast<R>(M_PI);
00230 return ang;
00231
00232
00233
00234
00235 }
00236
00237
00238 template<class T>
00239 R axisComponent(const T& v) const {
00240
00241
00242 R n = std::sqrt(x*x + y*y + z*z);
00243 if(n < std::numeric_limits<R>::epsilon())
00244 return 0;
00245 R ang_2 = std::atan2(n,w);
00246 return 2*ang_2*(x*v[0] + y*v[1] + z*v[2])/n;
00247 }
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 fmat::Column<3,R> ypr() const {
00260 const R sqw=w*w, sqx=x*x, sqy=y*y, sqz=z*z;
00261 const R unit = sqw + sqx + sqy + sqz;
00262 const R test = y*w - x*z;
00263 if (test > 0.4999*unit) {
00264 return packT<R>(-2 * std::atan2(x,w), (R)M_PI_2, 0);
00265 }
00266 if (test < -0.4999*unit) {
00267 return packT<R>(2 * std::atan2(x,w), -(R)M_PI_2, 0);
00268 }
00269 return packT<R>(
00270 std::atan2(2*z*w+2*x*y , sqx - sqz - sqy + sqw),
00271 std::asin(2*test/unit),
00272 std::atan2(2*x*w+2*z*y , -sqx + sqz - sqy + sqw)
00273 );
00274 }
00275
00276
00277 QuaternionT inverse() const ATTR_must_check { return QuaternionT(w,-x,-y,-z); }
00278
00279
00280
00281
00282
00283
00284
00285 template<typename Rb>
00286 QuaternionT<typename fmat_internal::promotion_trait<R,Rb>::type>
00287 operator*(const QuaternionT<Rb>& q) const {
00288 return QuaternionT<typename fmat_internal::promotion_trait<R,Rb>::type>(
00289 w*q.w - x*q.x - y*q.y - z*q.z,
00290 w*q.x + x*q.w + y*q.z - z*q.y,
00291 w*q.y - x*q.z + y*q.w + z*q.x,
00292 w*q.z + x*q.y - y*q.x + z*q.w
00293 );
00294 }
00295
00296
00297 QuaternionT operator*=(const QuaternionT& q) { return this->operator=(operator*(q)); }
00298
00299
00300 template<template<size_t H, size_t W, typename Rt> class T, size_t W>
00301 Matrix<3,W,R> operator*(const T<3,W,R>& m) const {
00302 const R t2 = w*x;
00303 const R t3 = w*y;
00304 const R t4 = w*z;
00305 const R t5 = -x*x;
00306 const R t6 = x*y;
00307 const R t7 = x*z;
00308 const R t8 = -y*y;
00309 const R t9 = y*z;
00310 const R t10 = -z*z;
00311 Matrix<3,W,R> o=fmat_internal::NoInit();
00312 for(size_t c = 0; c<W; ++c) {
00313 o(0,c) = 2*( (t8 + t10)*m(0,c) + (t6 - t4)*m(1,c) + (t3 + t7)*m(2,c) ) + m(0,c);
00314 o(1,c) = 2*( (t4 + t6)*m(0,c) + (t5 + t10)*m(1,c) + (t9 - t2)*m(2,c) ) + m(1,c);
00315 o(2,c) = 2*( (t7 - t3)*m(0,c) + (t2 + t9)*m(1,c) + (t5 + t8)*m(2,c) ) + m(2,c);
00316 }
00317 return o;
00318 }
00319
00320
00321 TransformT<R> operator*(const TransformT<R>& m) const {
00322 const R t2 = w*x;
00323 const R t3 = w*y;
00324 const R t4 = w*z;
00325 const R t5 = -x*x;
00326 const R t6 = x*y;
00327 const R t7 = x*z;
00328 const R t8 = -y*y;
00329 const R t9 = y*z;
00330 const R t10 = -z*z;
00331 TransformT<R> o=fmat_internal::NoInit();
00332 for(size_t c = 0; c<4; ++c) {
00333 o(0,c) = 2*( (t8 + t10)*m(0,c) + (t6 - t4)*m(1,c) + (t3 + t7)*m(2,c) ) + m(0,c);
00334 o(1,c) = 2*( (t4 + t6)*m(0,c) + (t5 + t10)*m(1,c) + (t9 - t2)*m(2,c) ) + m(1,c);
00335 o(2,c) = 2*( (t7 - t3)*m(0,c) + (t2 + t9)*m(1,c) + (t5 + t8)*m(2,c) ) + m(2,c);
00336 }
00337 return o;
00338 }
00339
00340
00341 Column<3,R> operator*(const Column<3,R> v) const {
00342 const R t2 = w*x;
00343 const R t3 = w*y;
00344 const R t4 = w*z;
00345 const R t5 = -x*x;
00346 const R t6 = x*y;
00347 const R t7 = x*z;
00348 const R t8 = -y*y;
00349 const R t9 = y*z;
00350 const R t10 = -z*z;
00351 Column<3,R> o=fmat_internal::NoInit();
00352 o[0] = 2*( (t8 + t10)*v[0] + (t6 - t4)*v[1] + (t3 + t7)*v[2] ) + v[0];
00353 o[1] = 2*( (t4 + t6)*v[0] + (t5 + t10)*v[1] + (t9 - t2)*v[2] ) + v[1];
00354 o[2] = 2*( (t7 - t3)*v[0] + (t2 + t9)*v[1] + (t5 + t8)*v[2] ) + v[2];
00355 return o;
00356 }
00357
00358
00359 R sumSq() const { return w*w + x*x + y*y + z*z; }
00360
00361
00362 R norm() const { return std::sqrt(w*w + x*x + y*y + z*z); }
00363
00364
00365 R normalize() {
00366 R n = sumSq();
00367 if(n < std::numeric_limits<R>::epsilon()) {
00368 w=x=y=z=0;
00369 return 0;
00370 }
00371 if(n<=1 && 1-n < std::numeric_limits<R>::epsilon()) {
00372
00373 if(w<0) {
00374 w=-w;
00375 x=-x;
00376 y=-y;
00377 z=-z;
00378 }
00379 return 1;
00380 }
00381 R sc = (w<0?-1:1) / std::sqrt(n);
00382 w*=sc;
00383 x*=sc;
00384 y*=sc;
00385 z*=sc;
00386 return n;
00387 }
00388
00389 friend inline std::ostream& operator<<(std::ostream& os, const QuaternionT<R>& q) { return os << fmat::SubVector<4,const R>((const R*)&q.w); }
00390
00391 protected:
00392 R w, x, y, z;
00393
00394
00395 QuaternionT(const fmat_internal::NoInit&) : w(), x(), y(), z() {}
00396 };
00397 typedef QuaternionT<> Quaternion;
00398
00399
00400 template<class Ra, class Rb>
00401 QuaternionT<typename fmat_internal::promotion_trait<Ra,Rb>::type>
00402 crossProduct(const QuaternionT<Ra>& p, const QuaternionT<Rb>& q) { return q * p.inverse(); }
00403
00404
00405 template<typename R> QuaternionT<R> invert(const QuaternionT<R>& q) { return q.inverse(); }
00406
00407
00408
00409
00410
00411 namespace fmat_internal {
00412
00413 template<typename R1, typename R2>
00414 struct transformOps {
00415
00416 typedef typename fmat_internal::promotion_trait<R1,R2>::type out_t;
00417
00418 template<typename V>
00419 inline static Column<3,out_t> multiply3(const TransformT<R1>& tr, const V& x) {
00420 Column<3,out_t> ans=fmat_internal::NoInit();
00421 const R1 *a = &tr(0,0);
00422 const R2 *b = &x[0];
00423 ans[0] = a[0+3*0]*b[0] + a[0+3*1]*b[1] + a[0+3*2]*b[2] + a[0+3*3];
00424 ans[1] = a[1+3*0]*b[0] + a[1+3*1]*b[1] + a[1+3*2]*b[2] + a[1+3*3];
00425 ans[2] = a[2+3*0]*b[0] + a[2+3*1]*b[1] + a[2+3*2]*b[2] + a[2+3*3];
00426 return ans;
00427 }
00428
00429 template<typename V>
00430 inline static Column<4,out_t> multiply4(const TransformT<R1>& tr, const V& x) {
00431 Column<4,out_t> ans=fmat_internal::NoInit();
00432 const R1 *a = &tr(0,0);
00433 const R2 *b = &x[0];
00434 ans[0] = a[0+3*0]*b[0] + a[0+3*1]*b[1] + a[0+3*2]*b[2] + a[0+3*3]*b[3];
00435 ans[1] = a[1+3*0]*b[0] + a[1+3*1]*b[1] + a[1+3*2]*b[2] + a[1+3*3]*b[3];
00436 ans[2] = a[2+3*0]*b[0] + a[2+3*1]*b[1] + a[2+3*2]*b[2] + a[2+3*3]*b[3];
00437 ans[3] = b[3];
00438 return ans;
00439 }
00440
00441 inline static void multiplyT(const R1* a, const R2* b, out_t* ans) {
00442 ans[0+3*0] = a[0+3*0]*b[0+3*0] + a[0+3*1]*b[1+3*0] + a[0+3*2]*b[2+3*0];
00443 ans[1+3*0] = a[1+3*0]*b[0+3*0] + a[1+3*1]*b[1+3*0] + a[1+3*2]*b[2+3*0];
00444 ans[2+3*0] = a[2+3*0]*b[0+3*0] + a[2+3*1]*b[1+3*0] + a[2+3*2]*b[2+3*0];
00445 ans[0+3*1] = a[0+3*0]*b[0+3*1] + a[0+3*1]*b[1+3*1] + a[0+3*2]*b[2+3*1];
00446 ans[1+3*1] = a[1+3*0]*b[0+3*1] + a[1+3*1]*b[1+3*1] + a[1+3*2]*b[2+3*1];
00447 ans[2+3*1] = a[2+3*0]*b[0+3*1] + a[2+3*1]*b[1+3*1] + a[2+3*2]*b[2+3*1];
00448 ans[0+3*2] = a[0+3*0]*b[0+3*2] + a[0+3*1]*b[1+3*2] + a[0+3*2]*b[2+3*2];
00449 ans[1+3*2] = a[1+3*0]*b[0+3*2] + a[1+3*1]*b[1+3*2] + a[1+3*2]*b[2+3*2];
00450 ans[2+3*2] = a[2+3*0]*b[0+3*2] + a[2+3*1]*b[1+3*2] + a[2+3*2]*b[2+3*2];
00451 ans[0+3*3] = a[0+3*0]*b[0+3*3] + a[0+3*1]*b[1+3*3] + a[0+3*2]*b[2+3*3] + a[0+3*3];
00452 ans[1+3*3] = a[1+3*0]*b[0+3*3] + a[1+3*1]*b[1+3*3] + a[1+3*2]*b[2+3*3] + a[1+3*3];
00453 ans[2+3*3] = a[2+3*0]*b[0+3*3] + a[2+3*1]*b[1+3*3] + a[2+3*2]*b[2+3*3] + a[2+3*3];
00454 }
00455 };
00456 }
00457
00458
00459
00460 template<typename R=fmatReal>
00461 class TransformT : public Matrix<3,4,R> {
00462 public:
00463 enum {
00464 HEIGHT=3, H=3,
00465 WIDTH=4, W=4,
00466 CAP=12
00467 };
00468 typedef R storage_t;
00469 typedef typename fmat_internal::unconst<R>::type out_t;
00470
00471 TransformT(const fmat_internal::NoInit& noinit) : Matrix<H,W,R>(noinit) {}
00472
00473 TransformT() : Matrix<H,W,R>(Matrix<H,W,R>::identity()) { }
00474 explicit TransformT(const R* x, size_t colStride=H) : Matrix<H,W,R>(x,colStride) {}
00475 TransformT(const SubMatrix<H,W,R>& x) : Matrix<H,W,R>(x) {}
00476 TransformT(const Matrix<H,W,R>& x) : Matrix<H,W,R>(x) {}
00477 template<typename Rot, typename Pt> TransformT(const Rot& r, const Pt& p) : Matrix<H,W,R>(fmat_internal::NoInit()) { rotation()=r; translation()=p; }
00478 template<size_t SH, size_t SW> explicit TransformT(const SubMatrix<SH,SW,R>& x) : Matrix<H,W,R>(x) {}
00479 template<size_t SH, size_t SW> explicit TransformT(const SubMatrix<SH,SW,R>& x, size_t rowOff, size_t colOff) : Matrix<H,W,R>(x,rowOff,colOff) {}
00480 template<size_t SH, size_t SW> explicit TransformT(const Matrix<SH,SW,R>& x) : Matrix<H,W,R>(x) {}
00481 template<size_t SH, size_t SW> explicit TransformT(const Matrix<SH,SW,R>& x, size_t rowOff, size_t colOff) : Matrix<H,W,R>(x,rowOff,colOff) {}
00482
00483 SubMatrix<3,3,R> rotation() { return SubMatrix<3,3,R>(data); }
00484 SubMatrix<3,3,const R> rotation() const { return SubMatrix<3,3,const R>(data); }
00485 SubVector<3,R> translation() { return Matrix<H,W,R>::column(3); }
00486 SubVector<3,const R> translation() const { return Matrix<H,W,R>::column(3); }
00487
00488
00489 static TransformT<R> aboutX(R rad) {
00490 TransformT<R> ans;
00491 ans(1,1) = ans(2,2) = std::cos(rad);
00492 ans(1,2) = -(ans(2,1) = std::sin(rad));
00493 return ans;
00494 }
00495
00496 static TransformT<R> aboutY(R rad) {
00497 TransformT<R> ans;
00498 ans(0,0) = ans(2,2) = std::cos(rad);
00499 ans(2,0) = -(ans(0,2) = std::sin(rad));
00500 return ans;
00501 }
00502
00503 static TransformT<R> aboutZ(R rad) {
00504 TransformT<R> ans;
00505 ans(0,0) = ans(1,1) = std::cos(rad);
00506 ans(0,1) = -(ans(1,0) = std::sin(rad));
00507 return ans;
00508 }
00509
00510 template<class V>
00511 static TransformT<R> offset(const V& x) { TransformT<R> ans; ans.translation() = x; return ans; }
00512
00513 static const TransformT& identity() { return IDENTITY; }
00514 static const TransformT IDENTITY;
00515
00516
00517 inline TransformT inverse() const ATTR_must_check {
00518 TransformT ans=fmat_internal::NoInit();
00519 ans.rotation() = fmat::invert(rotation());
00520 ans.translation() = -ans.rotation() * translation();
00521 return ans;
00522 }
00523
00524
00525 inline TransformT rigidInverse() const ATTR_must_check {
00526 TransformT ans=fmat_internal::NoInit();
00527 R * t2dat = &ans(0,0);
00528 t2dat[0] = data[0];
00529 t2dat[1] = data[3];
00530 t2dat[2] = data[6];
00531 t2dat[3] = data[1];
00532 t2dat[4] = data[4];
00533 t2dat[5] = data[7];
00534 t2dat[6] = data[2];
00535 t2dat[7] = data[5];
00536 t2dat[8] = data[8];
00537 t2dat[9] = -(data[0]*data[9] + data[1]*data[10] + data[2]*data[11]);
00538 t2dat[10] = -(data[3]*data[9] + data[4]*data[10] + data[5]*data[11]);
00539 t2dat[11] = -(data[6]*data[9] + data[7]*data[10] + data[8]*data[11]);
00540 return ans;
00541 }
00542
00543 template<typename R2>
00544 inline Column<3,typename fmat_internal::promotion_trait<R,R2>::type>
00545 operator*(const Column<3,R2>& x) const {
00546 return fmat_internal::transformOps<R,R2>::multiply3(*this,x);
00547 }
00548
00549 template<typename R2>
00550 inline Column<3,typename fmat_internal::promotion_trait<R,R2>::type>
00551 operator*(const SubVector<3,R2>& x) const {
00552 return fmat_internal::transformOps<R,R2>::multiply3(*this,x);
00553 }
00554
00555 template<size_t N, typename R2>
00556 inline Matrix<3,N,typename fmat_internal::promotion_trait<R,R2>::type>
00557 operator*(const Matrix<3,N,R2>& x) const {
00558 Matrix<3,N,typename fmat_internal::promotion_trait<R,R2>::type> ans = fmat_internal::NoInit();
00559 for(size_t i=0; i<N; ++i)
00560 ans.column(i) = fmat_internal::transformOps<R,R2>::multiply3(*this,x.column(i));
00561 return ans;
00562 }
00563
00564 template<typename R2>
00565 inline Column<4,typename fmat_internal::promotion_trait<R,R2>::type>
00566 operator*(const Column<4,R2>& x) const {
00567 return fmat_internal::transformOps<R,R2>::multiply4(*this,x);
00568 }
00569
00570 template<typename R2>
00571 inline Column<4,typename fmat_internal::promotion_trait<R,R2>::type>
00572 operator*(const SubVector<4,R2>& x) const {
00573 return fmat_internal::transformOps<R,R2>::multiply4(*this,x);
00574 }
00575
00576 template<size_t N, typename R2>
00577 inline Matrix<4,N,typename fmat_internal::promotion_trait<R,R2>::type>
00578 operator*(const Matrix<4,N,R2>& x) const {
00579 Matrix<4,N,typename fmat_internal::promotion_trait<R,R2>::type> ans = fmat_internal::NoInit();
00580 for(size_t i=0; i<N; ++i)
00581 ans.column(i) = fmat_internal::transformOps<R,R2>::multiply4(*this,x.column(i));
00582 return ans;
00583 }
00584
00585 template<typename R2>
00586 inline TransformT<typename fmat_internal::promotion_trait<R,R2>::type>
00587 operator*(const TransformT<R2>& tb) const {
00588 TransformT<typename fmat_internal::promotion_trait<R,R2>::type> mans=fmat_internal::NoInit();
00589 fmat_internal::transformOps<R,R2>::multiplyT(data,&tb(0,0),&mans(0,0));
00590 return mans;
00591 }
00592
00593 template<typename R2>
00594 TransformT&
00595 operator*=(const TransformT<R2>& t) {
00596 fmat_internal::transformOps<R,R2>::multiplyT(&TransformT(*this)(0,0),&t(0,0),data);
00597 return *this;
00598 }
00599 using Matrix<H,W,R>::operator=;
00600 using Matrix<H,W,R>::operator*=;
00601 using Matrix<H,W,R>::operator/=;
00602
00603 protected:
00604 using Matrix<H,W,R>::data;
00605 };
00606 typedef TransformT<> Transform;
00607
00608
00609 template<typename R>
00610 inline Matrix<4,4,R> invertTransform(const Matrix<4,4,R>& t) {
00611 fmat::Column<4> p = -t.column(3);
00612 const R * tdat = &t(0,0);
00613
00614
00615
00616
00617
00618
00619
00620 Matrix<4,4,R> t2(t);
00621 R * t2dat = &t2(0,0);
00622 t2dat[1] = tdat[4];
00623 t2dat[2] = tdat[8];
00624 t2dat[4] = tdat[1];
00625 t2dat[6] = tdat[9];
00626 t2dat[8] = tdat[2];
00627 t2dat[9] = tdat[6];
00628 t2dat[12] = fmat::dotProduct(t.column(0),p);
00629 t2dat[13] = fmat::dotProduct(t.column(1),p);
00630 t2dat[14] = fmat::dotProduct(t.column(2),p);
00631 return t2;
00632 }
00633
00634
00635 template<typename R>
00636 TransformT<R>
00637 invert(const TransformT<R>& m) { return m.inverse(); }
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649 template<typename R>
00650 Column<3,R>
00651 ypr(const QuaternionT<R>& q) { return q.ypr(); }
00652
00653
00654
00655
00656
00657
00658
00659
00660 template<typename R>
00661 Column<3,R>
00662 ypr(const TransformT<R>& m) { return ypr(m.rotation()); }
00663
00664
00665
00666
00667
00668
00669
00670
00671 template<template<size_t,size_t,typename R> class M, typename R>
00672 Column<3,typename fmat_internal::unconst<R>::type>
00673 ypr(const M<3,3,R>& m) {
00674 typedef typename fmat_internal::unconst<R>::type out_t;
00675 if (m(2,0) > 0.9998) {
00676 return packT<out_t>(std::atan2(-m(0,1),m(1,1)), -M_PI_2, 0);
00677 }
00678 if (m(2,0) < -0.9998) {
00679 return packT<out_t>(std::atan2(-m(0,1),m(1,1)), M_PI_2, 0);
00680 }
00681 return packT<out_t>(
00682 std::atan2(m(1,0),m(0,0)),
00683 std::asin(-m(2,0)),
00684 std::atan2(m(2,1),m(2,2))
00685 );
00686 }
00687
00688
00689
00690 template<typename R>
00691 Column<2,R>
00692 segmentIntersection(const Column<2,R>& p1, const Column<2,R>& d1, const Column<2,R>& p2, const Column<2,R>& d2) {
00693 fmat::Matrix<2,2,R> dm = fmat_internal::NoInit();
00694 dm.column(0) = d1;
00695 dm.column(1) = -d2;
00696 try {
00697 dm = invert(dm);
00698 } catch(...) {
00699
00700 return Column<2,R>(std::numeric_limits<fmat::fmatReal>::infinity());
00701 }
00702 Column<2,R> o = p2-p1;
00703 return dm * o;
00704 }
00705
00706
00707
00708 template<typename R>
00709 R
00710 rayIntersection(const Column<2,R>& p1, const Column<2,R>& d1, const Column<2,R>& p2, const Column<2,R>& d2) {
00711 return segmentIntersection(p1, d1, p2, d2)[0];
00712 }
00713
00714
00715
00716
00717 template<typename R>
00718 Column<2,R>
00719 lineIntersection(const Column<2,R>& p1, const Column<2,R>& d1, const Column<2,R>& p2, const Column<2,R>& d2) {
00720 return d1 * rayIntersection(p1,d1,p2,d2) + p1;
00721 }
00722
00723
00724 template<template<size_t,typename R> class V, typename R>
00725 Column<2,typename V<2,R>::out_t>
00726 normalLeft(const V<2,R>& v) { return fmat::pack(-v[1],v[0]); }
00727
00728
00729 template<template<size_t,typename R> class V, typename R>
00730 Column<2,typename V<2,R>::out_t>
00731 normalRight(const V<2,R>& v) { return fmat::pack(v[1],-v[0]); }
00732 }
00733
00734
00735
00736
00737
00738
00739 #endif