Xform.h
上传用户:kellyonhid
上传日期:2013-10-12
资源大小:932k
文件大小:37k
源码类别:

3D图形编程

开发平台:

Visual C++

  1. ////////////////////////////////////////////////////////////
  2. // Xform.h
  3. //
  4. // A class for doing 3D transformations using 4x4 matrices
  5. ////////////////////////////////////////////////////////////
  6. #ifndef _xform_h_
  7. #define _xform_h_
  8. #include <assert.h>
  9. #include <math.h>
  10. #include <float.h>
  11. #include <iostream.h>
  12. #include <iomanip.h>
  13. #include <algo.h>
  14. #include "Pnt3.h"
  15. #ifdef __GNUC__
  16. // G++ implements the standard for templated friend functions of template
  17. // classes.  This means that the following forward declarations are necessary..
  18. template <class T>
  19. class Xform;
  20. template <class T>
  21. Xform<T> operator*(const Xform<T> &a, const Xform<T> &b); 
  22. template <class T>
  23. Xform<T> delta(Xform<T> a, const Xform<T> &b); 
  24. template <class T>
  25. Xform<T> linear_interp(const Xform<T> &a,
  26.                        const Xform<T> &b,
  27.                        double          t);
  28. template <class T>
  29. Xform<T> bilinear_interp(const Xform<T> &u0v0,
  30.                          const Xform<T> &u1v0,
  31.                          const Xform<T> &u0v1,
  32.                          const Xform<T> &u1v1,
  33.                          double u, double v);
  34. template <class T>
  35. Xform<T> relative_xform(const Xform<T> &a, Xform<T> b);
  36. template <class T>
  37. ostream& operator<<(ostream &out, const Xform<T> &xf);
  38. template <class T>
  39. istream& operator>>(istream & in, Xform<T> &xf);
  40. #endif
  41. // logically Xform is applied to a point: p' = M*p
  42. // however, the transpose of the M is stored 
  43. // to keep it compatible with OpenGL
  44. template <class T> // use only with float or double
  45. class Xform {
  46. private:
  47.   T m[4][4];         // column major order
  48. public:
  49.   Xform(void);
  50.   Xform(const double *a);  // from OpenGL matrix
  51.   Xform(const float  *a);  // from OpenGL matrix
  52.   Xform(const T r[3][3], const T t[3]);
  53.   Xform<T> &operator=(const double *a);
  54.   Xform<T> &operator=(const float *a);
  55.   Xform<T> &operator=(const Xform<T> &xf);
  56.   Xform<T> &fromQuaternion(const double q[4], // q == {w,x,y,z}
  57.    double tx = 0.0,
  58.    double ty = 0.0, 
  59.    double tz = 0.0);
  60.   Xform<T> &fromQuaternion(const float q[4],  // q == {w,x,y,z}
  61.    float tx = 0.0,
  62.    float ty = 0.0, 
  63.    float tz = 0.0);
  64.   void toQuaternion(double q[4]) const;
  65.   void toQuaternion(float q[4]) const;
  66.   Xform<T> &addQuaternion(T q0, T q1, T q2, T q3, 
  67.   T tx = 0.0, T ty = 0.0, T tz = 0.0);
  68.   Xform<T> &addQuaternion(const float  *q, int n = 4);  // n == 4,7
  69.   Xform<T> &addQuaternion(const double *q, int n = 4);  // n == 4,7
  70.   void fromEuler(const T ea[3], int order);
  71.   void toEuler(T ea[3], int order);
  72.   Xform<T> &fromFrame(const Pnt3 &x, 
  73.       const Pnt3 &y,
  74.       const Pnt3 &z,
  75.       const Pnt3 &org);
  76.   Xform<T> &fromRotTrans(const T r[3][3], const T t[3]);
  77.   bool isIdentity (void) const;
  78.   Xform<T> &identity(void);             // set to identity
  79.   Xform<T> &fast_invert(void);          // assume rot + trans
  80.   Xform<T> &invert(void);               // general inversion
  81.   void translate(const double t[3]);    // M <- T*M
  82.   void translate(const float  t[3]);    // M <- T*M
  83.   void translate(T x, T y, T z);        // M <- T*M
  84.   void getTranslation(double t[3]) const;
  85.   void getTranslation(float  t[3]) const;
  86.   void removeTranslation(void);
  87.   void removeTranslation(double t[3]);
  88.   void removeTranslation(float t[3]);
  89.   void scale(const double t[3]);    // M <- S*M
  90.   void scale(const float  t[3]);    // M <- S*M
  91.   void scale(T x, T y, T z);        // M <- S*M
  92.   void get_e(int i, T e[3]) const; // get a basis vector, i=0,1,2
  93.   Xform<T> &rotX(T a);                  // M <- R*M
  94.   Xform<T> &rotY(T a);                  // M <- R*M
  95.   Xform<T> &rotZ(T a);                  // M <- R*M
  96.   Xform<T> &rot(T angle, T ax, T ay, T az); // M <- R*M
  97.   Xform<T> &rot(T angle, T ax, T ay, T az,
  98. T ox, T oy, T oz); // M <- R*M
  99.   Xform<T> &rotQ(T q0, T q1, T q2, T q3);   // M <- R*M
  100.   void      get_rot(T &angle, T &ax, T &ay, T &az);
  101.   void apply(const double i[3], double o[3]) const; // o = M*i
  102.   void apply(const float i[3],  float o[3]) const;  // o = M*i
  103.   void apply_inv(const double i[3], double o[3]) const; // o = M^-1*i
  104.   void apply_inv(const float i[3],  float o[3]) const;  // o = M^-1*i
  105.   void operator()(double i[3]) const;   // i <- M*i 
  106.   void operator()(float  i[3]) const;   // i <- M*i 
  107.   // apply to normal vector (no translation, only rotation)
  108.   void apply_nrm(const double i[3], double o[3]) const; // o = M*i
  109.   void apply_nrm(const float i[3],  float o[3]) const;  // o = M*i
  110.   T&   operator()(int i, int j);        // indexed access
  111.   T    operator()(int i, int j) const;  // indexed access
  112.   operator const T *(void) const { return m[0]; }  // array access
  113.   operator       T *(void)       { return m[0]; }
  114.   Pnt3 unproject(float u, float v, float z) const; // all input [-1,1]
  115.   Pnt3 unproject_fast(float u, float v, float z) const;
  116.   Xform<T> &operator*=(const Xform<T> &a); // (*this) = a * (*this)
  117.   // test how close to a rigid transformation the current
  118.   // transformation is, ideally returns 0
  119.   float test_rigidity(void);
  120.   // enforce the rigidity of the xform by setting the projective
  121.   // part to 0 0 0 1 and making sure rotation part is just a rotation
  122.   Xform<T> &enforce_rigidity(void);
  123. #ifndef __GNUC__
  124.   friend Xform<T> operator*(const Xform<T> &a,     // a*b
  125.     const Xform<T> &b); 
  126.   friend Xform<T> delta(Xform<T> a,                // d * a = b
  127. const Xform<T> &b); 
  128.   friend Xform<T> linear_interp(const Xform<T> &a, // r=t*a+(1-t)*b
  129. const Xform<T> &b,
  130. double          t);
  131.   friend Xform<T> bilinear_interp(const Xform<T> &u0v0,
  132.   const Xform<T> &u1v0,
  133.   const Xform<T> &u0v1,
  134.   const Xform<T> &u1v1,
  135.   double u, double v);
  136.   friend Xform<T> relative_xform(const Xform<T> &a, 
  137.  Xform<T> b); // c = b^-1 * a
  138.   friend ostream& operator<<(ostream &out, const Xform<T> &xf);
  139.   friend istream& operator>>(istream & in,       Xform<T> &xf);
  140. #else
  141.   friend Xform<T> operator*<>(const Xform<T> &a,     // a*b
  142.       const Xform<T> &b); 
  143.   friend Xform<T> delta<>(Xform<T> a,                // d * a = b
  144.   const Xform<T> &b); 
  145.   friend Xform<T> linear_interp<>(const Xform<T> &a, // r=t*a+(1-t)*b
  146.   const Xform<T> &b,
  147.   double          t);
  148.   friend Xform<T> bilinear_interp<>(const Xform<T> &u0v0,
  149.     const Xform<T> &u1v0,
  150.     const Xform<T> &u0v1,
  151.     const Xform<T> &u1v1,
  152.     double u, double v);
  153.   friend Xform<T> relative_xform<>(const Xform<T> &a, 
  154.    Xform<T> b); // c = b^-1 * a
  155.   friend ostream& operator<< <> (ostream &out, const Xform<T> &xf);
  156.   friend istream& operator>> <> (istream & in,       Xform<T> &xf);
  157. #endif
  158. };
  159. template <class T> inline
  160. Xform<T>::Xform(void) 
  161. {
  162.   m[1][0] = m[2][0] = m[3][0] = m[0][1] = m[2][1] = m[3][1] = 0.0;
  163.   m[0][2] = m[1][2] = m[3][2] = m[0][3] = m[1][3] = m[2][3] = 0.0;
  164.   m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0;
  165. }
  166. template <class T> inline
  167. Xform<T>::Xform(const double *a) 
  168. {
  169.   m[0][0] = a[0]; m[0][1] = a[1]; m[0][2] = a[2]; m[0][3] = a[3];
  170.   m[1][0] = a[4]; m[1][1] = a[5]; m[1][2] = a[6]; m[1][3] = a[7];
  171.   m[2][0] = a[8]; m[2][1] = a[9]; m[2][2] = a[10];m[2][3] = a[11];
  172.   m[3][0] = a[12];m[3][1] = a[13];m[3][2] = a[14];m[3][3] = a[15];
  173. }
  174. template <class T> inline
  175. Xform<T>::Xform(const float *a) 
  176. {
  177.   m[0][0] = a[0]; m[0][1] = a[1]; m[0][2] = a[2]; m[0][3] = a[3];
  178.   m[1][0] = a[4]; m[1][1] = a[5]; m[1][2] = a[6]; m[1][3] = a[7];
  179.   m[2][0] = a[8]; m[2][1] = a[9]; m[2][2] = a[10];m[2][3] = a[11];
  180.   m[3][0] = a[12];m[3][1] = a[13];m[3][2] = a[14];m[3][3] = a[15];
  181. }
  182. template <class T> inline
  183. Xform<T>::Xform(const T r[3][3], const T t[3])
  184. {
  185.   m[0][0] = r[0][0]; m[0][1]=r[1][0]; m[0][2]=r[2][0]; m[0][3]=0.0;
  186.   m[1][0] = r[0][1]; m[1][1]=r[1][1]; m[1][2]=r[2][1]; m[1][3]=0.0;
  187.   m[2][0] = r[0][2]; m[2][1]=r[1][2]; m[2][2]=r[2][2]; m[2][3]=0.0;
  188.   m[3][0] = t[0]; m[3][1] = t[1]; m[3][2] = t[2]; m[3][3] = 1.0;
  189. }
  190. template <class T> inline Xform<T> &
  191. Xform<T>::operator=(const double *a) 
  192. {
  193.   m[0][0] = a[0]; m[0][1] = a[1]; m[0][2] = a[2]; m[0][3] = a[3];
  194.   m[1][0] = a[4]; m[1][1] = a[5]; m[1][2] = a[6]; m[1][3] = a[7];
  195.   m[2][0] = a[8]; m[2][1] = a[9]; m[2][2] = a[10];m[2][3] = a[11];
  196.   m[3][0] = a[12];m[3][1] = a[13];m[3][2] = a[14];m[3][3] = a[15];
  197.   return *this;
  198. }
  199. template <class T> inline Xform<T> &
  200. Xform<T>::operator=(const float *a) 
  201. {
  202.   m[0][0] = a[0]; m[0][1] = a[1]; m[0][2] = a[2]; m[0][3] = a[3];
  203.   m[1][0] = a[4]; m[1][1] = a[5]; m[1][2] = a[6]; m[1][3] = a[7];
  204.   m[2][0] = a[8]; m[2][1] = a[9]; m[2][2] = a[10];m[2][3] = a[11];
  205.   m[3][0] = a[12];m[3][1] = a[13];m[3][2] = a[14];m[3][3] = a[15];
  206.   return *this;
  207. }
  208. template <class T> inline Xform<T> &
  209. Xform<T>::operator=(const Xform<T> &xf) 
  210. {
  211.   return operator=((const T *) xf);
  212. }
  213. // see Graphics Gems III p. 465
  214. // note quaternion order: w,x,y,z
  215. template <class T> inline Xform<T> &
  216. Xform<T>::fromQuaternion(const double q[4],
  217.  double tx, double ty, double tz)
  218. {
  219.   // q doesn't have to be unit
  220.   T norm2 = q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3];
  221.   T s = (norm2 > 0.0) ? 2.0/norm2 : 0.0;
  222.   T xs = q[1]*s,   ys = q[2]*s,   zs = q[3]*s;
  223.   T wx = q[0]*xs,  wy = q[0]*ys,  wz = q[0]*zs;
  224.   T xx = q[1]*xs,  xy = q[1]*ys,  xz = q[1]*zs;
  225.   T yy = q[2]*ys,  yz = q[2]*zs,  zz = q[3]*zs;
  226.   
  227.   m[0][0] = 1.0 - (yy+zz);  m[0][1] = xy + wz;  m[0][2] = xz - wy;
  228.   m[1][0] = xy - wz;  m[1][1] = 1.0 - (xx+zz);  m[1][2] = yz + wx;
  229.   m[2][0] = xz + wy;  m[2][1] = yz - wx;  m[2][2] = 1.0 - (xx+yy);
  230.   
  231.   m[3][0] = tx;  m[3][1] = ty;  m[3][2] = tz;
  232.   m[0][3] = m[1][3] = m[2][3] = 0.0;
  233.   m[3][3] = 1.0;
  234.   return *this;
  235. }
  236. template <class T> inline Xform<T> &
  237. Xform<T>::fromQuaternion(const float q[4],
  238.  float tx, float ty, float tz)
  239. {
  240.   // q doesn't have to be unit
  241.   T norm2 = q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3];
  242.   T s = (norm2 > 0.0) ? 2.0/norm2 : 0.0;
  243.   T xs = q[1]*s,   ys = q[2]*s,   zs = q[3]*s;
  244.   T wx = q[0]*xs,  wy = q[0]*ys,  wz = q[0]*zs;
  245.   T xx = q[1]*xs,  xy = q[1]*ys,  xz = q[1]*zs;
  246.   T yy = q[2]*ys,  yz = q[2]*zs,  zz = q[3]*zs;
  247.   
  248.   m[0][0] = 1.0 - (yy+zz);  m[0][1] = xy + wz;  m[0][2] = xz - wy;
  249.   m[1][0] = xy - wz;  m[1][1] = 1.0 - (xx+zz);  m[1][2] = yz + wx;
  250.   m[2][0] = xz + wy;  m[2][1] = yz - wx;  m[2][2] = 1.0 - (xx+yy);
  251.   m[3][0] = tx;  m[3][1] = ty;  m[3][2] = tz;
  252.   m[0][3] = m[1][3] = m[2][3] = 0.0;
  253.   m[3][3] = 1.0;
  254.   return *this;
  255. }
  256. // From Graphics Gems IV p. 213 
  257. // note transposed matrix and quaternion order w,x,y,z
  258. // see also Graphics Gems II pp. 351 - 354
  259. // Ignore translation and projective parts.
  260. // This algorithm avoids near-zero divides by looking for a 
  261. // large component - first w, then x, y, or z.  
  262. // When the trace is greater than zero, |w| is greater than 1/2,
  263. // which is as small as a largest component can be.
  264. // Otherwise, the largest diagonal entry corresponds to the 
  265. // largest of |x|, |y|, or |z|, one of which must be larger 
  266. // than |w|, and at least 1/2.
  267. template <class T> inline void 
  268. Xform<T>::toQuaternion(double q[4]) const
  269. {
  270.   T tr = m[0][0] + m[1][1]+ m[2][2];
  271.   if (tr >= 0.0) {
  272.     T s = sqrt(tr + m[3][3]);
  273.     q[0] = s*0.5;
  274.     s = 0.5 / s;
  275.     q[1] = (m[1][2] - m[2][1]) * s;
  276.     q[2] = (m[2][0] - m[0][2]) * s;
  277.     q[3] = (m[0][1] - m[1][0]) * s;
  278.   } else {
  279.     int i = 0;
  280.     if (m[1][1] > m[0][0]) i = 1;
  281.     if (m[2][2] > m[i][i]) i = 2;
  282.     int j = (i+1)%3;
  283.     int k = (j+1)%3;
  284.     T s = sqrt(m[3][3] + (m[i][i] - (m[j][j] + m[k][k])));
  285.     q[i+1] = s * 0.5;
  286.     s = 0.5 / s;
  287.     q[j+1] = (m[i][j] + m[j][i]) * s;
  288.     q[k+1] = (m[i][k] + m[k][i]) * s;
  289.     q[0]   = (m[j][k] - m[k][j]) * s;
  290.   }
  291.   if (m[3][3] != 1.0) {
  292.     T tmp = 1.0/sqrt(m[3][3]);
  293.     q[0]*=tmp; q[1]*=tmp; q[2]*=tmp; q[3]*=tmp; 
  294.   }
  295. }
  296. template <class T> inline void 
  297. Xform<T>::toQuaternion(float q[4]) const
  298. {
  299.   T tr = m[0][0] + m[1][1]+ m[2][2];
  300.   if (tr >= 0.0) {
  301.     T s = sqrt(tr + m[3][3]);
  302.     q[0] = s*0.5;
  303.     s = 0.5 / s;
  304.     q[1] = (m[1][2] - m[2][1]) * s;
  305.     q[2] = (m[2][0] - m[0][2]) * s;
  306.     q[3] = (m[0][1] - m[1][0]) * s;
  307.   } else {
  308.     int i = 0;
  309.     if (m[1][1] > m[0][0]) i = 1;
  310.     if (m[2][2] > m[i][i]) i = 2;
  311.     int j = (i+1)%3;
  312.     int k = (j+1)%3;
  313.     T s = sqrt(m[3][3] + (m[i][i] - (m[j][j] + m[k][k])));
  314.     q[i+1] = s * 0.5;
  315.     s = 0.5 / s;
  316.     q[j+1] = (m[i][j] + m[j][i]) * s;
  317.     q[k+1] = (m[i][k] + m[k][i]) * s;
  318.     q[0]   = (m[j][k] - m[k][j]) * s;
  319.   }
  320.   if (m[3][3] != 1.0) {
  321.     T tmp = 1.0/sqrt(m[3][3]);
  322.     q[0]*=tmp; q[1]*=tmp; q[2]*=tmp; q[3]*=tmp; 
  323.   }
  324. }
  325. template <class T> inline Xform<T> &
  326. Xform<T>::addQuaternion(T q0, T q1, T q2, T q3, T tx, T ty, T tz)
  327. {
  328.   rotQ(q0,q1,q2,q3);
  329.   translate(tx,ty,tz);
  330.   return *this;
  331. }
  332. template <class T> inline Xform<T> &
  333. Xform<T>::addQuaternion(const float *q, int n)
  334. {
  335.   rotQ(q[0],q[1],q[2],q[3]);
  336.   if (n == 7)
  337.     translate(q[4],q[5],q[6]);
  338.   return *this;
  339. }
  340. template <class T> inline Xform<T> &
  341. Xform<T>::addQuaternion(const double *q, int n)
  342. {
  343.   rotQ(q[0],q[1],q[2],q[3]);
  344.   if (n == 7)
  345.     translate(q[4],q[5],q[6]);
  346.   return *this;
  347. }
  348. //
  349. // Euler angle stuff from Graphics Gems IV pp. 222-229
  350. //
  351. /*** Order type constants, constructors, extractors ***/
  352.     /* There are 24 possible conventions, designated by:    */
  353.     /*   o EulAxI = axis used initially     */
  354.     /*   o EulPar = parity of axis permutation     */
  355.     /*   o EulRep = repetition of initial axis as last     */
  356.     /*   o EulFrm = frame from which axes are taken     */
  357.     /* Axes I,J,K will be a permutation of X,Y,Z.     */
  358.     /* Axis H will be either I or K, depending on EulRep.   */
  359.     /* Frame S takes axes from initial static frame.     */
  360.     /* If ord = (AxI=X, Par=Even, Rep=No, Frm=S), then     */
  361.     /* {a,b,c,ord} means Rz(c)Ry(b)Rx(a), where Rz(c)v     */
  362.     /* rotates v around Z by c radians.     */
  363. #define EulFrmS      0
  364. #define EulFrmR      1
  365. #define EulFrm(ord)  ((unsigned)(ord)&1)
  366. #define EulRepNo     0
  367. #define EulRepYes    1
  368. #define EulRep(ord)  (((unsigned)(ord)>>1)&1)
  369. #define EulParEven   0
  370. #define EulParOdd    1
  371. #define EulPar(ord)  (((unsigned)(ord)>>2)&1)
  372. #define EulSafe      "00010200"
  373. #define EulNext      "01020001"
  374. #define EulAxI(ord)  ((int)(EulSafe[(((unsigned)(ord)>>3)&3)]))
  375. #define EulAxJ(ord)  ((int)(EulNext[EulAxI(ord)+(EulPar(ord)==EulParOdd)]))
  376. #define EulAxK(ord)  ((int)(EulNext[EulAxI(ord)+(EulPar(ord)!=EulParOdd)]))
  377. #define EulAxH(ord)  ((EulRep(ord)==EulRepNo)?EulAxK(ord):EulAxI(ord))
  378. // EulGetOrd unpacks all useful information about order 
  379. // simultaneously. 
  380. #define EulGetOrd(ord,i,j,k,n,s,f) {
  381.   unsigned o=ord;f=o&1;o>>=1;s=o&1;o>>=1;
  382.   n=o&1;o>>=1;i=EulSafe[o&3];j=EulNext[i+n];
  383.   k=EulNext[i+1-n];}
  384. // EulOrd creates an order value between 0 and 23 from 4-tuple 
  385. // choices.
  386. #define EulOrd(i,p,r,f)    (((((((i)<<1)+(p))<<1)+(r))<<1)+(f))
  387. // Static axes 
  388. #define EulOrdXYZs    EulOrd(0,EulParEven,EulRepNo,EulFrmS)
  389. #define EulOrdXYXs    EulOrd(0,EulParEven,EulRepYes,EulFrmS)
  390. #define EulOrdXZYs    EulOrd(0,EulParOdd,EulRepNo,EulFrmS)
  391. #define EulOrdXZXs    EulOrd(0,EulParOdd,EulRepYes,EulFrmS)
  392. #define EulOrdYZXs    EulOrd(1,EulParEven,EulRepNo,EulFrmS)
  393. #define EulOrdYZYs    EulOrd(1,EulParEven,EulRepYes,EulFrmS)
  394. #define EulOrdYXZs    EulOrd(1,EulParOdd,EulRepNo,EulFrmS)
  395. #define EulOrdYXYs    EulOrd(1,EulParOdd,EulRepYes,EulFrmS)
  396. #define EulOrdZXYs    EulOrd(2,EulParEven,EulRepNo,EulFrmS)
  397. #define EulOrdZXZs    EulOrd(2,EulParEven,EulRepYes,EulFrmS)
  398. #define EulOrdZYXs    EulOrd(2,EulParOdd,EulRepNo,EulFrmS)
  399. #define EulOrdZYZs    EulOrd(2,EulParOdd,EulRepYes,EulFrmS)
  400. // Rotating axes
  401. #define EulOrdZYXr    EulOrd(0,EulParEven,EulRepNo,EulFrmR)
  402. #define EulOrdXYXr    EulOrd(0,EulParEven,EulRepYes,EulFrmR)
  403. #define EulOrdYZXr    EulOrd(0,EulParOdd,EulRepNo,EulFrmR)
  404. #define EulOrdXZXr    EulOrd(0,EulParOdd,EulRepYes,EulFrmR)
  405. #define EulOrdXZYr    EulOrd(1,EulParEven,EulRepNo,EulFrmR)
  406. #define EulOrdYZYr    EulOrd(1,EulParEven,EulRepYes,EulFrmR)
  407. #define EulOrdZXYr    EulOrd(1,EulParOdd,EulRepNo,EulFrmR)
  408. #define EulOrdYXYr    EulOrd(1,EulParOdd,EulRepYes,EulFrmR)
  409. #define EulOrdYXZr    EulOrd(2,EulParEven,EulRepNo,EulFrmR)
  410. #define EulOrdZXZr    EulOrd(2,EulParEven,EulRepYes,EulFrmR)
  411. #define EulOrdXYZr    EulOrd(2,EulParOdd,EulRepNo,EulFrmR)
  412. #define EulOrdZYZr    EulOrd(2,EulParOdd,EulRepYes,EulFrmR)
  413. template <class T> inline void 
  414. Xform<T>::fromEuler(const T _ea[3], int order)
  415. {
  416.   T ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
  417.   int i,j,k,n,s,f;
  418.   EulGetOrd(order,i,j,k,n,s,f);
  419.   T ea[3];
  420.   if (f==EulFrmR) { ea[0]=_ea[2]; ea[1]=_ea[1]; ea[2]=_ea[0]; }
  421.   else            { ea[0]=_ea[0]; ea[1]=_ea[1]; ea[2]=_ea[2]; }
  422.   if (n==EulParOdd) {ea[0] = -ea[0]; ea[1] =-ea[1]; ea[2] =-ea[2];}
  423.   ti = ea[0];   tj = ea[1];   th = ea[2];
  424.   ci = cos(ti); cj = cos(tj); ch = cos(th);
  425.   si = sin(ti); sj = sin(tj); sh = sin(th);
  426.   cc = ci*ch; cs = ci*sh; sc = si*ch; ss = si*sh;
  427.   if (s==EulRepYes) {
  428.     m[i][i] = cj;     m[j][i] =  sj*si;    m[k][i] =  sj*ci;
  429.     m[i][j] = sj*sh;  m[j][j] = -cj*ss+cc; m[k][j] = -cj*cs-sc;
  430.     m[i][k] = -sj*ch; m[j][k] =  cj*sc+cs; m[k][k] =  cj*cc-ss;
  431.   } else {
  432.     m[i][i] = cj*ch; m[j][i] = sj*sc-cs; m[k][i] = sj*cc+ss;
  433.     m[i][j] = cj*sh; m[j][j] = sj*ss+cc; m[k][j] = sj*cs-sc;
  434.     m[i][k] = -sj;   m[j][k] = cj*si;    m[k][k] = cj*ci;
  435.   }
  436.   m[3][0]=m[3][1]=m[3][2]=m[0][3]=m[1][3]=m[2][3]=0.0; m[3][3]=1.0;
  437. }
  438. template <class T> inline void 
  439. Xform<T>::toEuler(T ea[3], int order)
  440. {
  441.   int i,j,k,n,s,f;
  442.   EulGetOrd(order,i,j,k,n,s,f);
  443.   if (s==EulRepYes) {
  444.     T sy = sqrt(m[j][i]*m[j][i] + m[k][i]*m[k][i]);
  445.     if (sy > 16*FLT_EPSILON) {
  446.       ea[0] = atan2(m[j][i], m[i][k]);
  447.       ea[1] = atan2(sy, m[i][i]);
  448.       ea[2] = atan2(m[i][j], -m[i][k]);
  449.     } else {
  450.       ea[0] = atan2(-m[k][j], m[j][j]);
  451.       ea[1] = atan2(sy, m[i][i]);
  452.       ea[2] = 0;
  453.     }
  454.   } else {
  455.     T cy = sqrt(m[i][i]*m[i][i] + m[i][j]*m[i][j]);
  456.     if (cy > 16*FLT_EPSILON) {
  457.       ea[0] = atan2(m[j][k], m[k][k]);
  458.       ea[1] = atan2(-m[i][k], cy);
  459.       ea[2] = atan2(m[i][j], m[i][i]);
  460.     } else {
  461.       ea[0] = atan2(-m[k][j], m[j][j]);
  462.       ea[1] = atan2(-m[i][k], cy);
  463.       ea[2] = 0;
  464.     }
  465.   }
  466.   if (n==EulParOdd) {ea[0] = -ea[0]; ea[1] = -ea[1]; ea[2]=-ea[2];}
  467.   if (f==EulFrmR)   {T t = ea[0]; ea[0] = ea[2]; ea[2] = t;}
  468. }
  469. template <class T> inline Xform<T> &
  470. Xform<T>::fromFrame(const Pnt3 &x, 
  471.     const Pnt3 &y,
  472.     const Pnt3 &z,
  473.     const Pnt3 &org)
  474. {
  475.   m[0][0] = x[0]; m[0][1] = x[1]; m[0][2] = x[2]; m[0][3] = 0.0;
  476.   m[1][0] = y[0]; m[1][1] = y[1]; m[1][2] = y[2]; m[1][3] = 0.0;
  477.   m[2][0] = z[0]; m[2][1] = z[1]; m[2][2] = z[2]; m[2][3] = 0.0;
  478.   m[3][0] = org[0]; m[3][1] = org[1]; m[3][2] = org[2]; m[3][3] = 1.0;
  479.   return *this;
  480. }
  481. template <class T> inline Xform<T> &
  482. Xform<T>::fromRotTrans(const T r[3][3], const T t[3])
  483. {
  484.   m[0][0] = r[0][0]; m[0][1]=r[1][0]; m[0][2]=r[2][0]; m[0][3]=0.0;
  485.   m[1][0] = r[0][1]; m[1][1]=r[1][1]; m[1][2]=r[2][1]; m[1][3]=0.0;
  486.   m[2][0] = r[0][2]; m[2][1]=r[1][2]; m[2][2]=r[2][2]; m[2][3]=0.0;
  487.   m[3][0] = t[0]; m[3][1] = t[1]; m[3][2] = t[2]; m[3][3] = 1.0;
  488.   return *this;
  489. }
  490. template <class T> inline bool
  491. Xform<T>::isIdentity (void) const
  492. {
  493.   for (int i = 0; i < 4; i++)
  494.     for (int j = 0; j < 4; j++)
  495.       if (m[i][j] != (float)(i == j))
  496. return false;
  497.   return true;
  498. }
  499. template <class T> inline Xform<T> & 
  500. Xform<T>::identity(void)
  501. {
  502.   m[1][0] = m[2][0] = m[3][0] = m[0][1] = m[2][1] = m[3][1] = 0.0;
  503.   m[0][2] = m[1][2] = m[3][2] = m[0][3] = m[1][3] = m[2][3] = 0.0;
  504.   m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0;
  505.   return *this;
  506. }
  507. template <class T> inline Xform<T> & 
  508. Xform<T>::fast_invert(void)
  509. {
  510.   T tmp;
  511.   // transpose the rotation part
  512.   tmp = m[0][1]; m[0][1] = m[1][0]; m[1][0] = tmp;
  513.   tmp = m[0][2]; m[0][2] = m[2][0]; m[2][0] = tmp;
  514.   tmp = m[1][2]; m[1][2] = m[2][1]; m[2][1] = tmp;
  515.   // translation (T' = - T * R^-1)
  516.   T tx = -m[3][0];
  517.   T ty = -m[3][1];
  518.   T tz = -m[3][2];
  519.   m[3][0] = tx * m[0][0] + ty * m[1][0] + tz * m[2][0];
  520.   m[3][1] = tx * m[0][1] + ty * m[1][1] + tz * m[2][1];
  521.   m[3][2] = tx * m[0][2] + ty * m[1][2] + tz * m[2][2];
  522.   return *this;
  523. }
  524. template <class T> inline Xform<T> & 
  525. Xform<T>::invert(void)
  526. {
  527.    // Compute inverse matrix in place using Gauss-Jordan elimination
  528.    // with full pivoting for better numerical stability.
  529.    int swap_col[4], swap_row[4];
  530.    int pivot_used[4] = {0, 0, 0, 0};
  531.    int maxc, maxr, i, r, c;
  532.    double max, temp, pivot_inv;
  533.    
  534.    for (i=0; i<4; i++) {
  535.       // Determine largest magnitude pivot element
  536.       max = 0.0;
  537.       for (r=0; r<4; r++) {
  538.          if (pivot_used[r] != 1) {
  539.     for (c=0; c<4; c++) {
  540.        if (pivot_used[c] == 0) {
  541.           if (fabs(m[r][c]) >= max) {
  542.              max = fabs(m[r][c]);
  543.              maxr = r;
  544.              maxc = c;
  545.           }
  546.        }
  547.                else if (pivot_used[c] > 1) {
  548.           cerr << "invert: Singular Matrix-1" << endl;
  549.           return *this;
  550.        }
  551.             }
  552.  }
  553.       }
  554.       pivot_used[maxc] += 1;
  555.       // Swap rows to get the pivot element on the diagonal
  556.       if (maxr != maxc)
  557.          for (c=0; c<4; c++)
  558.             swap(m[maxr][c], m[maxc][c]);
  559.       // We need to remember what we swapped, for reversing later...
  560.       swap_row[i] = maxr;
  561.       swap_col[i] = maxc;
  562.       // If the pivot value is zero, matrix is singular
  563.       if (m[maxc][maxc] == 0.0) {
  564.          cerr << "invert: Singular Matrix-2" << endl;
  565.          return *this;
  566.       }
  567.       // Divide the row by the pivot value
  568.       pivot_inv = 1.0 / m[maxc][maxc];
  569.       m[maxc][maxc] = 1.0;
  570.       for (c=0; c<4; c++)
  571.          m[maxc][c] *= pivot_inv;
  572.       // Reduce the other, non-pivot rows
  573.       for (r=0; r<4; r++)  {
  574.          if (r != maxc) {
  575.     temp = m[r][maxc];
  576.     m[r][maxc] = 0.0;
  577.     for (c=0; c<4; c++)
  578.                m[r][c] -= m[maxc][c] * temp;
  579.          }
  580.       }
  581.    }
  582.    // Fix things up by swapping columns back in reverse order
  583.    
  584.    for (i=3; i>=0; i--) {
  585.       if (swap_row[i] != swap_col[i])
  586.          for (r=0; r<4; r++)
  587.             swap(m[r][swap_row[i]], m[r][swap_col[i]]);
  588.    }
  589.    return *this;
  590. }
  591. template <class T> inline void 
  592. Xform<T>::translate(const double t[3]) // M <- T*M
  593. {
  594.   for (int i=0; i<4; i++) m[i][0] += t[0]*m[i][3];
  595.   for (i=0; i<4; i++)     m[i][1] += t[1]*m[i][3];
  596.   for (i=0; i<4; i++)     m[i][2] += t[2]*m[i][3];
  597. }
  598. template <class T> inline void 
  599. Xform<T>::translate(const float t[3]) // M <- T*M
  600. {
  601.   for (int i=0; i<4; i++) m[i][0] += t[0]*m[i][3];
  602.   for (i=0; i<4; i++)     m[i][1] += t[1]*m[i][3];
  603.   for (i=0; i<4; i++)     m[i][2] += t[2]*m[i][3];
  604. }
  605. template <class T> inline void 
  606. Xform<T>::translate(T x, T y, T z) // M <- T*M
  607. {
  608.   for (int i=0; i<4; i++) m[i][0] += x*m[i][3];
  609.   for (i=0; i<4; i++)     m[i][1] += y*m[i][3];
  610.   for (i=0; i<4; i++)     m[i][2] += z*m[i][3];
  611. }
  612. template <class T> inline void 
  613. Xform<T>::getTranslation(double t[3]) const
  614. {
  615.   t[0] = m[3][0];  t[1] = m[3][1];  t[2] = m[3][2];
  616. }
  617. template <class T> inline void 
  618. Xform<T>::getTranslation(float t[3]) const
  619. {
  620.   t[0] = m[3][0];  t[1] = m[3][1];  t[2] = m[3][2];
  621. }
  622. template <class T> inline void 
  623. Xform<T>::removeTranslation(void)
  624. {
  625.   m[3][0] = m[3][1] = m[3][2] = 0.0;
  626. }
  627. template <class T> inline void 
  628. Xform<T>::removeTranslation(double t[3])
  629. {
  630.   t[0] = m[3][0];  t[1] = m[3][1];  t[2] = m[3][2];
  631.   m[3][0] = m[3][1] = m[3][2] = 0.0;
  632. }
  633. template <class T> inline void 
  634. Xform<T>::removeTranslation(float t[3])
  635. {
  636.   t[0] = m[3][0];  t[1] = m[3][1];  t[2] = m[3][2];
  637.   m[3][0] = m[3][1] = m[3][2] = 0.0;
  638. }
  639. template <class T> inline void 
  640. Xform<T>::scale(const double s[3]) // M <- S*M
  641. {
  642.   m[0][0] *= s[0]; m[1][0] *= s[0]; m[2][0] *= s[0]; m[3][0] *= s[0];
  643.   m[0][1] *= s[1]; m[1][1] *= s[1]; m[2][1] *= s[1]; m[3][1] *= s[1];
  644.   m[0][2] *= s[2]; m[1][2] *= s[2]; m[2][2] *= s[2]; m[3][2] *= s[2];
  645. }
  646. template <class T> inline void 
  647. Xform<T>::scale(const float s[3]) // M <- S*M
  648. {
  649.   m[0][0] *= s[0]; m[1][0] *= s[0]; m[2][0] *= s[0]; m[3][0] *= s[0];
  650.   m[0][1] *= s[1]; m[1][1] *= s[1]; m[2][1] *= s[1]; m[3][1] *= s[1];
  651.   m[0][2] *= s[2]; m[1][2] *= s[2]; m[2][2] *= s[2]; m[3][2] *= s[2];
  652. }
  653. template <class T> inline void 
  654. Xform<T>::scale(T x, T y, T z) // M <- S*M
  655. {
  656.   m[0][0] *= x; m[1][0] *= x; m[2][0] *= x; m[3][0] *= x;
  657.   m[0][1] *= y; m[1][1] *= y; m[2][1] *= y; m[3][1] *= y;
  658.   m[0][2] *= z; m[1][2] *= z; m[2][2] *= z; m[3][2] *= z;
  659. }
  660. template <class T> inline void 
  661. Xform<T>::get_e(int i, T e[3]) const
  662. {
  663.   e[0] = m[i][0];  e[1] = m[i][1];  e[2] = m[i][2];
  664. }
  665. template <class T> inline Xform<T> &
  666. Xform<T>::rotX(T a) // M <- R*M
  667. {
  668.   double sa = sin(a);
  669.   double ca = cos(a);
  670.   double row1[4];
  671.   for (int i=0; i<4; i++) row1[i] = m[i][1]; // temp. copy
  672.   for (i=0; i<4; i++)     m[i][1] = ca*row1[i] - sa*m[i][2];
  673.   for (i=0; i<4; i++)     m[i][2] = sa*row1[i] + ca*m[i][2];
  674.   return *this;
  675. }
  676. template <class T> inline Xform<T> &
  677. Xform<T>::rotY(T a) // M <- R*M
  678. {
  679.   double sa = sin(a);
  680.   double ca = cos(a);
  681.   double row0[4];
  682.   for (int i=0; i<4; i++) row0[i] =  m[i][0]; // temp. copy
  683.   for (i=0; i<4; i++)     m[i][0] =  ca*row0[i] + sa*m[i][2];
  684.   for (i=0; i<4; i++)     m[i][2] = -sa*row0[i] + ca*m[i][2];
  685.   return *this;
  686. }
  687. template <class T> inline Xform<T> & 
  688. Xform<T>::rotZ(T a) // M <- R*M
  689. {
  690.   double sa = sin(a);
  691.   double ca = cos(a);
  692.   double row0[4];
  693.   for (int i=0; i<4; i++) row0[i] = m[i][0]; // temp. copy
  694.   for (i=0; i<4; i++)     m[i][0] = ca*row0[i] - sa*m[i][1];
  695.   for (i=0; i<4; i++)     m[i][1] = sa*row0[i] + ca*m[i][1];
  696.   return *this;
  697. }
  698. // rotate around (0,0,0)
  699. template <class T> inline Xform<T> & 
  700. Xform<T>::rot(T angle, T ax, T ay, T az) // M <- R*M
  701. {
  702.   T q[4];
  703.   q[0] = cos(angle/2.0);
  704.   T fact = sin(angle/2.0) / sqrt(ax*ax+ay*ay+az*az);
  705.   q[1] = ax*fact;
  706.   q[2] = ay*fact;
  707.   q[3] = az*fact;
  708.   Xform<T> xf;
  709.   xf.fromQuaternion(q);
  710.   *this *= xf;
  711.   return *this;
  712. }
  713. // rotate around (ox,oy,oz)
  714. template <class T> inline Xform<T> & 
  715. Xform<T>::rot(T angle, T ax, T ay, T az,
  716.       T ox, T oy, T oz) // M <- R*M
  717. {
  718.   T q[4];
  719.   q[0] = cos(angle/2.0);
  720.   T fact = sin(angle/2.0) / sqrt(ax*ax+ay*ay+az*az);
  721.   q[1] = ax*fact;
  722.   q[2] = ay*fact;
  723.   q[3] = az*fact;
  724.   Xform<T> xf;
  725.   xf.fromQuaternion(q);
  726.   // add the part that makes the xf rotation to happen
  727.   // around (ox,oy,oz)
  728.   xf.m[3][0] += ox - (xf.m[0][0]*ox+xf.m[1][0]*oy+xf.m[2][0]*oz);
  729.   xf.m[3][1] += oy - (xf.m[0][1]*ox+xf.m[1][1]*oy+xf.m[2][1]*oz);
  730.   xf.m[3][2] += oz - (xf.m[0][2]*ox+xf.m[1][2]*oy+xf.m[2][2]*oz);
  731.   *this *= xf;
  732.   return *this;
  733. }
  734. template <class T> inline Xform<T> & 
  735. Xform<T>::rotQ(T q0, T q1, T q2, T q3)   // M <- R*M
  736. {
  737.   T q[4];
  738.   q[0] = q0;  q[1] = q1;  q[2] = q2;  q[3] = q3;
  739.   Xform<T> xf;
  740.   xf.fromQuaternion(q);
  741.   *this *= xf;
  742.   return *this;
  743. }
  744. template <class T> inline void
  745. Xform<T>::get_rot(T &angle, T &ax, T &ay, T &az)
  746. {
  747.   T q[4];
  748.   toQuaternion(q);
  749.   T len = sqrt(q[1]*q[1]+q[2]*q[2]+q[3]*q[3]);
  750.   if (len == 0.0) {
  751.     angle = ax = ay = 0.0; az = 1.0;
  752.   } else {
  753.     angle = acos(q[0]) * 2.0;
  754.     T invlen = 1.0/len;
  755.     if (sin(angle*.5) < 0.0) {
  756.       ax = -q[1]*invlen;
  757.       ay = -q[2]*invlen;
  758.       az = -q[3]*invlen;
  759.     } else {
  760.       ax = q[1]*invlen;
  761.       ay = q[2]*invlen;
  762.       az = q[3]*invlen;
  763.     }
  764.   }
  765. }
  766. template <class T> inline void 
  767. Xform<T>::apply(const double i[3], double o[3]) const // o = M*i
  768. {
  769.   T invw = 
  770.     1.0 / (m[0][3]*i[0]+m[1][3]*i[1]+m[2][3]*i[2]+m[3][3]);
  771.   o[0] = (m[0][0]*i[0]+m[1][0]*i[1]+m[2][0]*i[2]+m[3][0])*invw;
  772.   o[1] = (m[0][1]*i[0]+m[1][1]*i[1]+m[2][1]*i[2]+m[3][1])*invw;
  773.   o[2] = (m[0][2]*i[0]+m[1][2]*i[1]+m[2][2]*i[2]+m[3][2])*invw;
  774. }
  775. template <class T> inline void 
  776. Xform<T>::apply(const float i[3], float o[3]) const // o = M*i
  777. {
  778.   T invw = 
  779.     1.0 / (m[0][3]*i[0]+m[1][3]*i[1]+m[2][3]*i[2]+m[3][3]);
  780.   o[0] = (m[0][0]*i[0]+m[1][0]*i[1]+m[2][0]*i[2]+m[3][0])*invw;
  781.   o[1] = (m[0][1]*i[0]+m[1][1]*i[1]+m[2][1]*i[2]+m[3][1])*invw;
  782.   o[2] = (m[0][2]*i[0]+m[1][2]*i[1]+m[2][2]*i[2]+m[3][2])*invw;
  783. }
  784. template <class T> inline void 
  785. Xform<T>::apply_inv(const double i[3], double o[3]) const // o = M^-1*i
  786. {
  787.   T tx = i[0] - m[3][0];
  788.   T ty = i[1] - m[3][1];
  789.   T tz = i[2] - m[3][2];
  790.   o[0] = m[0][0]*tx + m[0][1]*ty + m[0][2]*tz;
  791.   o[1] = m[1][0]*tx + m[1][1]*ty + m[1][2]*tz;
  792.   o[2] = m[2][0]*tx + m[2][1]*ty + m[2][2]*tz;
  793. }
  794. template <class T> inline void 
  795. Xform<T>::apply_inv(const float i[3],  float o[3]) const // o = M^-1*i
  796. {
  797.   T tx = i[0] - m[3][0];
  798.   T ty = i[1] - m[3][1];
  799.   T tz = i[2] - m[3][2];
  800.   o[0] = m[0][0]*tx + m[0][1]*ty + m[0][2]*tz;
  801.   o[1] = m[1][0]*tx + m[1][1]*ty + m[1][2]*tz;
  802.   o[2] = m[2][0]*tx + m[2][1]*ty + m[2][2]*tz;
  803. }
  804. template <class T> inline void 
  805. Xform<T>::operator()(double i[3]) const
  806. {
  807.   T o[3];
  808.   o[0] = i[0]; o[1] = i[1]; o[2] = i[2];
  809.   T invw = 
  810.     1.0 / (m[0][3]*o[0]+m[1][3]*o[1]+m[2][3]*o[2]+m[3][3]);
  811.   i[0] = (m[0][0]*o[0]+m[1][0]*o[1]+m[2][0]*o[2]+m[3][0])*invw;
  812.   i[1] = (m[0][1]*o[0]+m[1][1]*o[1]+m[2][1]*o[2]+m[3][1])*invw;
  813.   i[2] = (m[0][2]*o[0]+m[1][2]*o[1]+m[2][2]*o[2]+m[3][2])*invw;
  814. }
  815. template <class T> inline void 
  816. Xform<T>::operator()(float i[3]) const
  817. {
  818.   T o[3];
  819.   o[0] = i[0]; o[1] = i[1]; o[2] = i[2];
  820.   T invw = 
  821.     1.0 / (m[0][3]*o[0]+m[1][3]*o[1]+m[2][3]*o[2]+m[3][3]);
  822.   i[0] = (m[0][0]*o[0]+m[1][0]*o[1]+m[2][0]*o[2]+m[3][0])*invw;
  823.   i[1] = (m[0][1]*o[0]+m[1][1]*o[1]+m[2][1]*o[2]+m[3][1])*invw;
  824.   i[2] = (m[0][2]*o[0]+m[1][2]*o[1]+m[2][2]*o[2]+m[3][2])*invw;
  825. }
  826. template <class T> inline void 
  827. Xform<T>::apply_nrm(const double i[3], double o[3]) const // o = M*i
  828. {
  829.   double invw = 
  830.     1.0 / (m[0][3]*i[0]+m[1][3]*i[1]+m[2][3]*i[2]+m[3][3]);
  831.   o[0] = (m[0][0]*i[0]+m[1][0]*i[1]+m[2][0]*i[2])*invw;
  832.   o[1] = (m[0][1]*i[0]+m[1][1]*i[1]+m[2][1]*i[2])*invw;
  833.   o[2] = (m[0][2]*i[0]+m[1][2]*i[1]+m[2][2]*i[2])*invw;
  834. }
  835. template <class T> inline void 
  836. Xform<T>::apply_nrm(const float i[3], float o[3]) const // o = M*i
  837. {
  838.   double invw = 
  839.     1.0 / (m[0][3]*i[0]+m[1][3]*i[1]+m[2][3]*i[2]+m[3][3]);
  840.   o[0] = (m[0][0]*i[0]+m[1][0]*i[1]+m[2][0]*i[2])*invw;
  841.   o[1] = (m[0][1]*i[0]+m[1][1]*i[1]+m[2][1]*i[2])*invw;
  842.   o[2] = (m[0][2]*i[0]+m[1][2]*i[1]+m[2][2]*i[2])*invw;
  843. }
  844. template <class T> inline T&
  845. Xform<T>::operator()(int i, int j)
  846. {
  847.   return m[j][i];
  848. }
  849. template <class T> inline T
  850. Xform<T>::operator()(int i, int j) const
  851. {
  852.   return m[j][i];
  853. }
  854. template <class T> inline Pnt3 
  855. Xform<T>::unproject(float u, float v, float z) const
  856. {
  857.   float w =  1.0/(u*m[0][3]+v*m[1][3]+z*m[2][3]+m[3][3]);
  858.   return Pnt3((u*m[0][0]+v*m[1][0]+z*m[2][0]+m[3][0])*w,
  859.       (u*m[0][1]+v*m[1][1]+z*m[2][1]+m[3][1])*w,
  860.       (u*m[0][2]+v*m[1][2]+z*m[2][2]+m[3][2])*w);
  861. }
  862. template <class T> inline Pnt3 
  863. Xform<T>::unproject_fast(float u, float v, float z) const
  864. {
  865.   float w =  1.0/(z*m[2][3]+m[3][3]);
  866.   return Pnt3((u*m[0][0]+m[3][0])*w,
  867.       (u*m[1][1]+m[3][1])*w,
  868.       -w);
  869. }
  870. template <class T> inline Xform<T> &
  871. Xform<T>::operator*=(const Xform<T> &a) // (*this) = a * (*this)
  872. {
  873.   Xform<T> b((T*)this);
  874.   for (int i=0; i<4; i++) {
  875.     for (int j=0; j<4; j++) {
  876.       m[j][i] = a.m[0][i] * b.m[j][0] + a.m[1][i] * b.m[j][1] +
  877.         a.m[2][i] * b.m[j][2] + a.m[3][i] * b.m[j][3];
  878.     }
  879.   }
  880.   return *this;
  881. }
  882. // test how close to a rigid transformation the current
  883. // transformation is, ideally returns 0
  884. template <class T> inline float
  885. Xform<T>::test_rigidity(void)
  886. {
  887.   float ans = 0.0;
  888.   // check the projective row
  889.   ans = max(ans, fabsf(m[0][3]));
  890.   ans = max(ans, fabsf(m[1][3]));
  891.   ans = max(ans, fabsf(m[2][3]));
  892.   ans = max(ans, fabsf(m[3][3]-1.0));
  893.   // test the dots of rows with itself
  894.   ans = max(ans, fabsf(dot(Pnt3(m[0]), Pnt3(m[0]))-1.0));
  895.   ans = max(ans, fabsf(dot(Pnt3(m[1]), Pnt3(m[1]))-1.0));
  896.   ans = max(ans, fabsf(dot(Pnt3(m[2]), Pnt3(m[2]))-1.0));
  897.   // test the dots of rows with other rows
  898.   ans = max(ans, fabsf(dot(Pnt3(m[0]), Pnt3(m[1]))));
  899.   ans = max(ans, fabsf(dot(Pnt3(m[1]), Pnt3(m[0]))));
  900.   ans = max(ans, fabsf(dot(Pnt3(m[2]), Pnt3(m[0]))));
  901.   ans = max(ans, fabsf(dot(Pnt3(m[0]), Pnt3(m[2]))));
  902.   ans = max(ans, fabsf(dot(Pnt3(m[1]), Pnt3(m[2]))));
  903.   ans = max(ans, fabsf(dot(Pnt3(m[2]), Pnt3(m[1]))));
  904.   return ans;
  905. }
  906. // force the rigidity of the xform by setting the projective
  907. // part to 0 0 0 1 and making sure rotation part is just a rotation
  908. template <class T> inline Xform<T> &
  909. Xform<T>::enforce_rigidity(void)
  910. {
  911.   m[0][3] = m[1][3] = m[2][3] = 0.0;
  912.   m[3][3] = 1.0;
  913.   T q[4];
  914.   toQuaternion(q);
  915.   // fromQuaternion() normalizes q
  916.   fromQuaternion(q, m[3][0], m[3][1], m[3][2]);
  917.   return *this;
  918. }
  919. template <class T> inline Xform<T>
  920. operator*(const Xform<T> &a, const Xform<T> &b)
  921.   Xform<T> out;
  922.   for (int i=0; i<4; i++) {
  923.     for (int j=0; j<4; j++) {
  924.       out.m[j][i] = 
  925. a.m[0][i] * b.m[j][0] + a.m[1][i] * b.m[j][1] +
  926. a.m[2][i] * b.m[j][2] + a.m[3][i] * b.m[j][3];
  927.     }
  928.   }
  929.   return out;
  930. }
  931. // delta * a = b
  932. template <class T> inline Xform<T>
  933. delta(Xform<T> a,
  934.       const Xform<T> &b)
  935. {
  936.   return b * a.fast_invert();
  937. }
  938. // Assume the transform only has rotation and translation.
  939. // Calculate a delta matrix that transforms a to b.
  940. // For other parts than rotation, do just regular interpolation.
  941. // For rotation, calculate the quaternion, rotation axis and
  942. // angle, interpolate the angle, transform back.
  943. template <class T> inline Xform<T>
  944. linear_interp(const Xform<T> &a,
  945.       const Xform<T> &b,
  946.       double          t)
  947. {
  948.   Xform<T> d = delta(a,b);
  949.   // make sure no projective or scaling part
  950.   assert(d.m[0][3] == 0.0);
  951.   assert(d.m[1][3] == 0.0);
  952.   assert(d.m[2][3] == 0.0);
  953.   assert(d.m[3][3] == 1.0);
  954.   // interpolate translation
  955.   T tx = d.m[3][0]*t;
  956.   T ty = d.m[3][1]*t;
  957.   T tz = d.m[3][2]*t;
  958.   // interpolate rotation
  959.   T angle, x,y,z;
  960.   d.get_rot(angle, x,y,z);
  961.   d.identity();
  962.   d.rot(angle*t, x,y,z);
  963.   d.m[3][0] = tx;
  964.   d.m[3][1] = ty;
  965.   d.m[3][2] = tz;
  966.   return d*a;
  967. }
  968. template <class T> inline Xform<T>
  969. bilinear_interp(const Xform<T> &u0v0,
  970. const Xform<T> &u1v0,
  971. const Xform<T> &u0v1,
  972. const Xform<T> &u1v1,
  973. double u, double v)
  974. {
  975.   return linear_interp(linear_interp(u0v0, u1v0, u),
  976.        linear_interp(u0v1, u1v1, u), v);
  977. }
  978. template <class T> inline Xform<T> 
  979. relative_xform(const Xform<T> &a, Xform<T> b)
  980. {
  981.   return b.fast_invert() * a;
  982. }
  983. template <class T> inline ostream&
  984. operator<<(ostream &out, const Xform<T> &xf)
  985.   for (int i=0; i<4; i++) {
  986.     for (int j=0; j<4; j++) {
  987.       //out << xf(i,j) << " ";
  988.       out << xf.m[j][i] << " ";
  989.     }
  990.     out << endl;
  991.   }
  992.   return out;
  993. }
  994. template <class T> inline istream&
  995. operator>>(istream &in, Xform<T> &xf)
  996.   for (int i=0; i<4; i++) {
  997.     for (int j=0; j<4; j++) {
  998.       in >> ws >> xf.m[j][i];
  999.     }
  1000.   }
  1001.   return in;
  1002. }
  1003. #endif
  1004. //
  1005. // testing part...
  1006. //
  1007. #if 0
  1008. #define SHOW(x) cout << #x " = " << x << endl
  1009. #define SHOW3(x) cout << #x " = " << x[0] << " " << x[1] << " " << x[2] << " " << endl
  1010. void 
  1011. main(void)
  1012. {
  1013.   Xform<double> xf;
  1014.   double a[3] = { 1, 2, 3 };
  1015.   double b[3] = { 3,-1, 2 };
  1016.   double c[3];
  1017.   xf.translate(a);
  1018.   SHOW3(a);
  1019.   xf.getTranslation(c);
  1020.   SHOW3(c);
  1021.   xf.apply(a,c);
  1022.   SHOW3(c);
  1023.   xf.apply(b,c);
  1024.   SHOW3(b);
  1025.   SHOW3(c);
  1026.   cout << endl << "Test Euler angle stuff" << endl;
  1027.   cout << "Rotate vector around X by 45 deg" << endl;
  1028.   SHOW3(a);
  1029.   xf.identity();
  1030.   xf.rotX(M_PI/4.0);
  1031.   xf.apply(a,c);
  1032.   SHOW3(c);
  1033.   cout << "Rotate vector around Y by 45 deg" << endl;
  1034.   SHOW3(a);
  1035.   xf.identity();
  1036.   xf.rotY(M_PI/4.0);
  1037.   xf.apply(a,c);
  1038.   SHOW3(c);
  1039.   cout << "Rotate vector around Z by 45 deg" << endl;
  1040.   SHOW3(a);
  1041.   xf.identity();
  1042.   xf.rotZ(M_PI/4.0);
  1043.   xf.apply(a,c);
  1044.   SHOW3(c);
  1045.   cout << endl;
  1046.   double ea[3] = { M_PI/8.0, M_PI/7.0, M_PI/6.0 };
  1047.   SHOW3(ea);
  1048.   xf.fromEuler(ea, EulOrdXYZs);
  1049.   cout << "fromEuler()" << endl;
  1050.   SHOW(xf);
  1051.   xf.identity();
  1052.   xf.rotX(ea[0]);
  1053.   xf.rotY(ea[1]);
  1054.   xf.rotZ(ea[2]);
  1055.   SHOW(xf);
  1056.   xf.toEuler(ea, EulOrdXYZs);
  1057.   SHOW3(ea);
  1058.   cout << endl << "Test quaternions: " << endl;
  1059.   double q[4] = { .5, .5, .5, .5 };
  1060.   cout << q[0] << " "<< q[1] << " "<< q[2] << " "<< q[3] << endl;
  1061.   xf.fromQuaternion(q);
  1062.   cout << xf << endl;
  1063.   q[0] = q[1] = q[2] = q[3] = 0.0;
  1064.   xf.toQuaternion(q);
  1065.   cout << q[0] << " "<< q[1] << " "<< q[2] << " "<< q[3] << endl;
  1066.   float fq[4] = { .5, .5, .5, .5 };
  1067.   cout << fq[0] << " "<< fq[1] << " "<< fq[2] << " "<< fq[3] << endl;
  1068.   xf.fromQuaternion(fq);
  1069.   cout << xf << endl;
  1070.   fq[0] = fq[1] = fq[2] = fq[3] = 0.0;
  1071.   xf.toQuaternion(fq);
  1072.   cout << fq[0] << " "<< fq[1] << " "<< fq[2] << " "<< fq[3] << endl;
  1073.   cout << endl << "Test multiplication and inversion" << endl;
  1074.   Xform<double> xa,xb;
  1075.   xa.rotZ(M_PI/4.0);
  1076.   xa.translate(1,2,3);
  1077.   SHOW(xa);
  1078.   xb = xa;
  1079.   xb.fast_invert();
  1080.   SHOW(xb);
  1081.   SHOW(xa*xb);
  1082.   SHOW(xb*xa);
  1083.   cout << endl << "Test rotation" << endl;
  1084.   double angle, ax, ay, az;
  1085.   xa.identity();
  1086.   xa.rotX(M_PI/4.0);
  1087.   SHOW(xa);
  1088.   xa.get_rot(angle, ax, ay, az);
  1089.   SHOW(angle);
  1090.   SHOW(ax);
  1091.   SHOW(ay);
  1092.   SHOW(az);
  1093.   xb.identity();
  1094.   xb.rot(M_PI/4.0, 1, 0, 0);
  1095.   SHOW(xb);
  1096.   xa.identity();
  1097.   xa.rotY(M_PI/4.0);
  1098.   SHOW(xa);
  1099.   xa.get_rot(angle, ax, ay, az);
  1100.   SHOW(angle);
  1101.   SHOW(ax);
  1102.   SHOW(ay);
  1103.   SHOW(az);
  1104.   xb.identity();
  1105.   xb.rot(M_PI/4.0, 0, 1, 0);
  1106.   SHOW(xb);
  1107.   xa.identity();
  1108.   xa.rotZ(M_PI/4.0);
  1109.   SHOW(xa);
  1110.   xa.get_rot(angle, ax, ay, az);
  1111.   SHOW(angle);
  1112.   SHOW(ax);
  1113.   SHOW(ay);
  1114.   SHOW(az);
  1115.   xb.identity();
  1116.   xb.rot(M_PI/4.0, 0, 0, 1);
  1117.   SHOW(xb);
  1118.   xa.identity();
  1119.   SHOW(xa.rot(-.34, 1, -1, 1));
  1120.   xa.get_rot(angle, ax, ay, az);
  1121.   SHOW(angle);
  1122.   SHOW(ax);
  1123.   SHOW(ay);
  1124.   SHOW(az);
  1125.   cout << endl << "Test interpolation" << endl;
  1126.   xa.identity();
  1127.   xa.rotZ(M_PI/4.0);
  1128.   xa.translate(1,2,3);
  1129.   SHOW(xa);
  1130.   xb.identity();
  1131.   xb.rotY(-M_PI/4.0);
  1132.   xb.translate(-3,-2,-1);
  1133.   SHOW(xb);
  1134.   for (int i=0; i<=10; i++) {
  1135.     xf = linear_interp(xa,xb,i/10.0);
  1136.     SHOW(xf);
  1137.     a[0]=1;a[1]=1;a[2]=1;
  1138.     xf.apply(a,b);
  1139.     SHOW3(b);
  1140.   }
  1141. }
  1142. #endif