Free Electron
Matrix.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_matrix_h__
8 #define __math_matrix_h__
9 
10 namespace fe
11 {
12 /**************************************************************************//**
13  @brief General template for fixed size numeric matrices
14 
15  @ingroup math
16 
17  @verbatim
18  Dimensions specified as MxN:
19 
20  N
21  ____
22  | |
23  M | |
24  |____|
25 
26  With storage for a 4x4 as:
27  0 4 8 12
28  1 5 9 13
29  2 6 10 14
30  3 7 11 15
31 
32  The operator(i,j) addressing for a 4x4 matrix is:
33  00 01 02 03
34  10 11 12 13
35  20 21 22 23
36  30 31 32 33
37 
38  This is sometimes called column-major.
39  @endverbatim
40 *//***************************************************************************/
41 template<int M, int N, class T>
42 class Matrix
43 {
44  public:
45  Matrix(void) {}
46  Matrix(const Matrix<M,N,T> &other) { operator=(other);}
47 
48  Matrix<M,N,T>& operator=(const Matrix<M,N,T> &other);
49  template<class U>
50  Matrix<M,N,T>& operator=(const Matrix<M,N,U> &other);
51  template<int I,int J,class U>
52  Matrix<M,N,T>& operator=(const Matrix<I,J,U> &other);
53  bool operator==(const Matrix<M,N,T> &other) const;
54 
55  /// Column Major addressing
56  T operator()(unsigned int i, unsigned int j) const;
57  /// Column Major addressing
58  T& operator()(unsigned int i, unsigned int j);
59 
60  T operator[](unsigned int index) const;
61  T& operator[](unsigned int index);
62 
63  Vector<M,T> column(unsigned int index) const
64  { return Vector<M,T>(m_data+4*index); }
65 
66  T *raw(void) { return m_data; }
67 const T *raw(void) const { return m_data; }
68 
69  protected:
70  T m_data[M*N];
71 };
72 
73 
74 template<int M, int N, class T>
76 {
77  if(this != &other)
78  for(unsigned int i = 0;i < M*N;i++)
79  m_data[i] = other[i];
80  return *this;
81 }
82 
83 template<int M, int N, class T>
84 template<class U>
86 {
87  for(unsigned int i = 0;i < M*N;i++)
88  m_data[i] = (T)other[i];
89  return *this;
90 }
91 
92 template<int M, int N, class T>
93 template<int I,int J,class U>
95 {
96  copy(*this,other);
97  return *this;
98 }
99 
100 template<int M, int N, class T>
101 inline bool Matrix<M,N,T>::operator==(const Matrix<M,N,T> &other) const
102 {
103  return (0 == memcmp(reinterpret_cast<const void *>(m_data),
104  reinterpret_cast<const void *>(other.m_data), M*N*sizeof(T)));
105 }
106 
107 template<int M, int N, class T>
108 inline T Matrix<M,N,T>::operator()(unsigned int i, unsigned int j) const
109 {
110 #if FE_BOUNDSCHECK
111  if(i >= M || j >= N) { feX(e_invalidRange); }
112 #endif
113  return m_data[ j*M + i ];
114 }
115 
116 template<int M, int N, class T>
117 inline T &Matrix<M,N,T>::operator()(unsigned int i, unsigned int j)
118 {
119 #if FE_BOUNDSCHECK
120  if(i >= M || j >= N) { feX(e_invalidRange); }
121 #endif
122  return m_data[ j*M + i ];
123 }
124 
125 template<int M, int N, class T>
126 inline T Matrix<M,N,T>::operator[](unsigned int index) const
127 {
128 #if FE_BOUNDSCHECK
129  if(index > M*N) { feX(e_invalidRange); }
130 #endif
131  return m_data[ index ];
132 }
133 
134 template<int M, int N, class T>
135 inline T &Matrix<M,N,T>::operator[](unsigned int index)
136 {
137 #if FE_BOUNDSCHECK
138  if(index > M*N) { feX(e_invalidRange); }
139 #endif
140  return m_data[ index ];
141 }
142 
143 /* non member operations */
144 
145 /** Return the horizonatal dimension
146  @relates Matrix
147  */
148 template<int M, int N, class T>
149 inline U32 width(const Matrix<M,N,T> &matrix)
150 {
151  return M;
152 }
153 
154 /** Return the vertical dimension
155  @relates Matrix
156  */
157 template<int M, int N, class T>
158 inline U32 height(const Matrix<M,N,T> &matrix)
159 {
160  return N;
161 }
162 
163 /** Return true is matrix is square, otherwise return false.
164  @relates Matrix
165  */
166 template<int M, int N, class T>
167 inline bool isSquare(const Matrix<M,N,T> &matrix)
168 {
169  return (M==N);
170 }
171 
172 /** Set matrix to identity matrix
173  @relates Matrix
174  */
175 template<int M, int N, class T>
177 {
178  set(matrix);
179  for(unsigned int i = 0;i < M && i < N;i++)
180  matrix(i,i) = 1.0;
181  return matrix;
182 }
183 
184 template<int M, int N, class T>
185 inline Matrix<M,N,T>& set(Matrix<M,N,T>& matrix)
186 {
187  return setAll(matrix,T(0));
188 }
189 
190 template<int M, int N, class T,class U>
191 inline Matrix<M,N,T>& set(Matrix<M,N,T>& matrix,const U* pArray)
192 {
193  for(unsigned int i = 0;i < M*N;i++)
194  matrix[i] = pArray[i];
195  return matrix;
196 }
197 
198 template<int M, int N, class T,class U>
199 inline Matrix<M,N,T>& setAll(Matrix<M,N,T>& matrix,const U value)
200 {
201  for(unsigned int i = 0;i < M*N;i++)
202  {
203  matrix[i] = value;
204  }
205  return matrix;
206 }
207 
208 /** Return transpose of matrix.
209  @relates Matrix
210  */
211 template<int M, int N, class T>
212 inline Matrix<N,M,T> transpose(const Matrix<M,N,T> &matrix)
213 {
214  Matrix<N,M,T> A;
215  for(unsigned int i=0; i<M; i++)
216  {
217  for(unsigned int j=0; j < N; j++)
218  {
219  A(j,i) = matrix(i,j);
220  }
221  }
222  return A;
223 }
224 
225 /** Transpose matrix in place.
226  @relates Matrix
227  */
228 template<int M, int N, class T>
230 {
231  if(!isSquare(matrix))
232  {
233  feX("transpose",
234  "cannot transpose non-square matrix in place");
235  }
236  T tmp;
237  for(unsigned int i=0; i<M; i++)
238  {
239  for(unsigned int j=i+1; j < N; j++)
240  {
241  tmp = matrix(i,j);
242  matrix(i,j) = matrix(j,i);
243  matrix(j,i) = tmp;
244  }
245  }
246  return matrix;
247 }
248 
249 /** Matrix Matrix add
250  @relates Matrix
251  */
252 template<int M, int N, class T, class U>
254  const Matrix<M,N,U> &B)
255 {
256  for(unsigned int i = 0;i < M; i++)
257  {
258  for(unsigned int j = 0;j < N; j++)
259  {
260  R(i,j) = A(i,j)+B(i,j);
261  }
262  }
263  return R;
264 }
265 
266 /** Matrix Matrix subtract
267  @relates Matrix
268  */
269 template<int M, int N, class T, class U>
271  const Matrix<M,N,U> &B)
272 {
273  for(unsigned int i = 0;i < M; i++)
274  {
275  for(unsigned int j = 0;j < N; j++)
276  {
277  R(i,j) = A(i,j)-B(i,j);
278  }
279  }
280  return R;
281 }
282 
283 /** Matrix Matrix multiply
284  @relates Matrix
285  */
286 template<int M, int N, int L, class T, class U>
288  const Matrix<L,N,U> &B)
289 {
290  for(unsigned int i = 0;i < M; i++)
291  {
292  for(unsigned int j = 0;j < N; j++)
293  {
294  T sum=T(0);
295  for(unsigned int k = 0;k < L; k++)
296  {
297  sum += A(i,k)*B(k,j);
298  }
299  R(i,j)=sum;
300  }
301  }
302  return R;
303 }
304 
305 /** Matrix Vector multiply
306  @relates Vector
307  */
308 template<int M, int N, class T, class U>
310  const Vector<N,U> &x)
311 {
312  for(unsigned int i = 0;i < M; i++)
313  {
314  T sum=T(0);
315  for(unsigned int j = 0;j < N; j++)
316  {
317  sum+=A(i,j) * x[j];
318  }
319  setAt(b,i,sum);
320  }
321  return b;
322 }
323 
324 /** Matrix Vector multiply
325  @relates Vector
326  */
327 template<int M, int N, class T, class U>
329  const Vector<N,U> &x)
330 {
331  Vector<M,T> b;
332  for(unsigned int i = 0;i < M; i++)
333  {
334  T sum=T(0);
335  for(unsigned int j = 0;j < N; j++)
336  {
337  sum+=A(i,j) * x[j];
338  }
339  setAt(b,i,sum);
340  }
341  return b;
342 }
343 
344 /** Matrix Vector multiply with the matrix transposed
345  @relates Vector
346  */
347 template<int M, int N, class T>
349  const Vector<N,T> &x)
350 {
351  Vector<M,T> b;
352  for(unsigned int i = 0;i < M; i++)
353  {
354  T sum=T(0);
355  for(unsigned int j = 0;j < N; j++)
356  {
357  sum+=A(j,i) * x[j];
358  }
359  setAt(b,i,sum);
360  }
361  return b;
362 }
363 
364 /** Matrix print
365  @relates Matrix
366  */
367 template<int M, int N, class T>
368 inline String print(const Matrix<M,N,T> &a_m)
369 {
370  String s;
371  for(unsigned int i = 0;i < M; i++)
372  {
373  for(unsigned int j = 0;j < N; j++)
374  {
375  s.catf("%6.3f ", a_m(i,j));
376  }
377  if(i!=M-1)
378  {
379  s.cat("\n");
380  }
381  }
382  return s;
383 }
384 
385 /** Matrix print
386  @relates Matrix
387  */
388 template<int M, int N, class T>
389 inline String fprint(FILE *a_fp, const Matrix<M,N,T> &a_m)
390 {
391  String s;
392  for(unsigned int i = 0;i < M; i++)
393  {
394  for(unsigned int j = 0;j < N; j++)
395  {
396  fe_fprintf(a_fp, "%6.3f ", a_m(i,j));
397  }
398  if(i!=M-1)
399  {
400  fe_fprintf(a_fp, "\n");
401  }
402  }
403  return s;
404 }
405 
406 /** Matrix copy
407  @relates Matrix
408  */
409 template<int M, int N, class T,int I, int J, class U>
410 inline void copy(Matrix<M,N,T> &lhs,const Matrix<I,J,U> &rhs)
411 {
412  int m;
413  if(M < I) { m = M; }
414  else { m = I; }
415  int n;
416  if(N < J) { n = N; }
417  else { n = J; }
418 
419  for(int i = 0;i < m; i++)
420  {
421  for(int j = 0;j < n; j++)
422  {
423  lhs(i,j) = rhs(i,j);
424  }
425  for(int j = n;j < N; j++)
426  {
427  lhs(i,j) = T(0);
428  }
429  }
430  for(int i = m;i < M; i++)
431  {
432  for(int j = 0;j < N; j++)
433  {
434  lhs(i,j) = T(0);
435  }
436  }
437 }
438 
439 /** Matrix overlay
440  @relates Matrix
441  */
442 template<int M, int N, int I, int J, class T>
443 inline void overlay(Matrix<M,N,T> &lhs,const Matrix<I,J,T> &rhs)
444 {
445  int m;
446  if(M < I) { m = M; }
447  else { m = I; }
448  int n;
449  if(N < J) { n = N; }
450  else { n = J; }
451 
452  for(int i = 0;i < m; i++)
453  {
454  for(int j = 0;j < n; j++)
455  {
456  lhs(i,j) = rhs(i,j);
457  }
458  }
459 }
460 
461 
462 /** Matrix scale in place
463  @relates Matrix
464  */
465 template<int M, int N, class T, class U>
466 inline Matrix<M,N,T> &multiply(Matrix<M,N,T> &A, const U &scale)
467 {
468  for(unsigned int i = 0;i < M*N; i++)
469  {
470  A[i]*=scale;
471  }
472  return A;
473 }
474 
475 /** Matrix scale
476  @relates Matrix
477  */
478 template<int M, int N, class T, class U>
479 inline Matrix<M,N,T> multiply(const Matrix<M,N,T> &A, const U &scale)
480 {
481  Matrix<M,N,T> tmp;
482  for(unsigned int i = 0;i < M*N; i++)
483  {
484  tmp[i] = scale * A[i];
485  }
486  return tmp;
487 }
488 
489 /** Matrix Matrix add
490  @relates Matrix
491  */
492 template<int M, int N, class T, class U>
494  const Matrix<M,N,U> &rhs)
495 {
496  Matrix<M,N,T> C;
497  add(C,lhs,rhs);
498  return C;
499 }
500 
501 /** Matrix Matrix subtract
502  @relates Matrix
503  */
504 template<int M, int N, class T, class U>
506  const Matrix<M,N,U> &rhs)
507 {
508  Matrix<M,N,T> C;
509  subtract(C,lhs,rhs);
510  return C;
511 }
512 
513 /** Matrix Matrix multiply
514  @relates Matrix
515  */
516 template<int M, int N, int L, class T, class U>
518  const Matrix<N,L,U> &rhs)
519 {
520  Matrix<M,L,T> C;
521  multiply(C,lhs,rhs);
522  return C;
523 }
524 
525 /** Matrix Scale
526  @relates Matrix
527  */
528 template<int M, int N, class T>
529 inline Matrix<M,N,T> operator*(const Matrix<M,N,T> &lhs, const Real rhs)
530 {
531  return multiply(lhs,rhs);
532 }
533 
534 /** Matrix Vector multiply
535  @relates Vector
536  */
537 template<int M, int N, class T, class U>
538 inline Vector<M,U> operator*(const Matrix<M,N,T> &lhs, const Vector<N,U> &rhs)
539 {
540  Vector<M,T> b;
541  multiply(b,lhs,rhs);
542  return b;
543 }
544 
545 /** Matrix Scale
546  @relates Matrix
547  */
548 template<int M, int N, class T, class U>
549 inline Matrix<M,N,T> operator*(const U lhs, const Matrix<M,N,T> &rhs)
550 {
551  return multiply(rhs,lhs);
552 }
553 
554 /** Matrix Scale
555  @relates Matrix
556  */
557 template<int M, int N, class T, class U>
558 inline Matrix<M,N,T> &operator*=(Matrix<M,N,T> &lhs, const U rhs)
559 {
560  return multiply(lhs,rhs);
561 }
562 
563 /** Square root of a matrix.
564  This is a Cholesky Factorization: trans(U)*U = A
565  */
566 template<int M, int N, class T>
567 inline void squareroot(Matrix<M,N,T> &a_U, const Matrix<M,N,T> &a_A)
568 {
569 #if 1
570  FEASSERT(M==N);
571  a_U = a_A;
572  for(unsigned int i = 0; i < N-1; i++)
573  {
574  //fe_fprintf(stderr, "pre [%d %g]\n", i, a_U(i,i));
575  if(a_U(i,i) < 0.0)
576  {
577  //fe_fprintf(stderr, "not positive definite, negative diagonal [%d %g]\n", i, a_U(i,i));
578  //a_U(i,i) = 1.0;
579  assert(0);
580  }
581 #if FE_COMPILER != FE_MICROSOFT
582  if(isnan(a_U(i,i)))
583  {
584  //fe_fprintf(stderr, "corruption, nan %d\n", i);
585  assert(0);
586  }
587 #endif
588  a_U(i,i) = sqrt(a_U(i,i));
589 #if FE_COMPILER != FE_MICROSOFT
590  if(isnan(a_U(i,i)))
591  {
592  //fe_fprintf(stderr, "diagonal post sqrt, nan %d\n", i);
593  assert(0);
594  }
595 #endif
596  if(a_U(i,i) <= 0.001) {
597  //fe_fprintf(stderr, "not positive definite [%g]\n", a_U(i,i));
598  assert(0);
599  }
600  else
601  {
602  //fe_fprintf(stderr, "-- %d %g\n", i, a_U(i,i));
603  }
604  T z = 1.0 / a_U(i,i);
605 #if FE_COMPILER != FE_MICROSOFT
606  if(isnan(z))
607  {
608  //fe_fprintf(stderr, "z, nan %d\n", i);
609  assert(0);
610  }
611 #endif
612  for(unsigned int j = i+1; j < N; j++)
613  {
614 #if FE_COMPILER != FE_MICROSOFT
615  if(isnan(a_U(i,j)))
616  {
617  //fe_fprintf(stderr, "off diag, nan %d %d\n", i, j);
618  assert(0);
619  }
620 #endif
621  a_U(i,j) *= z;
622  }
623  for(unsigned int j = i+1; j < N; j++)
624  {
625  for(unsigned int jj = j; jj < N; jj++)
626  {
627  a_U(j,jj) -= a_U(i,j) * a_U(i,jj);
628 #if FE_COMPILER != FE_MICROSOFT
629  if(isnan(a_U(j,jj)))
630  {
631  //fe_fprintf(stderr, "off diag 2, nan %d %d\n", j, jj);
632  assert(0);
633  }
634 #endif
635  }
636  }
637  }
638 
639 #if FE_COMPILER != FE_MICROSOFT
640  if(isnan(a_U(N-1,N-1)))
641  {
642  //fe_fprintf(stderr, "N-1,N-1, presqrt\n");
643  assert(0);
644  }
645 #endif
646 //fe_fprintf(stderr, "=-==- %g\n", a_U(N-1,N-1));
647  if(a_U(N-1,N-1) < 0.0)
648  {
649  //fe_fprintf(stderr, "not positive definite, negative diagonal [%d %g]\n", N-1, a_U(N-1,N-1));
650  //a_U(N-1,N-1) = 1.0;
651  assert(0);
652  }
653  a_U(N-1,N-1) = sqrt(a_U(N-1,N-1));
654 #if FE_COMPILER != FE_MICROSOFT
655  if(isnan(a_U(N-1,N-1)))
656  {
657  //fe_fprintf(stderr, "N-1,N-1, postsqrt\n");
658  assert(0);
659  }
660 #endif
661 #endif
662 
663 
664 
665 #if 0
666  arma::Mat<double> A(a_A.raw(),3,3);
667 
668  arma::Mat<double> U(a_U.raw(),3,3,false,true);
669 
670  try
671  {
672  if(!arma::chol(U, A))
673  {
674  fprint(stderr, a_A);
675  exit(101);
676  }
677  }
678  catch(...)
679  {
680  fprint(stderr, a_A);
681  exit(102);
682  }
683 #endif
684 
685 }
686 
687 template<int M, int N, class T>
688 inline void backSub(const Matrix<M,N,T> &a_A, Vector<N,T> &a_x, const Vector<N,T> &a_b)
689 {
690  FEASSERT(M==N);
691  const unsigned int n_1 = N-1;
692  a_x[n_1] = a_b[n_1]/a_A(n_1, n_1);
693 
694  for(int i = N-2; i >= 0; i--)
695  {
696  a_x[i] = a_b[i];
697  for(int j = i+1; j < N; j++)
698  {
699  a_x[i] -= a_A(i, j)*a_x[j];
700  }
701  a_x[i] = a_x[i] / a_A(i, i);
702  }
703 }
704 
705 // operates on upper tri as if it is a transpose of the upper and is lower
706 template<int M, int N, class T>
707 inline void transposeForeSub(const Matrix<M,N,T> &a_A, Vector<N,T> &a_x, const Vector<N,T> &a_b)
708 {
709  FEASSERT(M==N);
710  a_x[0] = a_b[0]/a_A(0, 0);
711  for(unsigned int i = 1; i < N; i++)
712  {
713  a_x[i] = a_b[i];
714  for(unsigned int j = 0; j < i; j++)
715  {
716  a_x[i] -= a_A(j, i)*a_x[j];
717  }
718  a_x[i] = a_x[i] / a_A(i, i);
719  }
720 }
721 
722 /** 4x4 invert
723  */
724 template <typename T>
726  const Matrix<4,4,T> &a_matrix)
727 {
728  /* Copied from OpenSceneGraph.org (transposed for column major) */
729  T r00, r01, r02, r10, r11, r12, r20, r21, r22;
730 
731  // Copy rotation components directly into variables for speed
732  r00 = a_matrix(0,0); r01 = a_matrix(0,1); r02 = a_matrix(0,2);
733  r10 = a_matrix(1,0); r11 = a_matrix(1,1); r12 = a_matrix(1,2);
734  r20 = a_matrix(2,0); r21 = a_matrix(2,1); r22 = a_matrix(2,2);
735 
736  // Partially compute inverse of rot
737  a_inverted(0,0) = r11*r22 - r21*r12;
738  a_inverted(1,0) = r20*r12 - r10*r22;
739  a_inverted(2,0) = r10*r21 - r20*r11;
740 
741  // Compute determinant of rot from 3 elements just computed
742  T one_over_det =
743  1.0/(r00*a_inverted(0,0) + r01*a_inverted(1,0) + r02*a_inverted(2,0));
744  r00 *= one_over_det; r01 *= one_over_det; r02 *= one_over_det;
745 
746  // Finish computing inverse of rot
747  a_inverted(0,0) *= one_over_det;
748  a_inverted(1,0) *= one_over_det;
749  a_inverted(2,0) *= one_over_det;
750  a_inverted(3,0) = 0.0;
751  a_inverted(0,1) = r21*r02 - r01*r22; // Have already been divided by det
752  a_inverted(1,1) = r00*r22 - r20*r02; // same
753  a_inverted(2,1) = r20*r01 - r00*r21; // same
754  a_inverted(3,1) = 0.0;
755  a_inverted(0,2) = r01*r12 - r11*r02; // Have already been divided by det
756  a_inverted(1,2) = r10*r02 - r00*r12; // same
757  a_inverted(2,2) = r00*r11 - r10*r01; // same
758  a_inverted(3,2) = 0.0;
759  a_inverted(3,3) = 1.0;
760 
761  // We no longer need the rxx or det variables anymore, so we can reuse
762  // them for whatever we want. But we will still rename them for the
763  // sake of clarity.
764 
765 #define d r22
766  d = a_matrix(3,3);
767 
768  T s = d-1.0;
769  if(s*s > 1.0e-6 ) // Involves perspective, so we compute the full inverse
770  {
771  Matrix<4,4,T> TPinv;
772  a_inverted(0,3) = 0.0;
773  a_inverted(1,3) = 0.0;
774  a_inverted(2,3) = 0.0;
775 
776 #define px r00
777 #define py r10
778 #define pz r20
779 #define one_over_s one_over_det
780 #define a r01
781 #define b r11
782 #define c r21
783 
784  a = a_matrix(3,0);
785  b = a_matrix(3,1);
786  c = a_matrix(3,2);
787  px = a_inverted(0,0)*a + a_inverted(1,0)*b + a_inverted(2,0)*c;
788  py = a_inverted(0,1)*a + a_inverted(1,1)*b + a_inverted(2,1)*c;
789  pz = a_inverted(0,2)*a + a_inverted(1,2)*b + a_inverted(2,2)*c;
790 
791 #undef a
792 #undef b
793 #undef c
794 #define tx r01
795 #define ty r11
796 #define tz r21
797 
798  tx = a_matrix(0,3);
799  ty = a_matrix(1,3);
800  tz = a_matrix(2,3);
801  one_over_s = 1.0/(d - (tx*px + ty*py + tz*pz));
802 
803  tx *= one_over_s; ty *= one_over_s; tz *= one_over_s;
804 
805  // Compute inverse of trans*corr
806  TPinv(0,0) = tx*px + 1.0;
807  TPinv(1,0) = ty*px;
808  TPinv(2,0) = tz*px;
809  TPinv(3,0) = -px * one_over_s;
810  TPinv(0,1) = tx*py;
811  TPinv(1,1) = ty*py + 1.0;
812  TPinv(2,1) = tz*py;
813  TPinv(3,1) = -py * one_over_s;
814  TPinv(0,2) = tx*pz;
815  TPinv(1,2) = ty*pz;
816  TPinv(2,2) = tz*pz + 1.0;
817  TPinv(3,2) = -pz * one_over_s;
818  TPinv(0,3) = -tx;
819  TPinv(1,3) = -ty;
820  TPinv(2,3) = -tz;
821  TPinv(3,3) = one_over_s;
822 
823  Matrix<4,4,T> preMult(a_inverted);
824  multiply(a_inverted, preMult, TPinv);
825 
826 #undef px
827 #undef py
828 #undef pz
829 #undef one_over_s
830 #undef d
831  }
832  else // bottommost row is [0; 0; 0; 1] so it can be ignored
833  {
834  tx = a_matrix(0,3);
835  ty = a_matrix(1,3);
836  tz = a_matrix(2,3);
837 
838  // Compute translation components of mat'
839  a_inverted(0,3) =
840  -(tx*a_inverted(0,0) + ty*a_inverted(0,1) + tz*a_inverted(0,2));
841  a_inverted(1,3) =
842  -(tx*a_inverted(1,0) + ty*a_inverted(1,1) + tz*a_inverted(1,2));
843  a_inverted(2,3) =
844  -(tx*a_inverted(2,0) + ty*a_inverted(2,1) + tz*a_inverted(2,2));
845 
846 #undef tx
847 #undef ty
848 #undef tz
849  }
850 
851  return a_inverted;
852 }
853 
854 template <typename T>
855 inline T determinant3x3( T a1,T a2,T a3,
856  T b1,T b2,T b3,
857  T c1,T c2,T c3)
858 {
859  return a1*(b2*c3-b3*c2)
860  -b1*(a2*c3-a3*c2)
861  +c1*(a2*b3-a3*b2);
862 }
863 
864 template <typename T>
865 inline T determinant(const Matrix<4,4,T> &m)
866 {
867  return
868  m[0]*determinant3x3(m[5],m[6],m[7],m[9],m[10],m[11],m[13],m[14],m[15])
869  -m[4]*determinant3x3(m[1],m[2],m[3],m[9],m[10],m[11],m[13],m[14],m[15])
870  +m[8]*determinant3x3(m[1],m[2],m[3],m[5],m[6],m[7],m[13],m[14],m[15])
871  -m[12]*determinant3x3(m[1],m[2],m[3],m[5],m[6],m[7],m[9],m[10],m[11]);
872 }
873 
874 template <typename T>
875 inline Matrix<4,4,T> &jad_invert(Matrix<4,4,T> &a_inverted,
876  const Matrix<4,4,T> &a_matrix)
877 {
878  Matrix<4,4,T> m(a_matrix);
879  setTranspose(m);
880  const F32 det=determinant(m);
881 
882  //* If determinant not valid, can't compute inverse (return identity)
883  if(fabsf(det)<1e-8)
884  {
885  feX("inversion failure");
886  return setIdentity(a_inverted);
887  }
888 
889  const F32 inv=1.0f/det;
890 
891  a_inverted[0]= inv*determinant3x3(
892  m[5],m[6],m[7],m[9],m[10],m[11],m[13],m[14],m[15]);
893  a_inverted[4]= -inv*determinant3x3(
894  m[1],m[2],m[3],m[9],m[10],m[11],m[13],m[14],m[15]);
895  a_inverted[8]= inv*determinant3x3(
896  m[1],m[2],m[3],m[5],m[6],m[7],m[13],m[14],m[15]);
897  a_inverted[12]= -inv*determinant3x3(
898  m[1],m[2],m[3],m[5],m[6],m[7],m[9],m[10],m[11]);
899 
900  a_inverted[1]= -inv*determinant3x3(
901  m[4],m[6],m[7],m[8],m[10],m[11],m[12],m[14],m[15]);
902  a_inverted[5]= inv*determinant3x3(
903  m[0],m[2],m[3],m[8],m[10],m[11],m[12],m[14],m[15]);
904  a_inverted[9]= -inv*determinant3x3(
905  m[0],m[2],m[3],m[4],m[6],m[7],m[12],m[14],m[15]);
906  a_inverted[13]= inv*determinant3x3(
907  m[0],m[2],m[3],m[4],m[6],m[7],m[8],m[10],m[11]);
908 
909  a_inverted[2]= inv*determinant3x3(
910  m[4],m[5],m[7],m[8],m[9],m[11],m[12],m[13],m[15]);
911  a_inverted[6]= -inv*determinant3x3(
912  m[0],m[1],m[3],m[8],m[9],m[11],m[12],m[13],m[15]);
913  a_inverted[10]= inv*determinant3x3(
914  m[0],m[1],m[3],m[4],m[5],m[7],m[12],m[13],m[15]);
915  a_inverted[14]= -inv*determinant3x3(
916  m[0],m[1],m[3],m[4],m[5],m[7],m[8],m[9],m[11]);
917 
918  a_inverted[3]= -inv*determinant3x3(
919  m[4],m[5],m[6],m[8],m[9],m[10],m[12],m[13],m[14]);
920  a_inverted[7]= inv*determinant3x3(
921  m[0],m[1],m[2],m[8],m[9],m[10],m[12],m[13],m[14]);
922  a_inverted[11]= -inv*determinant3x3(
923  m[0],m[1],m[2],m[4],m[5],m[6],m[12],m[13],m[14]);
924  a_inverted[15]= inv*determinant3x3(
925  m[0],m[1],m[2],m[4],m[5],m[6],m[8],m[9],m[10]);
926 
927  return a_inverted;
928 
929 }
930 
931 template <typename T>
932 inline Matrix<4,4,T> &brk_invert(Matrix<4,4,T> &a_inverted,
933  const Matrix<4,4,T> &a_matrix)
934 {
935  F32 src[16];
936  F32 tmp[12];
937  F32 det;
938  F32 dst[16];
939 
940  for(IWORD a = 0; a < 16; a++)
941  {
942  src[a] = a_matrix[a];
943  }
944 
945  // calculate pairs for first 8 cofactors
946  tmp[0] = src[10] * src[15];
947  tmp[1] = src[11] * src[14];
948  tmp[2] = src[9] * src[15];
949  tmp[3] = src[11] * src[13];
950  tmp[4] = src[9] * src[14];
951  tmp[5] = src[10] * src[13];
952  tmp[6] = src[8] * src[15];
953  tmp[7] = src[11] * src[12];
954  tmp[8] = src[8] * src[14];
955  tmp[9] = src[10] * src[12];
956  tmp[10] = src[8] * src[13];
957  tmp[11] = src[9] * src[12];
958 
959  // calculate first 8 cofactors
960  dst[0] = tmp[0]* src[5] + tmp[3]*src[6] + tmp[4]*src[7];
961  dst[0] -= tmp[1]*src[5] + tmp[2]*src[6] + tmp[5]*src[7];
962  dst[1] = tmp[1]* src[4] + tmp[6]*src[6] + tmp[9]*src[7];
963  dst[1] -= tmp[0]*src[4] + tmp[7]*src[6] + tmp[8]*src[7];
964  dst[2] = tmp[2]* src[4] + tmp[7]*src[5] + tmp[10]*src[7];
965  dst[2] -= tmp[3]*src[4] + tmp[6]*src[5] + tmp[11]*src[7];
966  dst[3] = tmp[5]* src[4] + tmp[8]*src[5] + tmp[11]*src[6];
967  dst[3] -= tmp[4]*src[4] + tmp[9]*src[5] + tmp[10]*src[6];
968  dst[4] = tmp[1]* src[1] + tmp[2]*src[2] + tmp[5]*src[3];
969  dst[4] -= tmp[0]*src[1] + tmp[3]*src[2] + tmp[4]*src[3];
970  dst[5] = tmp[0]* src[0] + tmp[7]*src[2] + tmp[8]*src[3];
971  dst[5] -= tmp[1]*src[0] + tmp[6]*src[2] + tmp[9]*src[3];
972  dst[6] = tmp[3]* src[0] + tmp[6]*src[1] + tmp[11]*src[3];
973  dst[6] -= tmp[2]*src[0] + tmp[7]*src[1] + tmp[10]*src[3];
974  dst[7] = tmp[4]* src[0] + tmp[9]*src[1] + tmp[10]*src[2];
975  dst[7] -= tmp[5]*src[0] + tmp[8]*src[1] + tmp[11]*src[2];
976 
977  // calculate pairs for first 8 cofactors
978  tmp[0] = src[2] * src[7];
979  tmp[1] = src[3] * src[6];
980  tmp[2] = src[1] * src[7];
981  tmp[3] = src[3] * src[5];
982  tmp[4] = src[1] * src[6];
983  tmp[5] = src[2] * src[5];
984  tmp[6] = src[0] * src[7];
985  tmp[7] = src[3] * src[4];
986  tmp[8] = src[0] * src[6];
987  tmp[9] = src[2] * src[4];
988  tmp[10] = src[0] * src[5];
989  tmp[11] = src[1] * src[4];
990 
991  // calculate second 8 cofactors
992  dst[8] = tmp[0]* src[13] + tmp[3]*src[14] + tmp[4]*src[15];
993  dst[8] -= tmp[1]*src[13] + tmp[2]*src[14] + tmp[5]*src[15];
994  dst[9] = tmp[1]* src[12] + tmp[6]*src[14] + tmp[9]*src[15];
995  dst[9] -= tmp[0]*src[12] + tmp[7]*src[14] + tmp[8]*src[15];
996  dst[10] = tmp[2]* src[12] + tmp[7]*src[13] + tmp[10]*src[15];
997  dst[10] -= tmp[3]*src[12] + tmp[6]*src[13] + tmp[11]*src[15];
998  dst[11] = tmp[5]* src[12] + tmp[8]*src[13] + tmp[11]*src[14];
999  dst[11] -= tmp[4]*src[12] + tmp[9]*src[13] + tmp[10]*src[14];
1000  dst[12] = tmp[2]* src[10] + tmp[5]*src[11] + tmp[1]*src[9];
1001  dst[12] -= tmp[4]*src[11] + tmp[0]*src[9] + tmp[3]*src[10];
1002  dst[13] = tmp[8]* src[11] + tmp[0]*src[8] + tmp[7]*src[10];
1003  dst[13] -= tmp[6]*src[10] + tmp[9]*src[11] + tmp[1]*src[8];
1004  dst[14] = tmp[6]* src[9] + tmp[11]*src[11] + tmp[3]*src[8];
1005  dst[14] -= tmp[10]*src[11] + tmp[2]*src[8] + tmp[7]*src[9];
1006  dst[15] = tmp[10]* src[10] + tmp[4]*src[8] + tmp[9]*src[9];
1007  dst[15] -= tmp[8]*src[9] + tmp[11]*src[10] + tmp[5]*src[8];
1008 
1009  // calculate determinate
1010  det = determinant(a_matrix);
1011 
1012  // calculate matrix inverse
1013  det = 1.0/det;
1014  for(IWORD j = 0; j < 16; j++)
1015  {
1016  dst[j] *= det;
1017  }
1018 
1019  for(IWORD i = 0; i < 4; i++)
1020  {
1021  a_inverted[i] = dst[i + 4];
1022  a_inverted[i + 4] = dst[i * 4 + 1];
1023  a_inverted[i + 8] = dst[i * 4 + 2];
1024  a_inverted[i + 12] = dst[i * 4 + 3];
1025  }
1026 
1027  return a_inverted;
1028 
1029 }
1030 
1031 /// 4x4 full matrix inversion
1032 template <typename T>
1033 inline Matrix<4,4,T> &invert(Matrix<4,4,T> &a_inverted,
1034  const Matrix<4,4,T> &a_matrix)
1035 {
1036  return osg_invert(a_inverted, a_matrix);
1037 }
1038 
1039 
1040 // TODO: test/validate this
1041 /// 3x3 matrix inversion
1042 template <typename T>
1043 inline Matrix<3,3,T> &invert(Matrix<3,3,T> &a_inverted,
1044  const Matrix<3,3,T> &a_matrix)
1045 {
1046  a_inverted(0,0)= a_matrix(1,1)*a_matrix(2,2) - a_matrix(2,1)*a_matrix(1,2);
1047  a_inverted(0,1)= -a_matrix(0,1)*a_matrix(2,2) + a_matrix(2,1)*a_matrix(0,2);
1048  a_inverted(0,2)= a_matrix(0,1)*a_matrix(1,2) - a_matrix(1,1)*a_matrix(0,2);
1049  a_inverted(1,0)= -a_matrix(1,0)*a_matrix(2,2) + a_matrix(2,0)*a_matrix(1,2);
1050  a_inverted(1,1)= a_matrix(0,0)*a_matrix(2,2) - a_matrix(2,0)*a_matrix(0,2);
1051  a_inverted(1,2)= -a_matrix(0,0)*a_matrix(1,2) + a_matrix(1,0)*a_matrix(0,2);
1052  a_inverted(2,0)= a_matrix(1,0)*a_matrix(2,1) - a_matrix(2,0)*a_matrix(1,1);
1053  a_inverted(2,1)= -a_matrix(0,0)*a_matrix(2,1) + a_matrix(2,0)*a_matrix(0,1);
1054  a_inverted(2,2)= a_matrix(0,0)*a_matrix(1,1) - a_matrix(1,0)*a_matrix(0,1);
1055 
1056  Real det = a_inverted(0,0) * a_matrix(0,0) + a_inverted(1,0) * a_matrix(0,1)
1057  + a_inverted(2,0) * a_matrix(0,2);
1058 
1059  if(fabs(det) < fe::tol)
1060  {
1061  feX("attempt to invert singular 3x3 matrix");
1062  }
1063 
1064  a_inverted *= 1.0 / det;
1065 
1066  return a_inverted;
1067 }
1068 
1069 template <typename T>
1070 inline bool inverted(Matrix<3,3,T> &a_inverted,
1071  const Matrix<3,3,T> &a_matrix)
1072 {
1073  a_inverted(0,0)= a_matrix(1,1)*a_matrix(2,2) - a_matrix(2,1)*a_matrix(1,2);
1074  a_inverted(0,1)= -a_matrix(0,1)*a_matrix(2,2) + a_matrix(2,1)*a_matrix(0,2);
1075  a_inverted(0,2)= a_matrix(0,1)*a_matrix(1,2) - a_matrix(1,1)*a_matrix(0,2);
1076  a_inverted(1,0)= -a_matrix(1,0)*a_matrix(2,2) + a_matrix(2,0)*a_matrix(1,2);
1077  a_inverted(1,1)= a_matrix(0,0)*a_matrix(2,2) - a_matrix(2,0)*a_matrix(0,2);
1078  a_inverted(1,2)= -a_matrix(0,0)*a_matrix(1,2) + a_matrix(1,0)*a_matrix(0,2);
1079  a_inverted(2,0)= a_matrix(1,0)*a_matrix(2,1) - a_matrix(2,0)*a_matrix(1,1);
1080  a_inverted(2,1)= -a_matrix(0,0)*a_matrix(2,1) + a_matrix(2,0)*a_matrix(0,1);
1081  a_inverted(2,2)= a_matrix(0,0)*a_matrix(1,1) - a_matrix(1,0)*a_matrix(0,1);
1082 
1083  Real det = a_inverted(0,0) * a_matrix(0,0) + a_inverted(1,0) * a_matrix(0,1)
1084  + a_inverted(2,0) * a_matrix(0,2);
1085 
1086  if(fabs(det) < fe::tol)
1087  {
1088  return false;
1089  }
1090 
1091  a_inverted *= 1.0 / det;
1092 
1093  return true;
1094 }
1095 
1096 /// @brief Create perspective projection transform just like gluPerspective
1097 template <typename T>
1098 inline Matrix<4,4,T> perspective(T fovy,T aspect,T nearplane,T farplane)
1099 {
1100  FEASSERT(fovy>0.0f);
1101  FEASSERT(aspect>0.0f);
1102  FEASSERT(nearplane>0.0f);
1103  FEASSERT(farplane>nearplane);
1104 
1105  Matrix<4,4,T> matrix;
1106  set(matrix);
1107 
1108  T f=1.0f/tan(0.5f*fovy*degToRad);
1109  T d=nearplane-farplane;
1110 
1111  matrix[0]=f/aspect;
1112  matrix[5]=f;
1113  matrix[10]=(nearplane+farplane)/d;
1114  matrix[11]= -1.0f;
1115  matrix[14]=2.0f*nearplane*farplane/d;
1116 
1117  return matrix;
1118 }
1119 
1120 /// @brief Try to extract settings of a perspective matrix
1121 template <typename T>
1122 inline void decomposePerspective(const Matrix<4,4,T>& a_rProjection,
1123  T &a_rFovy,T &a_rAspect,T &a_rNearplane,T &a_rFarplane)
1124 {
1125  const Real a=a_rProjection[10];
1126  const Real b=a_rProjection[14];
1127 
1128  a_rAspect=a_rProjection[5]/a_rProjection[0];
1129  a_rFovy=2.0/degToRad*atan(1.0/a_rProjection[5]);
1130  a_rNearplane=0.5*(b*(a+1.0)/(a-1.0)-b);
1131  a_rFarplane=a_rNearplane*(a-1.0)/(a+1.0);
1132 
1133 /*
1134  a=m[10]
1135  b=m[14]
1136 
1137  a=(n+f)/(n-f)
1138  b=2nf/(n-f)
1139 
1140  an-af=n+f
1141  bn-bf=2nf
1142 
1143  an-n=af+f
1144  n(a-1)=f(a+1)
1145  f=n(a-1)/(a+1)
1146 
1147  bn=f(2n+b)
1148  f=bn/(2n+b)
1149  n(a-1)/(a+1)=bn/(2n+b)
1150  (a-1)/(a+1)=b/(2n+b)
1151  (a-1)(2n+b)=b(a+1)
1152  2n+b=b(a+1)/(a-1)
1153  n=(b(a+1)/(a-1)-b)/2
1154 */
1155 }
1156 
1157 /// @brief Create orthogonal projection transform just like glOrtho
1158 template <typename T>
1159 inline Matrix<4,4,T> ortho(T left,T right,T bottom, T top,T near_val,T far_val)
1160 {
1161  Matrix<4,4,T> matrix;
1162  set(matrix);
1163 
1164  T dx = right-left;
1165  T dy = top-bottom;
1166  T dz = far_val-near_val;
1167 
1168  matrix[0] = 2.0/dx;
1169  matrix[5] = 2.0/dy;
1170  matrix[10] = -2.0/dz;
1171 
1172  matrix[12] = -(right+left)/dx;
1173  matrix[13] = -(top+bottom)/dy;
1174  matrix[14] = -(far_val+near_val)/dz;
1175  matrix[15] = 1.0;
1176 
1177  return matrix;
1178 }
1179 
1180 /// project vector through matrix. divides by transformed w
1181 template <typename T>
1182 inline void project(Vector<4,T> &a_r, const Matrix<4,4,T> &a_m,
1183  const Vector<4,T> &a_v)
1184 {
1185  const T w=1.0f/(a_v[0]*a_m[3]+a_v[1]*a_m[7]+a_v[2]*a_m[11]+a_m[15] );
1186  a_r[0]=a_v[0]*a_m[0]+a_v[1]*a_m[4]+a_v[2]*a_m[8]+a_m[12];
1187  a_r[1]=a_v[0]*a_m[1]+a_v[1]*a_m[5]+a_v[2]*a_m[9]+a_m[13];
1188  a_r[2]=a_v[0]*a_m[2]+a_v[1]*a_m[6]+a_v[2]*a_m[10]+a_m[14];
1189 
1190  a_r[0]*=w;
1191  a_r[1]*=w;
1192  a_r[2]*=w;
1193 }
1194 
1195 /// reverse project vector through matrix. reverses w division
1196 template <typename T>
1197 inline void unproject(Vector<4,T> &a_r, const Matrix<4,4,T> &a_m,
1198  const Vector<4,T> &a_v)
1199 {
1200  const Vector<4,T> inverted=inverseTransformVector(a_m,a_v);
1201  if(inverted[3]==T(0))
1202  {
1203  set(a_r,0,0,0,0);
1204  return;
1205  }
1206 
1207  a_r[3]=T(1)/inverted[3];
1208  a_r[0]=inverted[0]*a_r[3];
1209  a_r[1]=inverted[1]*a_r[3];
1210  a_r[2]=inverted[2]*a_r[3];
1211 }
1212 
1213 template <typename T>
1214 inline void transformVector(const Matrix<4,4,T> &a_m, const Vector<4,T> &a_v,
1215  Vector<4,T> &a_r)
1216 {
1217  set(a_r,
1218  a_v[0]*a_m[0] +a_v[1]*a_m[4] +a_v[2]*a_m[8] +a_v[3]*a_m[12],
1219  a_v[0]*a_m[1] +a_v[1]*a_m[5] +a_v[2]*a_m[9] +a_v[3]*a_m[13],
1220  a_v[0]*a_m[2] +a_v[1]*a_m[6] +a_v[2]*a_m[10] +a_v[3]*a_m[14],
1221  a_v[0]*a_m[3] +a_v[1]*a_m[7] +a_v[2]*a_m[11] +a_v[3]*a_m[15]);
1222 }
1223 
1224 template <int N, typename T>
1225 inline Vector<N,T> transformVector(const Matrix<4,4,T>& lhs,
1226  const Vector<N,T>& in)
1227 {
1228  FEASSERT(N>2);
1229  Vector<N,T> out;
1230  transformVector(lhs,in,out);
1231  return out;
1232 }
1233 
1234 
1235 template <int N, typename T>
1236 inline Vector<N,T> inverseTransformVector(const Matrix<4,4,T>& lhs,
1237  const Vector<N,T>& in)
1238 {
1239  FEASSERT(N>2);
1240  Matrix<4,4,T> inverse;
1241  invert(inverse,lhs);
1242  return transformVector(inverse,in);
1243 }
1244 
1245 template <typename T>
1246 inline void transposeTransformVector(const Matrix<4,4,T> &a_m,
1247  const Vector<4,T> &a_v,
1248  Vector<4,T> &a_r)
1249 {
1250  set(a_r,
1251  a_v[0]*a_m[0] +a_v[1]*a_m[1] +a_v[2]*a_m[2] +a_v[3]*a_m[3],
1252  a_v[0]*a_m[4] +a_v[1]*a_m[5] +a_v[2]*a_m[6] +a_v[3]*a_m[7],
1253  a_v[0]*a_m[8] +a_v[1]*a_m[9] +a_v[2]*a_m[10] +a_v[3]*a_m[11],
1254  a_v[0]*a_m[12] +a_v[1]*a_m[13] +a_v[2]*a_m[14] +a_v[3]*a_m[15]);
1255 }
1256 
1257 /** @brief Compute the per-element product of the vector and the
1258  inverse diagonal entries
1259 
1260  @relates Matrix
1261 
1262  Only the diagonal elements are used. The non-diagonal values are
1263  not read and treated as zero.
1264 */
1265 template<int N,typename T>
1267  Vector<N,T>& result,
1268  const Matrix<N,N,T>& diagonal,
1269  const Vector<N,T>& vector)
1270 {
1271  //* result[i] = vector[i] / diag[i][i]
1272 
1273  for(U32 m=0;m<N;m++)
1274  {
1275  result[m]=vector[m]/diagonal(m,m);
1276  }
1277 }
1278 
1279 /** Matrix-Matrix multiply where first matrix is presumed diagonal
1280  @relates Matrix
1281 
1282  This amounts to a scale of each row by the reciprical of the
1283  corresponding diagonal element.
1284 
1285  Diagonal elements of the first matrix are inverted during the multiply.
1286  Non-diagonal elements of the first matrix are ignored and treated as zero.
1287  */
1288 template<int N,class T>
1290  Matrix<N,N,T> &result,
1291  const Matrix<N,N,T> &lhs,const Matrix<N,N,T> &rhs)
1292 {
1293  for(U32 i=0;i<N;i++)
1294  {
1295  T d=T(1)/lhs(i,i);
1296  for(U32 j=0;j<N;j++)
1297  {
1298  result(i,j)=rhs(i,j)*d;
1299  }
1300  }
1301  return result;
1302 }
1303 
1304 /** Matrix-Matrix multiply where first matrix is presumed diagonal
1305  @relates Matrix
1306 
1307  This amounts to a scale of each column by the reciprical of the
1308  corresponding diagonal element.
1309 
1310  Diagonal elements of the second matrix are inverted during the multiply.
1311  Non-diagonal elements of the second matrix are ignored and treated as zero.
1312  */
1313 template<int N,class T>
1315  Matrix<N,N,T> &result,
1316  const Matrix<N,N,T> &lhs,const Matrix<N,N,T> &rhs)
1317 {
1318  for(U32 j=0;j<N;j++)
1319  {
1320  T d=T(1)/rhs(j,j);
1321  for(U32 i=0;i<N;i++)
1322  {
1323  result(i,j)=lhs(i,j)*d;
1324  }
1325  }
1326  return result;
1327 }
1328 
1329 template<int N,class T>
1330 inline Matrix<N,N,T>& outerProduct(
1331  Matrix<N,N,T> &result, const Vector<N,T> &a, const Vector<N,T> &b)
1332 {
1333  for(unsigned int i = 0; i < N; i++)
1334  {
1335  for(unsigned int j = 0; j < N; j++)
1336  {
1337  result(i,j) = a[i] * b[j];
1338  }
1339  }
1340 
1341  return result;
1342 }
1343 
1344 /** 3D Matrix rotation
1345  @relates Matrix
1346 
1347  Rotate a 3x3 matrix counterclockwise about the specified axis
1348  */template <typename T,typename U>
1349 inline Matrix<3,3,T>& rotateMatrix(Matrix<3,3,T>& lhs,U radians,Axis axis)
1350 {
1351  const T sina=sin(radians);
1352  const T cosa=cos(radians);
1353 
1354  static const U32 index[3][2]={{1,2},{2,0},{0,1}};
1355  U32 x1=index[axis][0];
1356  U32 x2=index[axis][1];
1357 
1358  T b=lhs(0,x1);
1359  T c=lhs(0,x2);
1360  lhs(0,x1)=c*sina+b*cosa;
1361  lhs(0,x2)=c*cosa-b*sina;
1362  b=lhs(1,x1);
1363  c=lhs(1,x2);
1364  lhs(1,x1)=c*sina+b*cosa;
1365  lhs(1,x2)=c*cosa-b*sina;
1366  b=lhs(2,x1);
1367  c=lhs(2,x2);
1368  lhs(2,x1)=c*sina+b*cosa;
1369  lhs(2,x2)=c*cosa-b*sina;
1370 
1371  return lhs;
1372 }
1373 
1374 } /* namespace */
1375 
1376 #endif /* __math_matrix_h__ */
Vector< M, T > transposeMultiply(const Matrix< M, N, T > &A, const Vector< N, T > &x)
Matrix Vector multiply with the matrix transposed.
Definition: Matrix.h:348
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< N, N, T > & postmultiplyInverseDiagonal(Matrix< N, N, T > &result, const Matrix< N, N, T > &lhs, const Matrix< N, N, T > &rhs)
Matrix-Matrix multiply where first matrix is presumed diagonal.
Definition: Matrix.h:1314
Matrix< 3, 3, T > & rotateMatrix(Matrix< 3, 3, T > &lhs, U radians, Axis axis)
3D Matrix rotation
Definition: Matrix.h:1349
void unproject(Vector< 4, T > &a_r, const Matrix< 4, 4, T > &a_m, const Vector< 4, T > &a_v)
reverse project vector through matrix. reverses w division
Definition: Matrix.h:1197
Matrix< M, N, T > operator*(const U lhs, const Matrix< M, N, T > &rhs)
Matrix Scale.
Definition: Matrix.h:549
Vector< M, T > & multiply(Vector< M, T > &b, const Matrix< M, N, T > &A, const Vector< N, U > &x)
Matrix Vector multiply.
Definition: Matrix.h:309
Matrix< N, N, T > & premultiplyInverseDiagonal(Matrix< N, N, T > &result, const Matrix< N, N, T > &lhs, const Matrix< N, N, T > &rhs)
Matrix-Matrix multiply where first matrix is presumed diagonal.
Definition: Matrix.h:1289
String fprint(FILE *a_fp, const Matrix< M, N, T > &a_m)
Matrix print.
Definition: Matrix.h:389
Vector< M, T > multiply(const Matrix< M, N, T > &A, const Vector< N, U > &x)
Matrix Vector multiply.
Definition: Matrix.h:328
Matrix< N, M, T > transpose(const Matrix< M, N, T > &matrix)
Return transpose of matrix.
Definition: Matrix.h:212
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
Matrix< 4, 4, T > ortho(T left, T right, T bottom, T top, T near_val, T far_val)
Create orthogonal projection transform just like glOrtho.
Definition: Matrix.h:1159
void decomposePerspective(const Matrix< 4, 4, T > &a_rProjection, T &a_rFovy, T &a_rAspect, T &a_rNearplane, T &a_rFarplane)
Try to extract settings of a perspective matrix.
Definition: Matrix.h:1122
Matrix< M, N, T > operator*(const Matrix< M, N, T > &lhs, const Real rhs)
Matrix Scale.
Definition: Matrix.h:529
Vector< M, U > operator*(const Matrix< M, N, T > &lhs, const Vector< N, U > &rhs)
Matrix Vector multiply.
Definition: Matrix.h:538
Dense vector - size fixed by template.
Definition: Vector.h:19
Matrix< M, L, T > operator*(const Matrix< M, N, T > &lhs, const Matrix< N, L, U > &rhs)
Matrix Matrix multiply.
Definition: Matrix.h:517
void overlay(Matrix< M, N, T > &lhs, const Matrix< I, J, T > &rhs)
Matrix overlay.
Definition: Matrix.h:443
T operator()(unsigned int i, unsigned int j) const
Column Major addressing.
Definition: Matrix.h:108
Matrix< 4, 4, T > & osg_invert(Matrix< 4, 4, T > &a_inverted, const Matrix< 4, 4, T > &a_matrix)
4x4 invert
Definition: Matrix.h:725
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
Matrix< M, N, T > multiply(const Matrix< M, N, T > &A, const U &scale)
Matrix scale.
Definition: Matrix.h:479
void project(Vector< 4, T > &a_r, const Matrix< 4, 4, T > &a_m, const Vector< 4, T > &a_v)
project vector through matrix. divides by transformed w
Definition: Matrix.h:1182
Matrix< 4, 4, T > perspective(T fovy, T aspect, T nearplane, T farplane)
Create perspective projection transform just like gluPerspective.
Definition: Matrix.h:1098
U32 width(const Matrix< M, N, T > &matrix)
Return the horizonatal dimension.
Definition: Matrix.h:149
Matrix< M, N, T > & setTranspose(Matrix< M, N, T > &matrix)
Transpose matrix in place.
Definition: Matrix.h:229
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 premultiplyInverseDiagonal(Vector< N, T > &result, const Matrix< N, N, T > &diagonal, const Vector< N, T > &vector)
Compute the per-element product of the vector and the inverse diagonal entries.
Definition: Matrix.h:1266
void copy(Matrix< M, N, T > &lhs, const Matrix< I, J, U > &rhs)
Matrix copy.
Definition: Matrix.h:410
bool isSquare(const Matrix< M, N, T > &matrix)
Return true is matrix is square, otherwise return false.
Definition: Matrix.h:167
Matrix< M, N, T > & operator*=(Matrix< M, N, T > &lhs, const U rhs)
Matrix Scale.
Definition: Matrix.h:558
Partially specialized 4-component vector intended for spatial use.
Definition: Vector4.h:21
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
Matrix< M, N, T > & multiply(Matrix< M, N, T > &A, const U &scale)
Matrix scale in place.
Definition: Matrix.h:466
void squareroot(Matrix< M, N, T > &a_U, const Matrix< M, N, T > &a_A)
Square root of a matrix.
Definition: Matrix.h:567