Free Electron
Matrix3x4.h
Go to the documentation of this file.
1 /* Copyright (C) 2003-2021 Free Electron Organization
2  Any use of this software requires a license. If a valid license
3  was not distributed with this file, visit freeelectron.org. */
4 
5 /** @file */
6 
7 #ifndef __math_Matrix3x4_h__
8 #define __math_Matrix3x4_h__
9 
10 namespace fe
11 {
12 
13 /**************************************************************************//**
14  \brief Matrix for 3D transformations
15 
16  @ingroup math
17 
18  \verbatim
19  Indexes
20 
21  0 3 6 9
22  1 4 7 10
23  2 5 8 11
24 
25  represent
26 
27  Rot Rot Rot Tx
28  Rot Rot Rot Ty
29  Rot Rot Rot Tz
30 
31  with the columns
32 
33  Direction Left Up Translation
34 
35  The operator(i,j) addressing for a 4x4 matrix is:
36  00 01 02 03
37  10 11 12 13
38  20 21 22 23
39  \endverbatim
40 
41  For translation on the right as shown, this is stored column major.
42  Note that a few references place translation on the bottom,
43  so this would act like row major.
44 
45 *//***************************************************************************/
46 template <typename T>
47 class Matrix<3,4,T>
48 {
49  public:
50  Matrix<3,4,T>(void)
51  {
52 #if FE_VEC_CHECK_VALID
53 // memset(this,0,sizeof(*this));
54  set(column(0), 0.0f, 0.0f, 0.0f);
55  set(column(1), 0.0f, 0.0f, 0.0f);
56  set(column(2), 0.0f, 0.0f, 0.0f);
57  set(column(3), 0.0f, 0.0f, 0.0f);
58 #endif
59  }
60  Matrix<3,4,T>(const Matrix<3,4,T>& other)
61  {
62  operator=(other);
63  }
64  template<int M,int N,class U>
65  Matrix<3,4,T>(const Matrix<M,N,U>& other)
66  {
67  operator=(other);
68  }
69  Matrix<3,4,T>(const Quaternion<T>& quat)
70  {
71  operator=(quat);
72  }
73 
74  Matrix<3,4,T>& operator=(const Matrix<3,4,T>& other)
75  {
76  if(this != &other)
77  {
78  direction()=other.direction();
79  left()=other.left();
80  up()=other.up();
81  translation()=other.translation();
82  }
83  return *this;
84  }
85 
86  template<int M,int N,class U>
87  Matrix<3,4,T>& operator=(const Matrix<M,N,U> &other)
88  {
89  direction()=other.column(0);
90  left()=other.column(1);
91  up()=other.column(2);
92  translation()=other.column(3);
93  return *this;
94  }
95 
96  bool operator==(const Matrix<3,4,T>& other) const;
97  bool operator!=(const Matrix<3,4,T>& other) const
98  { return !operator==(other); }
99 
100  Matrix<3,4,T>& operator=(const Quaternion<T>& quat);
101 
102  Matrix<3,4,T>& operator*=(const Matrix<3,4,T>& preMatrix);
103 
104  /** @brief Populate a 16 element one dimensional array
105  suitable for OpenGL operations
106 
107  Translation is placed in elements 13, 14, and 15.*/
108  template<class U>
109  void copy16(U* array) const;
110 
111  /** @brief Populate a three element array with
112  the current translation component */
113  template<class U>
114  void copyTranslation(U* array) const;
115 
116  Vector<3,T> column(U32 index) const
117  { return m_vector[index]; }
118  Vector<3,T>& column(U32 index)
119  { return m_vector[index]; }
120 
121  Vector<3,T> direction(void) const
122  { return m_vector[0]; }
123  Vector<3,T> left(void) const
124  { return m_vector[1]; }
125  Vector<3,T> up(void) const
126  { return m_vector[2]; }
127  Vector<3,T> translation(void) const
128  { return m_vector[3]; }
129 
130  Vector<3,T>& direction(void)
131  { return m_vector[0]; }
132  Vector<3,T>& left(void)
133  { return m_vector[1]; }
134  Vector<3,T>& up(void)
135  { return m_vector[2]; }
136  Vector<3,T>& translation(void)
137  { return m_vector[3]; }
138 
139  /// Column Major addressing
140  T operator()(unsigned int i, unsigned int j) const
141  { return m_vector[j][i]; }
142  /// Column Major addressing
143  T& operator()(unsigned int i, unsigned int j)
144  { return m_vector[j][i]; }
145 
146 static
147 const Matrix<3,4,T> identity(void);
148 
149  // undefined
150 // T operator[](unsigned int index) const;
151 // T& operator[](unsigned int index);
152 
153  private:
154 
155  Vector<3,T> m_vector[4];
156 
157 };
158 
159 template<class T>
160 inline bool Matrix<3,4,T>::operator==(const Matrix<3,4,T>& other) const
161 {
162  return (0 == memcmp(reinterpret_cast<const void *>(m_vector),
163  reinterpret_cast<const void *>(other.m_vector),
164  4*sizeof(Vector<3,T>)));
165 };
166 
167 /** Equivalence test within the given tolerance @em margin
168  @relates Vector
169  */
170 template<class T,class U>
171 inline bool equivalent(const Matrix<3,4,T>& lhs,
172  const Matrix<3,4,T>& rhs, U margin)
173 {
174  return (equivalent(lhs.direction(), rhs.direction(), margin) &&
175  equivalent(lhs.left(), rhs.left(), margin) &&
176  equivalent(lhs.up(), rhs.up(), margin) &&
177  equivalent(lhs.translation(), rhs.translation(), margin));
178 }
179 
180 /** @brief Copy from array of 16 values
181 
182  @relates Matrix3x4
183 
184  Note that the array is presumed to be in a standard OpenGL 4x4 layout.
185  Since Matrix3x4 retains 12 values, 4 of the input values will be ignored.
186  */
187 template<class T,class U>
188 inline Matrix<3,4,T>& set(Matrix<3,4,T>& lhs,const U* pArray)
189 {
190  set(lhs.column(0), pArray[0], pArray[1], pArray[2]);
191  set(lhs.column(1), pArray[4], pArray[5], pArray[6]);
192  set(lhs.column(2), pArray[8], pArray[9], pArray[10]);
193  set(lhs.column(3), pArray[12], pArray[13], pArray[14]);
194  return lhs;
195 }
196 
197 /** @brief Set as the rotation between two vectors
198 
199  @relates Matrix3x4
200 
201  Operands should be pre-normalized.
202 
203  Twist should be considered arbitrary.
204  */
205 template<class T>
206 inline Matrix<3,4,T>& set(Matrix<3,4,T>& lhs,const Vector<3,T>& from,
207  const Vector<3,T>& to)
208 {
209  if(isZero(from) || isZero(to))
210  {
211  feX("Matrix<3,4,T>:set (from,to)","zero length vector");
212  }
213 
214  F32 cosa=dot(from,to);
215  if(cosa>FE_ALMOST1)
216  {
217  setIdentity(lhs);
218  return lhs;
219  }
220 
221  Vector<3,T> axis;
222  F32 sina;
223  if(cosa< -FE_ALMOST1)
224  {
225  cosa= -1.0;
226  sina= 0.0;
227  set(axis,0.0,from[0],-from[1]);
228 
229  T len=sqrt(axis[1]*axis[1] + axis[2]*axis[2]);
230  if (len < FE_SLERP_DELTA)
231  {
232  set(axis,-from[2],0.0,from[0]);
233  }
234  }
235  else
236  {
237  sina=sin(acos(cosa));
238  axis=cross(from,to);
239  }
240 
241  normalize(axis);
242 
243  const F32 mcosa=1-cosa;
244 
245  set(lhs.column(0),
246  axis[0]*axis[0]*mcosa + cosa,
247  axis[1]*axis[0]*mcosa + axis[2]*sina,
248  axis[2]*axis[0]*mcosa - axis[1]*sina);
249 
250  set(lhs.column(1),
251  axis[0]*axis[1]*mcosa - axis[2]*sina,
252  axis[1]*axis[1]*mcosa + cosa,
253  axis[2]*axis[1]*mcosa + axis[0]*sina);
254 
255  set(lhs.column(2),
256  axis[0]*axis[2]*mcosa + axis[1]*sina,
257  axis[1]*axis[2]*mcosa - axis[0]*sina,
258  axis[2]*axis[2]*mcosa + cosa);
259 
260  set(lhs.column(3), 0.0f, 0.0f, 0.0f);
261 
262  return lhs;
263 }
264 
265 template <typename T>
267 {
268  set(lhs.column(0), 1.0f, 0.0f, 0.0f);
269  set(lhs.column(1), 0.0f, 1.0f, 0.0f);
270  set(lhs.column(2), 0.0f, 0.0f, 1.0f);
271  set(lhs.column(3), 0.0f, 0.0f, 0.0f);
272  return lhs;
273 }
274 
275 /** @brief Set the rotation of the transform
276 
277  @relates Matrix3x4
278 
279  Sets the first three columns of the transform equal to
280  a rotation matrix (3x3 / SpatialMatrix)
281  */
282 template <typename T>
283 inline Matrix<3,4,T>& setRotation(Matrix<3,4,T>& lhs,
284  const Matrix<3,3,T>& rotation)
285 {
286  set(lhs.column(0), rotation(0, 0), rotation(1, 0), rotation(2, 0));
287  set(lhs.column(1), rotation(0, 1), rotation(1, 1), rotation(2, 1));
288  set(lhs.column(2), rotation(0, 2), rotation(1, 2), rotation(2, 2));
289  return lhs;
290 }
291 
292 /** @brief Set the translation of the transform
293 
294  @relates Matrix3x4
295 
296  Sets the fourth column of the transform, which represents position,
297  equal to the supplied vector
298  */
299 template <int N, typename T>
300 inline Matrix<3,4,T>& setTranslation(Matrix<3,4,T>& lhs,
301  const Vector<N,T>& translation)
302 {
303  FEASSERT(N>2);
304  lhs.translation()=translation;
305 
306  return lhs;
307 }
308 
309 /** @brief Apply transform's rotation to a vector
310 
311  @relates Matrix3x4
312 
313  Rotates the supplied vector by the rotation matrix in the transform.
314  */
315 template <int N, typename T>
316 inline void rotateVector(const Matrix<3,4,T>& lhs,const Vector<N,T>& in,
317  Vector<N,T>& out)
318 {
319  FEASSERT(N>2);
320  fe::set(out,in[0]*lhs(0,0)+in[1]*lhs(0,1)+in[2]*lhs(0,2),
321  in[0]*lhs(1,0)+in[1]*lhs(1,1)+in[2]*lhs(1,2),
322  in[0]*lhs(2,0)+in[1]*lhs(2,1)+in[2]*lhs(2,2));
323 }
324 
325 template <int N, typename T>
326 inline Vector<N,T> rotateVector(const Matrix<3,4,T>& lhs,const Vector<N,T>& in)
327 {
328  FEASSERT(N>2);
329  Vector<N,T> out;
330  rotateVector(lhs,in,out);
331  return out;
332 }
333 
334 template <int N, typename T>
335 inline Vector<N,T> inverseRotateVector(const Matrix<3,4,T>& lhs,
336  const Vector<N,T>& in)
337 {
338  FEASSERT(N>2);
339  Matrix<3,4,T> inverse;
340  invert(inverse,lhs);
341  return rotateVector(inverse,in);
342 }
343 
344 /** @brief Transform the vector
345 
346  @relates Matrix3x4
347 
348  Applies the transform's rotation, then add the transform's translation.
349  */
350 template <int N, typename T>
351 inline void transformVector(const Matrix<3,4,T>& lhs,const Vector<N,T>& in,
352  Vector<N,T>& out)
353 {
354  FEASSERT(N>2);
355  fe::set(out,in[0]*lhs(0,0)+in[1]*lhs(0,1)+in[2]*lhs(0,2)+lhs(0,3),
356  in[0]*lhs(1,0)+in[1]*lhs(1,1)+in[2]*lhs(1,2)+lhs(1,3),
357  in[0]*lhs(2,0)+in[1]*lhs(2,1)+in[2]*lhs(2,2)+lhs(2,3));
358 }
359 
360 template <int N, typename T>
361 inline Vector<N,T> transformVector(const Matrix<3,4,T>& lhs,
362  const Vector<N,T>& in)
363 {
364  FEASSERT(N>2);
365  Vector<N,T> out;
366  transformVector(lhs,in,out);
367  return out;
368 }
369 
370 template <int N, typename T>
371 inline Vector<N,T> inverseTransformVector(const Matrix<3,4,T>& lhs,
372  const Vector<N,T>& in)
373 {
374  FEASSERT(N>2);
375  Matrix<3,4,T> inverse;
376  invert(inverse,lhs);
377  return transformVector(inverse,in);
378 }
379 
380 /** @brief Translate the transform
381 
382  @relates Matrix3x4
383 
384  Rotates the vector by the transform's rotation, then adds
385  to the transform's translation.
386  */
387 template <int N, typename T>
388 inline Matrix<3,4,T>& translate(Matrix<3,4,T>& lhs,
389  const Vector<N,T>& translation)
390 {
391  FEASSERT(N>2);
392  Vector<N,T> rotated;
393  rotateVector(lhs,translation,rotated);
394 
395  lhs.translation()+=rotated;
396  return lhs;
397 }
398 
399 template <typename T>
400 inline void setColumn(int i, Matrix<3,4,T>& lhs, const Vector<3,T>& v)
401 {
402  lhs.column(i)=v;
403 }
404 
405 template <typename T>
406 inline void getColumn(int i, const Matrix<3,4,T>& lhs, Vector<3,T>& v)
407 {
408  v=lhs.column(i);
409 }
410 
411 /** @brief Rotate the transform
412 
413  @relates Matrix3x4
414 
415  Rotates the transform ccw about the specified axis.
416  */
417 template <typename T,typename U>
418 inline Matrix<3,4,T>& rotate(Matrix<3,4,T>& lhs,U radians,Axis axis)
419 {
420  const T sina=sin(radians);
421  const T cosa=cos(radians);
422 
423  static const U32 index[3][2]={{1,2},{2,0},{0,1}};
424  U32 x1=index[axis][0];
425  U32 x2=index[axis][1];
426 
427  T b=lhs(0,x1);
428  T c=lhs(0,x2);
429  lhs(0,x1)=c*sina+b*cosa;
430  lhs(0,x2)=c*cosa-b*sina;
431  b=lhs(1,x1);
432  c=lhs(1,x2);
433  lhs(1,x1)=c*sina+b*cosa;
434  lhs(1,x2)=c*cosa-b*sina;
435  b=lhs(2,x1);
436  c=lhs(2,x2);
437  lhs(2,x1)=c*sina+b*cosa;
438  lhs(2,x2)=c*cosa-b*sina;
439 /*
440  static const U32 index[3][2]={{3,6},{6,0},{0,3}};
441  U32 x1=index[axis][0];
442  U32 x2=index[axis][1];
443 
444 #if FALSE
445  U32 y;
446  for(y=0;y<3;y++)
447  {
448  T b=lhs[x1];
449  T c=lhs[x2];
450 
451  lhs[x1++]=c*sina+b*cosa;
452  lhs[x2++]=c*cosa-b*sina;
453  }
454 #else
455  T b=lhs[x1];
456  T c=lhs[x2];
457  lhs[x1++]=c*sina+b*cosa;
458  lhs[x2++]=c*cosa-b*sina;
459  b=lhs[x1];
460  c=lhs[x2];
461  lhs[x1++]=c*sina+b*cosa;
462  lhs[x2++]=c*cosa-b*sina;
463  b=lhs[x1];
464  c=lhs[x2];
465  lhs[x1++]=c*sina+b*cosa;
466  lhs[x2++]=c*cosa-b*sina;
467 #endif
468 */
469 
470  return lhs;
471 }
472 
473 // cannot overload this as 'scale' since compiler has trouble matching
474 // Vector<N,U> derived classes to the other scales when this function exists
475 // as 'scale'.
476 template <typename T,typename U>
477 inline Matrix<3,4,T>& scaleAll(Matrix<3,4,T>& lhs,U scalefactor)
478 {
479  lhs(0,0)*=scalefactor;
480  lhs(1,1)*=scalefactor;
481  lhs(2,2)*=scalefactor;
482  return lhs;
483 }
484 
485 template <typename T,typename U,int N>
486 inline Matrix<3,4,T>& scale(Matrix<3,4,T>& lhs,Vector<N,U> scalefactor)
487 {
488  lhs(0,0)*=scalefactor[0];
489  lhs(1,1)*=scalefactor[1];
490  lhs(2,2)*=scalefactor[2];
491  return lhs;
492 }
493 
494 template <typename T,typename U>
495 inline Matrix<3,4,T>& scale(Matrix<3,4,T>& lhs,Vector<2,U> scalefactor)
496 {
497  lhs(0,0)*=scalefactor[0];
498  lhs(1,1)*=scalefactor[1];
499  return lhs;
500 }
501 
502 template <typename T,typename U>
503 inline Matrix<3,4,T>& scale(Matrix<3,4,T>& lhs,Vector<1,U> scalefactor)
504 {
505  lhs(0,0)*=scalefactor[0];
506  return lhs;
507 }
508 
509 template <typename T>
510 template <typename U>
511 inline void Matrix<3,4,T>::copy16(U* array) const
512 {
513  array[0]=m_vector[0][0];
514  array[1]=m_vector[0][1];
515  array[2]=m_vector[0][2];
516  array[3]=0.0f;
517 
518  array[4]=m_vector[1][0];
519  array[5]=m_vector[1][1];
520  array[6]=m_vector[1][2];
521  array[7]=0.0f;
522 
523  array[8]=m_vector[2][0];
524  array[9]=m_vector[2][1];
525  array[10]=m_vector[2][2];
526  array[11]=0.0f;
527 
528  array[12]=m_vector[3][0];
529  array[13]=m_vector[3][1];
530  array[14]=m_vector[3][2];
531  array[15]=1.0f;
532 }
533 
534 template<int M, int N, class T>
535 inline void copy(Matrix<3,4,T>& lhs,const Matrix<M,N,T>& rhs)
536 {
537  setIdentity(lhs);
538  int m;
539  if(M < 3) { m = M; }
540  else { m = 3; }
541  int n;
542  if(N < 4) { n = N; }
543  else { n = 4; }
544 
545  for(int i = 0;i < m; i++)
546  {
547  for(int j = 0;j < n; j++)
548  {
549  lhs(i,j) = rhs(i,j);
550  }
551  for(int j = n;j < 4; j++)
552  {
553  lhs(i,j) = T(0);
554  }
555  }
556  for(int i = m;i < 3; i++)
557  {
558  for(int j = 0;j < 4; j++)
559  {
560  lhs(i,j) = T(0);
561  }
562  }
563 }
564 
565 template<int M, int N, class T>
566 inline void copy(Matrix<M,N,T>& lhs,const Matrix<3,4,T>& rhs)
567 {
568  setIdentity(lhs);
569 
570  int m;
571  if(M < 3) { m = M; }
572  else { m = 3; }
573  int n;
574  if(N < 4) { n = N; }
575  else { n = 4; }
576 
577  for(int i = 0;i < m; i++)
578  {
579  for(int j = 0;j < n; j++)
580  {
581  lhs(i,j) = rhs(i,j);
582  }
583  for(int j = n;j < N; j++)
584  {
585  lhs(i,j) = T(0);
586  }
587  }
588  for(int i = m;i < M; i++)
589  {
590  for(int j = 0;j < N; j++)
591  {
592  lhs(i,j) = T(0);
593  }
594  }
595 }
596 
597 template <typename T>
598 template <typename U>
599 inline void Matrix<3,4,T>::copyTranslation(U* array) const
600 {
601  array[0]=m_vector[3][0];
602  array[1]=m_vector[3][1];
603  array[2]=m_vector[3][2];
604 }
605 
606 template <typename T>
607 inline const Matrix<3,4,T> Matrix<3,4,T>::identity(void)
608 {
609  Matrix<3,4,T> matrix;
610  setIdentity(matrix);
611  return matrix;
612 }
613 
614 template <typename T>
616 {
617  const T x2=quat[0]+quat[0];
618  const T y2=quat[1]+quat[1];
619  const T z2=quat[2]+quat[2];
620  const T xx=quat[0]*x2;
621  const T xy=quat[0]*y2;
622  const T xz=quat[0]*z2;
623  const T yy=quat[1]*y2;
624  const T yz=quat[1]*z2;
625  const T zz=quat[2]*z2;
626  const T wx=quat[3]*x2;
627  const T wy=quat[3]*y2;
628  const T wz=quat[3]*z2;
629 
630  // this is the transpose of what the reference said
631  set(m_vector[0], 1.0f-(yy+zz), xy+wz, xz-wy);
632  set(m_vector[1], xy-wz, 1.0f-(xx+zz), yz+wx);
633  set(m_vector[2], xz+wy, yz-wx, 1.0f-(xx+yy));
634  set(m_vector[3], 0.0f, 0.0f, 0.0f);
635 
636  return *this;
637 }
638 
639 #if FALSE
640 /** Matrix Matrix multiply
641  @relates Matrix3x4
642  */
643 template<typename T, typename U>
645  const Matrix<3,4,U>& B)
646 {
647  R[0] = A[0]*B[0] + A[3]*B[1] + A[6]*B[2] + A[9];
648  R[1] = A[1]*B[0] + A[4]*B[1] + A[7]*B[2] + A[10];
649  R[2] = A[2]*B[0] + A[5]*B[1] + A[8]*B[2] + A[11];
650 
651  R[3] = A[0]*B[3] + A[3]*B[4] + A[6]*B[5] + A[9];
652  R[4] = A[1]*B[3] + A[4]*B[4] + A[7]*B[5] + A[10];
653  R[5] = A[2]*B[3] + A[5]*B[4] + A[8]*B[5] + A[11];
654 
655  R[6] = A[0]*B[6] + A[3]*B[7] + A[6]*B[8] + A[9];
656  R[7] = A[1]*B[6] + A[4]*B[7] + A[7]*B[8] + A[10];
657  R[8] = A[2]*B[6] + A[5]*B[7] + A[8]*B[8] + A[11];
658 
659  R[9] = A[0]*B[9] + A[3]*B[10]+ A[6]*B[11]+ A[9];
660  R[10]= A[1]*B[9] + A[4]*B[10]+ A[7]*B[11]+ A[10];
661  R[11]= A[2]*B[9] + A[5]*B[10]+ A[8]*B[11]+ A[11];
662  return R;
663 }
664 
665 /** Matrix Matrix multiply
666  @relates Matrix3x4
667  */
668 template<typename T, typename U>
669 inline Matrix<3,4,T> operator*(const Matrix<3,4,T>& lhs,
670  const Matrix<3,4,U>& rhs)
671 {
672  Matrix<3,4,T> C;
673  multiply(C,lhs,rhs);
674  return C;
675 }
676 #endif
677 
678 /** Matrix Matrix add
679  @relates Matrix3x4
680  */
681 template<class T, class U>
682 inline Matrix<3,4,T>& add(Matrix<3,4,T>& result, const Matrix<3,4,T>& lhs,
683  const Matrix<3,4,U>& rhs)
684 {
685  result.column(0) = lhs.column(0) + rhs.column(0);
686  result.column(1) = lhs.column(1) + rhs.column(1);
687  result.column(2) = lhs.column(2) + rhs.column(2);
688  result.column(3) = lhs.column(3) + rhs.column(3);
689  return result;
690 }
691 
692 /** Matrix Matrix subtract
693  @relates Matrix3x4
694  */
695 template<class T, class U>
696 inline Matrix<3,4,T>& subtract(Matrix<3,4,T>& result, const Matrix<3,4,T>& lhs,
697  const Matrix<3,4,U>& rhs)
698 {
699  result.column(0) = lhs.column(0) - rhs.column(0);
700  result.column(1) = lhs.column(1) - rhs.column(1);
701  result.column(2) = lhs.column(2) - rhs.column(2);
702  result.column(3) = lhs.column(3) - rhs.column(3);
703  return result;
704 }
705 
706 /** Matrix scale
707  @relates Matrix3x4
708  */
709 template<class T, class U>
710 inline Matrix<3,4,T>& multiply(Matrix<3,4,T>& result,
711  const U lhs, const Matrix<3,4,T>& rhs)
712 {
713  result.column(0) = lhs * rhs.column(0);
714  result.column(1) = lhs * rhs.column(1);
715  result.column(2) = lhs * rhs.column(2);
716  result.column(3) = lhs * rhs.column(3);
717  return result;
718 }
719 
720 /** Matrix scale
721  @relates Matrix3x4
722  */
723 template<class T, class U>
724 inline Matrix<3,4,T>& multiply(Matrix<3,4,T>& result,
725  const Matrix<3,4,T>& lhs, const U rhs)
726 {
727  result.column(0) = rhs * lhs.column(0);
728  result.column(1) = rhs * lhs.column(1);
729  result.column(2) = rhs * lhs.column(2);
730  result.column(3) = rhs * lhs.column(3);
731  return result;
732 }
733 
734 /** Matrix Matrix add
735  @relates Matrix3x4
736  */
737 template<typename T, typename U>
738 inline Matrix<3,4,T> operator+(const Matrix<3,4,T>& lhs,
739  const Matrix<3,4,U>& rhs)
740 {
741  Matrix<3,4,T> tmp;
742  add(tmp,lhs,rhs);
743  return tmp;
744 }
745 
746 /** Matrix Matrix subtract
747  @relates Matrix3x4
748  */
749 template<typename T, typename U>
750 inline Matrix<3,4,T> operator-(const Matrix<3,4,T>& lhs,
751  const Matrix<3,4,U>& rhs)
752 {
753  Matrix<3,4,T> tmp;
754  subtract(tmp,lhs,rhs);
755  return tmp;
756 }
757 
758 /** Matrix scale
759  @relates Matrix3x4
760  */
761 template<class T, class U>
762 inline Matrix<3,4,T> operator*(const U lhs, const Matrix<3,4,T>& rhs)
763 {
764  Matrix<3,4,T> tmp;
765  multiply(tmp,lhs,rhs);
766  return tmp;
767 }
768 
769 /** Matrix scale
770  @relates Matrix3x4
771  */
772 template<class T, class U>
773 inline Matrix<3,4,T> operator*(const Matrix<3,4,T>& lhs, const U rhs)
774 {
775  Matrix<3,4,T> tmp;
776  multiply(tmp,lhs,rhs);
777  return tmp;
778 }
779 
780 template <typename T>
781 inline Matrix<3,4,T>& Matrix<3,4,T>::operator*=(const Matrix<3,4,T>& preMatrix)
782 {
783  return *this=preMatrix*(*this);
784 }
785 
786 /** Return the horizonatal dimension
787  @relates Matrix3x4
788  */
789 template<class T>
790 inline U32 width(const Matrix<3,4,T>& matrix)
791 {
792  return 3;
793 }
794 
795 /** Return the vertical dimension
796  @relates Matrix3x4
797  */
798 template<class T>
799 inline U32 height(const Matrix<3,4,T>& matrix)
800 {
801  return 4;
802 }
803 
804 /** Matrix print
805  @relates Matrix3x4
806  */
807 template<class T>
808 inline String print(const Matrix<3,4,T>& a_matrix)
809 {
810  String s;
811  for(unsigned int i = 0;i < 3; i++)
812  {
813  for(unsigned int j = 0;j < 4; j++)
814  {
815  s.catf("%6.3f ", a_matrix(i,j));
816  }
817  if(i!=2)
818  {
819  s.cat("\n");
820  }
821  }
822  return s;
823 }
824 
825 /** @brief 3x4 matrix inversion wrapped as a 4x4
826 
827  @relates Matrix3x4
828 */
829 template <typename T>
830 inline Matrix<3,4,T>& invert(Matrix<3,4,T>& inverse,
831  const Matrix<3,4,T>& matrix)
832 {
833  //* TODO optimize for zeros instead of reusing 4x4
834 
835  Matrix<4,4,T> inverse4x4,matrix4x4;
836 
837  copy(matrix4x4,matrix);
838  matrix4x4(3,3)=1.0f;
839  invert(inverse4x4,matrix4x4);
840  copy(inverse,inverse4x4);
841  return inverse;
842 }
843 
844 template <typename T>
845 inline T determinant(const Matrix<3,4,T>& matrix)
846 {
847  //* TODO optimize for zeros instead of reusing 4x4
848 
849  Matrix<4,4,T> matrix4x4;
850 
851  copy(matrix4x4,matrix);
852  matrix4x4(3,3)=1.0f;
853  return determinant(matrix4x4);
854 }
855 
856 /** @brief Interpolate between two matrices
857 
858  @relates Matrix3x4
859 
860  This is a naive linear interpolation that considers the translation
861  and rotation separately.
862  For an pure interpolation, see MatrixPower in the solve module.
863 */
864 template <typename T,typename U>
865 inline Matrix<3,4,T>& interpolate(Matrix<3,4,T>& result,
866  const Matrix<3,4,T>& matrix1,const Matrix<3,4,T>& matrix2,
867  U fraction)
868 {
869  Matrix<3,4,T> matrix1_inv;
870  invert(matrix1_inv,matrix1);
871  Matrix<3,4,T> delta=matrix2;
872  delta*=matrix1_inv;
873 
874  Quaternion<T> spin=delta;
875  spin*=fraction;
876  Matrix<3,4,T> mspin(spin);
877 
878  Vector<3,T> move=delta.translation();
879  move*=fraction;
880 
881  setIdentity(result);
882  translate(result,move);
883  result=mspin*matrix1*result;
884 
885  return result;
886 }
887 
888 /** @brief Return the transform to properly place a billboard
889 
890  @relates Matrix3x4
891 
892  The resulting transform should move a Z-facing object at the origin
893  to the given @em center and @direction, doing it's best to keep
894  the local x axis parallel to the world XZ plane. */
895 template <typename T>
896 inline Matrix<3,4,T> billboardTransform(const Vector<3,T>& center,
897  const Vector<3,T>& direction)
898 {
899  Vector<3,T> zAxis(0.0f,0.0f,1.0f);
900  Quaternion<T> rotation;
901 
902  set(rotation,zAxis,unit(direction));
903 // removeTwistAboutX(rotation);
904  Matrix<3,4,T> result=rotation;
905  setTranslation(result,center);
906 
907  return result;
908 }
909 
910 template<class T>
911 inline Matrix<3,4,T> operator*(const Matrix<3,4,T>& left,
912  const Matrix<3,4,T>& right)
913 {
914  // [i][j]=sum of [i][k]*[k][j] for all k
915 
916  Matrix<3,4,T> matrix;
917 
918  set(matrix.column(0),
919  left(0,0)*right(0,0)+left(1,0)*right(0,1)+left(2,0)*right(0,2),
920  left(0,0)*right(1,0)+left(1,0)*right(1,1)+left(2,0)*right(1,2),
921  left(0,0)*right(2,0)+left(1,0)*right(2,1)+left(2,0)*right(2,2));
922 
923  set(matrix.column(1),
924  left(0,1)*right(0,0)+left(1,1)*right(0,1)+left(2,1)*right(0,2),
925  left(0,1)*right(1,0)+left(1,1)*right(1,1)+left(2,1)*right(1,2),
926  left(0,1)*right(2,0)+left(1,1)*right(2,1)+left(2,1)*right(2,2));
927 
928  set(matrix.column(2),
929  left(0,2)*right(0,0)+left(1,2)*right(0,1)+left(2,2)*right(0,2),
930  left(0,2)*right(1,0)+left(1,2)*right(1,1)+left(2,2)*right(1,2),
931  left(0,2)*right(2,0)+left(1,2)*right(2,1)+left(2,2)*right(2,2));
932 
933  set(matrix.column(3),
934  left(0,3)*right(0,0)+left(1,3)*right(0,1)+left(2,3)*right(0,2)+
935  right(0,3),
936  left(0,3)*right(1,0)+left(1,3)*right(1,1)+left(2,3)*right(1,2)+
937  right(1,3),
938  left(0,3)*right(2,0)+left(1,3)*right(2,1)+left(2,3)*right(2,2)+
939  right(2,3));
940 
941  return matrix;
942 }
943 
944 template<class T>
945 inline Quaternion<T>::Quaternion(const Matrix<3,4,T>& matrix)
946 {
947  operator=(matrix);
948 }
949 
950 //* TODO might be invalid if Matrix is scaled
951 template<class T>
953 {
954  T tr,s;
955 
956  tr=matrix(0,0)+matrix(1,1)+matrix(2,2);
957 
958  if(tr>0.0f)
959  {
960  // diagonal is positive
961  s=sqrt(tr+1.0f);
962  T s2=0.5f/s;
963 
964  set(*this,(matrix(2,1)-matrix(1,2))*s2,(matrix(0,2)-matrix(2,0))*s2,
965  (matrix(1,0)-matrix(0,1))*s2,0.5f*s);
966  }
967  else
968  {
969  // diagonal is negative
970  int i=0;
971  if(matrix(1,1)>matrix(0,0))
972  {
973  i=1;
974  }
975 
976  if(matrix(2,2)>matrix(i,i))
977  {
978  i=2;
979  }
980 
981  const int nxt[3]={1,2,0};
982  int j=nxt[i];
983  int k=nxt[j];
984 
985  s=sqrt((matrix(i,i)-(matrix(j,j)+matrix(k,k)))+1.0f);
986 
987  T q[4];
988 
989  q[i]=s*0.5f;
990 
991  if(s!=0.0f)
992  s=0.5f/s;
993 
994  q[3]=(matrix(k,j)-matrix(j,k))*s;
995  q[j]=(matrix(j,i)+matrix(i,j))*s;
996  q[k]=(matrix(k,i)+matrix(i,k))*s;
997 
998  set(*this,q[0],q[1],q[2],q[3]);
999  }
1000 
1001  normalize(*this);
1002  return *this;
1003 }
1004 
1005 
1006 typedef Matrix<3,4,F32> Matrix3x4f;
1007 typedef Matrix<3,4,F64> Matrix3x4d;
1009 
1010 FE_DL_PUBLIC BWORD makeFrame(SpatialTransform &a_frame,
1011  const Vector<3,Real> &a_0, const Vector<3,Real> &a_1,
1012  const Vector<3,Real> &a_2, const Vector<3,Real> &a_offset);
1013 
1014 FE_DL_PUBLIC BWORD makeFrame(SpatialTransform &a_frame,
1015  const Vector<3,Real> &a_0, const Vector<3,Real> &a_1,
1016  const Vector<3,Real> &a_2, const SpatialTransform& a_transform);
1017 
1018 FE_DL_PUBLIC BWORD makeFrame(SpatialTransform &a_frame,
1019  const Vector<3,Real> &a_location,
1020  const Vector<3,Real> &a_direction, const Vector<3,Real> &a_up);
1021 
1022 FE_DL_PUBLIC BWORD makeFrameCameraZ(SpatialTransform &a_frame,
1023  const Vector<3,Real> &a_location,
1024  const Vector<3,Real> &a_yDir, const Vector<3,Real> &a_cameraZ);
1025 
1026 //* NOTE tangentX and normalY are only different by which axis is unchanged
1027 FE_DL_PUBLIC BWORD makeFrameTangentX(SpatialTransform &a_frame,
1028  const Vector<3,Real> &a_location,
1029  const Vector<3,Real> &a_tangentX, const Vector<3,Real> &a_normalY);
1030 
1031 FE_DL_PUBLIC BWORD makeFrameNormalY(SpatialTransform &a_frame,
1032  const Vector<3,Real> &a_location,
1033  const Vector<3,Real> &a_tangentX, const Vector<3,Real> &a_normalY);
1034 
1035 FE_DL_PUBLIC BWORD makeFrameNormalZ(SpatialTransform &a_frame,
1036  const Vector<3,Real> &a_location,
1037  const Vector<3,Real> &a_tangentX, const Vector<3,Real> &a_normalZ);
1038 
1039 } /* namespace */
1040 
1041 #endif /* __math_Matrix3x4_h__ */
T operator()(unsigned int i, unsigned int j) const
Column Major addressing.
Definition: Matrix3x4.h:140
Matrix< M, N, T > & subtract(Matrix< M, N, T > &R, const Matrix< M, N, T > &A, const Matrix< M, N, U > &B)
Matrix Matrix subtract.
Definition: Matrix.h:270
Matrix for 3D transformations.
Definition: Matrix3x4.h:47
kernel
Definition: namespace.dox:3
String print(const Matrix< M, N, T > &a_m)
Matrix print.
Definition: Matrix.h:368
Matrix< 4, 4, T > & invert(Matrix< 4, 4, T > &a_inverted, const Matrix< 4, 4, T > &a_matrix)
4x4 full matrix inversion
Definition: Matrix.h:1033
General template for fixed size numeric matrices.
Definition: Matrix.h:42
T & operator()(unsigned int i, unsigned int j)
Column Major addressing.
Definition: Matrix3x4.h:143
BWORD operator!=(const DualString &s1, const DualString &s2)
Compare two DualString&#39;s (reverse logic)
Definition: DualString.h:229
Matrix< M, L, T > operator*(const Matrix< M, N, T > &lhs, const Matrix< N, L, U > &rhs)
Matrix Matrix multiply.
Definition: Matrix.h:517
bool equivalent(const Matrix< 3, 4, T > &lhs, const Matrix< 3, 4, T > &rhs, U margin)
Equivalence test within the given tolerance margin.
Definition: Matrix3x4.h:171
String & cat(const char *operand)
Append the current String with the given text.
Definition: String.cc:545
U32 height(const Matrix< M, N, T > &matrix)
Return the vertical dimension.
Definition: Matrix.h:158
Matrix< M, N, T > operator+(const Matrix< M, N, T > &lhs, const Matrix< M, N, U > &rhs)
Matrix Matrix add.
Definition: Matrix.h:493
Automatically reference-counted string container.
Definition: String.h:128
U32 width(const Matrix< M, N, T > &matrix)
Return the horizonatal dimension.
Definition: Matrix.h:149
Matrix< M, N, T > operator-(const Matrix< M, N, T > &lhs, const Matrix< M, N, U > &rhs)
Matrix Matrix subtract.
Definition: Matrix.h:505
String & catf(const char *fmt,...)
Populate the string as with sPrintf(), but by concatenating the results to the existing string...
Definition: String.cc:554
Matrix< M, N, T > & add(Matrix< M, N, T > &R, const Matrix< M, N, T > &A, const Matrix< M, N, U > &B)
Matrix Matrix add.
Definition: Matrix.h:253
Matrix< M, N, T > & setIdentity(Matrix< M, N, T > &matrix)
Set matrix to identity matrix.
Definition: Matrix.h:176
void copy(Matrix< M, N, T > &lhs, const Matrix< I, J, U > &rhs)
Matrix copy.
Definition: Matrix.h:410
Matrix< M, N, T > & operator*=(Matrix< M, N, T > &lhs, const U rhs)
Matrix Scale.
Definition: Matrix.h:558
Matrix< M, N, T > & multiply(Matrix< M, N, T > &R, const Matrix< M, L, T > &A, const Matrix< L, N, U > &B)
Matrix Matrix multiply.
Definition: Matrix.h:287
Four-dimensional complex number.
Definition: Quaternion.h:32