Ark Server API (ASA) - Wiki
Loading...
Searching...
No Matches
TransformCalculus3D.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
6#include "Math/Vector.h"
7#include "Math/Rotator.h"
8#include "Math/Matrix.h"
9#include "Math/RotationMatrix.h"
10#include "Math/TranslationMatrix.h"
11#include "Math/Quat.h"
12#include "Math/ScaleMatrix.h"
13#include "Math/TransformCalculus.h"
14
15
16//////////////////////////////////////////////////////////////////////////
17// Transform calculus for 3D types. Since UE4 already has existing 3D transform
18// types, this is mostly a set of adapter overloads for the primitive operations
19// requires by the transform calculus framework.
20//
21// The following types are adapted.
22// * float/double -> represents a uniform scale.
23// * TScale<T> -> represents a 3D non-uniform scale.
24// * UE::Math::TVector<T> -> represents a 3D translation.
25// * UE::Math::TRotator<T> -> represents a pure rotation.
26// * UE::Math::TQuat<T> -> represents a pure rotation.
27// * UE::Math::TMatrix<T> -> represents a general 3D homogeneous transform.
28//
29//////////////////////////////////////////////////////////////////////////
30
31/**
32 * Represents a 3D non-uniform scale (to disambiguate from an UE::Math::TVector<T>, which is used for translation).
33 *
34 * Serves as a good base example of how to write a class that supports the basic transform calculus
35 * operations.
36 */
37template<typename T>
38class TScale
39{
40 static_assert(std::is_floating_point_v<T>, "T must be floating point");
41
42public:
43 using Vector3Type = UE::Math::TVector<T>;
44
45 /** Ctor. initialize to an identity scale, 1.0. */
46 TScale() :Scale(1.0f) {}
47 /** Ctor. initialize from a uniform scale. */
48 explicit TScale(T InScale) :Scale(InScale) {}
49 /** Ctor. initialize from an UE::Math::TVector<T> defining the 3D scale. */
50 template<typename VType>
51 explicit TScale(const UE::Math::TVector<VType>& InScale) : Scale((Vector3Type)InScale) {}
52 /** Access to the underlying UE::Math::TVector<T> that stores the scale. */
53 const Vector3Type& GetVector() const { return Scale; }
54 /** Concatenate two scales. */
55 const TScale Concatenate(const TScale& RHS) const
56 {
57 return TScale(Scale * RHS.GetVector());
58 }
59 /** Invert the scale. */
60 const TScale Inverse() const
61 {
62 return TScale(Vector3Type(1.0f / Scale.X, 1.0f / Scale.Y, 1.0f / Scale.Z));
63 }
64private:
65 /** Underlying storage of the 3D scale. */
66 Vector3Type Scale;
67};
68
69/** Core typedefs */
70typedef TScale<float> FScale3f;
71typedef TScale<double> FScale3d;
72typedef FScale3f FScale3D; // Default type, for backwards compat
73
74/** Specialization for converting a FMatrix to an FRotator. It uses a non-standard explicit conversion function. */
75template<> template<> inline FRotator3f TransformConverter<FRotator3f>::Convert<FMatrix44f>(const FMatrix44f& Transform)
76{
77 return Transform.Rotator();
78}
79template<> template<> inline FRotator3d TransformConverter<FRotator3d>::Convert<FMatrix44d>(const FMatrix44d& Transform)
80{
81 return Transform.Rotator();
82}
83
84//////////////////////////////////////////////////////////////////////////
85// UE::Math::TMatrix<T> Support
86//////////////////////////////////////////////////////////////////////////
87
88/**
89 * Converts a generic transform to a matrix using a ToMatrix() member function.
90 * Uses decltype to allow some classes to return const-ref types for efficiency.
91 *
92 * @param Transform
93 * @return the UE::Math::TMatrix<T> stored by the Transform.
94 */
95template<typename TransformType>
96inline auto ToMatrix(const TransformType& Transform) -> decltype(Transform.ToMatrix())
97{
98 return Transform.ToMatrix();
99}
100
101/**
102 * Specialization for the NULL Matrix conversion.
103 *
104 * @param Scale Uniform Scale
105 * @return Matrix that represents the uniform Scale space.
106 */
107inline const UE::Math::TMatrix<float>& ToMatrix(const UE::Math::TMatrix<float>& Transform)
108{
109 return Transform;
110}
111
112inline const UE::Math::TMatrix<double>& ToMatrix(const UE::Math::TMatrix<double>& Transform)
113{
114 return Transform;
115}
116
117/**
118 * Specialization for floats as a uniform scale.
119 *
120 * @param Scale Uniform Scale
121 * @return Matrix that represents the uniform Scale space.
122 */
123inline UE::Math::TMatrix<float> ToMatrix(float Scale)
124{
125 return UE::Math::TScaleMatrix<float>(Scale);
126}
127
128inline UE::Math::TMatrix<double> ToMatrix(double Scale)
129{
130 return UE::Math::TScaleMatrix<double>(Scale);
131}
132
133/**
134 * Specialization for non-uniform Scale.
135 *
136 * @param Scale Non-uniform Scale
137 * @return Matrix that represents the non-uniform Scale space.
138 */
139inline UE::Math::TMatrix<float> ToMatrix(const TScale<float>& Scale)
140{
141 return UE::Math::TScaleMatrix<float>(UE::Math::TVector<float>(Scale.GetVector()));
142}
143inline UE::Math::TMatrix<double> ToMatrix(const TScale<double>& Scale)
144{
145 return UE::Math::TScaleMatrix<double>(UE::Math::TVector<double>(Scale.GetVector()));
146}
147
148/**
149 * Specialization for translation.
150 *
151 * @param Translation Translation
152 * @return Matrix that represents the translated space.
153 */
154inline UE::Math::TMatrix<float> ToMatrix(const UE::Math::TVector<float>& Translation)
155{
156 return UE::Math::TTranslationMatrix<float>(UE::Math::TVector<float>(Translation));
157}
158inline UE::Math::TMatrix<double> ToMatrix(const UE::Math::TVector<double>& Translation)
159{
160 return UE::Math::TTranslationMatrix<double>(UE::Math::TVector<double>(Translation));
161}
162
163/**
164 * Specialization for rotation.
165 *
166 * @param Rotation Rotation
167 * @return Matrix that represents the rotated space.
168 */
169inline UE::Math::TMatrix<float> ToMatrix(const UE::Math::TRotator<float>& Rotation)
170{
171 return UE::Math::TRotationMatrix<float>(UE::Math::TRotator<float>(Rotation));
172}
173inline UE::Math::TMatrix<double> ToMatrix(const UE::Math::TRotator<double>& Rotation)
174{
175 return UE::Math::TRotationMatrix<double>(UE::Math::TRotator<double>(Rotation));
176}
177
178/**
179 * Specialization for rotation.
180 *
181 * @param Rotation Rotation
182 * @return Matrix that represents the rotated space.
183 */
184inline UE::Math::TMatrix<float> ToMatrix(const UE::Math::TQuat<float>& Rotation)
185{
186 return UE::Math::TRotationMatrix<float>::Make(UE::Math::TQuat<float>(Rotation));
187}
188inline UE::Math::TMatrix<double> ToMatrix(const UE::Math::TQuat<double>& Rotation)
189{
190 return UE::Math::TRotationMatrix<double>::Make(UE::Math::TQuat<double>(Rotation));
191}
192
193/**
194 * Specialization of TransformConverter for UE::Math::TMatrix<T>. Calls ToMatrix() by default.
195 * Allows custom types to easily provide support via a ToMatrix() overload or a ToMatrix() member function.
196 * Uses decltype to support efficient passthrough of classes that can convert to a UE::Math::TMatrix<T> without creating
197 * a new instance.
198 */
199template<>
200struct TransformConverter<FMatrix44f>
201{
202 template<typename OtherTransformType>
203 static auto Convert(const OtherTransformType& Transform) -> decltype((FMatrix44f)ToMatrix(Transform))
204 {
205 return (FMatrix44f)ToMatrix(Transform);
206 }
207};
208
209template<>
210struct TransformConverter<FMatrix44d>
211{
212 template<typename OtherTransformType>
213 static auto Convert(const OtherTransformType& Transform) -> decltype((FMatrix44d)ToMatrix(Transform))
214 {
215 return (FMatrix44d)ToMatrix(Transform);
216 }
217};
218
219/** concatenation rules for basic UE4 types. */
220template<typename T> struct ConcatenateRules<float , TScale<T> > { typedef TScale<T> ResultType; };
221template<typename T> struct ConcatenateRules<double , TScale<T> > { typedef TScale<T> ResultType; };
222template<typename T> struct ConcatenateRules<TScale<T> , float > { typedef TScale<T> ResultType; };
223template<typename T> struct ConcatenateRules<TScale<T> , double > { typedef TScale<T> ResultType; };
224template<typename T> struct ConcatenateRules<float , UE::Math::TVector<T> > { typedef UE::Math::TMatrix<T> ResultType; };
225template<typename T> struct ConcatenateRules<double , UE::Math::TVector<T> > { typedef UE::Math::TMatrix<T> ResultType; };
226template<typename T> struct ConcatenateRules<UE::Math::TVector<T> , float > { typedef UE::Math::TMatrix<T> ResultType; };
227template<typename T> struct ConcatenateRules<UE::Math::TVector<T> , double > { typedef UE::Math::TMatrix<T> ResultType; };
228template<typename T> struct ConcatenateRules<float , UE::Math::TRotator<T> > { typedef UE::Math::TMatrix<T> ResultType; };
229template<typename T> struct ConcatenateRules<double , UE::Math::TRotator<T> > { typedef UE::Math::TMatrix<T> ResultType; };
230template<typename T> struct ConcatenateRules<UE::Math::TRotator<T> , float > { typedef UE::Math::TMatrix<T> ResultType; };
231template<typename T> struct ConcatenateRules<UE::Math::TRotator<T> , double > { typedef UE::Math::TMatrix<T> ResultType; };
232template<typename T> struct ConcatenateRules<float , UE::Math::TQuat<T> > { typedef UE::Math::TMatrix<T> ResultType; };
233template<typename T> struct ConcatenateRules<double , UE::Math::TQuat<T> > { typedef UE::Math::TMatrix<T> ResultType; };
234template<typename T> struct ConcatenateRules<UE::Math::TQuat<T> , float > { typedef UE::Math::TMatrix<T> ResultType; };
235template<typename T> struct ConcatenateRules<UE::Math::TQuat<T> , double > { typedef UE::Math::TMatrix<T> ResultType; };
236template<typename T> struct ConcatenateRules<float , UE::Math::TMatrix<T> > { typedef UE::Math::TMatrix<T> ResultType; };
237template<typename T> struct ConcatenateRules<double , UE::Math::TMatrix<T> > { typedef UE::Math::TMatrix<T> ResultType; };
238template<typename T> struct ConcatenateRules<UE::Math::TMatrix<T> , float > { typedef UE::Math::TMatrix<T> ResultType; };
239template<typename T> struct ConcatenateRules<UE::Math::TMatrix<T> , double > { typedef UE::Math::TMatrix<T> ResultType; };
240template<typename T> struct ConcatenateRules<TScale<T> , UE::Math::TVector<T> > { typedef UE::Math::TMatrix<T> ResultType; };
241template<typename T> struct ConcatenateRules<UE::Math::TVector<T> , TScale<T> > { typedef UE::Math::TMatrix<T> ResultType; };
242template<typename T> struct ConcatenateRules<TScale<T> , UE::Math::TRotator<T> > { typedef UE::Math::TMatrix<T> ResultType; };
243template<typename T> struct ConcatenateRules<UE::Math::TRotator<T> , TScale<T> > { typedef UE::Math::TMatrix<T> ResultType; };
244template<typename T> struct ConcatenateRules<TScale<T> , UE::Math::TQuat<T> > { typedef UE::Math::TMatrix<T> ResultType; };
245template<typename T> struct ConcatenateRules<UE::Math::TQuat<T> , TScale<T> > { typedef UE::Math::TMatrix<T> ResultType; };
246template<typename T> struct ConcatenateRules<TScale<T> , UE::Math::TMatrix<T> > { typedef UE::Math::TMatrix<T> ResultType; };
247template<typename T> struct ConcatenateRules<UE::Math::TMatrix<T> , TScale<T> > { typedef UE::Math::TMatrix<T> ResultType; };
248template<typename T> struct ConcatenateRules<UE::Math::TVector<T> , UE::Math::TRotator<T> > { typedef UE::Math::TMatrix<T> ResultType; };
249template<typename T> struct ConcatenateRules<UE::Math::TRotator<T> , UE::Math::TVector<T> > { typedef UE::Math::TMatrix<T> ResultType; };
250template<typename T> struct ConcatenateRules<UE::Math::TVector<T> , UE::Math::TQuat<T> > { typedef UE::Math::TMatrix<T> ResultType; };
251template<typename T> struct ConcatenateRules<UE::Math::TQuat<T> , UE::Math::TVector<T> > { typedef UE::Math::TMatrix<T> ResultType; };
252template<typename T> struct ConcatenateRules<UE::Math::TVector<T> , UE::Math::TMatrix<T> > { typedef UE::Math::TMatrix<T> ResultType; };
253template<typename T> struct ConcatenateRules<UE::Math::TMatrix<T> , UE::Math::TVector<T> > { typedef UE::Math::TMatrix<T> ResultType; };
254template<typename T> struct ConcatenateRules<UE::Math::TRotator<T> , UE::Math::TQuat<T> > { typedef UE::Math::TQuat<T> ResultType; };
255template<typename T> struct ConcatenateRules<UE::Math::TQuat<T> , UE::Math::TRotator<T> > { typedef UE::Math::TQuat<T> ResultType; };
256template<typename T> struct ConcatenateRules<UE::Math::TRotator<T> , UE::Math::TMatrix<T> > { typedef UE::Math::TMatrix<T> ResultType; };
257template<typename T> struct ConcatenateRules<UE::Math::TMatrix<T> , UE::Math::TRotator<T> > { typedef UE::Math::TMatrix<T> ResultType; };
258template<typename T> struct ConcatenateRules<UE::Math::TQuat<T> , UE::Math::TMatrix<T> > { typedef UE::Math::TMatrix<T> ResultType; };
259template<typename T> struct ConcatenateRules<UE::Math::TMatrix<T> , UE::Math::TQuat<T> > { typedef UE::Math::TMatrix<T> ResultType; };
260
261//////////////////////////////////////////////////////////////////////////
262// Concatenate overloads.
263//
264// Since these are existing UE4 types, we cannot rely on the default
265// template that calls member functions. Instead, we provide direct overloads.
266//////////////////////////////////////////////////////////////////////////
267
268
269namespace UE
270{
271namespace Math
272{
273
274/**
275 * Specialization for concatenating two Matrices.
276 *
277 * @param LHS rotation that goes from space A to space B
278 * @param RHS rotation that goes from space B to space C.
279 * @return a new rotation representing the transformation from the input space of LHS to the output space of RHS.
280 */
281template<typename T>
282inline UE::Math::TMatrix<T> Concatenate(const UE::Math::TMatrix<T>& LHS, const UE::Math::TMatrix<T>& RHS)
283{
284 return LHS * RHS;
285}
286
287
288/**
289* Specialization for concatenating two translations.
290*
291* @param LHS Translation that goes from space A to space B
292* @param RHS Translation that goes from space B to space C.
293* @return a new Translation representing the transformation from the input space of LHS to the output space of RHS.
294*/
295template<typename T>
296inline UE::Math::TVector<T> Concatenate(const UE::Math::TVector<T>& LHS, const UE::Math::TVector<T>& RHS)
297{
298 return LHS + RHS;
299}
300
301
302/**
303 * Specialization for concatenating two rotations.
304 *
305 * NOTE: UE::Math::TQuat<T> concatenates right to left, opposite of how UE::Math::TMatrix<T> implements it.
306 * Confusing, no? That's why we have these high level functions!
307 *
308 * @param LHS rotation that goes from space A to space B
309 * @param RHS rotation that goes from space B to space C.
310 * @return a new rotation representing the transformation from the input space of LHS to the output space of RHS.
311 */
312template<typename T>
313inline UE::Math::TQuat<T> Concatenate(const UE::Math::TQuat<T>& LHS, const UE::Math::TQuat<T>& RHS)
314{
315 return RHS * LHS;
316}
317
318} // namespace UE::Math
319} // namespace UE
320
321/**
322 * Specialization for concatenating two rotations.
323 *
324 * @param LHS rotation that goes from space A to space B
325 * @param RHS rotation that goes from space B to space C.
326 * @return a new rotation representing the transformation from the input space of LHS to the output space of RHS.
327 */
328template<typename T>
329inline UE::Math::TRotator<T> Concatenate(const UE::Math::TRotator<T>& LHS, const UE::Math::TRotator<T>& RHS)
330{
331 //@todo implement a more efficient way to do this.
332 return TransformCast<UE::Math::TRotator<T>>(Concatenate(TransformCast<UE::Math::TMatrix<T>>(LHS), TransformCast<UE::Math::TMatrix<T>>(RHS)));
333}
334
335
336//////////////////////////////////////////////////////////////////////////
337// Inverse overloads.
338//
339// Since these are existing UE4 types, we cannot rely on the default
340// template that calls member functions. Instead, we provide direct overloads.
341//////////////////////////////////////////////////////////////////////////
342
343/**
344 * Inverts a transform from space A to space B so it transforms from space B to space A.
345 * Specialization for UE::Math::TMatrix<T>.
346 *
347 * @param Transform Input transform from space A to space B.
348 * @return Inverted transform from space B to space A.
349 */
350template<typename T>
351inline UE::Math::TMatrix<T> Inverse(const UE::Math::TMatrix<T>& Transform)
352{
353 return Transform.Inverse();
354}
355
356/**
357 * Inverts a transform from space A to space B so it transforms from space B to space A.
358 * Specialization for UE::Math::TRotator<T>.
359 *
360 * @param Transform Input transform from space A to space B.
361 * @return Inverted transform from space B to space A.
362 */
363template<typename T>
364inline UE::Math::TRotator<T> Inverse(const UE::Math::TRotator<T>& Transform)
365{
366 UE::Math::TVector<T> EulerAngles = Transform.Euler();
367 return UE::Math::TRotator<T>::MakeFromEuler(UE::Math::TVector<T>(-EulerAngles.Z, -EulerAngles.Y, -EulerAngles.X));
368}
369
370/**
371 * Inverts a transform from space A to space B so it transforms from space B to space A.
372 * Specialization for UE::Math::TQuat<T>.
373 *
374 * @param Transform Input transform from space A to space B.
375 * @return Inverted transform from space B to space A.
376 */
377template<typename T>
378inline UE::Math::TQuat<T> Inverse(const UE::Math::TQuat<T>& Transform)
379{
380 return Transform.Inverse();
381}
382
383/**
384 * Inverts a transform from space A to space B so it transforms from space B to space A.
385 * Specialization for translation.
386 *
387 * @param Transform Input transform from space A to space B.
388 * @return Inverted transform from space B to space A.
389 */
390template<typename T>
391inline UE::Math::TVector<T> Inverse(const UE::Math::TVector<T>& Transform)
392{
393 return -Transform;
394}
395
396//////////////////////////////////////////////////////////////////////////
397// TransformPoint overloads.
398//
399// Since these are existing UE4 types, we cannot rely on the default
400// template that calls member functions. Instead, we provide direct overloads.
401//////////////////////////////////////////////////////////////////////////
402
403/**
404 * Specialization for UE::Math::TMatrix<T> as it's member function is called something slightly different.
405 */
406template<typename T>
407inline UE::Math::TVector<T> TransformPoint(const UE::Math::TMatrix<T>& Transform, const UE::Math::TVector<T>& Point)
408{
409 return Transform.TransformPosition(Point);
410}
411
412/**
413 * Specialization for UE::Math::TQuat<T> as it's member function is called something slightly different.
414 */
415template<typename T>
416inline UE::Math::TVector<T> TransformPoint(const UE::Math::TQuat<T>& Transform, const UE::Math::TVector<T>& Point)
417{
418 return Transform.RotateVector(Point);
419}
420
421/**
422 * Specialization for UE::Math::TQuat<T> as it's member function is called something slightly different.
423 */
424template<typename T>
425inline UE::Math::TVector<T> TransformVector(const UE::Math::TQuat<T>& Transform, const UE::Math::TVector<T>& Vector)
426{
427 return Transform.RotateVector(Vector);
428}
429
430/**
431 * Specialization for UE::Math::TRotator<T> as it's member function is called something slightly different.
432 */
433template<typename T>
434inline UE::Math::TVector<T> TransformPoint(const UE::Math::TRotator<T>& Transform, const UE::Math::TVector<T>& Point)
435{
436 return Transform.RotateVector(Point);
437}
438
439/**
440 * Specialization for UE::Math::TRotator<T> as it's member function is called something slightly different.
441 */
442template<typename T>
443inline UE::Math::TVector<T> TransformVector(const UE::Math::TRotator<T>& Transform, const UE::Math::TVector<T>& Vector)
444{
445 return Transform.RotateVector(Vector);
446}
447
448/**
449 * Specialization for UE::Math::TVector<T> Translation.
450 */
451template<typename T>
452inline UE::Math::TVector<T> TransformPoint(const UE::Math::TVector<T>& Transform, const UE::Math::TVector<T>& Point)
453{
454 return Transform + Point;
455}
456
457/**
458 * Specialization for UE::Math::TVector<T> Translation (does nothing).
459 */
460template<typename T>
461inline const UE::Math::TVector<T>& TransformVector(const UE::Math::TVector<T>& Transform, const UE::Math::TVector<T>& Vector)
462{
463 return Vector;
464}
465
466/**
467 * Specialization for Scale.
468 */
469template<typename T>
470inline UE::Math::TVector<T> TransformPoint(const TScale<T>& Transform, const UE::Math::TVector<T>& Point)
471{
472 return Transform.GetVector() * Point;
473}
474
475/**
476 * Specialization for Scale.
477 */
478template<typename T>
479inline UE::Math::TVector<T> TransformVector(const TScale<T>& Transform, const UE::Math::TVector<T>& Vector)
480{
481 return Transform.GetVector() * Vector;
482}
UE::Math::TRotator< T > Inverse(const UE::Math::TRotator< T > &Transform)
const UE::Math::TVector< T > & TransformVector(const UE::Math::TVector< T > &Transform, const UE::Math::TVector< T > &Vector)
UE::Math::TRotator< T > Concatenate(const UE::Math::TRotator< T > &LHS, const UE::Math::TRotator< T > &RHS)
UE::Math::TVector< T > TransformVector(const UE::Math::TQuat< T > &Transform, const UE::Math::TVector< T > &Vector)
UE::Math::TVector< T > TransformPoint(const UE::Math::TRotator< T > &Transform, const UE::Math::TVector< T > &Point)
FScale3f FScale3D
UE::Math::TVector< T > TransformVector(const TScale< T > &Transform, const UE::Math::TVector< T > &Vector)
UE::Math::TVector< T > Inverse(const UE::Math::TVector< T > &Transform)
UE::Math::TVector< T > TransformPoint(const UE::Math::TVector< T > &Transform, const UE::Math::TVector< T > &Point)
TScale< double > FScale3d
UE::Math::TMatrix< T > Inverse(const UE::Math::TMatrix< T > &Transform)
UE::Math::TVector< T > TransformPoint(const UE::Math::TMatrix< T > &Transform, const UE::Math::TVector< T > &Point)
TScale< float > FScale3f
UE::Math::TQuat< T > Inverse(const UE::Math::TQuat< T > &Transform)
UE::Math::TVector< T > TransformPoint(const TScale< T > &Transform, const UE::Math::TVector< T > &Point)
UE::Math::TVector< T > TransformVector(const UE::Math::TRotator< T > &Transform, const UE::Math::TVector< T > &Vector)
UE::Math::TVector< T > TransformPoint(const UE::Math::TQuat< T > &Transform, const UE::Math::TVector< T > &Point)
const Vector3Type & GetVector() const
const TScale Inverse() const
Vector3Type Scale
TScale(T InScale)
const TScale Concatenate(const TScale &RHS) const
TScale(const UE::Math::TVector< VType > &InScale)
UE::Math::TMatrix< T > Concatenate(const UE::Math::TMatrix< T > &LHS, const UE::Math::TMatrix< T > &RHS)
UE::Math::TVector< T > Concatenate(const UE::Math::TVector< T > &LHS, const UE::Math::TVector< T > &RHS)
UE::Math::TQuat< T > Concatenate(const UE::Math::TQuat< T > &LHS, const UE::Math::TQuat< T > &RHS)
Definition Vector.h:40
Definition json.hpp:4518
static auto Convert(const OtherTransformType &Transform) -> decltype((FMatrix44d) ToMatrix(Transform))