MeshLib Documentation
Loading...
Searching...
No Matches
MRMatrix4.h
Go to the documentation of this file.
1#pragma once
2
3#include "MRVector4.h"
4#include <limits>
5#include <cassert>
6
7namespace MR
8{
9
12template <typename T>
13struct Matrix4
14{
15 using ValueType = T;
17
19 Vector4<T> x{ 1, 0, 0, 0 };
20 Vector4<T> y{ 0, 1, 0, 0 };
21 Vector4<T> z{ 0, 0, 1, 0 };
22 Vector4<T> w{ 0, 0, 0, 1 };
23
24 constexpr Matrix4() noexcept = default;
26 constexpr Matrix4( const Vector4<T>& x, const Vector4<T>& y, const Vector4<T>& z, const Vector4<T>& w ) : x( x ), y( y ), z( z ), w( w ) { }
27
29 constexpr Matrix4( const Matrix3<T>& r, const Vector3<T>& t )
30 {
31 x = Vector4<T>( r.x.x, r.x.y, r.x.z, t.x );
32 y = Vector4<T>( r.y.x, r.y.y, r.y.z, t.y );
33 z = Vector4<T>( r.z.x, r.z.y, r.z.z, t.z );
34 w = Vector4<T>( 0, 0, 0, 1 );
35 }
36
37 // Currently `AffineXf3<long long>` doesn't seem to compile, so we disable this constructor for `Matrix4<long long>`, because otherwise
38 // mrbind instantiates the entire `AffineXf3<long long>` and chokes on it.
39 constexpr Matrix4( const AffineXf3<T>& xf ) MR_REQUIRES_IF_SUPPORTED( std::floating_point<T> ) : Matrix4( xf.A, xf.b ) {}
40
41 template <typename U>
42 constexpr explicit Matrix4( const Matrix4<U> & m ) : x( m.x ), y( m.y ), z( m.z ), w( m.w ) { }
43 static constexpr Matrix4 zero() noexcept { return Matrix4( Vector4<T>(), Vector4<T>(), Vector4<T>(), Vector4<T>() ); }
44 static constexpr Matrix4 identity() noexcept { return Matrix4(); }
46 static constexpr Matrix4 scale( T s ) noexcept { return Matrix4( { s, T(0), T(0), T(0) }, { T(0), s, T(0), T(0) }, { T(0), T(0), s, T(0) }, { T(0), T(0), T(0), s } ); }
47
49 constexpr const T& operator ()( int row, int col ) const noexcept { return operator[]( row )[col]; }
50 constexpr T& operator ()( int row, int col ) noexcept { return operator[]( row )[col]; }
51
53 constexpr const Vector4<T> & operator []( int row ) const noexcept { return *( &x + row ); }
54 constexpr Vector4<T> & operator []( int row ) noexcept { return *( &x + row ); }
55
57 constexpr Vector4<T> col( int i ) const noexcept { return { x[i], y[i], z[i], w[i] }; }
58
60 constexpr T trace() const noexcept { return x.x + y.y + z.z + w.w; }
62 constexpr T normSq() const noexcept { return x.lengthSq() + y.lengthSq() + z.lengthSq() + w.lengthSq(); }
63 constexpr auto norm() const noexcept
64 {
65 // Calling `sqrt` this way to hopefully support boost.multiprecision numbers.
66 // Returning `auto` to not break on integral types.
67 using std::sqrt;
68 return sqrt( normSq() );
69 }
71 Matrix3<T> submatrix3( int i, int j ) const noexcept;
73 T det() const noexcept;
75 constexpr Matrix4<T> inverse() const noexcept;
77 constexpr Matrix4<T> transposed() const noexcept;
78
79 constexpr Matrix3<T> getRotation() const noexcept;
80 void setRotation( const Matrix3<T>& rot) noexcept;
81 constexpr Vector3<T> getTranslation() const noexcept;
82 void setTranslation( const Vector3<T>& t ) noexcept;
83
84 constexpr T* data() { return (T*) (&x); };
85 constexpr const T* data() const { return (T*) (&x); };
86 Matrix4 & operator +=( const Matrix4<T> & b ) { x += b.x; y += b.y; z += b.z; w += b.w; return * this; }
87 Matrix4 & operator -=( const Matrix4<T> & b ) { x -= b.x; y -= b.y; z -= b.z; w -= b.w; return * this; }
88 Matrix4 & operator *=( T b ) { x *= b; y *= b; z *= b; w *= b; return * this; }
90 {
91 if constexpr ( std::is_integral_v<T> )
92 { x /= b; y /= b; z /= b; w /= b; return * this; }
93 else
94 return *this *= ( 1 / b );
95 }
96
97 operator AffineXf3<T>() const MR_REQUIRES_IF_SUPPORTED( std::floating_point<T> )
98 {
99 assert( std::abs( w.x ) < std::numeric_limits<T>::epsilon() * 1000 );
100 assert( std::abs( w.y ) < std::numeric_limits<T>::epsilon() * 1000 );
101 assert( std::abs( w.z ) < std::numeric_limits<T>::epsilon() * 1000 );
102 assert( std::abs( 1 - w.w ) < std::numeric_limits<T>::epsilon() * 1000 );
103 AffineXf3<T> res;
104 res.A.x.x = x.x; res.A.x.y = x.y; res.A.x.z = x.z; res.b.x = x.w;
105 res.A.y.x = y.x; res.A.y.y = y.y; res.A.y.z = y.z; res.b.y = y.w;
106 res.A.z.x = z.x; res.A.z.y = z.y; res.A.z.z = z.z; res.b.z = z.w;
107 return res;
108 }
109
112 Vector3<T> operator ()( const Vector3<T> & b ) const MR_REQUIRES_IF_SUPPORTED( !std::is_integral_v<T> );
113};
114
117
119template <typename T>
120inline Vector4<T> operator *( const Matrix4<T> & a, const Vector4<T> & b )
121{
122 return { dot( a.x, b ), dot( a.y, b ), dot( a.z, b ), dot( a.w, b ) };
123}
124
126template <typename T>
127inline T dot( const Matrix4<T> & a, const Matrix4<T> & b )
128{
129 return dot( a.x, b.x ) + dot( a.y, b.y ) + dot( a.z, b.z ) + dot( a.w, b.w );
130}
131
132template <typename T>
133inline Vector3<T> Matrix4<T>::operator ()( const Vector3<T> & b ) const MR_REQUIRES_IF_SUPPORTED( !std::is_integral_v<T> )
134{
135 return ( *this * Vector4<T>{ b.x, b.y, b.z, T(1) } ).proj3d();
136}
137
139template <typename T>
140inline Matrix4<T> operator *( const Matrix4<T> & a, const Matrix4<T> & b )
141{
142 Matrix4<T> res;
143 for ( int i = 0; i < 4; ++i )
144 for ( int j = 0; j < 4; ++j )
145 res[i][j] = dot( a[i], b.col(j) );
146 return res;
147}
148
150template <typename T>
151inline Matrix4<T> outer( const Vector4<T> & a, const Vector4<T> & b )
152{
153 return { a.x * b, a.y * b, a.z * b, a.w * b };
154}
155
156template <typename T>
157inline bool operator ==( const Matrix4<T> & a, const Matrix4<T> & b )
158 { return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w; }
159
160template <typename T>
161inline bool operator !=( const Matrix4<T> & a, const Matrix4<T> & b )
162 { return !( a == b ); }
163
164template <typename T>
165inline Matrix4<T> operator +( const Matrix4<T> & a, const Matrix4<T> & b )
166 { return { a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w }; }
167
168template <typename T>
169inline Matrix4<T> operator -( const Matrix4<T> & a, const Matrix4<T> & b )
170 { return { a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w }; }
171
172template <typename T>
173inline Matrix4<T> operator *( T a, const Matrix4<T> & b )
174 { return { a * b.x, a * b.y, a * b.z, a * b.w }; }
175
176template <typename T>
177inline Matrix4<T> operator *( const Matrix4<T> & b, T a )
178 { return { a * b.x, a * b.y, a * b.z, a * b.z }; }
179
180template <typename T>
181inline Matrix4<T> operator /( Matrix4<T> b, T a )
182 { b /= a; return b; }
183
184template <typename T>
185Matrix3<T> Matrix4<T>::submatrix3( int i, int j ) const noexcept
186{
187 Matrix3<T> res;
188 auto* resM = (T*) &res.x;
189 int cur = 0;
190 for ( int m = 0; m < 4; m++ )
191 {
192 if ( m == i )
193 continue;
194 for ( int n = 0; n < 4; n++ )
195 {
196 if ( n == j )
197 continue;
198 resM[cur++] = (*this)[m][n];
199 }
200 }
201 assert( cur == 9 );
202 return res;
203}
204
205template <typename T>
206T Matrix4<T>::det() const noexcept
207{
208 return
209 x.x * submatrix3( 0, 0 ).det()
210 - x.y * submatrix3( 0, 1 ).det()
211 + x.z * submatrix3( 0, 2 ).det()
212 - x.w * submatrix3( 0, 3 ).det();
213}
214
215template <typename T>
216constexpr Matrix4<T> Matrix4<T>::transposed() const noexcept
217{
218 return Matrix4<T>
219 {
220 { x.x, y.x, z.x, w.x },
221 { x.y, y.y, z.y, w.y },
222 { x.z, y.z, z.z, w.z },
223 { x.w, y.w, z.w, w.w },
224 };
225}
226
227template <typename T>
228constexpr Matrix4<T> Matrix4<T>::inverse() const noexcept
229{
230 Matrix4<T> inv;
231 T* m = (T*) (&x);
232 T det;
233
234 inv[0][0] = m[5] * m[10] * m[15] -
235 m[5] * m[11] * m[14] -
236 m[9] * m[6] * m[15] +
237 m[9] * m[7] * m[14] +
238 m[13] * m[6] * m[11] -
239 m[13] * m[7] * m[10];
240
241 inv[1][0] = -m[4] * m[10] * m[15] +
242 m[4] * m[11] * m[14] +
243 m[8] * m[6] * m[15] -
244 m[8] * m[7] * m[14] -
245 m[12] * m[6] * m[11] +
246 m[12] * m[7] * m[10];
247
248 inv[2][0] = m[4] * m[9] * m[15] -
249 m[4] * m[11] * m[13] -
250 m[8] * m[5] * m[15] +
251 m[8] * m[7] * m[13] +
252 m[12] * m[5] * m[11] -
253 m[12] * m[7] * m[9];
254
255 inv[3][0] = -m[4] * m[9] * m[14] +
256 m[4] * m[10] * m[13] +
257 m[8] * m[5] * m[14] -
258 m[8] * m[6] * m[13] -
259 m[12] * m[5] * m[10] +
260 m[12] * m[6] * m[9];
261
262 inv[0][1] = -m[1] * m[10] * m[15] +
263 m[1] * m[11] * m[14] +
264 m[9] * m[2] * m[15] -
265 m[9] * m[3] * m[14] -
266 m[13] * m[2] * m[11] +
267 m[13] * m[3] * m[10];
268
269 inv[1][1] = m[0] * m[10] * m[15] -
270 m[0] * m[11] * m[14] -
271 m[8] * m[2] * m[15] +
272 m[8] * m[3] * m[14] +
273 m[12] * m[2] * m[11] -
274 m[12] * m[3] * m[10];
275
276 inv[2][1] = -m[0] * m[9] * m[15] +
277 m[0] * m[11] * m[13] +
278 m[8] * m[1] * m[15] -
279 m[8] * m[3] * m[13] -
280 m[12] * m[1] * m[11] +
281 m[12] * m[3] * m[9];
282
283 inv[3][1] = m[0] * m[9] * m[14] -
284 m[0] * m[10] * m[13] -
285 m[8] * m[1] * m[14] +
286 m[8] * m[2] * m[13] +
287 m[12] * m[1] * m[10] -
288 m[12] * m[2] * m[9];
289
290 inv[0][2] = m[1] * m[6] * m[15] -
291 m[1] * m[7] * m[14] -
292 m[5] * m[2] * m[15] +
293 m[5] * m[3] * m[14] +
294 m[13] * m[2] * m[7] -
295 m[13] * m[3] * m[6];
296
297 inv[1][2] = -m[0] * m[6] * m[15] +
298 m[0] * m[7] * m[14] +
299 m[4] * m[2] * m[15] -
300 m[4] * m[3] * m[14] -
301 m[12] * m[2] * m[7] +
302 m[12] * m[3] * m[6];
303
304 inv[2][2] = m[0] * m[5] * m[15] -
305 m[0] * m[7] * m[13] -
306 m[4] * m[1] * m[15] +
307 m[4] * m[3] * m[13] +
308 m[12] * m[1] * m[7] -
309 m[12] * m[3] * m[5];
310
311 inv[3][2] = -m[0] * m[5] * m[14] +
312 m[0] * m[6] * m[13] +
313 m[4] * m[1] * m[14] -
314 m[4] * m[2] * m[13] -
315 m[12] * m[1] * m[6] +
316 m[12] * m[2] * m[5];
317
318 inv[0][3] = -m[1] * m[6] * m[11] +
319 m[1] * m[7] * m[10] +
320 m[5] * m[2] * m[11] -
321 m[5] * m[3] * m[10] -
322 m[9] * m[2] * m[7] +
323 m[9] * m[3] * m[6];
324
325 inv[1][3] = m[0] * m[6] * m[11] -
326 m[0] * m[7] * m[10] -
327 m[4] * m[2] * m[11] +
328 m[4] * m[3] * m[10] +
329 m[8] * m[2] * m[7] -
330 m[8] * m[3] * m[6];
331
332 inv[2][3] = -m[0] * m[5] * m[11] +
333 m[0] * m[7] * m[9] +
334 m[4] * m[1] * m[11] -
335 m[4] * m[3] * m[9] -
336 m[8] * m[1] * m[7] +
337 m[8] * m[3] * m[5];
338
339 inv[3][3] = m[0] * m[5] * m[10] -
340 m[0] * m[6] * m[9] -
341 m[4] * m[1] * m[10] +
342 m[4] * m[2] * m[9] +
343 m[8] * m[1] * m[6] -
344 m[8] * m[2] * m[5];
345
346 det = m[0] * inv[0][0] + m[1] * inv[1][0] + m[2] * inv[2][0] + m[3] * inv[3][0];
347
348 if( det == 0 )
349 {
350 // impossible to invert singular matrix
351 assert( false );
352 return Matrix4<T>();
353 }
354
355 inv /= det;
356
357 return inv;
358}
359
360template <typename T>
361constexpr Matrix3<T> Matrix4<T>::getRotation() const noexcept
362{
363 return Matrix3<T>
364 {
365 { x.x, x.y, x.z },
366 { y.x, y.y, y.z },
367 { z.x, z.y, z.z }
368 };
369}
370
371template <typename T>
372void Matrix4<T>::setRotation( const Matrix3<T>& rot ) noexcept
373{
374 x.x = rot.x.x; x.y = rot.x.y; x.z = rot.x.z;
375 y.x = rot.y.x; y.y = rot.y.y; y.z = rot.y.z;
376 z.x = rot.z.x; z.y = rot.z.y; z.z = rot.z.z;
377}
378
379template <typename T>
380constexpr Vector3<T> Matrix4<T>::getTranslation() const noexcept
381{
382 return Vector3<T>{ x.w, y.w, z.w };
383}
384
385template <typename T>
386void Matrix4<T>::setTranslation( const Vector3<T>& t ) noexcept
387{
388 x.w = t.x; y.w = t.y; z.w = t.z;
389}
390
392
393} // namespace MR
#define MR_REQUIRES_IF_SUPPORTED(...)
Definition MRMacros.h:29
BitSet operator-(const BitSet &a, const BitSet &b)
Definition MRMesh/MRBitSet.h:342
MRMESH_API bool operator==(const BitSet &a, const BitSet &b)
compare that two bit sets have the same set bits (they can be equal even if sizes are distinct but la...
bool operator!=(const SetBitIteratorT< T > &a, const SetBitIteratorT< T > &b)
Definition MRMesh/MRBitSet.h:276
Definition MRCameraOrientationPlugin.h:8
Color operator/(const Color &b, float a)
Definition MRColor.h:128
Color operator*(float a, const Color &b)
Definition MRColor.h:118
MRMESH_CLASS Vector3< double > Matrix2< double > Matrix4
Definition MRMesh/MRMeshFwd.h:169
MRMESH_CLASS Vector3
Definition MRMesh/MRMeshFwd.h:137
AffineXf< Vector3< T > > AffineXf3
Definition MRMesh/MRMeshFwd.h:208
Color operator+(const Color &a, const Color &b)
Definition MRColor.h:108
Definition MRMesh/MRAffineXf.h:14
V b
Definition MRMesh/MRAffineXf.h:19
M A
Definition MRMesh/MRAffineXf.h:18
Definition MRMesh/MRMatrix3.h:13
Vector3< T > x
rows, identity matrix by default
Definition MRMesh/MRMatrix3.h:18
Vector3< T > y
Definition MRMesh/MRMatrix3.h:19
Vector3< T > z
Definition MRMesh/MRMatrix3.h:20
Definition MRMatrix4.h:14
Vector4< T > z
Definition MRMatrix4.h:21
T dot(const Matrix4< T > &a, const Matrix4< T > &b)
double-dot product: x = a : b
Definition MRMatrix4.h:127
constexpr T * data()
Definition MRMatrix4.h:84
constexpr Matrix4(const AffineXf3< T > &xf) MR_REQUIRES_IF_SUPPORTED(std
Definition MRMatrix4.h:39
T ValueType
Definition MRMatrix4.h:15
constexpr T trace() const noexcept
computes trace of the matrix
Definition MRMatrix4.h:60
void setTranslation(const Vector3< T > &t) noexcept
Matrix4 & operator+=(const Matrix4< T > &b)
Definition MRMatrix4.h:86
Matrix4 & operator*=(T b)
Definition MRMatrix4.h:88
Matrix3< T > submatrix3(int i, int j) const noexcept
computes submatrix of the matrix with excluded i-th row and j-th column
static constexpr Matrix4 zero() noexcept
Definition MRMatrix4.h:43
constexpr T normSq() const noexcept
compute sum of squared matrix elements
Definition MRMatrix4.h:62
constexpr const T & operator()(int row, int col) const noexcept
element access
Definition MRMatrix4.h:49
Vector4< T > y
Definition MRMatrix4.h:20
static constexpr Matrix4 scale(T s) noexcept
returns a matrix that scales uniformly
Definition MRMatrix4.h:46
void setRotation(const Matrix3< T > &rot) noexcept
constexpr Matrix3< T > getRotation() const noexcept
constexpr Matrix4(const Matrix3< T > &r, const Vector3< T > &t)
construct from rotation matrix and translation vector
Definition MRMatrix4.h:29
T det() const noexcept
computes determinant of the matrix
Vector4< T > w
Definition MRMatrix4.h:22
constexpr Matrix4< T > transposed() const noexcept
computes transposed matrix
constexpr auto norm() const noexcept
Definition MRMatrix4.h:63
constexpr Matrix4(const Matrix4< U > &m)
Definition MRMatrix4.h:42
constexpr const Vector4< T > & operator[](int row) const noexcept
row access
Definition MRMatrix4.h:53
constexpr Vector4< T > col(int i) const noexcept
column access
Definition MRMatrix4.h:57
constexpr Matrix4() noexcept=default
Matrix4 & operator/=(T b)
Definition MRMatrix4.h:89
constexpr const T * data() const
Definition MRMatrix4.h:85
static constexpr Matrix4 identity() noexcept
Definition MRMatrix4.h:44
constexpr Matrix4< T > inverse() const noexcept
computes inverse matrix
Matrix4 & operator-=(const Matrix4< T > &b)
Definition MRMatrix4.h:87
constexpr Vector3< T > getTranslation() const noexcept
Vector4< T > x
rows, identity matrix by default
Definition MRMatrix4.h:19
Matrix4< T > outer(const Vector4< T > &a, const Vector4< T > &b)
x = a * b^T
Definition MRMatrix4.h:151
Definition MRMesh/MRVector3.h:19
T x
Definition MRMesh/MRVector3.h:25
T y
Definition MRMesh/MRVector3.h:25
T z
Definition MRMesh/MRVector3.h:25
Definition MRVector4.h:13
T y
Definition MRVector4.h:19
T z
Definition MRVector4.h:19
T x
Definition MRVector4.h:19
T w
Definition MRVector4.h:19