Ark Server API (ASA) - Wiki
Loading...
Searching...
No Matches
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
12UE_DECLARE_LWC_TYPE(BasisVectorMatrix, 44);
13UE_DECLARE_LWC_TYPE(LookAtMatrix, 44);
14struct FMath;
15
16namespace UE
17{
18namespace Math
19{
20
21/**
22 * TMatrix inline functions.
23 */
24
25 // Constructors.
26template<typename T>
28{
29}
30
31template<typename T>
32FORCEINLINE TMatrix<T>::TMatrix(const TPlane<T>& InX, const TPlane<T>& InY, const TPlane<T>& InZ, const TPlane<T>& InW)
33{
34 M[0][0] = InX.X; M[0][1] = InX.Y; M[0][2] = InX.Z; M[0][3] = InX.W;
35 M[1][0] = InY.X; M[1][1] = InY.Y; M[1][2] = InY.Z; M[1][3] = InY.W;
36 M[2][0] = InZ.X; M[2][1] = InZ.Y; M[2][2] = InZ.Z; M[2][3] = InZ.W;
37 M[3][0] = InW.X; M[3][1] = InW.Y; M[3][2] = InW.Z; M[3][3] = InW.W;
39}
40
41template<typename T>
42FORCEINLINE TMatrix<T>::TMatrix(const TVector<T>& InX, const TVector<T>& InY, const TVector<T>& InZ, const TVector<T>& InW)
43{
44 M[0][0] = InX.X; M[0][1] = InX.Y; M[0][2] = InX.Z; M[0][3] = 0.0f;
45 M[1][0] = InY.X; M[1][1] = InY.Y; M[1][2] = InY.Z; M[1][3] = 0.0f;
46 M[2][0] = InZ.X; M[2][1] = InZ.Y; M[2][2] = InZ.Z; M[2][3] = 0.0f;
47 M[3][0] = InW.X; M[3][1] = InW.Y; M[3][2] = InW.Z; M[3][3] = 1.0f;
49}
50
51
52template<typename T>
53inline void TMatrix<T>::SetIdentity()
54{
55 M[0][0] = 1; M[0][1] = 0; M[0][2] = 0; M[0][3] = 0;
56 M[1][0] = 0; M[1][1] = 1; M[1][2] = 0; M[1][3] = 0;
57 M[2][0] = 0; M[2][1] = 0; M[2][2] = 1; M[2][3] = 0;
58 M[3][0] = 0; M[3][1] = 0; M[3][2] = 0; M[3][3] = 1;
59}
60
61
62template<typename T>
64{
65 VectorMatrixMultiply(this, this, &Other);
67}
68
69
70template<typename T>
72{
76 return Result;
77}
78
79
80template<typename T>
82{
84
85 for (int32 X = 0; X < 4; X++)
86 {
87 ResultMat.M[X][0] = M[X][0] + Other.M[X][0];
88 ResultMat.M[X][1] = M[X][1] + Other.M[X][1];
89 ResultMat.M[X][2] = M[X][2] + Other.M[X][2];
90 ResultMat.M[X][3] = M[X][3] + Other.M[X][3];
91 }
92
94 return ResultMat;
95}
96
97template<typename T>
99{
100 *this = *this + Other;
102}
103
104template<typename T>
106{
108
109 for (int32 X = 0; X < 4; X++)
110 {
111 ResultMat.M[X][0] = M[X][0] * Other;
112 ResultMat.M[X][1] = M[X][1] * Other;
113 ResultMat.M[X][2] = M[X][2] * Other;
114 ResultMat.M[X][3] = M[X][3] * Other;
115 }
116
118 return ResultMat;
119}
120
121template<typename T>
123{
124 *this = *this * Other;
126}
127
128// Comparison operators.
129
130template<typename T>
131inline bool TMatrix<T>::operator==(const TMatrix<T>& Other) const
132{
133 for (int32 X = 0; X < 4; X++)
134 {
135 for (int32 Y = 0; Y < 4; Y++)
136 {
137 if (M[X][Y] != Other.M[X][Y])
138 {
139 return false;
140 }
141 }
142 }
143
144 return true;
145}
146
147// Error-tolerant comparison.
148template<typename T>
149inline bool TMatrix<T>::Equals(const TMatrix<T>& Other, T Tolerance/*=KINDA_SMALL_NUMBER*/) const
150{
151 for (int32 X = 0; X < 4; X++)
152 {
153 for (int32 Y = 0; Y < 4; Y++)
154 {
155 if (FMath::Abs(M[X][Y] - Other.M[X][Y]) > Tolerance)
156 {
157 return false;
158 }
159 }
160 }
161
162 return true;
163}
164
165template<typename T>
166inline bool TMatrix<T>::operator!=(const TMatrix<T>& Other) const
167{
168 return !(*this == Other);
169}
170
171
172// Homogeneous transform.
173
174template<typename T>
176{
181 return Result;
182}
183
184
185// Transform position
186
187/** Transform a location - will take into account translation part of the TMatrix<T>. */
188template<typename T>
190{
191 return TransformFVector4(TVector4<T>(V.X, V.Y, V.Z, 1.0f));
192}
193
194/** Inverts the matrix and then transforms V - correctly handles scaling in this matrix. */
195template<typename T>
197{
198 TMatrix<T> InvSelf = this->InverseFast();
200}
201
202// Transform vector
203
204/**
205 * Transform a direction vector - will not take into account translation part of the TMatrix<T>.
206 * If you want to transform a surface normal (or plane) and correctly account for non-uniform scaling you should use TransformByUsingAdjointT.
207 */
208template<typename T>
210{
211 return TransformFVector4(TVector4<T>(V.X, V.Y, V.Z, 0.0f));
212}
213
214/** Faster version of InverseTransformVector that assumes no scaling. WARNING: Will NOT work correctly if there is scaling in the matrix. */
215template<typename T>
217{
218 TMatrix<T> InvSelf = this->InverseFast();
219 return InvSelf.TransformVector(V);
220}
221
222
223// Transpose.
224
225template<typename T>
227{
229
230 Result.M[0][0] = M[0][0];
231 Result.M[0][1] = M[1][0];
232 Result.M[0][2] = M[2][0];
233 Result.M[0][3] = M[3][0];
234
235 Result.M[1][0] = M[0][1];
236 Result.M[1][1] = M[1][1];
237 Result.M[1][2] = M[2][1];
238 Result.M[1][3] = M[3][1];
239
240 Result.M[2][0] = M[0][2];
241 Result.M[2][1] = M[1][2];
242 Result.M[2][2] = M[2][2];
243 Result.M[2][3] = M[3][2];
244
245 Result.M[3][0] = M[0][3];
246 Result.M[3][1] = M[1][3];
247 Result.M[3][2] = M[2][3];
248 Result.M[3][3] = M[3][3];
249
250 return Result;
251}
252
253// Determinant.
254
255template<typename T>
256inline T TMatrix<T>::Determinant() const
257{
258 return M[0][0] * (
259 M[1][1] * (M[2][2] * M[3][3] - M[2][3] * M[3][2]) -
260 M[2][1] * (M[1][2] * M[3][3] - M[1][3] * M[3][2]) +
261 M[3][1] * (M[1][2] * M[2][3] - M[1][3] * M[2][2])
262 ) -
263 M[1][0] * (
264 M[0][1] * (M[2][2] * M[3][3] - M[2][3] * M[3][2]) -
265 M[2][1] * (M[0][2] * M[3][3] - M[0][3] * M[3][2]) +
266 M[3][1] * (M[0][2] * M[2][3] - M[0][3] * M[2][2])
267 ) +
268 M[2][0] * (
269 M[0][1] * (M[1][2] * M[3][3] - M[1][3] * M[3][2]) -
270 M[1][1] * (M[0][2] * M[3][3] - M[0][3] * M[3][2]) +
271 M[3][1] * (M[0][2] * M[1][3] - M[0][3] * M[1][2])
272 ) -
273 M[3][0] * (
274 M[0][1] * (M[1][2] * M[2][3] - M[1][3] * M[2][2]) -
275 M[1][1] * (M[0][2] * M[2][3] - M[0][3] * M[2][2]) +
276 M[2][1] * (M[0][2] * M[1][3] - M[0][3] * M[1][2])
277 );
278}
279
280/** Calculate determinant of rotation 3x3 matrix */
281template<typename T>
282inline T TMatrix<T>::RotDeterminant() const
283{
284 return
285 M[0][0] * (M[1][1] * M[2][2] - M[1][2] * M[2][1]) -
286 M[1][0] * (M[0][1] * M[2][2] - M[0][2] * M[2][1]) +
287 M[2][0] * (M[0][1] * M[1][2] - M[0][2] * M[1][1]);
288}
289
290// Inverse.
291/** Fast path, doesn't check for nil matrices in final release builds */
292template<typename T>
293inline TMatrix<T> TMatrix<T>::InverseFast() const
294{
295 // If we're in non final release, then make sure we're not creating NaNs
297 // Check for zero scale matrix to invert
301 {
302 ErrorEnsure(TEXT("TMatrix<T>::InverseFast(), trying to invert a NIL matrix, this results in NaNs! Use Inverse() instead."));
303 }
304 else
305 {
306 const T Det = Determinant();
307
308 if (Det == 0.0f || !FMath::IsFinite(Det))
309 {
310 ErrorEnsure(TEXT("TMatrix<T>::InverseFast(), trying to invert a non-invertible matrix, this results in NaNs! Use Inverse() instead."));
311 }
312 }
313#endif
317 return Result;
318}
319
320// Inverse.
321template<typename T>
322inline TMatrix<T> TMatrix<T>::Inverse() const
323{
325
326 // Check for zero scale matrix to invert
330 {
331 // just set to zero - avoids unsafe inverse of zero and duplicates what QNANs were resulting in before (scaling away all children)
333 }
334 else
335 {
336 const T Det = Determinant();
337
338 if (Det == 0.0f)
339 {
341 }
342 else
343 {
345 }
346 }
347
349 return Result;
350}
351
352template<typename T>
354{
355 TMatrix<T> TA;
356
357 TA.M[0][0] = this->M[1][1] * this->M[2][2] - this->M[1][2] * this->M[2][1];
358 TA.M[0][1] = this->M[1][2] * this->M[2][0] - this->M[1][0] * this->M[2][2];
359 TA.M[0][2] = this->M[1][0] * this->M[2][1] - this->M[1][1] * this->M[2][0];
360 TA.M[0][3] = 0.f;
361
362 TA.M[1][0] = this->M[2][1] * this->M[0][2] - this->M[2][2] * this->M[0][1];
363 TA.M[1][1] = this->M[2][2] * this->M[0][0] - this->M[2][0] * this->M[0][2];
364 TA.M[1][2] = this->M[2][0] * this->M[0][1] - this->M[2][1] * this->M[0][0];
365 TA.M[1][3] = 0.f;
366
367 TA.M[2][0] = this->M[0][1] * this->M[1][2] - this->M[0][2] * this->M[1][1];
368 TA.M[2][1] = this->M[0][2] * this->M[1][0] - this->M[0][0] * this->M[1][2];
369 TA.M[2][2] = this->M[0][0] * this->M[1][1] - this->M[0][1] * this->M[1][0];
370 TA.M[2][3] = 0.f;
371
372 TA.M[3][0] = 0.f;
373 TA.M[3][1] = 0.f;
374 TA.M[3][2] = 0.f;
375 TA.M[3][3] = 1.f;
376
378 return TA;
379}
380
381// NOTE: There is some compiler optimization issues with WIN64 that cause FORCEINLINE to cause a crash
382// Remove any scaling from this matrix (ie magnitude of each row is 1)
383template<typename T>
384inline void TMatrix<T>::RemoveScaling(T Tolerance/*=UE_SMALL_NUMBER*/)
385{
386 // For each row, find magnitude, and if its non-zero re-scale so its unit length.
387 const T SquareSum0 = (M[0][0] * M[0][0]) + (M[0][1] * M[0][1]) + (M[0][2] * M[0][2]);
388 const T SquareSum1 = (M[1][0] * M[1][0]) + (M[1][1] * M[1][1]) + (M[1][2] * M[1][2]);
389 const T SquareSum2 = (M[2][0] * M[2][0]) + (M[2][1] * M[2][1]) + (M[2][2] * M[2][2]);
393 M[0][0] *= Scale0;
394 M[0][1] *= Scale0;
395 M[0][2] *= Scale0;
396 M[1][0] *= Scale1;
397 M[1][1] *= Scale1;
398 M[1][2] *= Scale1;
399 M[2][0] *= Scale2;
400 M[2][1] *= Scale2;
401 M[2][2] *= Scale2;
403}
404
405// Returns matrix without scale information
406template<typename T>
407inline TMatrix<T> TMatrix<T>::GetMatrixWithoutScale(T Tolerance/*=UE_SMALL_NUMBER*/) const
408{
409 TMatrix<T> Result = (TMatrix<T>&)*this;
411 return Result;
412}
413
414/** Remove any scaling from this matrix (ie magnitude of each row is 1) and return the 3D scale vector that was initially present. */
415template<typename T>
416inline TVector<T> TMatrix<T>::ExtractScaling(T Tolerance/*=UE_SMALL_NUMBER*/)
417{
418 TVector<T> Scale3D(0, 0, 0);
419
420 // For each row, find magnitude, and if its non-zero re-scale so its unit length.
421 const T SquareSum0 = (M[0][0] * M[0][0]) + (M[0][1] * M[0][1]) + (M[0][2] * M[0][2]);
422 const T SquareSum1 = (M[1][0] * M[1][0]) + (M[1][1] * M[1][1]) + (M[1][2] * M[1][2]);
423 const T SquareSum2 = (M[2][0] * M[2][0]) + (M[2][1] * M[2][1]) + (M[2][2] * M[2][2]);
424
425 if (SquareSum0 > Tolerance)
426 {
428 Scale3D[0] = Scale0;
429 T InvScale0 = 1.f / Scale0;
430 M[0][0] *= InvScale0;
431 M[0][1] *= InvScale0;
432 M[0][2] *= InvScale0;
433 }
434 else
435 {
436 Scale3D[0] = 0;
437 }
438
439 if (SquareSum1 > Tolerance)
440 {
442 Scale3D[1] = Scale1;
443 T InvScale1 = 1.f / Scale1;
444 M[1][0] *= InvScale1;
445 M[1][1] *= InvScale1;
446 M[1][2] *= InvScale1;
447 }
448 else
449 {
450 Scale3D[1] = 0;
451 }
452
453 if (SquareSum2 > Tolerance)
454 {
456 Scale3D[2] = Scale2;
457 T InvScale2 = 1.f / Scale2;
458 M[2][0] *= InvScale2;
459 M[2][1] *= InvScale2;
460 M[2][2] *= InvScale2;
461 }
462 else
463 {
464 Scale3D[2] = 0;
465 }
466
467 return Scale3D;
468}
469
470/** return a 3D scale vector calculated from this matrix (where each component is the magnitude of a row vector). */
471template<typename T>
472inline TVector<T> TMatrix<T>::GetScaleVector(T Tolerance/*=UE_SMALL_NUMBER*/) const
473{
474 TVector<T> Scale3D(1, 1, 1);
475
476 // For each row, find magnitude, and if its non-zero re-scale so its unit length.
477 for (int32 i = 0; i < 3; i++)
478 {
479 const T SquareSum = (M[i][0] * M[i][0]) + (M[i][1] * M[i][1]) + (M[i][2] * M[i][2]);
480 if (SquareSum > Tolerance)
481 {
483 }
484 else
485 {
486 Scale3D[i] = 0.f;
487 }
488 }
489
490 return Scale3D;
491}
492// Remove any translation from this matrix
493template<typename T>
495{
496 TMatrix<T> Result = (TMatrix<T>&)*this;
497 Result.M[3][0] = 0.0f;
498 Result.M[3][1] = 0.0f;
499 Result.M[3][2] = 0.0f;
500 return Result;
501}
502
503template<typename T>
505{
507
508 T* RESTRICT Dest = &Result.M[0][0];
509 const T* RESTRICT Src = &M[0][0];
510 const T* RESTRICT Trans = &Translation.X;
511
512 Dest[0] = Src[0];
513 Dest[1] = Src[1];
514 Dest[2] = Src[2];
515 Dest[3] = Src[3];
516 Dest[4] = Src[4];
517 Dest[5] = Src[5];
518 Dest[6] = Src[6];
519 Dest[7] = Src[7];
520 Dest[8] = Src[8];
521 Dest[9] = Src[9];
522 Dest[10] = Src[10];
523 Dest[11] = Src[11];
524 Dest[12] = Src[12] + Trans[0];
525 Dest[13] = Src[13] + Trans[1];
526 Dest[14] = Src[14] + Trans[2];
527 Dest[15] = Src[15];
528
530 return Result;
531}
532
533/** Returns true if any element of this matrix is not finite */
534template<typename T>
535inline bool TMatrix<T>::ContainsNaN() const
536{
537 for (int32 i = 0; i < 4; i++)
538 {
539 for (int32 j = 0; j < 4; j++)
540 {
541 if (!FMath::IsFinite(M[i][j]))
542 {
543 return true;
544 }
545 }
546 }
547
548 return false;
549}
550
551/** @return the minimum magnitude of any row of the matrix. */
552template<typename T>
554{
555 const T MaxRowScaleSquared = FMath::Min(
557 FMath::Min(
560 )
561 );
563}
564
565/** @return the maximum magnitude of any row of the matrix. */
566template<typename T>
568{
569 const T MaxRowScaleSquared = FMath::Max(
571 FMath::Max(
574 )
575 );
577}
578
579template<typename T>
581{
582 M[3][0] *= InScale3D.X;
583 M[3][1] *= InScale3D.Y;
584 M[3][2] *= InScale3D.Z;
585}
586
587// GetOrigin
588
589template<typename T>
590inline TVector<T> TMatrix<T>::GetOrigin() const
591{
592 return TVector<T>(M[3][0], M[3][1], M[3][2]);
593}
594
595template<typename T>
597{
598 switch (InAxis)
599 {
600 case EAxis::X:
601 return TVector<T>(M[0][0], M[0][1], M[0][2]);
602
603 case EAxis::Y:
604 return TVector<T>(M[1][0], M[1][1], M[1][2]);
605
606 case EAxis::Z:
607 return TVector<T>(M[2][0], M[2][1], M[2][2]);
608
609 default:
610 ensure(0);
611 return TVector<T>::ZeroVector;
612 }
613}
614
615template<typename T>
616inline void TMatrix<T>::GetScaledAxes(TVector<T>& X, TVector<T>& Y, TVector<T>& Z) const
617{
618 X.X = M[0][0]; X.Y = M[0][1]; X.Z = M[0][2];
619 Y.X = M[1][0]; Y.Y = M[1][1]; Y.Z = M[1][2];
620 Z.X = M[2][0]; Z.Y = M[2][1]; Z.Z = M[2][2];
621}
622
623template<typename T>
625{
627}
628
629template<typename T>
630inline void TMatrix<T>::GetUnitAxes(TVector<T>& X, TVector<T>& Y, TVector<T>& Z) const
631{
632 GetScaledAxes(X, Y, Z);
633 X.Normalize();
634 Y.Normalize();
635 Z.Normalize();
636}
637
638template<typename T>
639inline void TMatrix<T>::SetAxis(int32 i, const TVector<T>& Axis)
640{
641 checkSlow(i >= 0 && i <= 2);
642 M[i][0] = Axis.X;
643 M[i][1] = Axis.Y;
644 M[i][2] = Axis.Z;
646}
647
648template<typename T>
649inline void TMatrix<T>::SetOrigin(const TVector<T>& NewOrigin)
650{
651 M[3][0] = NewOrigin.X;
652 M[3][1] = NewOrigin.Y;
653 M[3][2] = NewOrigin.Z;
655}
656
657template<typename T>
658inline void TMatrix<T>::SetAxes(const TVector<T>* Axis0 /*= NULL*/, const TVector<T>* Axis1 /*= NULL*/, const TVector<T>* Axis2 /*= NULL*/, const TVector<T>* Origin /*= NULL*/)
659{
660 if (Axis0 != NULL)
661 {
662 M[0][0] = Axis0->X;
663 M[0][1] = Axis0->Y;
664 M[0][2] = Axis0->Z;
665 }
666 if (Axis1 != NULL)
667 {
668 M[1][0] = Axis1->X;
669 M[1][1] = Axis1->Y;
670 M[1][2] = Axis1->Z;
671 }
672 if (Axis2 != NULL)
673 {
674 M[2][0] = Axis2->X;
675 M[2][1] = Axis2->Y;
676 M[2][2] = Axis2->Z;
677 }
678 if (Origin != NULL)
679 {
680 M[3][0] = Origin->X;
681 M[3][1] = Origin->Y;
682 M[3][2] = Origin->Z;
683 }
685}
686
687template<typename T>
689{
690 checkSlow(i >= 0 && i <= 3);
691 return TVector<T>(M[0][i], M[1][i], M[2][i]);
692}
693
694template<typename T>
696{
697 checkSlow(i >= 0 && i <= 3);
698 M[0][i] = Value.X;
699 M[1][i] = Value.Y;
700 M[2][i] = Value.Z;
701}
702
703template <typename T>
705{
706 const T LengthSquared = A * A + B * B + C * C;
708 {
711 return 1;
712 }
713 else
714 return 0;
715}
716
717// Frustum plane extraction. Assumes reverse Z. Near is depth == 1. Far is depth == 0.
718template<typename T>
720{
721 return MakeFrustumPlane(
722 M[0][3] - M[0][2],
723 M[1][3] - M[1][2],
724 M[2][3] - M[2][2],
725 M[3][3] - M[3][2],
727 );
728}
729
730template<typename T>
732{
733 return MakeFrustumPlane(
734 M[0][2],
735 M[1][2],
736 M[2][2],
737 M[3][2],
739 );
740}
741
742template<typename T>
744{
745 return MakeFrustumPlane(
746 M[0][3] + M[0][0],
747 M[1][3] + M[1][0],
748 M[2][3] + M[2][0],
749 M[3][3] + M[3][0],
751 );
752}
753
754template<typename T>
756{
757 return MakeFrustumPlane(
758 M[0][3] - M[0][0],
759 M[1][3] - M[1][0],
760 M[2][3] - M[2][0],
761 M[3][3] - M[3][0],
763 );
764}
765
766template<typename T>
768{
769 return MakeFrustumPlane(
770 M[0][3] - M[0][1],
771 M[1][3] - M[1][1],
772 M[2][3] - M[2][1],
773 M[3][3] - M[3][1],
775 );
776}
777
778template<typename T>
780{
781 return MakeFrustumPlane(
782 M[0][3] + M[0][1],
783 M[1][3] + M[1][1],
784 M[2][3] + M[2][1],
785 M[3][3] + M[3][1],
787 );
788}
789
790/**
791 * Utility for mirroring this transform across a certain plane,
792 * and flipping one of the axis as well.
793 */
794template<typename T>
796{
797 if (MirrorAxis == EAxis::X)
798 {
799 M[0][0] *= -1.f;
800 M[1][0] *= -1.f;
801 M[2][0] *= -1.f;
802
803 M[3][0] *= -1.f;
804 }
805 else if (MirrorAxis == EAxis::Y)
806 {
807 M[0][1] *= -1.f;
808 M[1][1] *= -1.f;
809 M[2][1] *= -1.f;
810
811 M[3][1] *= -1.f;
812 }
813 else if (MirrorAxis == EAxis::Z)
814 {
815 M[0][2] *= -1.f;
816 M[1][2] *= -1.f;
817 M[2][2] *= -1.f;
818
819 M[3][2] *= -1.f;
820 }
821
822 if (FlipAxis == EAxis::X)
823 {
824 M[0][0] *= -1.f;
825 M[0][1] *= -1.f;
826 M[0][2] *= -1.f;
827 }
828 else if (FlipAxis == EAxis::Y)
829 {
830 M[1][0] *= -1.f;
831 M[1][1] *= -1.f;
832 M[1][2] *= -1.f;
833 }
834 else if (FlipAxis == EAxis::Z)
835 {
836 M[2][0] *= -1.f;
837 M[2][1] *= -1.f;
838 M[2][2] *= -1.f;
839 }
840}
841
842/**
843 * Apply Scale to this matrix
844 */
845template<typename T>
847{
849 TPlane<T>(Scale, 0.0f, 0.0f, 0.0f),
850 TPlane<T>(0.0f, Scale, 0.0f, 0.0f),
851 TPlane<T>(0.0f, 0.0f, Scale, 0.0f),
852 TPlane<T>(0.0f, 0.0f, 0.0f, 1.0f)
853 );
854 return ScaleMatrix * ((TMatrix<T>&)*this);
855}
856
857
858/**
859 * TPlane inline functions.
860 */
861
862template<typename T>
863inline TPlane<T> TPlane<T>::TransformBy(const TMatrix<T>& M) const
864{
865 const TMatrix<T> tmpTA = M.TransposeAdjoint();
866 const T DetM = M.Determinant();
867 return this->TransformByUsingAdjointT(M, DetM, tmpTA);
868}
869
870template<typename T>
871inline TPlane<T> UE::Math::TPlane<T>::TransformByUsingAdjointT(const TMatrix<T>& M, T DetM, const TMatrix<T>& TA) const
872{
874
875 if (DetM < 0.f)
876 {
877 newNorm *= -1.0f;
878 }
879
880 return TPlane<T>(M.TransformPosition(*this * W), newNorm);
881}
882
883/**
884* TMatrix variation inline functions.
885*/
886
887template<typename T>
889{
890 for(uint32 RowIndex = 0;RowIndex < 3;RowIndex++)
891 {
892 M[RowIndex][0] = (&XAxis.X)[RowIndex];
893 M[RowIndex][1] = (&YAxis.X)[RowIndex];
894 M[RowIndex][2] = (&ZAxis.X)[RowIndex];
895 M[RowIndex][3] = 0.0f;
896 }
897 M[3][0] = Origin | XAxis;
898 M[3][1] = Origin | YAxis;
899 M[3][2] = Origin | ZAxis;
900 M[3][3] = 1.0f;
901 this->DiagnosticCheckNaN();
902}
903
904
905template<typename T>
907{
909 const TVector<T> XAxis = (UpVector ^ ZAxis).GetSafeNormal();
910 const TVector<T> YAxis = ZAxis ^ XAxis;
911
912 for (uint32 RowIndex = 0; RowIndex < 3; RowIndex++)
913 {
914 M[RowIndex][0] = (&XAxis.X)[RowIndex];
915 M[RowIndex][1] = (&YAxis.X)[RowIndex];
916 M[RowIndex][2] = (&ZAxis.X)[RowIndex];
917 M[RowIndex][3] = 0.0f;
918 }
919 M[3][0] = -EyePosition | XAxis;
920 M[3][1] = -EyePosition | YAxis;
921 M[3][2] = -EyePosition | ZAxis;
922 M[3][3] = 1.0f;
923 this->DiagnosticCheckNaN();
924}
925
926
927template<typename T>
930{
931}
932
933
934} // namespace UE::Core
935} // namespace UE
936
937template<>
938inline bool FMatrix44f::SerializeFromMismatchedTag(FName StructTag, FArchive& Ar)
939{
940 return UE_SERIALIZE_VARIANT_FROM_MISMATCHED_TAG(Ar, Matrix, Matrix44f, Matrix44d);
941}
942
943template<>
944inline bool FMatrix44d::SerializeFromMismatchedTag(FName StructTag, FArchive& Ar)
945{
946 return UE_SERIALIZE_VARIANT_FROM_MISMATCHED_TAG(Ar, Matrix, Matrix44d, Matrix44f);
947}
#define UE_BUILD_TEST
Definition Build.h:23
#define UE_BUILD_SHIPPING
Definition Build.h:4
#define UE_DECLARE_LWC_TYPE(...)
#define FORCEINLINE
Definition Platform.h:644
#define RESTRICT
Definition Platform.h:650
Definition Vector.h:40