6#include "Misc/AssertionMacros.h"
7#include "Math/UnrealMathUtility.h"
8#include "Containers/UnrealString.h"
9#include "Math/Vector.h"
10#include "Math/Sphere.h"
11#include "Misc/LargeWorldCoordinatesSerializer.h"
14
15
16
17
18
22struct TBoxConstInit {};
45
46
47
48
49 explicit TBox( EForceInit )
54 constexpr TBox(EForceInit, TBoxConstInit)
55 : Min(0, TVectorConstInit{}), Max(0, TVectorConstInit{}), IsValid(0)
60
61
62
63
64
65 template<
typename FArg>
66 TBox(
const TVector<FArg>& InMin,
const TVector<FArg>& InMax)
72 static_assert(
sizeof(FArg) <=
sizeof(T),
"Losing precision when constructing a box of floats from vectors of doubles");
75 TBox(
const TVector4<T>& InMin,
const TVector4<T>& InMax)
82
83
84
85
86
87 TBox(
const TVector<T>* Points, int32 Count) : Min(0, 0, 0), Max(0, 0, 0), IsValid(0)
89 for (int32 i = 0; i < Count; i++)
96
97
98
99
100 TBox(
const TArray<TVector<T>>& Points) : TBox<T>(&Points[0], Points.Num()) {};
104 explicit TBox(
const TBox<FArg>& From) : TBox<T>(TVector<T>(From.Min), TVector<T>(From.Max)) {}
109
110
111
112
113
114
117 return (!IsValid && !Other.IsValid) || ((IsValid && Other.IsValid) && (Min == Other.Min) && (Max == Other.Max));
121
122
123
124
127 return !(*
this == Other);
131
132
133
134
135
136
137
138
141 return (!IsValid && !Other.IsValid) || ((IsValid && Other.IsValid) && Min.Equals(Other.Min, Tolerance) && Max.Equals(Other.Max, Tolerance));
145
146
147
148
149
150 FORCEINLINE TBox<T>& operator+=(
const TVector<T> &Other );
153
154
155
156
157
160 return TBox<T>(*
this) += Other;
164
165
166
167
168
169 FORCEINLINE TBox<T>& operator+=(
const TBox<T>& Other );
172
173
174
175
176
179 return TBox<T>(*
this) += Other;
183
184
185
186
187
190 check((Index >= 0) && (Index < 2));
203
204
205
206
207
208 FORCEINLINE T ComputeSquaredDistanceToPoint(
const TVector<T>& Point )
const
210 return ComputeSquaredDistanceFromBoxToPoint(Min, Max, Point);
214
215
216 FORCEINLINE T ComputeSquaredDistanceToBox(
const TBox<T>& Box)
const
218 TVector<T> AxisDistances = (GetCenter() - Box.GetCenter()).GetAbs() - (GetExtent() + Box.GetExtent());
219 AxisDistances = TVector<T>::Max(AxisDistances, TVector<T>(0.0f, 0.0f, 0.0f));
220 return TVector<T>::DotProduct(AxisDistances, AxisDistances);
224
225
226
227
228
231 return TBox<T>(Min - TVector<T>(W, W, W), Max + TVector<T>(W, W, W));
235
236
237
238
239
242 return TBox<T>(Min - V, Max + V);
246
247
248
249
250
251
252 UE_NODISCARD TBox<T> ExpandBy(
const TVector<T>& Neg,
const TVector<T>& Pos)
const
254 return TBox<T>(Min - Neg, Max + Pos);
258
259
260
261
262
265 return TBox<T>(Min + Offset, Max + Offset);
269
270
271
272
273
276 const TVector<T> Offset = Destination - GetCenter();
277 return TBox<T>(Min + Offset, Max + Offset);
281
282
283
284
285
288 return TVector<T>((Min + Max) * 0.5f);
292
293
294
295
296
297
298 FORCEINLINE void GetCenterAndExtents( TVector<T>& Center, TVector<T>& Extents )
const
300 Extents = GetExtent();
301 Center = Min + Extents;
305
306
307
308
309
310 FORCEINLINE TVector<T> GetClosestPointTo(
const TVector<T>& Point )
const;
313
314
315
316
317
320 return 0.5f * (Max - Min);
323 UE_DEPRECATED(4.24,
"This method performed unsafe operations and should be replaced with using .Min and .Max directly or using the [] operator on this class instead.")
326 return (&Min)[PointIndex];
329 UE_DEPRECATED(4.24,
"This method performed unsafe operations and should be replaced with using .Min and .Max directly or using the [] operator on this class instead.")
332 return (&Min)[PointIndex];
336
337
338
339
340
347
348
349
350
351
354 return (Max.X - Min.X) * (Max.Y - Min.Y) * (Max.Z - Min.Z);
358
359
362 Min = Max = TVector<T>::ZeroVector;
367
368
369
370
371
372 FORCEINLINE bool Intersect(
const TBox<T>& Other )
const;
375
376
377
378
379
380 FORCEINLINE bool IntersectXY(
const TBox<T>& Other )
const;
383
384
385
386
387
388 UE_NODISCARD TBox<T> Overlap(
const TBox<T>& Other )
const;
391
392
393
394
395
396 UE_NODISCARD TBox<T> InverseTransformBy(
const TTransform<T>& M )
const;
399
400
401
402
403
404
407 return ((In.X > Min.X) && (In.X < Max.X) && (In.Y > Min.Y) && (In.Y < Max.Y) && (In.Z > Min.Z) && (In.Z < Max.Z));
411
412
413
414
415
416
419 return ((In.X >= Min.X) && (In.X <= Max.X) && (In.Y >= Min.Y) && (In.Y <= Max.Y) && (In.Z >= Min.Z) && (In.Z <= Max.Z));
423
424
425
426
427
430 return (IsInside(Other.Min) && IsInside(Other.Max));
434
435
436
437
438
439
442 return ((In.X > Min.X) && (In.X < Max.X) && (In.Y > Min.Y) && (In.Y < Max.Y));
446
447
448
449
450
451
454 return ((In.X >= Min.X) && (In.X <= Max.X) && (In.Y >= Min.Y) && (In.Y <= Max.Y));
458
459
460
461
462
465 return (IsInsideXY(Other.Min) && IsInsideXY(Other.Max));
469
470
471
472
473
474
475 UE_NODISCARD TBox<T> TransformBy(
const TMatrix<T>& M )
const;
478
479
480
481
482
483
484 UE_NODISCARD TBox<T> TransformBy(
const TTransform<T>& M )
const;
487
488
489
490
491
492
493 UE_NODISCARD TBox<T> TransformProjectBy(
const TMatrix<T>& ProjM )
const;
496
497
498
499
500 FString ToString()
const;
503
504
505
506
507 void GetVertices( TVector<T> (&Vertices)[8] )
const;
512
513
514
515
516
517
518 static TBox<T> BuildAABB(
const TVector<T>& Origin,
const TVector<T>& Extent )
520 TBox<T> NewBox(Origin - Extent, Origin + Extent);
528
529
530
531
532
533
534 friend FArchive& operator<<( FArchive& Ar, TBox<T>& Box )
536 return Ar << Box.Min << Box.Max << Box.IsValid;
540
541
542
543
544
545 friend void operator<<(FStructuredArchive::FSlot Slot, TBox<T>& Box)
547 FStructuredArchive::FRecord Record = Slot.EnterRecord();
551 bool Serialize( FArchive& Ar )
557 bool Serialize( FStructuredArchive::FSlot Slot )
563 bool SerializeFromMismatchedTag(FName StructTag, FArchive& Ar);
567
570FORCEINLINE TBox<T>& TBox<T>::operator+=(
const TVector<T> &Other )
574 Min.X = FMath::Min(Min.X, Other.X);
575 Min.Y = FMath::Min(Min.Y, Other.Y);
576 Min.Z = FMath::Min(Min.Z, Other.Z);
578 Max.X = FMath::Max(Max.X, Other.X);
579 Max.Y = FMath::Max(Max.Y, Other.Y);
580 Max.Z = FMath::Max(Max.Z, Other.Z);
595 if (IsValid && Other.IsValid)
597 Min.X = FMath::Min(Min.X, Other.Min.X);
598 Min.Y = FMath::Min(Min.Y, Other.Min.Y);
599 Min.Z = FMath::Min(Min.Z, Other.Min.Z);
601 Max.X = FMath::Max(Max.X, Other.Max.X);
602 Max.Y = FMath::Max(Max.Y, Other.Max.Y);
603 Max.Z = FMath::Max(Max.Z, Other.Max.Z);
605 else if (Other.IsValid)
614FORCEINLINE TVector<T> TBox<T>::GetClosestPointTo(
const TVector<T>& Point )
const
617 TVector<T> ClosestPoint = Point;
622 ClosestPoint.X = Min.X;
624 else if (Point.X > Max.X)
626 ClosestPoint.X = Max.X;
632 ClosestPoint.Y = Min.Y;
634 else if (Point.Y > Max.Y)
636 ClosestPoint.Y = Max.Y;
642 ClosestPoint.Z = Min.Z;
644 else if (Point.Z > Max.Z)
646 ClosestPoint.Z = Max.Z;
656 if ((Min.X > Other.Max.X) || (Other.Min.X > Max.X))
661 if ((Min.Y > Other.Max.Y) || (Other.Min.Y > Max.Y))
666 if ((Min.Z > Other.Max.Z) || (Other.Min.Z > Max.Z))
676FORCEINLINE bool TBox<T>::IntersectXY(
const TBox<T>& Other )
const
678 if ((Min.X > Other.Max.X) || (Other.Min.X > Max.X))
683 if ((Min.Y > Other.Max.Y) || (Other.Min.Y > Max.Y))
695 return FString::Printf(
TEXT(
"IsValid=%s, Min=(%s), Max=(%s)"), IsValid ?
TEXT(
"true") :
TEXT(
"false"), *Min.ToString(), *Max.ToString());
700TBox<T> TBox<T>::TransformBy(
const TMatrix<T>& M)
const
705 return TBox<T>(ForceInit);
710 const TVectorRegisterType<T> VecMin = VectorLoadFloat3_W0(&Min);
711 const TVectorRegisterType<T> VecMax = VectorLoadFloat3_W0(&Max);
713 const TVectorRegisterType<T> m0 = VectorLoadAligned(M.M[0]);
714 const TVectorRegisterType<T> m1 = VectorLoadAligned(M.M[1]);
715 const TVectorRegisterType<T> m2 = VectorLoadAligned(M.M[2]);
716 const TVectorRegisterType<T> m3 = VectorLoadAligned(M.M[3]);
718 const TVectorRegisterType<T> Half = VectorSetFloat1((T)0.5f);
719 const TVectorRegisterType<T> Origin = VectorMultiply(VectorAdd(VecMax, VecMin), Half);
720 const TVectorRegisterType<T> Extent = VectorMultiply(VectorSubtract(VecMax, VecMin), Half);
722 TVectorRegisterType<T> NewOrigin = VectorMultiply(
VectorReplicate(Origin, 0), m0);
723 NewOrigin = VectorMultiplyAdd(
VectorReplicate(Origin, 1), m1, NewOrigin);
724 NewOrigin = VectorMultiplyAdd(
VectorReplicate(Origin, 2), m2, NewOrigin);
725 NewOrigin = VectorAdd(NewOrigin, m3);
727 TVectorRegisterType<T> NewExtent = VectorAbs(VectorMultiply(
VectorReplicate(Extent, 0), m0));
728 NewExtent = VectorAdd(NewExtent, VectorAbs(VectorMultiply(
VectorReplicate(Extent, 1), m1)));
729 NewExtent = VectorAdd(NewExtent, VectorAbs(VectorMultiply(
VectorReplicate(Extent, 2), m2)));
731 const TVectorRegisterType<T> NewVecMin = VectorSubtract(NewOrigin, NewExtent);
732 const TVectorRegisterType<T> NewVecMax = VectorAdd(NewOrigin, NewExtent);
734 VectorStoreFloat3(NewVecMin, &(NewBox.Min.X));
735 VectorStoreFloat3(NewVecMax, &(NewBox.Max.X));
743TBox<T> TBox<T>::TransformBy(
const TTransform<T>& M)
const
745 return TransformBy(M.ToMatrixWithScale());
749void TBox<T>::GetVertices(TVector<T>(&Vertices)[8])
const
751 Vertices[0] = TVector<T>(Min);
752 Vertices[1] = TVector<T>(Min.X, Min.Y, Max.Z);
753 Vertices[2] = TVector<T>(Min.X, Max.Y, Min.Z);
754 Vertices[3] = TVector<T>(Max.X, Min.Y, Min.Z);
755 Vertices[4] = TVector<T>(Max.X, Max.Y, Min.Z);
756 Vertices[5] = TVector<T>(Max.X, Min.Y, Max.Z);
757 Vertices[6] = TVector<T>(Min.X, Max.Y, Max.Z);
758 Vertices[7] = TVector<T>(Max);
762TBox<T> TBox<T>::InverseTransformBy(
const TTransform<T>& M)
const
764 TVector<T> Vertices[8];
765 GetVertices(Vertices);
767 TBox<T> NewBox(ForceInit);
769 for (int32 VertexIndex = 0; VertexIndex <
UE_ARRAY_COUNT(Vertices); VertexIndex++)
771 TVector<T> ProjectedVertex = M.InverseTransformPosition(Vertices[VertexIndex]);
772 NewBox += ProjectedVertex;
779TBox<T> TBox<T>::TransformProjectBy(
const TMatrix<T>& ProjM)
const
781 TVector<T> Vertices[8];
782 GetVertices(Vertices);
784 TBox<T> NewBox(ForceInit);
786 for (int32 VertexIndex = 0; VertexIndex <
UE_ARRAY_COUNT(Vertices); VertexIndex++)
788 TVector4<T> ProjectedVertex = ProjM.TransformPosition(Vertices[VertexIndex]);
789 NewBox += ((TVector<T>)ProjectedVertex) / ProjectedVertex.W;
796TBox<T> TBox<T>::Overlap(
const TBox<T>& Other)
const
798 if (Intersect(Other) ==
false)
800 static TBox<T> EmptyBox(ForceInit);
806 TVector<T> MinVector, MaxVector;
808 MinVector.X = FMath::Max(Min.X, Other.Min.X);
809 MaxVector.X = FMath::Min(Max.X, Other.Max.X);
811 MinVector.Y = FMath::Max(Min.Y, Other.Min.Y);
812 MaxVector.Y = FMath::Min(Max.Y, Other.Max.Y);
814 MinVector.Z = FMath::Max(Min.Z, Other.Min.Z);
815 MaxVector.Z = FMath::Min(Max.Z, Other.Max.Z);
817 return TBox<T>(MinVector, MaxVector);
827template<>
struct TIsPODType<FBox3f> {
enum {
Value =
true }; };
828template<>
struct TIsUECoreVariant<FBox3f> {
enum { Value =
true }; };
831template<>
struct TIsPODType<FBox3d> {
enum {
Value =
true }; };
832template<>
struct TIsUECoreVariant<FBox3d> {
enum { Value =
true }; };
835inline bool FBox3f::SerializeFromMismatchedTag(FName StructTag, FArchive& Ar)
841inline bool FBox3d::SerializeFromMismatchedTag(FName StructTag, FArchive& Ar)
847
849template<
typename FReal>
850inline bool FMath::PointBoxIntersection
852 const UE::Math::TVector<FReal>& Point,
853 const UE::Math::TBox<FReal>& Box
856 return (Point.X >= Box.Min.X && Point.X <= Box.Max.X &&
857 Point.Y >= Box.Min.Y && Point.Y <= Box.Max.Y &&
858 Point.Z >= Box.Min.Z && Point.Z <= Box.Max.Z);
861template<
typename FReal>
862inline bool FMath::LineBoxIntersection
864 const UE::Math::TBox<FReal>& Box,
865 const UE::Math::TVector<FReal>& Start,
866 const UE::Math::TVector<FReal>& End,
867 const UE::Math::TVector<FReal>& StartToEnd
870 return LineBoxIntersection(Box, Start, End, StartToEnd, StartToEnd.Reciprocal());
873template<
typename FReal>
874inline bool FMath::LineBoxIntersection
876 const UE::Math::TBox<FReal>& Box,
877 const UE::Math::TVector<FReal>& Start,
878 const UE::Math::TVector<FReal>& End,
879 const UE::Math::TVector<FReal>& StartToEnd,
880 const UE::Math::TVector<FReal>& OneOverStartToEnd
883 UE::Math::TVector<FReal> Time;
884 bool bStartIsOutside =
false;
886 if(Start.X < Box.Min.X)
888 bStartIsOutside =
true;
889 if(End.X >= Box.Min.X)
891 Time.X = (Box.Min.X - Start.X) * OneOverStartToEnd.X;
898 else if(Start.X > Box.Max.X)
900 bStartIsOutside =
true;
901 if(End.X <= Box.Max.X)
903 Time.X = (Box.Max.X - Start.X) * OneOverStartToEnd.X;
915 if(Start.Y < Box.Min.Y)
917 bStartIsOutside =
true;
918 if(End.Y >= Box.Min.Y)
920 Time.Y = (Box.Min.Y - Start.Y) * OneOverStartToEnd.Y;
927 else if(Start.Y > Box.Max.Y)
929 bStartIsOutside =
true;
930 if(End.Y <= Box.Max.Y)
932 Time.Y = (Box.Max.Y - Start.Y) * OneOverStartToEnd.Y;
944 if(Start.Z < Box.Min.Z)
946 bStartIsOutside =
true;
947 if(End.Z >= Box.Min.Z)
949 Time.Z = (Box.Min.Z - Start.Z) * OneOverStartToEnd.Z;
956 else if(Start.Z > Box.Max.Z)
958 bStartIsOutside =
true;
959 if(End.Z <= Box.Max.Z)
961 Time.Z = (Box.Max.Z - Start.Z) * OneOverStartToEnd.Z;
975 const FReal MaxTime = Max3(Time.X,Time.Y,Time.Z);
977 if(MaxTime >= 0.0f && MaxTime <= 1.0f)
979 const UE::Math::TVector<FReal> Hit = Start + StartToEnd * MaxTime;
980 const FReal BOX_SIDE_THRESHOLD = 0.1f;
981 if( Hit.X > Box.Min.X - BOX_SIDE_THRESHOLD && Hit.X < Box.Max.X + BOX_SIDE_THRESHOLD &&
982 Hit.Y > Box.Min.Y - BOX_SIDE_THRESHOLD && Hit.Y < Box.Max.Y + BOX_SIDE_THRESHOLD &&
983 Hit.Z > Box.Min.Z - BOX_SIDE_THRESHOLD && Hit.Z < Box.Max.Z + BOX_SIDE_THRESHOLD)
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010template<
typename FReal>
1011inline bool FMath::SphereAABBIntersection(
const UE::Math::TVector<FReal>& SphereCenter,
const FReal RadiusSquared,
const UE::Math::TBox<FReal>& AABB)
1014 FReal DistSquared = 0.f;
1017 if (SphereCenter.X < AABB.Min.X)
1019 DistSquared += FMath::Square(SphereCenter.X - AABB.Min.X);
1021 else if (SphereCenter.X > AABB.Max.X)
1023 DistSquared += FMath::Square(SphereCenter.X - AABB.Max.X);
1025 if (SphereCenter.Y < AABB.Min.Y)
1027 DistSquared += FMath::Square(SphereCenter.Y - AABB.Min.Y);
1029 else if (SphereCenter.Y > AABB.Max.Y)
1031 DistSquared += FMath::Square(SphereCenter.Y - AABB.Max.Y);
1033 if (SphereCenter.Z < AABB.Min.Z)
1035 DistSquared += FMath::Square(SphereCenter.Z - AABB.Min.Z);
1037 else if (SphereCenter.Z > AABB.Max.Z)
1039 DistSquared += FMath::Square(SphereCenter.Z - AABB.Max.Z);
1042 return DistSquared <= RadiusSquared;
1046
1047
1048template<
typename FReal>
1049inline bool FMath::SphereAABBIntersection(
const UE::Math::TSphere<FReal>& Sphere,
const UE::Math::TBox<FReal>& AABB)
1051 FReal RadiusSquared = FMath::Square(Sphere.W);
1053 return SphereAABBIntersection(Sphere.Center, RadiusSquared, AABB);
#define UE_DEPRECATED(Version, Message)
#define UE_DECLARE_LWC_TYPE(...)
#define UE_SERIALIZE_VARIANT_FROM_MISMATCHED_TAG(AR_OR_SLOT, ALIAS, TYPE, ALT_TYPE)
#define SA_VALUE(Name, Value)
#define VectorReplicate(Vec, ElementIndex)
#define UE_KINDA_SMALL_NUMBER
#define UE_ARRAY_COUNT(array)
#define TEMPLATE_REQUIRES(...)