UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
Matrix.inl
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3/*=============================================================================
4 NOTE: This file should ONLY be included by UnrealMath.h!
5=============================================================================*/
6
7#pragma once
8
9#include "CoreTypes.h"
10#include "CoreFwd.h"
11
14struct FMath;
15
16namespace UE
17{
18namespace Math
19{
20
25 // Constructors.
26template<typename T>
27inline TMatrix<T>::TMatrix(const TPlane<T>& InX, const TPlane<T>& InY, const TPlane<T>& InZ, const TPlane<T>& InW)
28{
29 M[0][0] = InX.X; M[0][1] = InX.Y; M[0][2] = InX.Z; M[0][3] = InX.W;
30 M[1][0] = InY.X; M[1][1] = InY.Y; M[1][2] = InY.Z; M[1][3] = InY.W;
31 M[2][0] = InZ.X; M[2][1] = InZ.Y; M[2][2] = InZ.Z; M[2][3] = InZ.W;
32 M[3][0] = InW.X; M[3][1] = InW.Y; M[3][2] = InW.Z; M[3][3] = InW.W;
33 DiagnosticCheckNaN();
34}
35
36template<typename T>
38{
39 M[0][0] = InX.X; M[0][1] = InX.Y; M[0][2] = InX.Z; M[0][3] = 0.0f;
40 M[1][0] = InY.X; M[1][1] = InY.Y; M[1][2] = InY.Z; M[1][3] = 0.0f;
41 M[2][0] = InZ.X; M[2][1] = InZ.Y; M[2][2] = InZ.Z; M[2][3] = 0.0f;
42 M[3][0] = InW.X; M[3][1] = InW.Y; M[3][2] = InW.Z; M[3][3] = 1.0f;
43 DiagnosticCheckNaN();
44}
45
46
47template<typename T>
49{
50 M[0][0] = 1; M[0][1] = 0; M[0][2] = 0; M[0][3] = 0;
51 M[1][0] = 0; M[1][1] = 1; M[1][2] = 0; M[1][3] = 0;
52 M[2][0] = 0; M[2][1] = 0; M[2][2] = 1; M[2][3] = 0;
53 M[3][0] = 0; M[3][1] = 0; M[3][2] = 0; M[3][3] = 1;
54}
55
56
57template<typename T>
59{
60 VectorMatrixMultiply(this, this, &Other);
61 DiagnosticCheckNaN();
62}
63
64
65template<typename T>
67{
68 TMatrix<T> Result;
69 VectorMatrixMultiply(&Result, this, &Other);
70 Result.DiagnosticCheckNaN();
71 return Result;
72}
73
74
75template<typename T>
77{
79
80 for (int32 X = 0; X < 4; X++)
81 {
82 ResultMat.M[X][0] = M[X][0] + Other.M[X][0];
83 ResultMat.M[X][1] = M[X][1] + Other.M[X][1];
84 ResultMat.M[X][2] = M[X][2] + Other.M[X][2];
85 ResultMat.M[X][3] = M[X][3] + Other.M[X][3];
86 }
87
88 ResultMat.DiagnosticCheckNaN();
89 return ResultMat;
91
92template<typename T>
94{
95 *this = *this + Other;
96 DiagnosticCheckNaN();
97}
98
99template<typename T>
101{
104 for (int32 X = 0; X < 4; X++)
105 {
106 ResultMat.M[X][0] = M[X][0] * Other;
107 ResultMat.M[X][1] = M[X][1] * Other;
108 ResultMat.M[X][2] = M[X][2] * Other;
109 ResultMat.M[X][3] = M[X][3] * Other;
110 }
112 ResultMat.DiagnosticCheckNaN();
113 return ResultMat;
114}
115
116template<typename T>
118{
119 *this = *this * Other;
120 DiagnosticCheckNaN();
121}
122
123// Comparison operators.
124
125template<typename T>
126inline bool TMatrix<T>::operator==(const TMatrix<T>& Other) const
128 for (int32 X = 0; X < 4; X++)
129 {
130 for (int32 Y = 0; Y < 4; Y++)
131 {
132 if (M[X][Y] != Other.M[X][Y])
133 {
134 return false;
136 }
137 }
138
139 return true;
141
142// Error-tolerant comparison.
143template<typename T>
144inline bool TMatrix<T>::Equals(const TMatrix<T>& Other, T Tolerance/*=KINDA_SMALL_NUMBER*/) const
145{
146 for (int32 X = 0; X < 4; X++)
147 {
148 for (int32 Y = 0; Y < 4; Y++)
149 {
150 if (FMath::Abs(M[X][Y] - Other.M[X][Y]) > Tolerance)
151 {
152 return false;
153 }
154 }
155 }
157 return true;
158}
159
160template<typename T>
161inline bool TMatrix<T>::operator!=(const TMatrix<T>& Other) const
162{
163 return !(*this == Other);
164}
166
167// Homogeneous transform.
168
169template<typename T>
171{
172 TVector4<T> Result;
175 VectorStoreAligned(VecR, &Result);
176 return Result;
177}
178
180// Transform position
181
183template<typename T>
185{
186 return TransformFVector4(TVector4<T>(V.X, V.Y, V.Z, 1.0f));
187}
190template<typename T>
192{
193 TMatrix<T> InvSelf = this->InverseFast();
194 return InvSelf.TransformPosition(V);
195}
196
197// Transform vector
203template<typename T>
206 return TransformFVector4(TVector4<T>(V.X, V.Y, V.Z, 0.0f));
207}
210template<typename T>
212{
213 TMatrix<T> InvSelf = this->InverseFast();
214 return InvSelf.TransformVector(V);
215}
216
218// Transpose.
219
220template<typename T>
222{
224
225 Result.M[0][0] = M[0][0];
226 Result.M[0][1] = M[1][0];
227 Result.M[0][2] = M[2][0];
228 Result.M[0][3] = M[3][0];
230 Result.M[1][0] = M[0][1];
231 Result.M[1][1] = M[1][1];
232 Result.M[1][2] = M[2][1];
233 Result.M[1][3] = M[3][1];
234
235 Result.M[2][0] = M[0][2];
236 Result.M[2][1] = M[1][2];
237 Result.M[2][2] = M[2][2];
238 Result.M[2][3] = M[3][2];
239
240 Result.M[3][0] = M[0][3];
241 Result.M[3][1] = M[1][3];
242 Result.M[3][2] = M[2][3];
243 Result.M[3][3] = M[3][3];
245 return Result;
246}
251template<typename T>
252inline void TMatrix<T>::To3x4MatrixTranspose(T* Out) const
253{
254 const T* RESTRICT Src = &(M[0][0]);
255 T* RESTRICT Dest = Out;
256
257 Dest[0] = Src[0]; // [0][0]
258 Dest[1] = Src[4]; // [1][0]
259 Dest[2] = Src[8]; // [2][0]
260 Dest[3] = Src[12]; // [3][0]
261
262 Dest[4] = Src[1]; // [0][1]
263 Dest[5] = Src[5]; // [1][1]
264 Dest[6] = Src[9]; // [2][1]
265 Dest[7] = Src[13]; // [3][1]
266
267 Dest[8] = Src[2]; // [0][2]
268 Dest[9] = Src[6]; // [1][2]
269 Dest[10] = Src[10]; // [2][2]
270 Dest[11] = Src[14]; // [3][2]
271}
272
273template<>
274inline void TMatrix<float>::To3x4MatrixTranspose(float* Out) const
276 const float* RESTRICT Src = &(M[0][0]);
277 float* RESTRICT Dest = Out;
278
279#if PLATFORM_ENABLE_VECTORINTRINSICS
289
290 VectorRegister4Float Row0, Row1, Row2, Row3;
291 VectorDeinterleave(Row0, Row1, Temp0, Temp1);
293
294 VectorStore(Row0, &Dest[0]);
295 VectorStore(Row1, &Dest[4]);
296 VectorStore(Row2, &Dest[8]);
297#else
298 Dest[0] = Src[0]; // [0][0]
299 Dest[1] = Src[4]; // [1][0]
300 Dest[2] = Src[8]; // [2][0]
301 Dest[3] = Src[12]; // [3][0]
302
303 Dest[4] = Src[1]; // [0][1]
304 Dest[5] = Src[5]; // [1][1]
305 Dest[6] = Src[9]; // [2][1]
306 Dest[7] = Src[13]; // [3][1]
307
308 Dest[8] = Src[2]; // [0][2]
309 Dest[9] = Src[6]; // [1][2]
310 Dest[10] = Src[10]; // [2][2]
311 Dest[11] = Src[14]; // [3][2]
312#endif
314
315// Determinant.
316
317template<typename T>
319{
320 return M[0][0] * (
321 M[1][1] * (M[2][2] * M[3][3] - M[2][3] * M[3][2]) -
322 M[2][1] * (M[1][2] * M[3][3] - M[1][3] * M[3][2]) +
323 M[3][1] * (M[1][2] * M[2][3] - M[1][3] * M[2][2])
324 ) -
325 M[1][0] * (
326 M[0][1] * (M[2][2] * M[3][3] - M[2][3] * M[3][2]) -
327 M[2][1] * (M[0][2] * M[3][3] - M[0][3] * M[3][2]) +
328 M[3][1] * (M[0][2] * M[2][3] - M[0][3] * M[2][2])
329 ) +
330 M[2][0] * (
331 M[0][1] * (M[1][2] * M[3][3] - M[1][3] * M[3][2]) -
332 M[1][1] * (M[0][2] * M[3][3] - M[0][3] * M[3][2]) +
333 M[3][1] * (M[0][2] * M[1][3] - M[0][3] * M[1][2])
334 ) -
335 M[3][0] * (
336 M[0][1] * (M[1][2] * M[2][3] - M[1][3] * M[2][2]) -
337 M[1][1] * (M[0][2] * M[2][3] - M[0][3] * M[2][2]) +
338 M[2][1] * (M[0][2] * M[1][3] - M[0][3] * M[1][2])
339 );
341
343template<typename T>
345{
346 return
347 M[0][0] * (M[1][1] * M[2][2] - M[1][2] * M[2][1]) -
348 M[1][0] * (M[0][1] * M[2][2] - M[0][2] * M[2][1]) +
349 M[2][0] * (M[0][1] * M[1][2] - M[0][2] * M[1][1]);
350}
351
352// InverseFast.
353// Unlike Inverse, this may ensure if used on nil/nan matrix in non-final builds
354// should not be used on matrices that may be nil/nan
355// note: not actually faster than Inverse
356template<typename T>
358{
359 // If we're in non final release, then make sure we're not creating NaNs
360#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
361 // Check for zero scale matrix to invert
362 // @todo : remove this axis length check
363 if (GetScaledAxis(EAxis::X).IsNearlyZero(UE_SMALL_NUMBER) &&
364 GetScaledAxis(EAxis::Y).IsNearlyZero(UE_SMALL_NUMBER) &&
365 GetScaledAxis(EAxis::Z).IsNearlyZero(UE_SMALL_NUMBER))
366 {
367 ErrorEnsure(TEXT("TMatrix<T>::InverseFast(), trying to invert a NIL matrix, this results in NaNs! Use Inverse() instead."));
368 }
369#endif
370
371 TMatrix<T> Result;
372 if ( ! VectorMatrixInverse(&Result, this) )
373 {
374#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
375 ErrorEnsure(TEXT("TMatrix<T>::InverseFast(), trying to invert a non-invertible matrix, this results in NaNs! Use Inverse() instead."));
376#endif
377 }
378 Result.DiagnosticCheckNaN(); // <- pointless, VectorMatrixInverse ensures output is valid
379 return Result;
380}
381
382// Inverse. zero & NaN matrices are silently changed to identity
383template<typename T>
385{
386 // Check for zero scale matrix to invert
387 // @todo : remove this axis length check
388 if (GetScaledAxis(EAxis::X).IsNearlyZero(UE_SMALL_NUMBER) &&
389 GetScaledAxis(EAxis::Y).IsNearlyZero(UE_SMALL_NUMBER) &&
390 GetScaledAxis(EAxis::Z).IsNearlyZero(UE_SMALL_NUMBER))
391 {
392 // just set to zero - avoids unsafe inverse of zero and duplicates what QNANs were resulting in before (scaling away all children)
393 return Identity;
394 }
395
396 TMatrix<T> Result;
397 // VectorMatrixInverse will return false and fill identity for non-invertible matrices
398 VectorMatrixInverse(&Result, this);
399 Result.DiagnosticCheckNaN(); // <- pointless, VectorMatrixInverse ensures output is valid
400 return Result;
401}
402
403template<typename T>
405{
407
408 TA.M[0][0] = this->M[1][1] * this->M[2][2] - this->M[1][2] * this->M[2][1];
409 TA.M[0][1] = this->M[1][2] * this->M[2][0] - this->M[1][0] * this->M[2][2];
410 TA.M[0][2] = this->M[1][0] * this->M[2][1] - this->M[1][1] * this->M[2][0];
411 TA.M[0][3] = 0.f;
412
413 TA.M[1][0] = this->M[2][1] * this->M[0][2] - this->M[2][2] * this->M[0][1];
414 TA.M[1][1] = this->M[2][2] * this->M[0][0] - this->M[2][0] * this->M[0][2];
415 TA.M[1][2] = this->M[2][0] * this->M[0][1] - this->M[2][1] * this->M[0][0];
416 TA.M[1][3] = 0.f;
417
418 TA.M[2][0] = this->M[0][1] * this->M[1][2] - this->M[0][2] * this->M[1][1];
419 TA.M[2][1] = this->M[0][2] * this->M[1][0] - this->M[0][0] * this->M[1][2];
420 TA.M[2][2] = this->M[0][0] * this->M[1][1] - this->M[0][1] * this->M[1][0];
421 TA.M[2][3] = 0.f;
422
423 TA.M[3][0] = 0.f;
424 TA.M[3][1] = 0.f;
425 TA.M[3][2] = 0.f;
426 TA.M[3][3] = 1.f;
427
428 TA.DiagnosticCheckNaN();
429 return TA;
430}
431
432// NOTE: There is some compiler optimization issues with WIN64 that cause FORCEINLINE to cause a crash
433// Remove any scaling from this matrix (ie magnitude of each row is 1)
434template<typename T>
435inline void TMatrix<T>::RemoveScaling(T Tolerance/*=UE_SMALL_NUMBER*/)
436{
437 // For each row, find magnitude, and if its non-zero re-scale so its unit length.
438 const T SquareSum0 = (M[0][0] * M[0][0]) + (M[0][1] * M[0][1]) + (M[0][2] * M[0][2]);
439 const T SquareSum1 = (M[1][0] * M[1][0]) + (M[1][1] * M[1][1]) + (M[1][2] * M[1][2]);
440 const T SquareSum2 = (M[2][0] * M[2][0]) + (M[2][1] * M[2][1]) + (M[2][2] * M[2][2]);
441 const T Scale0 = FMath::FloatSelect(SquareSum0 - Tolerance, FMath::InvSqrt(SquareSum0), T(1));
442 const T Scale1 = FMath::FloatSelect(SquareSum1 - Tolerance, FMath::InvSqrt(SquareSum1), T(1));
443 const T Scale2 = FMath::FloatSelect(SquareSum2 - Tolerance, FMath::InvSqrt(SquareSum2), T(1));
444 M[0][0] *= Scale0;
445 M[0][1] *= Scale0;
446 M[0][2] *= Scale0;
447 M[1][0] *= Scale1;
448 M[1][1] *= Scale1;
449 M[1][2] *= Scale1;
450 M[2][0] *= Scale2;
451 M[2][1] *= Scale2;
452 M[2][2] *= Scale2;
453 DiagnosticCheckNaN();
454}
455
456// Returns matrix without scale information
457template<typename T>
458inline TMatrix<T> TMatrix<T>::GetMatrixWithoutScale(T Tolerance/*=UE_SMALL_NUMBER*/) const
459{
460 TMatrix<T> Result = (TMatrix<T>&)*this;
461 Result.RemoveScaling(Tolerance);
462 return Result;
463}
464
466template<typename T>
467inline TVector<T> TMatrix<T>::ExtractScaling(T Tolerance/*=UE_SMALL_NUMBER*/)
468{
469 TVector<T> Scale3D(0, 0, 0);
470
471 // For each row, find magnitude, and if its non-zero re-scale so its unit length.
472 const T SquareSum0 = (M[0][0] * M[0][0]) + (M[0][1] * M[0][1]) + (M[0][2] * M[0][2]);
473 const T SquareSum1 = (M[1][0] * M[1][0]) + (M[1][1] * M[1][1]) + (M[1][2] * M[1][2]);
474 const T SquareSum2 = (M[2][0] * M[2][0]) + (M[2][1] * M[2][1]) + (M[2][2] * M[2][2]);
475
476 if (SquareSum0 > Tolerance)
477 {
478 T Scale0 = FMath::Sqrt(SquareSum0);
479 Scale3D[0] = Scale0;
480 T InvScale0 = 1.f / Scale0;
481 M[0][0] *= InvScale0;
482 M[0][1] *= InvScale0;
483 M[0][2] *= InvScale0;
484 }
485 else
486 {
487 Scale3D[0] = 0;
488 }
489
490 if (SquareSum1 > Tolerance)
491 {
492 T Scale1 = FMath::Sqrt(SquareSum1);
493 Scale3D[1] = Scale1;
494 T InvScale1 = 1.f / Scale1;
495 M[1][0] *= InvScale1;
496 M[1][1] *= InvScale1;
497 M[1][2] *= InvScale1;
498 }
499 else
500 {
501 Scale3D[1] = 0;
502 }
503
504 if (SquareSum2 > Tolerance)
505 {
506 T Scale2 = FMath::Sqrt(SquareSum2);
507 Scale3D[2] = Scale2;
508 T InvScale2 = 1.f / Scale2;
509 M[2][0] *= InvScale2;
510 M[2][1] *= InvScale2;
511 M[2][2] *= InvScale2;
512 }
513 else
514 {
515 Scale3D[2] = 0;
516 }
517
518 return Scale3D;
519}
520
522template<typename T>
523inline TVector<T> TMatrix<T>::GetScaleVector(T Tolerance/*=UE_SMALL_NUMBER*/) const
524{
525 TVector<T> Scale3D(1, 1, 1);
526
527 // For each row, find magnitude, and if its non-zero re-scale so its unit length.
528 for (int32 i = 0; i < 3; i++)
529 {
530 const T SquareSum = (M[i][0] * M[i][0]) + (M[i][1] * M[i][1]) + (M[i][2] * M[i][2]);
531 if (SquareSum > Tolerance)
532 {
533 Scale3D[i] = FMath::Sqrt(SquareSum);
534 }
535 else
536 {
537 Scale3D[i] = 0.f;
538 }
539 }
540
541 return Scale3D;
542}
543// Remove any translation from this matrix
544template<typename T>
546{
547 TMatrix<T> Result = (TMatrix<T>&)*this;
548 Result.M[3][0] = 0.0f;
549 Result.M[3][1] = 0.0f;
550 Result.M[3][2] = 0.0f;
551 return Result;
552}
553
554template<typename T>
556{
557 TMatrix<T> Result;
558
559 T* RESTRICT Dest = &Result.M[0][0];
560 const T* RESTRICT Src = &M[0][0];
561 const T* RESTRICT Trans = &Translation.X;
562
563 Dest[0] = Src[0];
564 Dest[1] = Src[1];
565 Dest[2] = Src[2];
566 Dest[3] = Src[3];
567 Dest[4] = Src[4];
568 Dest[5] = Src[5];
569 Dest[6] = Src[6];
570 Dest[7] = Src[7];
571 Dest[8] = Src[8];
572 Dest[9] = Src[9];
573 Dest[10] = Src[10];
574 Dest[11] = Src[11];
575 Dest[12] = Src[12] + Trans[0];
576 Dest[13] = Src[13] + Trans[1];
577 Dest[14] = Src[14] + Trans[2];
578 Dest[15] = Src[15];
579
580 DiagnosticCheckNaN();
581 return Result;
582}
583
585template<typename T>
586inline bool TMatrix<T>::ContainsNaN() const
587{
588 for (int32 i = 0; i < 4; i++)
589 {
590 for (int32 j = 0; j < 4; j++)
591 {
592 if (!FMath::IsFinite(M[i][j]))
593 {
594 return true;
595 }
596 }
597 }
598
599 return false;
600}
601
603template<typename T>
605{
606 const T MaxRowScaleSquared = FMath::Min(
607 GetScaledAxis(EAxis::X).SizeSquared(),
608 FMath::Min(
609 GetScaledAxis(EAxis::Y).SizeSquared(),
610 GetScaledAxis(EAxis::Z).SizeSquared()
611 )
612 );
613 return FMath::Sqrt(MaxRowScaleSquared);
614}
615
617template<typename T>
619{
620 const T MaxRowScaleSquared = FMath::Max(
621 GetScaledAxis(EAxis::X).SizeSquared(),
622 FMath::Max(
623 GetScaledAxis(EAxis::Y).SizeSquared(),
624 GetScaledAxis(EAxis::Z).SizeSquared()
625 )
626 );
627 return FMath::Sqrt(MaxRowScaleSquared);
628}
629
630template<typename T>
632{
633 M[3][0] *= InScale3D.X;
634 M[3][1] *= InScale3D.Y;
635 M[3][2] *= InScale3D.Z;
636}
637
638// GetOrigin
639
640template<typename T>
642{
643 return TVector<T>(M[3][0], M[3][1], M[3][2]);
644}
645
646template<typename T>
648{
649 switch (InAxis)
650 {
651 case EAxis::X:
652 return TVector<T>(M[0][0], M[0][1], M[0][2]);
653
654 case EAxis::Y:
655 return TVector<T>(M[1][0], M[1][1], M[1][2]);
656
657 case EAxis::Z:
658 return TVector<T>(M[2][0], M[2][1], M[2][2]);
659
660 case EAxis::None:
661 default:
662 ensure(0);
664 }
665}
666
667template<typename T>
669{
670 X.X = M[0][0]; X.Y = M[0][1]; X.Z = M[0][2];
671 Y.X = M[1][0]; Y.Y = M[1][1]; Y.Z = M[1][2];
672 Z.X = M[2][0]; Z.Y = M[2][1]; Z.Z = M[2][2];
673}
674
675template<typename T>
677{
678 return GetScaledAxis(InAxis).GetSafeNormal();
679}
680
681template<typename T>
683{
684 GetScaledAxes(X, Y, Z);
685 X.Normalize();
686 Y.Normalize();
687 Z.Normalize();
688}
689
690template<typename T>
692{
693 checkSlow(i >= 0 && i <= 2);
694 M[i][0] = Axis.X;
695 M[i][1] = Axis.Y;
696 M[i][2] = Axis.Z;
697 DiagnosticCheckNaN();
698}
699
700template<typename T>
701inline void TMatrix<T>::SetOrigin(const TVector<T>& NewOrigin)
702{
703 M[3][0] = NewOrigin.X;
704 M[3][1] = NewOrigin.Y;
705 M[3][2] = NewOrigin.Z;
706 DiagnosticCheckNaN();
707}
708
709template<typename T>
710inline void TMatrix<T>::SetAxes(const TVector<T>* Axis0 /*= NULL*/, const TVector<T>* Axis1 /*= NULL*/, const TVector<T>* Axis2 /*= NULL*/, const TVector<T>* Origin /*= NULL*/)
711{
712 if (Axis0 != NULL)
713 {
714 M[0][0] = Axis0->X;
715 M[0][1] = Axis0->Y;
716 M[0][2] = Axis0->Z;
717 }
718 if (Axis1 != NULL)
719 {
720 M[1][0] = Axis1->X;
721 M[1][1] = Axis1->Y;
722 M[1][2] = Axis1->Z;
723 }
724 if (Axis2 != NULL)
725 {
726 M[2][0] = Axis2->X;
727 M[2][1] = Axis2->Y;
728 M[2][2] = Axis2->Z;
729 }
730 if (Origin != NULL)
731 {
732 M[3][0] = Origin->X;
733 M[3][1] = Origin->Y;
734 M[3][2] = Origin->Z;
735 }
736 DiagnosticCheckNaN();
737}
738
739template<typename T>
741{
742 checkSlow(i >= 0 && i <= 3);
743 return TVector<T>(M[0][i], M[1][i], M[2][i]);
744}
745
746template<typename T>
748{
749 checkSlow(i >= 0 && i <= 3);
750 M[0][i] = Value.X;
751 M[1][i] = Value.Y;
752 M[2][i] = Value.Z;
753}
754
755template <typename T>
756inline bool MakeFrustumPlane(T A, T B, T C, T D, TPlane<T>& OutPlane)
757{
758 const T LengthSquared = A * A + B * B + C * C;
760 {
761 const T InvLength = FMath::InvSqrt(LengthSquared);
762 OutPlane = TPlane<T>(-A * InvLength, -B * InvLength, -C * InvLength, D * InvLength);
763 return 1;
764 }
765 else
766 return 0;
767}
768
769// Frustum plane extraction. Assumes reverse Z. Near is depth == 1. Far is depth == 0.
770template<typename T>
771inline bool TMatrix<T>::GetFrustumNearPlane(TPlane<T>& OutPlane) const
772{
773 return MakeFrustumPlane(
774 M[0][3] - M[0][2],
775 M[1][3] - M[1][2],
776 M[2][3] - M[2][2],
777 M[3][3] - M[3][2],
778 OutPlane
779 );
780}
781
782template<typename T>
783inline bool TMatrix<T>::GetFrustumFarPlane(TPlane<T>& OutPlane) const
784{
785 return MakeFrustumPlane(
786 M[0][2],
787 M[1][2],
788 M[2][2],
789 M[3][2],
790 OutPlane
791 );
792}
793
794template<typename T>
795inline bool TMatrix<T>::GetFrustumLeftPlane(TPlane<T>& OutPlane) const
796{
797 return MakeFrustumPlane(
798 M[0][3] + M[0][0],
799 M[1][3] + M[1][0],
800 M[2][3] + M[2][0],
801 M[3][3] + M[3][0],
802 OutPlane
803 );
804}
805
806template<typename T>
807inline bool TMatrix<T>::GetFrustumRightPlane(TPlane<T>& OutPlane) const
808{
809 return MakeFrustumPlane(
810 M[0][3] - M[0][0],
811 M[1][3] - M[1][0],
812 M[2][3] - M[2][0],
813 M[3][3] - M[3][0],
814 OutPlane
815 );
816}
817
818template<typename T>
819inline bool TMatrix<T>::GetFrustumTopPlane(TPlane<T>& OutPlane) const
820{
821 return MakeFrustumPlane(
822 M[0][3] - M[0][1],
823 M[1][3] - M[1][1],
824 M[2][3] - M[2][1],
825 M[3][3] - M[3][1],
826 OutPlane
827 );
828}
829
830template<typename T>
832{
833 return MakeFrustumPlane(
834 M[0][3] + M[0][1],
835 M[1][3] + M[1][1],
836 M[2][3] + M[2][1],
837 M[3][3] + M[3][1],
838 OutPlane
839 );
840}
841
846template<typename T>
847inline void TMatrix<T>::Mirror(EAxis::Type MirrorAxis, EAxis::Type FlipAxis)
848{
849 if (MirrorAxis == EAxis::X)
850 {
851 M[0][0] *= -1.f;
852 M[1][0] *= -1.f;
853 M[2][0] *= -1.f;
854
855 M[3][0] *= -1.f;
856 }
857 else if (MirrorAxis == EAxis::Y)
858 {
859 M[0][1] *= -1.f;
860 M[1][1] *= -1.f;
861 M[2][1] *= -1.f;
862
863 M[3][1] *= -1.f;
864 }
865 else if (MirrorAxis == EAxis::Z)
866 {
867 M[0][2] *= -1.f;
868 M[1][2] *= -1.f;
869 M[2][2] *= -1.f;
870
871 M[3][2] *= -1.f;
872 }
873
874 if (FlipAxis == EAxis::X)
875 {
876 M[0][0] *= -1.f;
877 M[0][1] *= -1.f;
878 M[0][2] *= -1.f;
879 }
880 else if (FlipAxis == EAxis::Y)
881 {
882 M[1][0] *= -1.f;
883 M[1][1] *= -1.f;
884 M[1][2] *= -1.f;
885 }
886 else if (FlipAxis == EAxis::Z)
887 {
888 M[2][0] *= -1.f;
889 M[2][1] *= -1.f;
890 M[2][2] *= -1.f;
891 }
892}
893
897template<typename T>
899{
901 TPlane<T>(Scale, 0.0f, 0.0f, 0.0f),
902 TPlane<T>(0.0f, Scale, 0.0f, 0.0f),
903 TPlane<T>(0.0f, 0.0f, Scale, 0.0f),
904 TPlane<T>(0.0f, 0.0f, 0.0f, 1.0f)
905 );
906 return ScaleMatrix * ((TMatrix<T>&)*this);
907}
908
909
914template<typename T>
916{
918 const T DetM = M.Determinant();
919 return this->TransformByUsingAdjointT(M, DetM, tmpTA);
920}
921
922template<typename T>
924{
925 TVector<T> newNorm = TA.TransformVector(*this).GetSafeNormal();
926
927 if (DetM < 0.f)
928 {
929 newNorm *= -1.0f;
930 }
931
932 return TPlane<T>(M.TransformPosition(*this * W), newNorm);
933}
934
939template<typename T>
940inline TBasisVectorMatrix<T>::TBasisVectorMatrix(const TVector<T>& XAxis,const TVector<T>& YAxis,const TVector<T>& ZAxis,const TVector<T>& Origin)
941{
942 for(uint32 RowIndex = 0;RowIndex < 3;RowIndex++)
943 {
944 M[RowIndex][0] = (&XAxis.X)[RowIndex];
945 M[RowIndex][1] = (&YAxis.X)[RowIndex];
946 M[RowIndex][2] = (&ZAxis.X)[RowIndex];
947 M[RowIndex][3] = 0.0f;
948 }
949 M[3][0] = Origin | XAxis;
950 M[3][1] = Origin | YAxis;
951 M[3][2] = Origin | ZAxis;
952 M[3][3] = 1.0f;
953 this->DiagnosticCheckNaN();
954}
955
956
957template<typename T>
959{
960 const TVector<T> ZAxis = LookDirection.GetSafeNormal();
961 const TVector<T> XAxis = (UpVector ^ ZAxis).GetSafeNormal();
962 const TVector<T> YAxis = ZAxis ^ XAxis;
963
964 for (uint32 RowIndex = 0; RowIndex < 3; RowIndex++)
965 {
966 M[RowIndex][0] = (&XAxis.X)[RowIndex];
967 M[RowIndex][1] = (&YAxis.X)[RowIndex];
968 M[RowIndex][2] = (&ZAxis.X)[RowIndex];
969 M[RowIndex][3] = 0.0f;
970 }
971 M[3][0] = -EyePosition | XAxis;
972 M[3][1] = -EyePosition | YAxis;
973 M[3][2] = -EyePosition | ZAxis;
974 M[3][3] = 1.0f;
975 this->DiagnosticCheckNaN();
976}
977
978
979template<typename T>
984
985
986} // namespace UE::Core
987} // namespace UE
#define NULL
Definition oodle2base.h:134
#define checkSlow(expr)
Definition AssertionMacros.h:332
#define ensure( InExpression)
Definition AssertionMacros.h:464
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define UE_FORCEINLINE_HINT
Definition Platform.h:723
#define RESTRICT
Definition Platform.h:706
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define X(Name, Desc)
Definition FormatStringSan.h:47
#define UE_DECLARE_LWC_TYPE(...)
Definition LargeWorldCoordinates.h:27
FORCEINLINE void VectorDeinterleave(VectorRegister4Float &RESTRICT OutEvens, VectorRegister4Float &RESTRICT OutOdds, const VectorRegister4Float &RESTRICT Lo, const VectorRegister4Float &RESTRICT Hi)
Definition UnrealMathFPU.h:1777
FORCEINLINE bool VectorMatrixInverse(FMatrix44d *DstMatrix, const FMatrix44d *SrcMatrix)
Definition UnrealMathFPU.h:1603
FORCEINLINE VectorRegister4Float VectorCombineLow(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:1757
FORCEINLINE void VectorMatrixMultiply(FMatrix44d *Result, const FMatrix44d *Matrix1, const FMatrix44d *Matrix2)
Definition UnrealMathFPU.h:1538
VectorRegister4Float VectorLoadAligned(const float *Ptr)
Definition UnrealMathFPU.h:451
FORCEINLINE void VectorStore(const VectorRegister4Float &Vec, float *Dst)
Definition UnrealMathFPU.h:566
FORCEINLINE VectorRegister4Float VectorTransformVector(const VectorRegister4Float &VecP, const FMatrix44f *MatrixM)
Definition UnrealMathFPU.h:1619
FORCEINLINE VectorRegister4Float VectorCombineHigh(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:1740
void VectorStoreAligned(const VectorRegister4Float &Vec, float *Ptr)
Definition UnrealMathFPU.h:534
FORCEINLINE VectorRegister4Float VectorLoad(const float *Ptr)
Definition UnrealMathFPU.h:394
#define UE_SMALL_NUMBER
Definition UnrealMathUtility.h:130
#define UE_DELTA
Definition UnrealMathUtility.h:186
typename UE::Math::VectorRegisterPrivate::TVectorRegisterTypeHelper< T >::Type TVectorRegisterType
Definition VectorRegister.h:49
uint32_t uint32
Definition binka_ue_file_header.h:6
Type
Definition Axis.h:11
@ Z
Definition Axis.h:15
@ Y
Definition Axis.h:14
@ X
Definition Axis.h:13
@ None
Definition Axis.h:12
bool MakeFrustumPlane(T A, T B, T C, T D, TPlane< T > &OutPlane)
Definition Matrix.inl:756
Definition AdvancedWidgetsModule.cpp:13
Definition UnrealMathUtility.h:270
TBasisVectorMatrix(const TVector< T > &XAxis, const TVector< T > &YAxis, const TVector< T > &ZAxis, const TVector< T > &Origin)
Definition Matrix.inl:940
TLookAtMatrix(const TVector< T > &EyePosition, const TVector< T > &LookAtPosition, const TVector< T > &UpVector)
Definition Matrix.inl:980
Definition Matrix.h:549
TLookFromMatrix(const TVector< T > &EyePosition, const TVector< T > &LookDirection, const TVector< T > &UpVector)
Definition Matrix.inl:958
Definition Matrix.h:43
void SetColumn(int32 i, TVector< T > Value)
Definition Matrix.inl:747
TMatrix< T > Inverse() const
Definition Matrix.inl:384
TVector4< T > TransformPosition(const TVector< T > &V) const
Definition Matrix.inl:184
TVector4< T > TransformVector(const TVector< T > &V) const
Definition Matrix.inl:204
T GetMinimumAxisScale() const
Definition Matrix.inl:604
TMatrix< T > TransposeAdjoint() const
Definition Matrix.inl:404
TMatrix< T > operator+(const TMatrix< T > &Other) const
Definition Matrix.inl:76
T M[4][4]
Definition Matrix.h:49
bool GetFrustumBottomPlane(TPlane< T > &OuTPln) const
Definition Matrix.inl:831
void To3x4MatrixTranspose(T *Out) const
Definition Matrix.inl:252
TVector< T > GetUnitAxis(EAxis::Type Axis) const
Definition Matrix.inl:676
bool GetFrustumLeftPlane(TPlane< T > &OuTPln) const
Definition Matrix.inl:795
TVector< T > GetColumn(int32 i) const
Definition Matrix.inl:740
bool operator!=(const TMatrix< T > &Other) const
Definition Matrix.inl:161
TVector< T > InverseTransformVector(const TVector< T > &V) const
Definition Matrix.inl:211
bool GetFrustumNearPlane(TPlane< T > &OuTPln) const
Definition Matrix.inl:771
TMatrix< T > ApplyScale(T Scale) const
Definition Matrix.inl:898
TMatrix< T > GetMatrixWithoutScale(T Tolerance=UE_SMALL_NUMBER) const
Definition Matrix.inl:458
T GetMaximumAxisScale() const
Definition Matrix.inl:618
bool GetFrustumFarPlane(TPlane< T > &OuTPln) const
Definition Matrix.inl:783
void Mirror(EAxis::Type MirrorAxis, EAxis::Type FlipAxis)
Definition Matrix.inl:847
TVector< T > ExtractScaling(T Tolerance=UE_SMALL_NUMBER)
Definition Matrix.inl:467
bool ContainsNaN() const
Definition Matrix.inl:586
bool GetFrustumRightPlane(TPlane< T > &OuTPln) const
Definition Matrix.inl:807
TMatrix< T > ConcatTranslation(const TVector< T > &Translation) const
Definition Matrix.inl:555
TVector< T > GetScaleVector(T Tolerance=UE_SMALL_NUMBER) const
Definition Matrix.inl:523
TMatrix< T > RemoveTranslation() const
Definition Matrix.inl:545
bool Equals(const TMatrix< T > &Other, T Tolerance=UE_KINDA_SMALL_NUMBER) const
Definition Matrix.inl:144
TMatrix< T > GetTransposed() const
Definition Matrix.inl:221
void SetIdentity()
Definition Matrix.inl:48
TVector< T > GetScaledAxis(EAxis::Type Axis) const
Definition Matrix.inl:647
bool GetFrustumTopPlane(TPlane< T > &OuTPln) const
Definition Matrix.inl:819
void GetUnitAxes(TVector< T > &X, TVector< T > &Y, TVector< T > &Z) const
Definition Matrix.inl:682
TMatrix< T > InverseFast() const
Definition Matrix.inl:357
TVector4< T > TransformFVector4(const TVector4< T > &V) const
Definition Matrix.inl:170
void GetScaledAxes(TVector< T > &X, TVector< T > &Y, TVector< T > &Z) const
Definition Matrix.inl:668
void operator+=(const TMatrix< T > &Other)
Definition Matrix.inl:93
void SetAxis(int32 i, const TVector< T > &Axis)
Definition Matrix.inl:691
bool operator==(const TMatrix< T > &Other) const
Definition Matrix.inl:126
TVector< T > GetOrigin() const
Definition Matrix.inl:641
T Determinant() const
Definition Matrix.inl:318
void ScaleTranslation(const TVector< T > &Scale3D)
Definition Matrix.inl:631
void RemoveScaling(T Tolerance=UE_SMALL_NUMBER)
Definition Matrix.inl:435
void operator*=(const TMatrix< T > &Other)
Definition Matrix.inl:58
TMatrix< T > operator*(const TMatrix< T > &Other) const
Definition Matrix.inl:66
TVector< T > InverseTransformPosition(const TVector< T > &V) const
Definition Matrix.inl:191
void SetOrigin(const TVector< T > &NewOrigin)
Definition Matrix.inl:701
void SetAxes(const TVector< T > *Axis0=NULL, const TVector< T > *Axis1=NULL, const TVector< T > *Axis2=NULL, const TVector< T > *Origin=NULL)
Definition Matrix.inl:710
T RotDeterminant() const
Definition Matrix.inl:344
Definition Plane.h:35
TPlane< T > TransformByUsingAdjointT(const TMatrix< T > &M, T DetM, const TMatrix< T > &TA) const
Definition Matrix.inl:923
TPlane< T > TransformBy(const TMatrix< T > &M) const
Definition Matrix.inl:915
Definition Vector4.h:30
Definition Vector.h:51
T Z
Definition Vector.h:68
T Y
Definition Vector.h:65
T X
Definition Vector.h:62
TVector< T > GetSafeNormal(T Tolerance=UE_SMALL_NUMBER, const TVector< T > &ResultIfZero=ZeroVector) const
Definition Vector.h:2060
Definition UnrealMathFPU.h:20