MeshLib
 
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 constexpr Matrix4( const AffineXf3<T>& xf ) : Matrix4( xf.A, xf.b ) {}
38
39 template <typename U>
40 constexpr explicit Matrix4( const Matrix4<U> & m ) : x( m.x ), y( m.y ), z( m.z ), w( m.w ) { }
41 static constexpr Matrix4 zero() noexcept { return Matrix4( Vector4<T>(), Vector4<T>(), Vector4<T>(), Vector4<T>() ); }
42 static constexpr Matrix4 identity() noexcept { return Matrix4(); }
44 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 } ); }
45
47 constexpr const T& operator ()( int row, int col ) const noexcept { return operator[]( row )[col]; }
48 constexpr T& operator ()( int row, int col ) noexcept { return operator[]( row )[col]; }
49
51 constexpr const Vector4<T> & operator []( int row ) const noexcept { return *( &x + row ); }
52 constexpr Vector4<T> & operator []( int row ) noexcept { return *( &x + row ); }
53
55 constexpr Vector4<T> col( int i ) const noexcept { return { x[i], y[i], z[i], w[i] }; }
56
58 constexpr T trace() const noexcept { return x.x + y.y + z.z + w.w; }
60 constexpr T normSq() const noexcept { return x.lengthSq() + y.lengthSq() + z.lengthSq() + w.lengthSq(); }
61 constexpr auto norm() const noexcept
62 {
63 // Calling `sqrt` this way to hopefully support boost.multiprecision numbers.
64 // Returning `auto` to not break on integral types.
65 using std::sqrt;
66 return sqrt( normSq() );
67 }
69 Matrix3<T> submatrix3( int i, int j ) const noexcept;
71 T det() const noexcept;
73 constexpr Matrix4<T> inverse() const noexcept;
75 constexpr Matrix4<T> transposed() const noexcept;
76
77 constexpr Matrix3<T> getRotation() const noexcept;
78 void setRotation( const Matrix3<T>& rot) noexcept;
79 constexpr Vector3<T> getTranslation() const noexcept;
80 void setTranslation( const Vector3<T>& t ) noexcept;
81
82 constexpr T* data() { return (T*) (&x); };
83 constexpr const T* data() const { return (T*) (&x); };
84 Matrix4 & operator +=( const Matrix4<T> & b ) { x += b.x; y += b.y; z += b.z; w += b.w; return * this; }
85 Matrix4 & operator -=( const Matrix4<T> & b ) { x -= b.x; y -= b.y; z -= b.z; w -= b.w; return * this; }
86 Matrix4 & operator *=( T b ) { x *= b; y *= b; z *= b; w *= b; return * this; }
88 {
89 if constexpr ( std::is_integral_v<T> )
90 { x /= b; y /= b; z /= b; w /= b; return * this; }
91 else
92 return *this *= ( 1 / b );
93 }
94
95 operator AffineXf3<T>() const MR_REQUIRES_IF_SUPPORTED( std::is_arithmetic_v<T> && !std::is_same_v<T, bool> )
96 {
97 assert( std::abs( w.x ) < std::numeric_limits<T>::epsilon() * 1000 );
98 assert( std::abs( w.y ) < std::numeric_limits<T>::epsilon() * 1000 );
99 assert( std::abs( w.z ) < std::numeric_limits<T>::epsilon() * 1000 );
100 assert( std::abs( 1 - w.w ) < std::numeric_limits<T>::epsilon() * 1000 );
101 AffineXf3<T> res;
102 res.A.x.x = x.x; res.A.x.y = x.y; res.A.x.z = x.z; res.b.x = x.w;
103 res.A.y.x = y.x; res.A.y.y = y.y; res.A.y.z = y.z; res.b.y = y.w;
104 res.A.z.x = z.x; res.A.z.y = z.y; res.A.z.z = z.z; res.b.z = z.w;
105 return res;
106 }
107
110 Vector3<T> operator ()( const Vector3<T> & b ) const MR_REQUIRES_IF_SUPPORTED( !std::is_integral_v<T> );
111};
112
115
117template <typename T>
118inline Vector4<T> operator *( const Matrix4<T> & a, const Vector4<T> & b )
119{
120 return { dot( a.x, b ), dot( a.y, b ), dot( a.z, b ), dot( a.w, b ) };
121}
122
124template <typename T>
125inline T dot( const Matrix4<T> & a, const Matrix4<T> & b )
126{
127 return dot( a.x, b.x ) + dot( a.y, b.y ) + dot( a.z, b.z ) + dot( a.w, b.w );
128}
129
130template <typename T>
131inline Vector3<T> Matrix4<T>::operator ()( const Vector3<T> & b ) const MR_REQUIRES_IF_SUPPORTED( !std::is_integral_v<T> )
132{
133 return ( *this * Vector4<T>{ b.x, b.y, b.z, T(1) } ).proj3d();
134}
135
137template <typename T>
138inline Matrix4<T> operator *( const Matrix4<T> & a, const Matrix4<T> & b )
139{
140 Matrix4<T> res;
141 for ( int i = 0; i < 4; ++i )
142 for ( int j = 0; j < 4; ++j )
143 res[i][j] = dot( a[i], b.col(j) );
144 return res;
145}
146
148template <typename T>
149inline Matrix4<T> outer( const Vector4<T> & a, const Vector4<T> & b )
150{
151 return { a.x * b, a.y * b, a.z * b, a.w * b };
152}
153
154template <typename T>
155inline bool operator ==( const Matrix4<T> & a, const Matrix4<T> & b )
156 { return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w; }
157
158template <typename T>
159inline bool operator !=( const Matrix4<T> & a, const Matrix4<T> & b )
160 { return !( a == b ); }
161
162template <typename T>
163inline Matrix4<T> operator +( const Matrix4<T> & a, const Matrix4<T> & b )
164 { return { a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w }; }
165
166template <typename T>
167inline Matrix4<T> operator -( const Matrix4<T> & a, const Matrix4<T> & b )
168 { return { a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w }; }
169
170template <typename T>
171inline Matrix4<T> operator *( T a, const Matrix4<T> & b )
172 { return { a * b.x, a * b.y, a * b.z, a * b.w }; }
173
174template <typename T>
175inline Matrix4<T> operator *( const Matrix4<T> & b, T a )
176 { return { a * b.x, a * b.y, a * b.z, a * b.z }; }
177
178template <typename T>
179inline Matrix4<T> operator /( Matrix4<T> b, T a )
180 { b /= a; return b; }
181
182template <typename T>
183Matrix3<T> Matrix4<T>::submatrix3( int i, int j ) const noexcept
184{
185 Matrix3<T> res;
186 auto* resM = (T*) &res.x;
187 int cur = 0;
188 for ( int m = 0; m < 4; m++ )
189 {
190 if ( m == i )
191 continue;
192 for ( int n = 0; n < 4; n++ )
193 {
194 if ( n == j )
195 continue;
196 resM[cur++] = (*this)[m][n];
197 }
198 }
199 assert( cur == 9 );
200 return res;
201}
202
203template <typename T>
204T Matrix4<T>::det() const noexcept
205{
206 return
207 x.x * submatrix3( 0, 0 ).det()
208 - x.y * submatrix3( 0, 1 ).det()
209 + x.z * submatrix3( 0, 2 ).det()
210 - x.w * submatrix3( 0, 3 ).det();
211}
212
213template <typename T>
214constexpr Matrix4<T> Matrix4<T>::transposed() const noexcept
215{
216 return Matrix4<T>
217 {
218 { x.x, y.x, z.x, w.x },
219 { x.y, y.y, z.y, w.y },
220 { x.z, y.z, z.z, w.z },
221 { x.w, y.w, z.w, w.w },
222 };
223}
224
225template <typename T>
226constexpr Matrix4<T> Matrix4<T>::inverse() const noexcept
227{
228 Matrix4<T> inv;
229 T* m = (T*) (&x);
230 T det;
231
232 inv[0][0] = m[5] * m[10] * m[15] -
233 m[5] * m[11] * m[14] -
234 m[9] * m[6] * m[15] +
235 m[9] * m[7] * m[14] +
236 m[13] * m[6] * m[11] -
237 m[13] * m[7] * m[10];
238
239 inv[1][0] = -m[4] * m[10] * m[15] +
240 m[4] * m[11] * m[14] +
241 m[8] * m[6] * m[15] -
242 m[8] * m[7] * m[14] -
243 m[12] * m[6] * m[11] +
244 m[12] * m[7] * m[10];
245
246 inv[2][0] = m[4] * m[9] * m[15] -
247 m[4] * m[11] * m[13] -
248 m[8] * m[5] * m[15] +
249 m[8] * m[7] * m[13] +
250 m[12] * m[5] * m[11] -
251 m[12] * m[7] * m[9];
252
253 inv[3][0] = -m[4] * m[9] * m[14] +
254 m[4] * m[10] * m[13] +
255 m[8] * m[5] * m[14] -
256 m[8] * m[6] * m[13] -
257 m[12] * m[5] * m[10] +
258 m[12] * m[6] * m[9];
259
260 inv[0][1] = -m[1] * m[10] * m[15] +
261 m[1] * m[11] * m[14] +
262 m[9] * m[2] * m[15] -
263 m[9] * m[3] * m[14] -
264 m[13] * m[2] * m[11] +
265 m[13] * m[3] * m[10];
266
267 inv[1][1] = m[0] * m[10] * m[15] -
268 m[0] * m[11] * m[14] -
269 m[8] * m[2] * m[15] +
270 m[8] * m[3] * m[14] +
271 m[12] * m[2] * m[11] -
272 m[12] * m[3] * m[10];
273
274 inv[2][1] = -m[0] * m[9] * m[15] +
275 m[0] * m[11] * m[13] +
276 m[8] * m[1] * m[15] -
277 m[8] * m[3] * m[13] -
278 m[12] * m[1] * m[11] +
279 m[12] * m[3] * m[9];
280
281 inv[3][1] = m[0] * m[9] * m[14] -
282 m[0] * m[10] * m[13] -
283 m[8] * m[1] * m[14] +
284 m[8] * m[2] * m[13] +
285 m[12] * m[1] * m[10] -
286 m[12] * m[2] * m[9];
287
288 inv[0][2] = m[1] * m[6] * m[15] -
289 m[1] * m[7] * m[14] -
290 m[5] * m[2] * m[15] +
291 m[5] * m[3] * m[14] +
292 m[13] * m[2] * m[7] -
293 m[13] * m[3] * m[6];
294
295 inv[1][2] = -m[0] * m[6] * m[15] +
296 m[0] * m[7] * m[14] +
297 m[4] * m[2] * m[15] -
298 m[4] * m[3] * m[14] -
299 m[12] * m[2] * m[7] +
300 m[12] * m[3] * m[6];
301
302 inv[2][2] = m[0] * m[5] * m[15] -
303 m[0] * m[7] * m[13] -
304 m[4] * m[1] * m[15] +
305 m[4] * m[3] * m[13] +
306 m[12] * m[1] * m[7] -
307 m[12] * m[3] * m[5];
308
309 inv[3][2] = -m[0] * m[5] * m[14] +
310 m[0] * m[6] * m[13] +
311 m[4] * m[1] * m[14] -
312 m[4] * m[2] * m[13] -
313 m[12] * m[1] * m[6] +
314 m[12] * m[2] * m[5];
315
316 inv[0][3] = -m[1] * m[6] * m[11] +
317 m[1] * m[7] * m[10] +
318 m[5] * m[2] * m[11] -
319 m[5] * m[3] * m[10] -
320 m[9] * m[2] * m[7] +
321 m[9] * m[3] * m[6];
322
323 inv[1][3] = m[0] * m[6] * m[11] -
324 m[0] * m[7] * m[10] -
325 m[4] * m[2] * m[11] +
326 m[4] * m[3] * m[10] +
327 m[8] * m[2] * m[7] -
328 m[8] * m[3] * m[6];
329
330 inv[2][3] = -m[0] * m[5] * m[11] +
331 m[0] * m[7] * m[9] +
332 m[4] * m[1] * m[11] -
333 m[4] * m[3] * m[9] -
334 m[8] * m[1] * m[7] +
335 m[8] * m[3] * m[5];
336
337 inv[3][3] = m[0] * m[5] * m[10] -
338 m[0] * m[6] * m[9] -
339 m[4] * m[1] * m[10] +
340 m[4] * m[2] * m[9] +
341 m[8] * m[1] * m[6] -
342 m[8] * m[2] * m[5];
343
344 det = m[0] * inv[0][0] + m[1] * inv[1][0] + m[2] * inv[2][0] + m[3] * inv[3][0];
345
346 if( det == 0 )
347 {
348 // impossible to invert singular matrix
349 assert( false );
350 return Matrix4<T>();
351 }
352
353 inv /= det;
354
355 return inv;
356}
357
358template <typename T>
359constexpr Matrix3<T> Matrix4<T>::getRotation() const noexcept
360{
361 return Matrix3<T>
362 {
363 { x.x, x.y, x.z },
364 { y.x, y.y, y.z },
365 { z.x, z.y, z.z }
366 };
367}
368
369template <typename T>
370void Matrix4<T>::setRotation( const Matrix3<T>& rot ) noexcept
371{
372 x.x = rot.x.x; x.y = rot.x.y; x.z = rot.x.z;
373 y.x = rot.y.x; y.y = rot.y.y; y.z = rot.y.z;
374 z.x = rot.z.x; z.y = rot.z.y; z.z = rot.z.z;
375}
376
377template <typename T>
378constexpr Vector3<T> Matrix4<T>::getTranslation() const noexcept
379{
380 return Vector3<T>{ x.w, y.w, z.w };
381}
382
383template <typename T>
384void Matrix4<T>::setTranslation( const Vector3<T>& t ) noexcept
385{
386 x.w = t.x; y.w = t.y; z.w = t.z;
387}
388
390
391} // namespace MR
#define MR_REQUIRES_IF_SUPPORTED(...)
Definition MRMacros.h:26
BitSet operator-(const BitSet &a, const BitSet &b)
Definition MRMesh/MRBitSet.h:325
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:259
Definition MRCameraOrientationPlugin.h:7
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:168
MRMESH_CLASS Vector3
Definition MRMesh/MRMeshFwd.h:136
AffineXf< Vector3< T > > AffineXf3
Definition MRMesh/MRMeshFwd.h:207
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
constexpr Matrix4(const AffineXf3< T > &xf)
Definition MRMatrix4.h:37
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:125
constexpr T * data()
Definition MRMatrix4.h:82
T ValueType
Definition MRMatrix4.h:15
constexpr T trace() const noexcept
computes trace of the matrix
Definition MRMatrix4.h:58
void setTranslation(const Vector3< T > &t) noexcept
Matrix4 & operator+=(const Matrix4< T > &b)
Definition MRMatrix4.h:84
Matrix4 & operator*=(T b)
Definition MRMatrix4.h:86
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:41
constexpr T normSq() const noexcept
compute sum of squared matrix elements
Definition MRMatrix4.h:60
constexpr const T & operator()(int row, int col) const noexcept
element access
Definition MRMatrix4.h:47
Vector4< T > y
Definition MRMatrix4.h:20
static constexpr Matrix4 scale(T s) noexcept
returns a matrix that scales uniformly
Definition MRMatrix4.h:44
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:61
constexpr Matrix4(const Matrix4< U > &m)
Definition MRMatrix4.h:40
constexpr const Vector4< T > & operator[](int row) const noexcept
row access
Definition MRMatrix4.h:51
constexpr Vector4< T > col(int i) const noexcept
column access
Definition MRMatrix4.h:55
constexpr Matrix4() noexcept=default
Matrix4 & operator/=(T b)
Definition MRMatrix4.h:87
constexpr const T * data() const
Definition MRMatrix4.h:83
static constexpr Matrix4 identity() noexcept
Definition MRMatrix4.h:42
constexpr Matrix4< T > inverse() const noexcept
computes inverse matrix
Matrix4 & operator-=(const Matrix4< T > &b)
Definition MRMatrix4.h:85
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:149
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