UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
Transform.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
4#include "Chaos/Real.h"
5#include "Chaos/Matrix.h"
6#include "Chaos/Rotation.h"
7#include "Chaos/Vector.h"
8
9#if !COMPILE_WITHOUT_UNREAL_SUPPORT
10#include "Math/Transform.h"
11#else
12//TODO(mlentine): If we use this class in engine we need to make it more efficient.
13struct _FTransform
14{
15public:
16 _FTransform() {}
19 {
20 }
22 {
23 MTranslation[0] = Matrix.M[0][3];
24 MTranslation[1] = Matrix.M[1][3];
25 MTranslation[2] = Matrix.M[2][3];
26
27 Chaos::FReal angle = sqrt(Matrix.M[0][0] * Matrix.M[0][0] + Matrix.M[1][0] * Matrix.M[1][0]);
28 if (angle > 1e-6)
29 {
30 MRotation[0] = atan2(Matrix.M[2][1], Matrix.M[2][2]);
31 MRotation[1] = atan2(-Matrix.M[2][0], angle);
32 MRotation[2] = atan2(Matrix.M[1][0], Matrix.M[0][0]);
33 }
34 else
35 {
36 MRotation[0] = atan2(-Matrix.M[1][2], Matrix.M[1][1]);
37 MRotation[1] = atan2(-Matrix.M[2][0], angle);
38 MRotation[2] = 0;
39 }
40 }
43 {
44 }
46 {
50 }
52 {
56 }
58 {
62 }
63 Chaos::TVector<float, 3> InverseTransformVector(const Chaos::TVector<float, 3>& Vector)
64 {
68 }
69 Chaos::PMatrix<Chaos::FReal, 3, 3> ToRotationMatrix()
70 {
72 cos(MRotation[0]), sin(MRotation[0]), 0,
73 -sin(MRotation[0]), cos(MRotation[0]), 0,
74 0, 0, 1) *
76 cos(MRotation[1]), 0, -sin(MRotation[1]),
77 0, 1, 0,
78 sin(MRotation[1]), 0, cos(MRotation[1])) *
80 1, 0, 0,
81 0, cos(MRotation[2]), sin(MRotation[2]),
82 0, -sin(MRotation[2]), cos(MRotation[2]));
83 }
85 {
86 auto RotationMatrix = ToRotationMatrix();
88 RotationMatrix.M[0][0], RotationMatrix.M[1][0], RotationMatrix.M[2][0], 0,
89 RotationMatrix.M[0][1], RotationMatrix.M[1][1], RotationMatrix.M[2][1], 0,
90 RotationMatrix.M[0][2], RotationMatrix.M[1][2], RotationMatrix.M[2][2], 0,
92 }
94 {
95 auto RotationMatrix = ToRotationMatrix().GetTransposed();
96 auto Vector = (RotationMatrix * MTranslation) * -1;
98 RotationMatrix.M[0][0], RotationMatrix.M[1][0], RotationMatrix.M[2][0], 0,
99 RotationMatrix.M[0][1], RotationMatrix.M[1][1], RotationMatrix.M[2][1], 0,
100 RotationMatrix.M[0][2], RotationMatrix.M[1][2], RotationMatrix.M[2][2], 0,
101 Vector[0], Vector[1], Vector[2], 1);
102 }
103
104private:
107};
108using FTransform = _FTransform; // Work around include tool not understanding that this can't be compiled alongside MathFwd.h
109#endif
110
111namespace Chaos
112{
113 template<class T, int d>
115 {
116 private:
117 TRigidTransform() {}
119 };
120
121 template<>
146
147 template<>
148 class TRigidTransform<FRealSingle, 3> : public UE::Math::TTransform<FRealSingle>
149 {
151 public:
166 template<typename OtherType>
168 : BaseTransform(TRotation<FRealSingle, 3>(Other.GetRotation()), TVector<FRealSingle, 3>(Other.GetTranslation())) {}
169
171 {
172 return BaseTransform::Inverse();
173 }
174
176 {
177 return BaseTransform::ToMatrixWithScale();
178 }
179
181 {
182 return BaseTransform::ToMatrixNoScale();
183 }
184
186
188 {
189 return BaseTransform::operator*(Other);
190 }
191
192 // Get the transform which maps from Other to This, ignoring the scale on both.
194 {
195#if ENABLE_VECTORIZED_TRANSFORM
196 // A * B(-1) = VQS(B)(-1) (VQS (A))
197 //
198 // Rotation = Q(B)(-1) * Q(A)
199 // Translation = [Q(B)(-1)*(T(A)-T(B))*Q(B)]
200 // where A = this, B = Other
201
202 //VQTranslation = ( ( T(A).X - T(B).X ), ( T(A).Y - T(B).Y ), ( T(A).Z - T(B).Z), 0.f );
204
205 // Inverse RotatedTranslation
208
209 // Rotation = Q(B)(-1) * Q(A)
211
213#else
214 // @todo(chaos): optimize
215 TRotation<FRealSingle, 3> OtherInverse = Other.GetRotation().Inverse();
217 (OtherInverse * (GetTranslation() - Other.GetTranslation())),
218 OtherInverse * GetRotation());
219#endif
220 }
221
223 {
224 return TransformVectorNoScale(Normal);
225 }
226
227 // Transform the normal when scale may be non-unitary. Assumes no scale components are zero.
229 {
230 const TVector<FRealSingle, 3> ScaledNormal = Normal / GetScale3D();
231 const FRealSingle ScaledNormal2 = ScaledNormal.SizeSquared();
233 {
234 return TransformNormalNoScale(ScaledNormal * FMath::InvSqrt(ScaledNormal2));
235 }
236 else
237 {
238 return TransformNormalNoScale(Normal);
239 }
240 }
241
242 // Transform the normal when scale may be non-unitary.
244 {
245 // Apply inverse scaling without a per-component divide (conceptually, by scaling the normal by an extra det*sign(det))
246 const TVector<FRealSingle, 3>& S = GetScale3D();
247 FRealSingle DetSign = (S.X * S.Y * S.Z) < 0 ? (FRealSingle)-1 : (FRealSingle)1;
248 const TVector<FRealSingle, 3> SafeInvS(S.Y * S.Z * DetSign, S.X * S.Z * DetSign, S.X * S.Y * DetSign);
250 const FRealSingle ScaledNormalLengthSq = ScaledNormal.SizeSquared();
251 // If inverse scaling would not zero the normal, normalize it and rotate
253 {
254 return TransformVectorNoScale(ScaledNormal * FMath::InvSqrt(ScaledNormalLengthSq));
255 }
256 // Otherwise just rotate without scaling
257 else
258 {
259 return TransformVectorNoScale(Normal);
260 }
261 }
262
267 {
269
270#if ENABLE_VECTORIZED_TRANSFORM
271 const TransformVectorRegister QuatA = A.Rotation;
272 const TransformVectorRegister QuatB = B.Rotation;
273 const TransformVectorRegister TranslateA = A.Translation;
274 const TransformVectorRegister TranslateB = B.Translation;
275
279
280 Result.Rotation = Rotation;
281 Result.Translation = Translation;
282 Result.Scale3D = VectorOne();
283#else
284 Result.Rotation = B.Rotation * A.Rotation;
285 Result.Translation = B.Rotation * A.Translation + B.Translation;
286 Result.Scale3D = FVector3f::OneVector;
287#endif
288
289 return Result;
290 }
291
293 {
294 return HashCombine(GetTypeHash(InTransform.GetTranslation()), HashCombine(GetTypeHash(InTransform.GetRotation().Euler()), GetTypeHash(InTransform.GetScale3D())));
295 }
296 };
297
298 template<>
299 class TRigidTransform<FRealDouble, 3> : public UE::Math::TTransform<FRealDouble>
300 {
302 public:
317 template<typename OtherType>
319 : BaseTransform(TRotation<FRealDouble, 3>(Other.GetRotation()), TVector<FRealDouble, 3>(Other.GetTranslation())) {}
320
322 {
323 return BaseTransform::Inverse();
324 }
325
327 {
328 return BaseTransform::ToMatrixWithScale();
329 }
330
332 {
333 return BaseTransform::ToMatrixNoScale();
334 }
335
337
339 {
340 return BaseTransform::operator*(Other);
341 }
342
343 // Get the transform which maps from Other to This, ignoring the scale on both.
345 {
346#if ENABLE_VECTORIZED_TRANSFORM
347 // A * B(-1) = VQS(B)(-1) (VQS (A))
348 //
349 // Rotation = Q(B)(-1) * Q(A)
350 // Translation = [Q(B)(-1)*(T(A)-T(B))*Q(B)]
351 // where A = this, B = Other
352
353 //VQTranslation = ( ( T(A).X - T(B).X ), ( T(A).Y - T(B).Y ), ( T(A).Z - T(B).Z), 0.f );
355
356 // Inverse RotatedTranslation
359
360 // Rotation = Q(B)(-1) * Q(A)
362
364#else
365 // @todo(chaos): optimize
366 TRotation<FRealDouble, 3> OtherInverse = Other.GetRotation().Inverse();
368 (OtherInverse * (GetTranslation() - Other.GetTranslation())),
369 OtherInverse * GetRotation());
370#endif
371 }
372
374 {
375 return TransformVectorNoScale(Normal);
376 }
377
378 // Transform the normal when scale may be non-unitary. Assumes no scale components are zero.
380 {
381 const TVector<FRealDouble, 3> ScaledNormal = Normal / GetScale3D();
382 const FRealDouble ScaledNormal2 = ScaledNormal.SizeSquared();
384 {
385 return TransformNormalNoScale(ScaledNormal * FMath::InvSqrt(ScaledNormal2));
386 }
387 else
388 {
389 return TransformNormalNoScale(Normal);
390 }
391 }
392
393 // Transform the normal when scale may be non-unitary.
395 {
396 // Apply inverse scaling without a per-component divide (conceptually, by scaling the normal by an extra det*sign(det))
397 const TVector<FRealDouble, 3>& S = GetScale3D();
398 FRealDouble DetSign = (S.X * S.Y * S.Z) < 0 ? (FRealDouble)-1 : (FRealDouble)1;
399 const TVector<FRealDouble, 3> SafeInvS(S.Y * S.Z * DetSign, S.X * S.Z * DetSign, S.X * S.Y * DetSign);
401 const FRealDouble ScaledNormalLengthSq = ScaledNormal.SizeSquared();
402 // If inverse scaling would not zero the normal, normalize it and rotate
404 {
405 return TransformVectorNoScale(ScaledNormal * FMath::InvSqrt(ScaledNormalLengthSq));
406 }
407 // Otherwise just rotate without scaling
408 else
409 {
410 return TransformVectorNoScale(Normal);
411 }
412 }
413
418 {
420
421#if ENABLE_VECTORIZED_TRANSFORM
422 const TransformVectorRegister QuatA = A.Rotation;
423 const TransformVectorRegister QuatB = B.Rotation;
424 const TransformVectorRegister TranslateA = A.Translation;
425 const TransformVectorRegister TranslateB = B.Translation;
426
430
431 Result.Rotation = Rotation;
432 Result.Translation = Translation;
433 Result.Scale3D = VectorOne();
434#else
435 Result.Rotation = B.Rotation * A.Rotation;
436 Result.Translation = B.Rotation * A.Translation + B.Translation;
437 Result.Scale3D = FVector3d::OneVector;
438#endif
439
440 return Result;
441 }
442
444 {
445 return HashCombine(GetTypeHash(InTransform.GetTranslation()), HashCombine(GetTypeHash(InTransform.GetRotation().Euler()), GetTypeHash(InTransform.GetScale3D())));
446 }
447 };
448}
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
auto ToMatrix(const TransformType &Transform) -> decltype(Transform.ToMatrix())
Definition TransformCalculus3D.h:99
VectorType TransformVector(const TransformType &Transform, const VectorType &Vector)
Definition TransformCalculus.h:367
constexpr uint32 HashCombine(uint32 A, uint32 C)
Definition TypeHash.h:36
FORCEINLINE VectorRegister4Float VectorSubtract(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:731
FORCEINLINE VectorRegister4Float VectorSet_W0(const VectorRegister4Float &Vec)
Definition UnrealMathFPU.h:1391
FORCEINLINE VectorRegister4Float VectorAdd(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:704
FORCEINLINE VectorRegister4Float VectorQuaternionMultiply2(const VectorRegister4Float &Quat1, const VectorRegister4Float &Quat2)
Definition UnrealMathFPU.h:1517
#define UE_SMALL_NUMBER
Definition UnrealMathUtility.h:130
FORCEINLINE VectorRegister4Float VectorOne(void)
Definition UnrealMathVectorCommon.h.inl:21
FORCEINLINE VectorRegister4Float VectorQuaternionInverse(VectorRegister4Float NormalizedQuat)
Definition UnrealMathVectorCommon.h.inl:723
FORCEINLINE VectorRegister4Float VectorQuaternionRotateVector(VectorRegister4Float Quat, VectorRegister4Float VectorW0)
Definition UnrealMathVectorCommon.h.inl:741
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition Matrix.h:21
TRigidTransform()
Definition Transform.h:303
TRigidTransform(const TVector< FRealDouble, 3 > &Translation, const TRotation< FRealDouble, 3 > &Rotation, const TVector< FRealDouble, 3 > &Scale)
Definition Transform.h:307
PMatrix< FRealDouble, 4, 4 > ToMatrixWithScale() const
Definition Transform.h:326
TVector< FRealDouble, 3 > TransformNormalUnsafe(const TVector< FRealDouble, 3 > &Normal) const
Definition Transform.h:379
TRigidTransform(const OtherType &Other)
Definition Transform.h:318
TRigidTransform(const FMatrix44d &Matrix)
Definition Transform.h:309
TVector< FRealDouble, 3 > TransformNormal(const TVector< FRealDouble, 3 > &Normal) const
Definition Transform.h:394
TRigidTransform(const FMatrix44f &Matrix)
Definition Transform.h:311
PMatrix< FRealDouble, 4, 4 > ToMatrixNoScale() const
Definition Transform.h:331
TRigidTransform(TransformVectorRegister InRotation, TransformVectorRegister InTranslation)
Definition Transform.h:313
static TRigidTransform< FRealDouble, 3 > MultiplyNoScale(const TRigidTransform< FRealDouble, 3 > &A, const TRigidTransform< FRealDouble, 3 > &B)
Equivalent to (A * B) but assuming both have unit scale.
Definition Transform.h:417
TRigidTransform(const BaseTransform &Transform)
Definition Transform.h:315
TRigidTransform(const TVector< FRealDouble, 3 > &Translation, const TRotation< FRealDouble, 3 > &Rotation)
Definition Transform.h:305
TVector< FRealDouble, 3 > TransformNormalNoScale(const TVector< FRealDouble, 3 > &Normal) const
Definition Transform.h:373
friend uint32 GetTypeHash(const TRigidTransform< FRealDouble, 3 > &InTransform)
Definition Transform.h:443
TRigidTransform< FRealDouble, 3 > Inverse() const
Definition Transform.h:321
TRigidTransform< FRealDouble, 3 > GetRelativeTransformNoScale(const TRigidTransform< FRealDouble, 3 > &Other) const
Definition Transform.h:344
TRigidTransform< FRealDouble, 3 > operator*(const TRigidTransform< FRealDouble, 3 > &Other) const
Definition Transform.h:338
PMatrix< FRealSingle, 4, 4 > ToMatrixNoScale() const
Definition Transform.h:180
TRigidTransform(const FMatrix44f &Matrix)
Definition Transform.h:158
TRigidTransform< FRealSingle, 3 > GetRelativeTransformNoScale(const TRigidTransform< FRealSingle, 3 > &Other) const
Definition Transform.h:193
TRigidTransform(const BaseTransform &Transform)
Definition Transform.h:164
TRigidTransform< FRealSingle, 3 > operator*(const TRigidTransform< FRealSingle, 3 > &Other) const
Definition Transform.h:187
TRigidTransform(const FMatrix44d &Matrix)
Definition Transform.h:160
TVector< FRealSingle, 3 > TransformNormal(const TVector< FRealSingle, 3 > &Normal) const
Definition Transform.h:243
TRigidTransform(const OtherType &Other)
Definition Transform.h:167
PMatrix< FRealSingle, 4, 4 > ToMatrixWithScale() const
Definition Transform.h:175
TRigidTransform(TransformVectorRegister InRotation, TransformVectorRegister InTranslation)
Definition Transform.h:162
static TRigidTransform< FRealSingle, 3 > MultiplyNoScale(const TRigidTransform< FRealSingle, 3 > &A, const TRigidTransform< FRealSingle, 3 > &B)
Equivalent to (A * B) but assuming both have unit scale.
Definition Transform.h:266
TRigidTransform(const TVector< FRealSingle, 3 > &Translation, const TRotation< FRealSingle, 3 > &Rotation)
Definition Transform.h:154
TVector< FRealSingle, 3 > TransformNormalNoScale(const TVector< FRealSingle, 3 > &Normal) const
Definition Transform.h:222
TRigidTransform()
Definition Transform.h:152
TRigidTransform(const TVector< FRealSingle, 3 > &Translation, const TRotation< FRealSingle, 3 > &Rotation, const TVector< FRealSingle, 3 > &Scale)
Definition Transform.h:156
friend uint32 GetTypeHash(const TRigidTransform< FRealSingle, 3 > &InTransform)
Definition Transform.h:292
TVector< FRealSingle, 3 > TransformNormalUnsafe(const TVector< FRealSingle, 3 > &Normal) const
Definition Transform.h:228
TRigidTransform< FRealSingle, 3 > Inverse() const
Definition Transform.h:170
TRigidTransform< FReal, 2 > Inverse() const
Definition Transform.h:136
TRigidTransform(const FMatrix44f &Matrix)
Definition Transform.h:132
TRigidTransform()
Definition Transform.h:126
TRigidTransform(const FMatrix44d &Matrix)
Definition Transform.h:130
TRigidTransform(const TVector< FReal, 3 > &Translation, const TRotation< FReal, 3 > &Rotation)
Definition Transform.h:128
TRigidTransform< FReal, 2 > operator*(const TRigidTransform< FReal, 2 > &Other) const
Definition Transform.h:141
TRigidTransform(const BaseTransform &Transform)
Definition Transform.h:134
Definition Transform.h:115
Definition Rotation.h:41
Definition Vector.h:41
Definition SkeletalMeshComponent.h:307
FRealDouble FReal
Definition Real.h:22
float FRealSingle
Definition Real.h:14
double FRealDouble
Definition Real.h:13
FORCEINLINE uint32 GetTypeHash(const FParticleID &Unique)
Definition GeometryParticles.h:99
FComplex operator*(const FReal Other, const FComplex Complex)
Definition Complex.h:32
Definition UnrealMathVectorConstants.h.inl:39
TVectorRegisterType< FRealSingle > TransformVectorRegister
Definition TransformNonVectorized.h:45
FReal FReal
Definition TransformNonVectorized.h:44
static CORE_API const TVector< float > OneVector
Definition Vector.h:82