Fermat
matrix_inline.h
1 /*
2  * Copyright (c) 2010-2018, NVIDIA Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of NVIDIA Corporation nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #pragma once
29 
30 #include <cugar/linalg/vector.h>
31 #include <cmath>
32 
33 namespace cugar {
34 
35 //
36 // I M P L E M E N T A T I O N
37 //
38 
39 #ifdef _V
40 #undef _V
41 #endif
42 #define _V(v, i) (((Vector<T,M>&)v).x[(i)])
43 
44 #ifdef _M
45 #undef _M
46 #endif
47 #define _M(m, i, j) (((Matrix<T,N,M>&)m).r[(i)].x[(j)])
48 
49 #ifdef _CM
50 #undef _CM
51 #endif
52 #define _CM(m, i, j) (((const Matrix<T,N,M>&)m).r[(i)].x[(j)])
53 
54 
55 //
56 // Matrix inline methods
57 //
58 
59 template <typename T, int N, int M> Matrix<T,N,M>::Matrix() { }
60 
61 template <typename T, int N, int M> Matrix<T,N,M>::Matrix(const T s)
62 {
63  for (int i = 0; i < N; i++)
64  r[i] = Vector<T,M>(s);
65 }
66 
67 template <typename T, int N, int M> Matrix<T,N,M>::Matrix(const Matrix<T,N,M>& m)
68 {
69  for (int i = 0; i < N; i++)
70  r[i] = m.r[i];
71 }
72 
73 template <typename T, int N, int M> Matrix<T,N,M>::Matrix(const Vector<T,M>& v)
74 {
75  for (int i = 0; i < N; i++)
76  for (int j = 0; j < M; j++)
77  r[i][j] = 0.0f;
78 
79  // NOTE: only set the first M rows
80  if (M < N)
81  {
82  for (int i = 0; i < M; i++)
83  r[i][i] = v[i];
84  }
85 }
86 
87 template <typename T, int N, int M> Matrix<T,N,M>::Matrix(const Vector<T,M> *v)
88 {
89  for (int i = 0; i < N; i++)
90  r[i] = v[i];
91 }
92 
93 template <typename T, int N, int M> Matrix<T,N,M>::Matrix(const T *v)
94 {
95  for (int i = 0; i < N; i++)
96  for (int j = 0; j < M; j++)
97  r[i][j] = v[i*M + j];
98 }
99 
100 template <typename T, int N, int M> Matrix<T,N,M>::Matrix(const T **v)
101 {
102  for (int i = 0; i < N; i++)
103  for (int j = 0; j < M; j++)
104  r[i][j] = v[i][j];
105 }
106 /*
107 template <typename T, int N, int M> Matrix<T,N,M>::Matrix(const T v[N][M])
108 {
109  for (int i = 0; i < N; i++)
110  for (int j = 0; j < M; j++)
111  r[i][j] = v[i][j];
112 }
113 */
114 template <typename T, int N, int M> Matrix<T,N,M>& Matrix<T,N,M>::operator = (const Matrix<T,N,M>& m)
115 {
116  for (int i = 0; i < N; i++)
117  r[i] = m.r[i];
118  return *this;
119 }
120 
121 template <typename T, int N, int M> Matrix<T,N,M>& Matrix<T,N,M>::operator += (const Matrix<T,N,M>& m)
122 {
123  for (int i = 0; i < N; i++)
124  r[i] += m.r[i];
125  return *this;
126 }
127 
128 template <typename T, int N, int M> Matrix<T,N,M>& Matrix<T,N,M>::operator -= (const Matrix<T,N,M>& m)
129 {
130  for (int i = 0; i < N; i++)
131  r[i] -= m.r[i];
132  return *this;
133 }
134 
135 template <typename T, int N, int M> Matrix<T,N,M>& Matrix<T,N,M>::operator *= (T k)
136 {
137  for (int i = 0; i < N; i++)
138  r[i] *= k;
139  return *this;
140 }
141 
142 template <typename T, int N, int M> Matrix<T,N,M>& Matrix<T,N,M>::operator /= (T k)
143 {
144  for (int i = 0; i < N; i++)
145  r[i] /= k;
146  return *this;
147 }
148 
149 template <typename T, int N, int M> const Vector<T,M>& Matrix<T,N,M>::operator [] (int i) const
150 {
151  return r[i];
152 }
153 template <typename T, int N, int M> Vector<T,M>& Matrix<T,N,M>::operator [] (int i)
154 {
155  return r[i];
156 }
157 
158 template <typename T, int N, int M> const Vector<T,M>& Matrix<T,N,M>::get(int i) const
159 {
160  return r[i];
161 }
162 template <typename T, int N, int M> void Matrix<T,N,M>::set(int i, const Vector<T,M>& v)
163 {
164  r[i] = v;
165 }
166 
167 template <typename T, int N, int M> const T& Matrix<T,N,M>::operator () (int i, int j) const
168 {
169  return r[i][j];
170 }
171 template <typename T, int N, int M> T& Matrix<T,N,M>::operator () (int i, int j)
172 {
173  return r[i][j];
174 }
175 
176 template <typename T, int N, int M> T Matrix<T,N,M>::det() const
177 {
178  return det(*this);
179 }
180 
181 template <typename T, int N, int M>
182 Matrix<T, N, M> Matrix<T,N,M>::one()
183 {
184  Matrix<T,N,M> r;
185 
186  for (int i = 0; i < N; i++)
187  for (int j = 0; j < M; j++)
188  r[i][j] = (i == j) ? 1.0f : 0.0f;
189 
190  return r;
191 }
192 
193 
194 template <typename T, int N, int M, int Q> CUGAR_HOST_DEVICE Matrix<T,N,Q>& multiply(const Matrix<T,N,M>& a, const Matrix<T,M,Q>& b, Matrix<T,N,Q>& r)
195 {
196  for (int i = 0; i < N; i++)
197  {
198  for (int j = 0; j < Q; j++)
199  {
200  r[i][j] = 0.0;
201  for (int k = 0; k < M; k++)
202  r[i][j] += a[i][k]*b[k][j];
203  }
204  }
205  return r;
206 }
207 
208 // OPTIMAL
209 template <typename T, int N, int M> CUGAR_HOST_DEVICE Vector<T,M>& multiply(const Vector<T,N>& v, const Matrix<T,N,M>& m, Vector<T,M>& r)
210 {
211  for (int i = 0; i < M; i++)
212  {
213  r[i] = 0.0;
214  for (int j = 0; j < N; j++)
215  r[i] += v[j]*m(j,i);
216  }
217  return r;
218 }
219 // OPTIMAL
220 template <typename T, int N, int M> CUGAR_HOST_DEVICE Vector<T,N>& multiply(const Matrix<T,N,M>& m, const Vector<T,M>& v, Vector<T,N>& r)
221 {
222  for (int i = 0; i < N; i++)
223  {
224  r[i] = 0.0;
225  for (int j = 0; j < M; j++)
226  r[i] += m(i,j)*v[j];
227  }
228  return r;
229 }
230 
231 template <typename T, int N, int M> CUGAR_HOST_DEVICE Matrix<T,M,N> transpose(const Matrix<T,N,M>& m)
232 {
233  Matrix<T,M,N> r;
234 
235  return transpose(m, r);
236 }
237 
238 template <typename T, int N, int M> CUGAR_HOST_DEVICE Matrix<T,M,N>& transpose(const Matrix<T,N,M>& m, Matrix<T,M,N>& r)
239 {
240  for (int i = 0; i < N; i++)
241  for (int j = 0; j < M; j++)
242  r[j][i] = m[i][j];
243 
244  return r;
245 }
246 
247 template <typename T, int N, int M> bool invert(const Matrix<T,N,M>& a, Matrix<T,M,N>& r)
248 {
249  T d = a.det();
250  if (d < 1.0e-10f) return false;
251 
252  return true;
253 }
254 
255 template <typename T>
256 CUGAR_HOST_DEVICE
257 bool invert(const Matrix<T,2,2>& a, Matrix<T,2,2>& r)
258 {
259  const T det = cugar::det(a);
260  if (fabsf(det) < 1.0e-10f) return false;
261 
262  const T invdet = T(1.0) / det;
263 
264  r(0,0) = a(1,1) * invdet;
265  r(0,1) = -a(0,1) * invdet;
266  r(1,0) = -a(1,0) * invdet;
267  r(1,1) = a(0,0) * invdet;
268  return true;
269 }
270 
271 template <typename T>
272 CUGAR_HOST_DEVICE
273 bool invert(const Matrix<T,3,3>& a, Matrix<T,3,3>& r)
274 {
275  const T det = cugar::det(a);
276  if (fabsf(det) < 1.0e-10f) return false;
277 
278  const T invdet = T(1.0) / det;
279 
280  r(0,0) = (a(1,1) * a(2,2) - a(2,1) * a(1,2)) * invdet;
281  r(0,1) = (a(0,2) * a(2,1) - a(0,1) * a(2,2)) * invdet;
282  r(0,2) = (a(0,1) * a(1,2) - a(0,2) * a(1,1)) * invdet;
283  r(1,0) = (a(1,2) * a(2,0) - a(1,0) * a(2,2)) * invdet;
284  r(1,1) = (a(0,0) * a(2,2) - a(0,2) * a(2,0)) * invdet;
285  r(1,2) = (a(1,0) * a(0,2) - a(0,0) * a(1,2)) * invdet;
286  r(2,0) = (a(1,0) * a(2,1) - a(2,0) * a(1,1)) * invdet;
287  r(2,1) = (a(2,0) * a(0,1) - a(0,0) * a(2,1)) * invdet;
288  r(2,2) = (a(0,0) * a(1,1) - a(1,0) * a(0,1)) * invdet;
289  return true;
290 }
291 
292 template <typename T>
293 CUGAR_HOST_DEVICE
294 bool invert(const Matrix<T,4,4>& a, Matrix<T,4,4>& r)
295 {
296  T t1, t2, t3, t4, t5, t6;
297 
298  // We calculate the adjoint matrix of a, then we divide it by the determinant of a
299  // We indicate with Aij the cofactor of a[i][j]: Aij = (-1)^(i+j)*Det(Tij), where
300  // Tij is the minor complementary of a[i][j]
301 
302  // First block ([0,0] - [3,1])
303 
304  t1 = a(2,2)*a(3,3) - a(2,3)*a(3,2);
305  t2 = a(2,1)*a(3,3) - a(2,3)*a(3,1);
306  t3 = a(2,1)*a(3,2) - a(2,2)*a(3,1);
307  t4 = a(2,0)*a(3,3) - a(2,3)*a(3,0);
308  t5 = a(2,0)*a(3,2) - a(2,2)*a(3,0);
309  t6 = a(2,0)*a(3,1) - a(2,1)*a(3,0);
310 
311  r[0][0] = a(1,1) * t1 - a(1,2) * t2 + a(1,3) * t3; // A00
312  r[0][1] = -(a(0,1) * t1 - a(0,2) * t2 + a(0,3) * t3); // A10
313  r[1][0] = -(a(1,0) * t1 - a(1,2) * t4 + a(1,3) * t5); // A01
314  r[1][1] = a(0,0) * t1 - a(0,2) * t4 + a(0,3) * t5; // A11
315  r[2][0] = a(1,0) * t2 - a(1,1) * t4 + a(1,3) * t6; // A02
316  r[2][1] = -(a(0,0) * t2 - a(0,1) * t4 + a(0,3) * t6); // A21
317  r[3][0] = -(a(1,0) * t3 - a(1,1) * t5 + a(1,2) * t6); // A03
318  r[3][1] = a(0,0) * t3 - a(0,1) * t5 + a(0,2) * t6; // A13
319 
320  // Second block ([0,2] - [3,2])
321 
322  t1 = a(1,2)*a(3,3) - a(1,3)*a(3,2);
323  t2 = a(1,1)*a(3,3) - a(1,3)*a(3,1);
324  t3 = a(1,1)*a(3,2) - a(1,2)*a(3,1);
325  t4 = a(1,0)*a(3,3) - a(1,3)*a(3,0);
326  t5 = a(1,0)*a(3,2) - a(1,2)*a(3,0);
327  t6 = a(1,0)*a(3,1) - a(1,1)*a(3,0);
328 
329  r[0][2] = a(0,1) * t1 - a(0,2) * t2 + a(0,3) * t3; // A20
330  r[1][2] = -(a(0,0) * t1 - a(0,2) * t4 + a(0,3) * t5); // A21
331  r[2][2] = a(0,0) * t2 - a(0,1) * t4 + a(0,3) * t6; // A22
332  r[3][2] = -(a(0,0) * t3 - a(0,1) * t5 + a(0,2) * t6); // A23
333 
334  // Third block ([0,3] - [3,3])
335 
336  t1 = a(1,2)*a(2,3) - a(1,3)*a(2,2);
337  t2 = a(1,1)*a(2,3) - a(1,3)*a(2,1);
338  t3 = a(1,1)*a(2,2) - a(1,2)*a(2,1);
339  t4 = a(1,0)*a(2,3) - a(1,3)*a(2,0);
340  t5 = a(1,0)*a(2,2) - a(1,2)*a(2,0);
341  t6 = a(1,0)*a(2,1) - a(1,1)*a(2,0);
342 
343  r[0][3] = -(a(0,1) * t1 - a(0,2) * t2 + a(0,3) * t3); // A30
344  r[1][3] = a(0,0) * t1 - a(0,2) * t4 + a(0,3) * t5; // A31
345  r[2][3] = -(a(0,0) * t2 - a(0,1) * t4 + a(0,3) * t6); // A32
346  r[3][3] = a(0,0) * t3 - a(0,1) * t5 + a(0,2) * t6; // A33
347 
348  // We save some time calculating Det(a) this way (now r is adjoint of a)
349  // Det(a) = a00 * A00 + a01 * A01 + a02 * A02 + a03 * A03
350  T d = a(0,0)*r[0][0] + a(0,1)*r[1][0] + a(0,2)*r[2][0] + a(0,3)*r[3][0];
351 
352  if (d == T(0.0)) return false; // Singular matrix => no inverse
353 
354  d = T(1.0)/d;
355 
356  r *= d;
357  return true;
358 }
359 
360 template <typename T, int N, int M>
361 CUGAR_HOST_DEVICE
362 T det(const Matrix<T,N,M>& m)
363 {
364  return 0.0f;
365 }
366 
367 template <typename T>
368 CUGAR_HOST_DEVICE
369 T det(const Matrix<T,2,2>& m)
370 {
371  return m(0,0) * m(1,1) - m(0,1) * m(1,0);
372 }
373 
374 template <typename T>
375 CUGAR_HOST_DEVICE
376 T det(const Matrix<T,3,3>& m)
377 {
378 
379  return m(0,0) * (m(1,1)*m(2,2) - m(1,2)*m(2,1))
380  - m(0,1) * (m(1,0)*m(2,2) - m(1,2)*m(2,0))
381  + m(0,2) * (m(1,0)*m(2,1) - m(1,1)*m(2,0));
382 }
383 
384 template <typename T>
385 CUGAR_HOST_DEVICE
386 void cholesky(const Matrix<T,2,2>& m, Matrix<T,2,2>& r)
387 {
388  const T a = sqrt(m(0,0));
389  const T b = m(0, 1) / a;
390  const T c = sqrt(m(1,1) - b*b);
391  r(0,0) = a;
392  r(0,1) = 0;
393  r(1,0) = b;
394  r(1,1) = c;
395 }
396 
397 //
398 // Matrix<T,N,M> template <typename T, int N, int M> functions (not members)
399 //
400 
401 template <typename T, int N, int M> CUGAR_API_CS CUGAR_HOST_DEVICE int operator == (const Matrix<T,N,M>& a, const Matrix<T,N,M>& b)
402 {
403  for (int i = 0; i < N; i++)
404  {
405  if (a[i] != b[i])
406  return 0;
407  }
408  return 1;
409 }
410 
411 template <typename T, int N, int M> CUGAR_API_CS CUGAR_HOST_DEVICE int operator != (const Matrix<T,N,M>& a, const Matrix<T,N,M>& b)
412 {
413  return !(a == b);
414 }
415 
416 template <typename T, int N, int M> CUGAR_API_CS Matrix<T,N,M> CUGAR_HOST_DEVICE operator - (const Matrix<T,N,M>& a)
417 {
418  return (Matrix<T,N,M>(a) *= -1.0);
419 }
420 
421 template <typename T, int N, int M> CUGAR_API_CS Matrix<T,N,M> CUGAR_HOST_DEVICE operator + (const Matrix<T,N,M>& a, const Matrix<T,N,M>& b)
422 {
423  Matrix<T,N,M> r;
424  for (int i = 0; i < N; i++)
425  for (int j = 0; j < N; j++)
426  r(i,j) = a(i,j) + b(i,j);
427 
428  return r;
429 }
430 
431 template <typename T, int N, int M> CUGAR_API_CS Matrix<T,N,M> CUGAR_HOST_DEVICE operator - (const Matrix<T,N,M>& a, const Matrix<T,N,M>& b)
432 {
433  Matrix<T,N,M> r;
434  for (int i = 0; i < N; i++)
435  for (int j = 0; j < N; j++)
436  r(i,j) = a(i,j) - b(i,j);
437 
438  return r;
439 }
440 
441 template <typename T, int N, int M, int Q> CUGAR_API_CS CUGAR_HOST_DEVICE Matrix<T,N,Q> operator * (const Matrix<T,N,M>& a, const Matrix<T,M,Q>& b)
442 {
443  Matrix<T,N,Q> r;
444 
445  return multiply(a, b, r);
446 }
447 
448 template <typename T, int N, int M> CUGAR_API_CS CUGAR_HOST_DEVICE Matrix<T,N,M> operator * (const Matrix<T,N,M>& a, T k)
449 {
450  Matrix<T,N,M> r;
451  for (int i = 0; i < N; i++)
452  for (int j = 0; j < N; j++)
453  r(i,j) = a(i,j) * k;
454 
455  return r;
456 }
457 
458 template <typename T, int N, int M> CUGAR_API_CS CUGAR_HOST_DEVICE Matrix<T,N,M> operator * (T k, const Matrix<T,N,M>& a)
459 {
460  Matrix<T,N,M> r;
461  for (int i = 0; i < N; i++)
462  for (int j = 0; j < N; j++)
463  r(i,j) = a(i,j) * k;
464 
465  return r;
466 }
467 
468 template <typename T, int N, int M> CUGAR_API_CS CUGAR_HOST_DEVICE Vector<T,M> operator * (const Vector<T,N>& v, const Matrix<T,N,M>& m)
469 {
470  Vector<T,M> r;
471 
472  return multiply(v, m, r);
473 }
474 template <typename T, int N, int M> CUGAR_API_CS CUGAR_HOST_DEVICE Vector<T,N> operator * (const Matrix<T,N,M>& m, const Vector<T,M>& v)
475 {
476  Vector<T,N> r;
477 
478  return multiply(m, v, r);
479 }
480 
481 template <typename T, int N, int M> CUGAR_API_CS CUGAR_HOST_DEVICE Matrix<T,N,M> operator / (const Matrix<T,N,M>& a, T k)
482 {
483  Matrix<T,N,M> r;
484  for (int i = 0; i < N; i++)
485  for (int j = 0; j < N; j++)
486  r(i,j) = a(i,j) / k;
487 
488  return r;
489 }
490 
491 template <typename T, int N> CUGAR_API_CS CUGAR_HOST_DEVICE Matrix<T,N,N> operator + (const Matrix<T,N,N>& a, const Vector<T,N>& b)
492 {
493  return a + Matrix<T,N,N>(b);
494 }
495 
496 template <typename T, int N> CUGAR_API_CS CUGAR_HOST_DEVICE Matrix<T,N,N> operator + (const Vector<T,N>& a, const Matrix<T,N,N>& b)
497 {
498  return Matrix<T,N,N>(a) + b;
499 }
500 
501 template <typename T, uint32 N, uint32 M>
502 CUGAR_API_CS CUGAR_HOST_DEVICE
504 {
505  Matrix<T,N,M> r;
506  for (uint32 i = 0; i < N; ++i)
507  for (uint32 j = 0; j < M; ++j)
508  r(i,j) = op1[i]*op2[j];
509  return r;
510 }
511 
512 CUGAR_API_CS CUGAR_HOST_DEVICE
513 inline Matrix2x2f outer_product(const Vector2f op1, const Vector2f op2)
514 {
515  Matrix2x2f r;
516  r(0,0) = op1.x * op2.x;
517  r(0,1) = op1.x * op2.y;
518  r(1,0) = op1.y * op2.x;
519  r(1,1) = op1.y * op2.y;
520  return r;
521 }
522 
523 template <typename T>
524 CUGAR_HOST_DEVICE Matrix<T,4,4> translate(const Vector<T,3>& vec)
525 {
526  Matrix<T,4,4> m( T(0) );
527 
528  m(0,0) = m(1,1) = m(2,2) = m(3,3) = 1.0f;
529 
530  m(0,3) = vec.x;
531  m(1,3) = vec.y;
532  m(2,3) = vec.z;
533 
534  return m;
535 }
536 
538 template <typename T>
539 CUGAR_HOST_DEVICE Matrix<T, 4, 4> scale(const Vector<T, 3>& vec)
540 {
541  Matrix<T,4,4> m( T(0) );
542 
543  m(0,0) = vec[0];
544  m(1,1) = vec[1];
545  m(2,2) = vec[2];
546  m(3,3) = 1.0f;
547 
548  return m;
549 }
550 
551 template <typename T>
552 Matrix<T,4,4> perspective(T fovy, T aspect, T zNear, T zFar)
553 {
554  Matrix<T,4,4> m( T(0) );
555 
556  T f = T(1) / std::tan(fovy / T(2));
557 
558  m(0,0) = f / aspect;
559  m(1,1) = f;
560  m(2,2) = (zFar + zNear) / (zNear - zFar);
561  m(2,3) = T(2) * zFar * zNear / (zNear - zFar);
562  m(3,2) = T(-1);
563  m(3,3) = T(0);
564 
565  return m;
566 }
567 template <typename T>
568 Matrix<T,4,4> look_at(const Vector<T,3>& eye, const Vector<T,3>& center, const Vector<T,3>& up, bool flip_sign)
569 {
570  Vector<T,3> f = normalize(center - eye);
571  Vector<T,3> r = normalize(cross(f, up));
572  Vector<T,3> u = cross(r, f);
573 
574  Matrix<T,4,4> m(T(0));
575  m(0,0) = r.x;
576  m(0,1) = r.y;
577  m(0,2) = r.z;
578  m(1,0) = u.x;
579  m(1,1) = u.y;
580  m(1,2) = u.z;
581  m(2,0) = (flip_sign ? -1.0f : 1.0f) * f.x;
582  m(2,1) = (flip_sign ? -1.0f : 1.0f) * f.y;
583  m(2,2) = (flip_sign ? -1.0f : 1.0f) * f.z;
584  m(3,0) = eye.x;
585  m(3,1) = eye.y;
586  m(3,2) = eye.z;
587  m(3,3) = 1.0f;
588 
589  return m;
590 }
591 template <typename T>
592 Matrix<T,4,4> inverse_look_at(const Vector<T,3>& eye, const Vector<T,3>& center, const Vector<T,3>& up, bool flip_sign)
593 {
594  Vector<T,3> f = normalize(center - eye);
595  Vector<T,3> r = normalize(cross(f, up));
596  Vector<T,3> u = cross(r, f);
597 
598  Matrix<T,4,4> m(T(0));
599  m(0,0) = r.x;
600  m(1,0) = r.y;
601  m(2,0) = r.z;
602  m(0,1) = u.x;
603  m(1,1) = u.y;
604  m(2,1) = u.z;
605  m(0,2) = (flip_sign ? -1.0f : 1.0f) * f.x;
606  m(1,2) = (flip_sign ? -1.0f : 1.0f) * f.y;
607  m(2,2) = (flip_sign ? -1.0f : 1.0f) * f.z;
608  m(3,0) = -eye.x;
609  m(3,1) = -eye.y;
610  m(3,2) = -eye.z;
611  m(3,3) = 1.0f;
612 
613  return m;
614 }
615 template <typename T>
616 CUGAR_HOST_DEVICE Matrix<T,4,4> rotation_around_X(const T q)
617 {
618  Matrix<T,4,4> m;
619 
620  const float sin_q = sin(q);
621  m[1][1] = m[2][2] = cos(q);
622  m[1][2] = -sin_q;
623  m[2][1] = sin_q;
624  m[0][0] = m[3][3] = T(1.0f);
625  m[0][1] =
626  m[0][2] =
627  m[0][3] =
628  m[1][0] =
629  m[1][3] =
630  m[2][0] =
631  m[2][3] =
632  m[3][0] =
633  m[3][1] =
634  m[3][2] = T(0.0f);
635  return m;
636 }
637 template <typename T>
638 CUGAR_HOST_DEVICE Matrix<T,4,4> rotation_around_Y(const T q)
639 {
640  Matrix<T,4,4> m;
641 
642  const float sin_q = sin(q);
643  m[0][0] = m[2][2] = cos(q);
644  m[2][0] = -sin_q;
645  m[0][2] = sin_q;
646  m[1][1] = m[3][3] = T(1.0f);
647  m[0][1] =
648  m[0][3] =
649  m[1][0] =
650  m[1][2] =
651  m[1][3] =
652  m[2][1] =
653  m[2][3] =
654  m[3][0] =
655  m[3][1] =
656  m[3][2] = T(0.0f);
657  return m;
658 }
659 template <typename T>
660 CUGAR_HOST_DEVICE Matrix<T,4,4> rotation_around_Z(const T q)
661 {
662  Matrix<T,4,4> m;
663 
664  const float sin_q = sin(q);
665  m[0][0] = m[1][1] = cos(q);
666  m[1][0] = sin_q;
667  m[0][1] = -sin_q;
668  m[2][2] = m[3][3] = T(1.0f);
669  m[0][2] =
670  m[0][3] =
671  m[1][2] =
672  m[1][3] =
673  m[2][0] =
674  m[2][1] =
675  m[2][3] =
676  m[3][0] =
677  m[3][1] =
678  m[3][2] = T(0.0f);
679  return m;
680 }
681 // build a 3d rotation around an arbitrary axis
682 template <typename T>
683 CUGAR_HOST_DEVICE Matrix<T, 4, 4> rotation_around_axis(const T q, const Vector3f& axis)
684 {
685  const Vector3f tangent = orthogonal( axis );
686  const Vector3f binormal = cross( axis, tangent );
687 
688  Matrix4x4f basis_change;
689  basis_change[0] = Vector4f( tangent, 0.0f );
690  basis_change[1] = Vector4f( binormal, 0.0f );
691  basis_change[2] = Vector4f( axis, 0.0f );
692  basis_change[3] = Vector4f( 0.0f, 0.0f, 0.0f, 1.0f );
693 
694  Matrix4x4f inv_basis_change = transpose( basis_change );
695  //invert( basis_change, inv_basis_change );
696 
697  const Matrix4x4f rot = rotation_around_Z( q );
698 
699  return basis_change * rot * inv_basis_change;
700 }
701 CUGAR_HOST_DEVICE inline Vector3f ptrans(const Matrix4x4f& m, const Vector3f& v)
702 {
703  const Vector4f r = m * Vector4f(v,1.0f);
704  return Vector3f( r[0], r[1], r[2] );
705 }
706 CUGAR_HOST_DEVICE inline Vector3f vtrans(const Matrix4x4f& m, const Vector3f& v)
707 {
708  const Vector4f r = m * Vector4f(v,0.0f);
709  return Vector3f( r[0], r[1], r[2] );
710 }
711 
712 // get the eigenvalues of a matrix
713 //
714 CUGAR_HOST_DEVICE inline Vector2f eigen_values(const Matrix2x2f& m)
715 {
716  const float T = m(0,0) + m(1,1);
717  const float D = m(0,0) * m(1,1) - m(1,0) * m(0,1);
718  const float S = sqrtf(T*T*0.25f - D);
719  const float l1 = T*0.5f + S;
720  const float l2 = T*0.5f - S;
721  return Vector2f(l1,l2);
722 }
723 
724 // get the singular values of a matrix
725 //
726 CUGAR_HOST_DEVICE inline Vector2f singular_values(const Matrix2x2f& m)
727 {
728  const float a = m(0,0);
729  const float b = m(0,1);
730  const float c = m(1,0);
731  const float d = m(1,1);
732 
733  #if 0
734  const float S1 = a*a + b*b + c*c + d*d;
735  const float S2 = sqrtf( sqr(a*a + b*b - c*c - d*d) + 4*sqr(a*c + b*d) );
736  return Vector2f(
737  sqrtf((S1 + S2)*0.5f),
738  sqrtf((S1 - S2)*0.5f));
739  #else
740  const float s00 = sqrtf( sqr(a - d) + sqr(b + c) );
741  const float s01 = sqrtf( sqr(a + d) + sqr(b - c) );
742 
743  const float s0 = (s00 + s01) / 2;
744  const float s1 = fabsf(s0 - s00);
745 
746  return Vector2f(s0,s1);
747  #endif
748 }
749 
750 // get the singular value decomposition of a matrix
751 //
752 CUGAR_HOST_DEVICE inline void svd(
753  const Matrix2x2f& m,
754  Matrix2x2f& u,
755  Vector2f& s,
756  Matrix2x2f& v)
757 {
758  const float a = m(0,0);
759  const float b = m(0,1);
760  const float c = m(1,0);
761  const float d = m(1,1);
762 
763  s = singular_values(m);
764 
765  v(1,0) = (s[0] > s[1]) ? sinf((atan2f(2 * (a*b + c*d), a*a - b*b + c*c - d*d)) / 2) : 0;
766  v(0,0) = sqrtf(1 - v(1,0) * v(1,0));
767  v(0,1) = -v(1,0);
768  v(1,1) = v(0,0);
769 
770  u(0,0) = (s[0] != 0) ? (a * v(0,0) + b * v(1,0)) / s[0] : 1;
771  u(1,1) = (s[0] != 0) ? (c * v(0,0) + d * v(1,0)) / s[0] : 0;
772  u(0,1) = (s[1] != 0) ? (a * v(0,1) + b * v(1,1)) / s[1] : -u(1,1);
773  u(1,1) = (s[1] != 0) ? (c * v(0,1) + d * v(1,1)) / s[1] : u(0,0);
774 }
775 
776 #undef _V
777 #undef _M
778 #undef _CM
779 
780 } // namespace cugar
CUGAR_HOST_DEVICE Vector2f eigen_values(const Matrix2x2f &m)
Definition: matrix_inline.h:714
CUGAR_HOST_DEVICE Matrix< T, 4, 4 > rotation_around_axis(const T q, const Vector3f &axis)
Definition: matrix_inline.h:683
CUGAR_HOST_DEVICE Matrix< T, 4, 4 > translate(const Vector< T, 3 > &vec)
Definition: matrix_inline.h:524
CUGAR_HOST_DEVICE Vector2f singular_values(const Matrix2x2f &m)
Definition: matrix_inline.h:726
CUGAR_HOST_DEVICE Vector3f vtrans(const Matrix4x4f &m, const Vector3f &v)
Definition: matrix_inline.h:706
Definition: matrix.h:54
Matrix< T, 4, 4 > perspective(T fovy, T aspect, T zNear, T zFar)
Definition: matrix_inline.h:552
CUGAR_HOST_DEVICE Matrix< T, 4, 4 > rotation_around_Y(const T q)
Definition: matrix_inline.h:638
CUGAR_HOST_DEVICE Vector3f ptrans(const Matrix4x4f &m, const Vector3f &v)
Definition: matrix_inline.h:701
CUGAR_HOST_DEVICE Matrix< T, 4, 4 > rotation_around_Z(const T q)
Definition: matrix_inline.h:660
CUGAR_HOST_DEVICE void svd(const Matrix2x2f &m, Matrix2x2f &u, Vector2f &s, Matrix2x2f &v)
Definition: matrix_inline.h:752
float CUGAR_HOST_DEVICE sqr(const float x)
Definition: numbers.h:610
Matrix< T, 4, 4 > look_at(const Vector< T, 3 > &eye, const Vector< T, 3 > &center, const Vector< T, 3 > &up, bool flip_sign=false)
Definition: matrix_inline.h:568
Define a vector_view POD type and plain_view() for std::vector.
Definition: diff.h:38
CUGAR_API_CS CUGAR_HOST_DEVICE Matrix< T, N, M > outer_product(const Vector< T, N > op1, const Vector< T, M > op2)
Definition: matrix_inline.h:503
CUGAR_HOST_DEVICE Matrix< T, 4, 4 > rotation_around_X(const T q)
Definition: matrix_inline.h:616
Definition: vector.h:187
Matrix< T, 4, 4 > inverse_look_at(const Vector< T, 3 > &eye, const Vector< T, 3 > &center, const Vector< T, 3 > &up, bool flip_sign=false)
Definition: matrix_inline.h:592
CUGAR_HOST_DEVICE Matrix< T, 4, 4 > scale(const Vector< T, 3 > &vec)
build a 3d scaling matrix
Definition: matrix_inline.h:539