MeshLib C++ Docs
Loading...
Searching...
No Matches
MRMatrix4.h
Go to the documentation of this file.
1#pragma once
2
3#include "MRMacros.h"
4#include "MRVector4.h"
5#include <cassert>
6#include <iosfwd>
7#include <limits>
8
9namespace MR
10{
13
14
15#ifdef _MSC_VER
16#pragma warning(push)
17#pragma warning(disable: 4804)
18#pragma warning(disable: 4146)
19#endif
20
23template <typename T>
24struct Matrix4
25{
26 using ValueType = T;
28
30 Vector4<T> x{ 1, 0, 0, 0 };
31 Vector4<T> y{ 0, 1, 0, 0 };
32 Vector4<T> z{ 0, 0, 1, 0 };
33 Vector4<T> w{ 0, 0, 0, 1 };
34
35 constexpr Matrix4() noexcept
36 {
37 static_assert( sizeof( Matrix4<ValueType> ) == 4 * sizeof( VectorType ), "Struct size invalid" );
38 }
39
40 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 ) { }
41
43 constexpr Matrix4( const Matrix3<T>& r, const Vector3<T>& t )
44 {
45 x = Vector4<T>( r.x.x, r.x.y, r.x.z, t.x );
46 y = Vector4<T>( r.y.x, r.y.y, r.y.z, t.y );
47 z = Vector4<T>( r.z.x, r.z.y, r.z.z, t.z );
48 w = Vector4<T>( 0, 0, 0, 1 );
49 }
50
53 constexpr Matrix4( const AffineXf3OrPlaceholder<T>& xf ) MR_REQUIRES_IF_SUPPORTED( std::floating_point<T> ) : Matrix4( xf.A, xf.b ) {}
54
57 template <typename U> MR_REQUIRES_IF_SUPPORTED( !std::is_same_v<T, U> )
58 constexpr explicit Matrix4( const Matrix4<U> & m ) : x( m.x ), y( m.y ), z( m.z ), w( m.w ) { }
59
60 static constexpr Matrix4 zero() noexcept { return Matrix4( Vector4<T>(), Vector4<T>(), Vector4<T>(), Vector4<T>() ); }
61 static constexpr Matrix4 identity() noexcept { return Matrix4(); }
63 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 } ); }
64
66 constexpr const T& operator ()( int row, int col ) const noexcept { return operator[]( row )[col]; }
67 constexpr T& operator ()( int row, int col ) noexcept { return operator[]( row )[col]; }
68
70 constexpr const Vector4<T> & operator []( int row ) const noexcept { return *( ( VectorType* )this + row ); }
71 constexpr Vector4<T> & operator []( int row ) noexcept { return *( ( VectorType* )this + row ); }
72
74 constexpr Vector4<T> col( int i ) const noexcept { return { x[i], y[i], z[i], w[i] }; }
75
77 constexpr T trace() const noexcept { return x.x + y.y + z.z + w.w; }
79 constexpr T normSq() const noexcept { return x.lengthSq() + y.lengthSq() + z.lengthSq() + w.lengthSq(); }
80 constexpr auto norm() const noexcept
81 {
84 using std::sqrt;
85 return sqrt( normSq() );
86 }
87
88 Matrix3<T> submatrix3( int i, int j ) const noexcept;
90 T det() const noexcept;
92 constexpr Matrix4<T> inverse() const noexcept MR_REQUIRES_IF_SUPPORTED( !std::is_integral_v<T> );
94 constexpr Matrix4<T> transposed() const noexcept;
95
96 constexpr Matrix3<T> getRotation() const noexcept;
97 void setRotation( const Matrix3<T>& rot) noexcept;
98 constexpr Vector3<T> getTranslation() const noexcept;
99 void setTranslation( const Vector3<T>& t ) noexcept;
100
101 constexpr T* data() { return (T*) (&x); };
102 constexpr const T* data() const { return (T*) (&x); };
103
104 operator AffineXf3OrPlaceholder<T>() const MR_REQUIRES_IF_SUPPORTED( std::floating_point<T> )
105 {
106 assert( std::abs( w.x ) < std::numeric_limits<T>::epsilon() * 1000 );
107 assert( std::abs( w.y ) < std::numeric_limits<T>::epsilon() * 1000 );
108 assert( std::abs( w.z ) < std::numeric_limits<T>::epsilon() * 1000 );
109 assert( std::abs( 1 - w.w ) < std::numeric_limits<T>::epsilon() * 1000 );
110 AffineXf3<T> res;
111 res.A.x.x = x.x; res.A.x.y = x.y; res.A.x.z = x.z; res.b.x = x.w;
112 res.A.y.x = y.x; res.A.y.y = y.y; res.A.y.z = y.z; res.b.y = y.w;
113 res.A.z.x = z.x; res.A.z.y = z.y; res.A.z.z = z.z; res.b.z = z.w;
114 return res;
115 }
116
119 Vector3<T> operator ()( const Vector3<T> & b ) const MR_REQUIRES_IF_SUPPORTED( !std::is_integral_v<T> );
120
121 [[nodiscard]] friend constexpr bool operator ==( const Matrix4<T> & a, const Matrix4<T> & b ) { return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w; }
122 [[nodiscard]] friend constexpr bool operator !=( const Matrix4<T> & a, const Matrix4<T> & b ) { return !( a == b ); }
123
125
126 [[nodiscard]] friend constexpr auto operator +( const Matrix4<T> & a, const Matrix4<T> & b ) -> Matrix4<decltype( std::declval<T>() + std::declval<T>() )> { return { a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w }; }
127 [[nodiscard]] friend constexpr auto operator -( const Matrix4<T> & a, const Matrix4<T> & b ) -> Matrix4<decltype( std::declval<T>() - std::declval<T>() )> { return { a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w }; }
128 [[nodiscard]] friend constexpr auto operator *( T a, const Matrix4<T> & b ) -> Matrix4<decltype( std::declval<T>() * std::declval<T>() )> { return { a * b.x, a * b.y, a * b.z, a * b.w }; }
129 [[nodiscard]] friend constexpr auto operator *( const Matrix4<T> & b, T a ) -> Matrix4<decltype( std::declval<T>() * std::declval<T>() )> { return { a * b.x, a * b.y, a * b.z, a * b.z }; }
130 [[nodiscard]] friend constexpr auto operator /( Matrix4<T> b, T a ) -> Matrix4<decltype( std::declval<T>() / std::declval<T>() )>
131 {
132 if constexpr ( std::is_integral_v<T> )
133 return { b.x / a, b.y / a, b.z / a, b.w / a };
134 else
135 return b * ( 1 / a );
136 }
137
138 friend constexpr Matrix4<T> & operator +=( Matrix4<T> & a, const Matrix4<T> & b ) { a.x += b.x; a.y += b.y; a.z += b.z; a.w += b.w; return a; }
139 friend constexpr Matrix4<T> & operator -=( Matrix4<T> & a, const Matrix4<T> & b ) { a.x -= b.x; a.y -= b.y; a.z -= b.z; a.w -= b.w; return a; }
140 friend constexpr Matrix4<T> & operator *=( Matrix4<T> & a, T b ) { a.x *= b; a.y *= b; a.z *= b; a.w *= b; return a; }
141 friend constexpr Matrix4<T> & operator /=( Matrix4<T> & a, T b )
142 {
143 if constexpr ( std::is_integral_v<T> )
144 { a.x /= b; a.y /= b; a.z /= b; a.w /= b; return a; }
145 else
146 return a *= ( 1 / b );
147 }
148
150 [[nodiscard]] friend constexpr auto operator *( const Matrix4<T> & a, const Vector4<T> & b ) -> Vector4<decltype( dot( std::declval<Vector4<T>>(), std::declval<Vector4<T>>() ) )>
151 {
152 return { dot( a.x, b ), dot( a.y, b ), dot( a.z, b ), dot( a.w, b ) };
153 }
154
156 [[nodiscard]] friend constexpr auto operator *( const Matrix4<T> & a, const Matrix4<T> & b ) -> Matrix4<decltype( dot( std::declval<Vector4<T>>(), std::declval<Vector4<T>>() ) )>
157 {
158 Matrix4<decltype( dot( std::declval<Vector4<T>>(), std::declval<Vector4<T>>() ) )> res;
159 for ( int i = 0; i < 4; ++i )
160 for ( int j = 0; j < 4; ++j )
161 res[i][j] = dot( a[i], b.col(j) );
162 return res;
163 }
164
165 friend std::ostream& operator<<( std::ostream& s, const Matrix4& mat )
166 {
167 return s << mat.x << '\n' << mat.y << '\n' << mat.z << '\n' << mat.w << '\n';
168 }
169
170 friend std::istream& operator>>( std::istream& s, Matrix4& mat )
171 {
172 return s >> mat.x >> mat.y >> mat.z >> mat.w;
173 }
174};
175
178
180template <typename T>
181inline auto dot( const Matrix4<T> & a, const Matrix4<T> & b ) -> decltype( dot( a.x, b.x ) )
182{
183 return dot( a.x, b.x ) + dot( a.y, b.y ) + dot( a.z, b.z ) + dot( a.w, b.w );
184}
185
186template <typename T>
187inline Vector3<T> Matrix4<T>::operator ()( const Vector3<T> & b ) const MR_REQUIRES_IF_SUPPORTED( !std::is_integral_v<T> )
188{
189 return ( *this * Vector4<T>{ b.x, b.y, b.z, T(1) } ).proj3d();
190}
191
193template <typename T>
194inline Matrix4<T> outer( const Vector4<T> & a, const Vector4<T> & b )
195{
196 return { a.x * b, a.y * b, a.z * b, a.w * b };
197}
198
199template <typename T>
200Matrix3<T> Matrix4<T>::submatrix3( int i, int j ) const noexcept
201{
202 Matrix3<T> res;
203 int nrow = 0;
204 for ( int m = 0; m < 4; m++ )
205 {
206 if ( m == i )
207 continue;
208 auto & row = res[nrow++];
209 int ncol = 0;
210 for ( int n = 0; n < 4; n++ )
211 {
212 if ( n == j )
213 continue;
214 row[ncol++] = ( *this )[m][n];
215 }
216 assert( ncol == 3 );
217 }
218 assert( nrow == 3 );
219 return res;
220}
221
222template <typename T>
223T Matrix4<T>::det() const noexcept
224{
225 return
226 x.x * submatrix3( 0, 0 ).det()
227 - x.y * submatrix3( 0, 1 ).det()
228 + x.z * submatrix3( 0, 2 ).det()
229 - x.w * submatrix3( 0, 3 ).det();
230}
231
232template <typename T>
233constexpr Matrix4<T> Matrix4<T>::transposed() const noexcept
234{
235 return Matrix4<T>
236 {
237 { x.x, y.x, z.x, w.x },
238 { x.y, y.y, z.y, w.y },
239 { x.z, y.z, z.z, w.z },
240 { x.w, y.w, z.w, w.w },
241 };
242}
243
244template <typename T>
245constexpr Matrix4<T> Matrix4<T>::inverse() const noexcept MR_REQUIRES_IF_SUPPORTED( !std::is_integral_v<T> )
246{
247 Matrix4<T> inv;
248 T* m = (T*) (&x);
249 T det;
250
251 inv[0][0] = m[5] * m[10] * m[15] -
252 m[5] * m[11] * m[14] -
253 m[9] * m[6] * m[15] +
254 m[9] * m[7] * m[14] +
255 m[13] * m[6] * m[11] -
256 m[13] * m[7] * m[10];
257
258 inv[1][0] = -m[4] * m[10] * m[15] +
259 m[4] * m[11] * m[14] +
260 m[8] * m[6] * m[15] -
261 m[8] * m[7] * m[14] -
262 m[12] * m[6] * m[11] +
263 m[12] * m[7] * m[10];
264
265 inv[2][0] = m[4] * m[9] * m[15] -
266 m[4] * m[11] * m[13] -
267 m[8] * m[5] * m[15] +
268 m[8] * m[7] * m[13] +
269 m[12] * m[5] * m[11] -
270 m[12] * m[7] * m[9];
271
272 inv[3][0] = -m[4] * m[9] * m[14] +
273 m[4] * m[10] * m[13] +
274 m[8] * m[5] * m[14] -
275 m[8] * m[6] * m[13] -
276 m[12] * m[5] * m[10] +
277 m[12] * m[6] * m[9];
278
279 inv[0][1] = -m[1] * m[10] * m[15] +
280 m[1] * m[11] * m[14] +
281 m[9] * m[2] * m[15] -
282 m[9] * m[3] * m[14] -
283 m[13] * m[2] * m[11] +
284 m[13] * m[3] * m[10];
285
286 inv[1][1] = m[0] * m[10] * m[15] -
287 m[0] * m[11] * m[14] -
288 m[8] * m[2] * m[15] +
289 m[8] * m[3] * m[14] +
290 m[12] * m[2] * m[11] -
291 m[12] * m[3] * m[10];
292
293 inv[2][1] = -m[0] * m[9] * m[15] +
294 m[0] * m[11] * m[13] +
295 m[8] * m[1] * m[15] -
296 m[8] * m[3] * m[13] -
297 m[12] * m[1] * m[11] +
298 m[12] * m[3] * m[9];
299
300 inv[3][1] = m[0] * m[9] * m[14] -
301 m[0] * m[10] * m[13] -
302 m[8] * m[1] * m[14] +
303 m[8] * m[2] * m[13] +
304 m[12] * m[1] * m[10] -
305 m[12] * m[2] * m[9];
306
307 inv[0][2] = m[1] * m[6] * m[15] -
308 m[1] * m[7] * m[14] -
309 m[5] * m[2] * m[15] +
310 m[5] * m[3] * m[14] +
311 m[13] * m[2] * m[7] -
312 m[13] * m[3] * m[6];
313
314 inv[1][2] = -m[0] * m[6] * m[15] +
315 m[0] * m[7] * m[14] +
316 m[4] * m[2] * m[15] -
317 m[4] * m[3] * m[14] -
318 m[12] * m[2] * m[7] +
319 m[12] * m[3] * m[6];
320
321 inv[2][2] = m[0] * m[5] * m[15] -
322 m[0] * m[7] * m[13] -
323 m[4] * m[1] * m[15] +
324 m[4] * m[3] * m[13] +
325 m[12] * m[1] * m[7] -
326 m[12] * m[3] * m[5];
327
328 inv[3][2] = -m[0] * m[5] * m[14] +
329 m[0] * m[6] * m[13] +
330 m[4] * m[1] * m[14] -
331 m[4] * m[2] * m[13] -
332 m[12] * m[1] * m[6] +
333 m[12] * m[2] * m[5];
334
335 inv[0][3] = -m[1] * m[6] * m[11] +
336 m[1] * m[7] * m[10] +
337 m[5] * m[2] * m[11] -
338 m[5] * m[3] * m[10] -
339 m[9] * m[2] * m[7] +
340 m[9] * m[3] * m[6];
341
342 inv[1][3] = m[0] * m[6] * m[11] -
343 m[0] * m[7] * m[10] -
344 m[4] * m[2] * m[11] +
345 m[4] * m[3] * m[10] +
346 m[8] * m[2] * m[7] -
347 m[8] * m[3] * m[6];
348
349 inv[2][3] = -m[0] * m[5] * m[11] +
350 m[0] * m[7] * m[9] +
351 m[4] * m[1] * m[11] -
352 m[4] * m[3] * m[9] -
353 m[8] * m[1] * m[7] +
354 m[8] * m[3] * m[5];
355
356 inv[3][3] = m[0] * m[5] * m[10] -
357 m[0] * m[6] * m[9] -
358 m[4] * m[1] * m[10] +
359 m[4] * m[2] * m[9] +
360 m[8] * m[1] * m[6] -
361 m[8] * m[2] * m[5];
362
363 det = m[0] * inv[0][0] + m[1] * inv[1][0] + m[2] * inv[2][0] + m[3] * inv[3][0];
364
365 if( det == 0 )
366 {
368 assert( false );
369 return Matrix4<T>();
370 }
371
372 inv /= det;
373
374 return inv;
375}
376
377template <typename T>
378constexpr Matrix3<T> Matrix4<T>::getRotation() const noexcept
379{
380 return Matrix3<T>
381 {
382 { x.x, x.y, x.z },
383 { y.x, y.y, y.z },
384 { z.x, z.y, z.z }
385 };
386}
387
388template <typename T>
389void Matrix4<T>::setRotation( const Matrix3<T>& rot ) noexcept
390{
391 x.x = rot.x.x; x.y = rot.x.y; x.z = rot.x.z;
392 y.x = rot.y.x; y.y = rot.y.y; y.z = rot.y.z;
393 z.x = rot.z.x; z.y = rot.z.y; z.z = rot.z.z;
394}
395
396template <typename T>
397constexpr Vector3<T> Matrix4<T>::getTranslation() const noexcept
398{
399 return Vector3<T>{ x.w, y.w, z.w };
400}
401
402template <typename T>
403void Matrix4<T>::setTranslation( const Vector3<T>& t ) noexcept
404{
405 x.w = t.x; y.w = t.y; z.w = t.z;
406}
407
409
410#ifdef _MSC_VER
411#pragma warning(pop)
412#endif
413
414}
#define MR_REQUIRES_IF_SUPPORTED(...)
Definition MRMacros.h:33
T y
Definition MRVector4.h:32
friend constexpr bool operator!=(const Matrix4< T > &a, const Matrix4< T > &b)
Definition MRMatrix4.h:122
T z
Definition MRVector4.h:32
Vector4< T > z
Definition MRMatrix4.h:32
T x
Definition MRVector4.h:32
Vector3< T > operator()(const Vector3< T > &b) const MR_REQUIRES_IF_SUPPORTED(!std friend constexpr bool operator==(const Matrix4< T > &a, const Matrix4< T > &b)
Definition MRMatrix4.h:121
constexpr T * data()
Definition MRMatrix4.h:101
T w
Definition MRVector4.h:32
Vector3< T > x
rows, identity matrix by default
Definition MRMatrix3.h:29
T ValueType
Definition MRMatrix4.h:26
auto dot(const Matrix2< T > &a, const Matrix2< T > &b) -> decltype(dot(a.x, b.x))
double-dot product: x = a : b
Definition MRMatrix2.h:142
T x
Definition MRVector3.h:39
Vector4< T > VectorType
Definition MRMatrix4.h:27
constexpr T trace() const noexcept
computes trace of the matrix
Definition MRMatrix4.h:77
void setTranslation(const Vector3< T > &t) noexcept
T y
Definition MRVector3.h:39
friend constexpr auto operator*(T a, const Matrix4< T > &b) -> Matrix4< decltype(std::declval< T >() *std::declval< T >())>
Definition MRMatrix4.h:128
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:60
constexpr T normSq() const noexcept
compute sum of squared matrix elements
Definition MRMatrix4.h:79
constexpr const T & operator()(int row, int col) const noexcept
element access
Definition MRMatrix4.h:66
Matrix4
Definition MRMeshFwd.h:235
Vector4< T > y
Definition MRMatrix4.h:31
constexpr Matrix4(const AffineXf3OrPlaceholder< T > &xf) MR_REQUIRES_IF_SUPPORTED(std
Definition MRMatrix4.h:53
static constexpr Matrix4 scale(T s) noexcept
returns a matrix that scales uniformly
Definition MRMatrix4.h:63
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:43
friend constexpr auto operator/(Matrix4< T > b, T a) -> Matrix4< decltype(std::declval< T >()/std::declval< T >())>
Definition MRMatrix4.h:130
T det() const noexcept
computes determinant of the matrix
Vector4< T > w
Definition MRMatrix4.h:33
constexpr auto norm() const noexcept
Definition MRMatrix4.h:80
constexpr Matrix4< T > inverse() const noexcept MR_REQUIRES_IF_SUPPORTED(!std constexpr Matrix4< T > transposed() const noexcept
computes inverse matrix
MR_REQUIRES_IF_SUPPORTED(!std::is_same_v< T, U >) const expr explicit Matrix4(const Matrix4< U > &m)
Definition MRMatrix4.h:57
Vector3< T > y
Definition MRMatrix3.h:30
auto dot(const Matrix4< T > &a, const Matrix4< T > &b) -> decltype(dot(a.x, b.x))
double-dot product: x = a : b
Definition MRMatrix4.h:181
constexpr Matrix4() noexcept
Definition MRMatrix4.h:35
friend constexpr auto operator+(const Matrix4< T > &a, const Matrix4< T > &b) -> Matrix4< decltype(std::declval< T >()+std::declval< T >())>
NOTE: We use std::declval() in the operators below because libclang 18 in our binding generator is bu...
Definition MRMatrix4.h:126
constexpr Matrix4(const Vector4< T > &x, const Vector4< T > &y, const Vector4< T > &z, const Vector4< T > &w)
initializes matrix from 4 row-vectors
Definition MRMatrix4.h:40
MRMESH_CLASS Vector4
Definition MRMeshFwd.h:202
constexpr const Vector4< T > & operator[](int row) const noexcept
row access
Definition MRMatrix4.h:70
AffineXf< Vector3< T > > AffineXf3
Definition MRMeshFwd.h:297
friend constexpr Matrix4< T > & operator+=(Matrix4< T > &a, const Matrix4< T > &b)
Definition MRMatrix4.h:138
constexpr Vector4< T > col(int i) const noexcept
column access
Definition MRMatrix4.h:74
friend constexpr Matrix4< T > & operator*=(Matrix4< T > &a, T b)
Definition MRMatrix4.h:140
friend constexpr Matrix4< T > & operator-=(Matrix4< T > &a, const Matrix4< T > &b)
Definition MRMatrix4.h:139
friend constexpr auto operator-(const Matrix4< T > &a, const Matrix4< T > &b) -> Matrix4< decltype(std::declval< T >() - std::declval< T >())>
Definition MRMatrix4.h:127
Vector3< T > z
Definition MRMatrix3.h:31
constexpr const T * data() const
Definition MRMatrix4.h:102
friend std::ostream & operator<<(std::ostream &s, const Matrix4 &mat)
Definition MRMatrix4.h:165
typename detail::AffineXf3f::TypeOrPlaceholder< Vector3< T > >::type AffineXf3OrPlaceholder
Definition MRMeshFwd.h:306
T z
Definition MRVector3.h:39
static constexpr Matrix4 identity() noexcept
Definition MRMatrix4.h:61
friend std::istream & operator>>(std::istream &s, Matrix4 &mat)
Definition MRMatrix4.h:170
friend constexpr Matrix4< T > & operator/=(Matrix4< T > &a, T b)
Definition MRMatrix4.h:141
constexpr Vector3< T > getTranslation() const noexcept
Vector4< T > x
rows, identity matrix by default
Definition MRMatrix4.h:30
Matrix4< T > outer(const Vector4< T > &a, const Vector4< T > &b)
x = a * b^T
Definition MRMatrix4.h:194
MR_REQUIRES_IF_SUPPORTED(detail::AffineXf3f::IsValidTemplateArg< V >) struct AffineXf
Definition MRAffineXf.h:24
only for bindings generation
Definition MRCameraOrientationPlugin.h:8
Definition MRMatrix3.h:24
Definition MRMatrix4.h:25
Definition MRVector3.h:33
Definition MRVector4.h:26