MVE - Multi-View Environment mve-devel
Loading...
Searching...
No Matches
matrix_tools.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015, Simon Fuhrmann
3 * TU Darmstadt - Graphics, Capture and Massively Parallel Computing
4 * All rights reserved.
5 *
6 * This software may be modified and distributed under the terms
7 * of the BSD 3-Clause license. See the LICENSE.txt file for details.
8 */
9
10#ifndef MATH_MATRIX_TOOLS_HEADER
11#define MATH_MATRIX_TOOLS_HEADER
12
13#include <algorithm>
14
15#include "math/defines.h"
16#include "math/matrix.h"
17#include "math/vector.h"
18
20
27template <typename T>
28Matrix<T,4,4>
29matrix_gl_projection (T const& znear, T const& zfar,
30 T const& top, T const& right);
31
35template <typename T>
36Matrix<T,4,4>
37matrix_inverse_gl_projection (T const& znear, T const& zfar,
38 T const& top, T const& right);
39
45template <typename T>
46Matrix<T,4,4>
47matrix_viewtrans (Vector<T,3> const& campos,
48 Vector<T,3> const& viewdir, Vector<T,3> const& upvec);
49
53template <typename T>
54Matrix<T,4,4>
55matrix_inverse_viewtrans (Vector<T,3> const& campos,
56 Vector<T,3> const& viewdir, Vector<T,3> const& upvec);
57
61template <typename T>
62Matrix<T,4,4>
63matrix_invert_trans (Matrix<T,4,4> const& mat);
64
69template <typename T, int N>
70Matrix<T,N,N>&
71matrix_set_identity (Matrix<T,N,N>* mat);
72
77template <typename T>
78T*
79matrix_set_identity (T* mat, int n);
80
84template <typename T, int N>
85bool
86matrix_is_identity (Matrix<T,N,N> const& mat, T const& epsilon = T(0));
87
91template <typename T, int N>
92Matrix<T,N,N>
94
98template <typename T, int N>
99Matrix<T,N,N>&
100matrix_set_diagonal (Matrix<T,N,N>& mat, T const* diag);
101
106template <typename T>
107bool
108matrix_is_diagonal (T* const mat, int rows, int cols, T const& epsilon = T(0));
109
113template <typename T, int N>
114Vector<T,N>
115matrix_get_diagonal (Matrix<T,N,N> const& mat);
116
120template <typename T, int N>
121T
123
128template <typename T, int N>
129T
131
136template <typename T, int N>
139
144template <typename T, int N>
146matrix_inverse (Matrix<T,N,N> const& mat, T const& det);
147
151template <typename T>
153matrix_rotation_from_axis_angle (Vector<T,3> const& axis, T const& angle);
154
159template <typename T>
160void
161matrix_transpose (T const* mat, int rows, int cols);
162
167template <typename T>
168void
169matrix_multiply (T const* mat_a, int rows_a, int cols_a,
170 T const* mat_b, int cols_b, T* mat_res);
171
177template <typename T>
178void
179matrix_transpose_multiply (T const* mat_a, int rows, int cols, T* mat_res);
180
184template <typename T>
185void
186matrix_swap_rows (T* mat, int rows, int cols, int r1, int r2);
187
191template <typename T>
192void
193matrix_swap_columns (T* const mat, int rows, int cols, int c1, int c2);
194
198template <typename T, int N>
199void
201
205template <typename T, int N>
208
210
211/* ------------------------ Implementation ------------------------ */
212
214
215template <typename T>
217matrix_gl_projection (T const& znear, T const& zfar,
218 T const& top, T const& right)
219{
220 Matrix<T,4,4> proj(0.0f);
221 proj(0,0) = znear / right;
222 proj(1,1) = znear / top;
223 proj(2,2) = -(zfar + znear) / (zfar - znear);
224 proj(2,3) = T(-2) * zfar * znear / (zfar - znear);
225 proj(3,2) = -1;
226
227 return proj;
228}
229
230template <typename T>
231Matrix<T,4,4>
232matrix_inverse_gl_projection (T const& znear, T const& zfar,
233 T const& top, T const& right)
234{
235 Matrix<T,4,4> iproj(0.0f);
236 iproj(0,0) = right / znear;
237 iproj(1,1) = top / znear;
238 iproj(2,3) = -1;
239 iproj(3,2) = (zfar - znear) / (T(-2) * zfar * znear);
240 iproj(3,3) = -(zfar + znear) / (T(-2) * zfar * znear);
241
242 return iproj;
243}
244
245template <typename T>
246Matrix<T,4,4>
248 Vector<T,3> const& viewdir, Vector<T,3> const& upvec)
249{
250 /* Normalize x in case upvec is not perpendicular to viewdir. */
251 Vector<T,3> z(-viewdir);
252 Vector<T,3> x(upvec.cross(z).normalized());
253 Vector<T,3> y(z.cross(x));
254
256 m(0,0) = x[0]; m(0,1) = x[1]; m(0,2) = x[2]; m(0,3) = 0.0f;
257 m(1,0) = y[0]; m(1,1) = y[1]; m(1,2) = y[2]; m(1,3) = 0.0f;
258 m(2,0) = z[0]; m(2,1) = z[1]; m(2,2) = z[2]; m(2,3) = 0.0f;
259 m(3,0) = 0.0f; m(3,1) = 0.0f; m(3,2) = 0.0f; m(3,3) = 1.0f;
260
261 Vector<T,3> t(-campos);
262 m(0,3) = m(0,0) * t[0] + m(0,1) * t[1] + m(0,2) * t[2];
263 m(1,3) = m(1,0) * t[0] + m(1,1) * t[1] + m(1,2) * t[2];
264 m(2,3) = m(2,0) * t[0] + m(2,1) * t[1] + m(2,2) * t[2];
265
266 return m;
267}
268
269template <typename T>
270Matrix<T,4,4>
272 Vector<T,3> const& viewdir, Vector<T,3> const& upvec)
273{
274 Vector<T,3> z(-viewdir);
275 Vector<T,3> x(upvec.cross(z).normalized());
276 Vector<T,3> y(z.cross(x));
277
279 m(0,0) = x[0]; m(0,1) = y[0]; m(0,2) = z[0]; m(0,3) = campos[0];
280 m(1,0) = x[1]; m(1,1) = y[1]; m(1,2) = z[1]; m(1,3) = campos[1];
281 m(2,0) = x[2]; m(2,1) = y[2]; m(2,2) = z[2]; m(2,3) = campos[2];
282 m(3,0) = 0.0f; m(3,1) = 0.0f; m(3,2) = 0.0f; m(3,3) = 1.0f;
283
284 return m;
285}
286
287template <typename T>
288Matrix<T,4,4>
290{
291 Matrix<T,4,4> ret(0.0f);
292 /* Transpose rotation. */
293 ret[0] = mat[0]; ret[1] = mat[4]; ret[2] = mat[8];
294 ret[4] = mat[1]; ret[5] = mat[5]; ret[6] = mat[9];
295 ret[8] = mat[2]; ret[9] = mat[6]; ret[10] = mat[10];
296 /* Invert translation. */
297 ret[3] = -(ret[0] * mat[3] + ret[1] * mat[7] + ret[2] * mat[11]);
298 ret[7] = -(ret[4] * mat[3] + ret[5] * mat[7] + ret[6] * mat[11]);
299 ret[11] = -(ret[8] * mat[3] + ret[9] * mat[7] + ret[10] * mat[11]);
300 ret[15] = 1.0f;
301
302 return ret;
303}
304
305template <typename T, int N>
306Matrix<T,N,N>&
308{
309 mat->fill(T(0));
310 for (int i = 0; i < N * N; i += N + 1)
311 (*mat)[i] = T(1);
312 return *mat;
313}
314
315template <typename T>
316T*
317matrix_set_identity (T* mat, int n)
318{
319 int const len = n * n;
320 std::fill(mat, mat + len, T(0));
321 for (int i = 0; i < len; i += n + 1)
322 mat[i] = T(1);
323 return mat;
324}
325
326template <typename T, int N>
327bool
328matrix_is_identity (Matrix<T,N,N> const& mat, T const& epsilon)
329{
330 for (int y = 0, i = 0; y < N; ++y)
331 for (int x = 0; x < N; ++x, ++i)
332 if ((x == y && !MATH_EPSILON_EQ(mat[i], T(1), epsilon))
333 || (x != y && !MATH_EPSILON_EQ(mat[i], T(0), epsilon)))
334 return false;
335 return true;
336}
337
338template <typename T, int N>
339Matrix<T,N,N>
341{
342 Matrix<T,N,N> mat;
343 std::fill(*mat, *mat + N*N, T(0));
344 for (int i = 0, j = 0; i < N*N; i += N+1, j += 1)
345 mat[i] = v[j];
346 return mat;
347}
348
349template <typename T, int N>
350Matrix<T,N,N>&
352{
353 for (int i = 0, j = 0; i < N*N; i += N+1, j += 1)
354 mat[i] = diag[j];
355 return mat;
356}
357
358template <typename T, int N>
359Vector<T,N>
361{
362 Vector<T,N> diag;
363 for (int i = 0, j = 0; i < N*N; i += N+1, j += 1)
364 diag[j] = mat[i];
365 return diag;
366}
367
368template <typename T, int N>
369inline T
371{
372 T ret(0.0);
373 for (int i = 0; i < N * N; i += N + 1)
374 ret += mat[i];
375 return ret;
376}
377
378template <typename T>
379inline T
381{
382 return mat[0];
383}
384
385template <typename T>
386inline T
388{
389 return mat[0] * mat[3] - mat[1] * mat [2];
390}
391
392template <typename T>
393inline T
395{
396 return m[0] * m[4] * m[8] + m[1] * m[5] * m[6] + m[2] * m[3] * m[7]
397 - m[2] * m[4] * m[6] - m[1] * m[3] * m[8] - m[0] * m[5] * m[7];
398}
399
400template <typename T>
401T
403{
404 return m[0] * (m[5] * m[10] * m[15] - m[5] * m[11] * m[14]
405 - m[9] * m[6] * m[15] + m[9] * m[7] * m[14]
406 + m[13] * m[6] * m[11] - m[13] * m[7] * m[10])
407 //
408 + m[1] * (-m[4] * m[10] * m[15] + m[4] * m[11] * m[14]
409 + m[8] * m[6] * m[15] - m[8] * m[7] * m[14]
410 - m[12] * m[6] * m[11] + m[12] * m[7] * m[10])
411 //
412 + m[2] * (m[4] * m[9] * m[15] - m[4] * m[11] * m[13]
413 - m[8] * m[5] * m[15] + m[8] * m[7] * m[13]
414 + m[12] * m[5] * m[11] - m[12] * m[7] * m[9])
415 //
416 + m[3] * (-m[4] * m[9] * m[14] + m[4] * m[10] * m[13]
417 + m[8] * m[5] * m[14] - m[8] * m[6] * m[13]
418 - m[12] * m[5] * m[10] + m[12] * m[6] * m[9]);
419}
420
421template <typename T>
422inline Matrix<T,1,1>
424{
425 return matrix_inverse(mat, matrix_determinant(mat));
426}
427
428template <typename T>
429inline Matrix<T,2,2>
431{
432 return matrix_inverse(mat, matrix_determinant(mat));
433}
434
435template <typename T>
436inline Matrix<T,3,3>
438{
440}
441
442template <typename T>
443Matrix<T,1,1>
444matrix_inverse (Matrix<T,1,1> const& /*mat*/, T const& det)
445{
446 Matrix<T,1,1> ret(T(1));
447 return ret / det;
448}
449
450template <typename T>
451Matrix<T,2,2>
452matrix_inverse (Matrix<T,2,2> const& mat, T const& det)
453{
454 Matrix<T,2,2> ret;
455 ret[0] = mat[3]; ret[1] = -mat[1];
456 ret[2] = -mat[2]; ret[3] = mat[0];
457 return ret / det;
458}
459
460template <typename T>
461Matrix<T,3,3>
462matrix_inverse (Matrix<T,3,3> const& m, T const& det)
463{
464 Matrix<T,3,3> ret;
465 ret[0] = m[4] * m[8] - m[5] * m[7];
466 ret[1] = m[2] * m[7] - m[1] * m[8];
467 ret[2] = m[1] * m[5] - m[2] * m[4];
468 ret[3] = m[5] * m[6] - m[3] * m[8];
469 ret[4] = m[0] * m[8] - m[2] * m[6];
470 ret[5] = m[2] * m[3] - m[0] * m[5];
471 ret[6] = m[3] * m[7] - m[4] * m[6];
472 ret[7] = m[1] * m[6] - m[0] * m[7];
473 ret[8] = m[0] * m[4] - m[1] * m[3];
474 return ret / det;
475}
476
477template <typename T>
478Matrix<T,4,4>
480{
481 Matrix<T,4,4> ret;
482
483 ret[0] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15]
484 + m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10];
485 ret[1] = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15]
486 - m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10];
487 ret[2] = m[1] * m[6] * m[15] - m[1] * m[7] * m[14] - m[5] * m[2] * m[15]
488 + m[5] * m[3] * m[14] + m[13] * m[2] * m[7] - m[13] * m[3] * m[6];
489 ret[3] = -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] + m[5] * m[2] * m[11]
490 - m[5] * m[3] * m[10] - m[9] * m[2] * m[7] + m[9] * m[3] * m[6];
491
492 ret[4] = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15]
493 - m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10];
494 ret[5] = m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15]
495 + m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10];
496 ret[6] = -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] + m[4] * m[2] * m[15]
497 - m[4] * m[3] * m[14] - m[12] * m[2] * m[7] + m[12] * m[3] * m[6];
498 ret[7] = m[0] * m[6] * m[11] - m[0] * m[7] * m[10] - m[4] * m[2] * m[11]
499 + m[4] * m[3] * m[10] + m[8] * m[2] * m[7] - m[8] * m[3] * m[6];
500
501 ret[8] = m[4] * m[9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15]
502 + m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[9];
503 ret[9] = -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15]
504 - m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[9];
505 ret[10] = m[0] * m[5] * m[15] - m[0] * m[7] * m[13] - m[4] * m[1] * m[15]
506 + m[4] * m[3] * m[13] + m[12] * m[1] * m[7] - m[12] * m[3] * m[5];
507 ret[11] = -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] + m[4] * m[1] * m[11]
508 - m[4] * m[3] * m[9] - m[8] * m[1] * m[7] + m[8] * m[3] * m[5];
509
510 ret[12] = -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14]
511 - m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[9];
512 ret[13] = m[0] * m[9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14]
513 + m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[9];
514 ret[14] = -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] + m[4] * m[1] * m[14]
515 - m[4] * m[2] * m[13] - m[12] * m[1] * m[6] + m[12] * m[2] * m[5];
516 ret[15] = m[0] * m[5] * m[10] - m[0] * m[6] * m[9] - m[4] * m[1] * m[10]
517 + m[4] * m[2] * m[9] + m[8] * m[1] * m[6] - m[8] * m[2] * m[5];
518
519 T det = m[0] * ret[0] + m[1] * ret[4] + m[2] * ret[8] + m[3] * ret[12];
520 return ret / det;
521}
522
523template <typename T>
524Matrix<T,3,3>
525matrix_rotation_from_axis_angle (Vector<T,3> const& axis, T const& angle)
526{
527 /*
528 * http://en.wikipedia.org/wiki/Rotation_matrix
529 * #Rotation_matrix_from_axis_and_angle
530 */
531 T const ca = std::cos(angle);
532 T const sa = std::sin(angle);
533 T const omca = T(1) - ca;
534
536 rot[0] = ca + MATH_POW2(axis[0]) * omca;
537 rot[1] = axis[0] * axis[1] * omca - axis[2] * sa;
538 rot[2] = axis[0] * axis[2] * omca + axis[1] * sa;
539
540 rot[3] = axis[1] * axis[0] * omca + axis[2] * sa;
541 rot[4] = ca + MATH_POW2(axis[1]) * omca;
542 rot[5] = axis[1] * axis[2] * omca - axis[0] * sa;
543
544 rot[6] = axis[2] * axis[0] * omca - axis[1] * sa;
545 rot[7] = axis[2] * axis[1] * omca + axis[0] * sa;
546 rot[8] = ca + MATH_POW2(axis[2]) * omca;
547
548 return rot;
549}
550
551template <typename T>
552void
553matrix_transpose (T* mat, int rows, int cols)
554{
555 /* Create a temporary copy of the matrix. */
556 T* tmp = new T[rows * cols];
557 std::copy(mat, mat + rows * cols, tmp);
558
559 /* Transpose matrix elements. */
560 for (int iter = 0, col = 0; col < cols; ++col)
561 for (int row = 0; row < rows; ++row, ++iter)
562 mat[iter] = tmp[row * cols + col];
563
564 delete[] tmp;
565}
566
567template <typename T>
568void
569matrix_multiply (T const* mat_a, int rows_a, int cols_a,
570 T const* mat_b, int cols_b, T* mat_res)
571{
572 std::fill(mat_res, mat_res + rows_a * cols_b, T(0));
573 for (int j = 0; j < cols_b; ++j)
574 {
575 for (int i = 0; i < rows_a; ++i)
576 {
577 int const ica = i * cols_a;
578 int const icb = i * cols_b;
579 for (int k = 0; k < cols_a; ++k)
580 mat_res[icb + j] += mat_a[ica + k] * mat_b[k * cols_b + j];
581 }
582 }
583}
584
585template <typename T>
586void
587matrix_transpose_multiply (T const* mat_a, int rows, int cols, T* mat_res)
588{
589 std::fill(mat_res, mat_res + cols * cols, T(0));
590
591 T const* A_trans_iter = mat_a;
592 T const* A_row = mat_a;
593 for (int ri = 0; ri < rows; ++ri, A_row += cols)
594 {
595 T* R_iter = mat_res;
596 for (int c1 = 0; c1 < cols; ++c1, ++A_trans_iter)
597 for (int c2 = 0; c2 < cols; ++c2, ++R_iter)
598 (*R_iter) += A_row[c2] * (*A_trans_iter);
599 }
600}
601
602template <typename T>
603bool
604matrix_is_diagonal (T* const mat, int rows, int cols, T const& epsilon)
605{
606 for (int y = 0; y < rows; ++y)
607 {
608 for (int x = 0; x < y && x < cols; ++x)
609 if (!MATH_EPSILON_EQ(T(0), mat[y * cols + x], epsilon))
610 return false;
611 for (int x = y + 1; x < cols; ++x)
612 if (!MATH_EPSILON_EQ(T(0), mat[y * cols + x], epsilon))
613 return false;
614 }
615 return true;
616}
617
618template <typename T>
619void
620matrix_swap_columns (T* mat, int rows, int cols, int c1, int c2)
621{
622 for (int i = 0; i < rows; ++i, c1 += cols, c2 += cols)
623 std::swap(mat[c1], mat[c2]);
624}
625
626template <typename T>
627void
628matrix_swap_rows (T* mat, int /*rows*/, int cols, int r1, int r2)
629{
630 r1 = cols * r1;
631 r2 = cols * r2;
632 for (int i = 0; i < cols; ++i, ++r1, ++r2)
633 std::swap(mat[r1], mat[r2]);
634}
635
636template <typename T, int N>
637void
639{
640 for (int i = 0, j = N * N - 1; i < j; ++i, --j)
641 std::swap((*mat_a)[i], (*mat_a)[j]);
642}
643
644template <typename T, int N>
645Matrix<T, N, N>
647{
648 Matrix<T, N, N> ret = mat_a;
650 return ret;
651}
652
654
655#endif /* MATH_MATRIX_TOOLS_HEADER */
Matrix class for arbitrary dimensions and types.
Definition matrix.h:54
Matrix< T, N, M > & fill(T const &value)
Fills all vector elements with the given value.
Definition matrix.h:294
Vector class for arbitrary dimensions and types.
Definition vector.h:87
Vector< T, N > cross(Vector< T, N > const &other) const
Cross product between this and another vector.
Definition vector.h:549
#define MATH_EPSILON_EQ(x, v, eps)
Definition defines.h:96
#define MATH_NAMESPACE_BEGIN
Definition defines.h:15
#define MATH_NAMESPACE_END
Definition defines.h:16
#define MATH_POW2(x)
Definition defines.h:68
void matrix_rotate_180_inplace(Matrix< T, N, N > *mat_a)
Rotates the entries of the given matrix by 180 degrees in-place.
Matrix< T, N, N > matrix_rotate_180(Matrix< T, N, N > const &mat_a)
Rotates the entries of the given matrix by 180 degrees.
Matrix< T, 4, 4 > matrix_invert_trans(Matrix< T, 4, 4 > const &mat)
Inverts a transformation matrix.
void matrix_multiply(T const *mat_a, int rows_a, int cols_a, T const *mat_b, int cols_b, T *mat_res)
Matrix multiplication of dynamically sized dense matrices.
Matrix< T, 4, 4 > matrix_inverse_gl_projection(T const &znear, T const &zfar, T const &top, T const &right)
Creates a symmetric inverse projection matrix as used in OpenGL.
Matrix< T, 3, 3 > matrix_rotation_from_axis_angle(Vector< T, 3 > const &axis, T const &angle)
Computes the 3x3 rotation matrix from axis and angle notation.
bool matrix_is_identity(Matrix< T, N, N > const &mat, T const &epsilon=T(0))
Returns true if and only if the given matrix is the identity matrix.
T matrix_trace(math::Matrix< T, N, N > const &mat)
Calculates the trace of the given matrix.
Matrix< T, N, N > matrix_inverse(Matrix< T, N, N > const &mat)
Calculates the inverse of the given matrix.
void matrix_swap_columns(T *const mat, int rows, int cols, int c1, int c2)
Swaps the columns c1 and c2 of matrix mat with dimension rows, cols.
void matrix_swap_rows(T *mat, int rows, int cols, int r1, int r2)
Swaps the rows r1 and r2 of matrix mat with dimension rows, cols.
Matrix< T, N, N > & matrix_set_identity(Matrix< T, N, N > *mat)
Sets the given square matrix to the identity matrix.
Matrix< T, 4, 4 > matrix_inverse_viewtrans(Vector< T, 3 > const &campos, Vector< T, 3 > const &viewdir, Vector< T, 3 > const &upvec)
Creates an inverse view transformation matrix.
void matrix_transpose(T const *mat, int rows, int cols)
In-place transpose of a dynamically sized dense matrix.
Matrix< T, N, N > matrix_from_diagonal(math::Vector< T, N > const &v)
Returns a diagonal matrix from the given vector.
Matrix< T, N, N > & matrix_set_diagonal(Matrix< T, N, N > &mat, T const *diag)
Sets the diagonal elements of the given matrix.
T matrix_determinant(Matrix< T, N, N > const &mat)
Calculates the determinant of the given matrix.
Matrix< T, 4, 4 > matrix_viewtrans(Vector< T, 3 > const &campos, Vector< T, 3 > const &viewdir, Vector< T, 3 > const &upvec)
Creates a view transformation matrix for camera parameters given as camera position,...
void matrix_transpose_multiply(T const *mat_a, int rows, int cols, T *mat_res)
Matrix multiplication of the transposed with itself.
Vector< T, N > matrix_get_diagonal(Matrix< T, N, N > const &mat)
Returns the diagonal elements of the matrix as a vector.
Matrix< T, 4, 4 > matrix_gl_projection(T const &znear, T const &zfar, T const &top, T const &right)
Creates a symmetric projection matrix as used in OpenGL.
bool matrix_is_diagonal(T *const mat, int rows, int cols, T const &epsilon=T(0))
Checks whether the input matrix is a diagonal matrix.
void swap(mve::Image< T > &a, mve::Image< T > &b)
Specialization of std::swap for efficient image swapping.
Definition image.h:478