UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
Plane.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
4#include "Chaos/CorePlane.h"
6#include "ChaosArchive.h"
7#include "ChaosCheck.h"
8
9namespace Chaos
10{
11
12template<class T, int d>
13class TPlane final : public FImplicitObject
14{
15 public:
17
18
19 TPlane() : FImplicitObject(0, ImplicitObjectType::Plane) {} //needed for serialization
21 : FImplicitObject(0, ImplicitObjectType::Plane)
22 , MPlaneConcrete(InX, InNormal)
23 {
24 }
26 : FImplicitObject(0, ImplicitObjectType::Plane)
27 , MPlaneConcrete(Other.MPlaneConcrete)
28 {
29 }
31 : FImplicitObject(0, ImplicitObjectType::Plane)
32 , MPlaneConcrete(MoveTemp(Other.MPlaneConcrete))
33 {
34 }
35 virtual ~TPlane() {}
36
38 {
40 }
41
42 virtual FReal GetRadius() const override
43 {
44 return 0.0f;
45 }
46
50 T SignedDistance(const TVector<T, d>& x) const
51 {
52 return MPlaneConcrete.SignedDistance(x);
53 }
54
58 virtual FReal PhiWithNormal(const FVec3& x, FVec3& Normal) const override
59 {
60 return MPlaneConcrete.PhiWithNormal(x,Normal);
61 }
62
63 TVector<T, d> FindClosestPoint(const TVector<T, d>& x, const T Thickness = (T)0) const
64 {
65 return MPlaneConcrete.FindClosestPoint(x,Thickness);
66 }
67
68 virtual bool Raycast(const FVec3& StartPoint, const FVec3& Dir, const FReal Length, const FReal Thickness, FReal& OutTime, FVec3& OutPosition, FVec3& OutNormal, int32& OutFaceIndex) const override
69 {
70 return MPlaneConcrete.Raycast(StartPoint,Dir,Length,Thickness,OutTime,OutPosition,OutNormal,OutFaceIndex);
71 }
72
73 virtual Pair<FVec3, bool> FindClosestIntersectionImp(const FVec3& StartPoint, const FVec3& EndPoint, const FReal Thickness) const override
74 {
75 return MPlaneConcrete.FindClosestIntersection(StartPoint,EndPoint,Thickness);
76 }
77
78 const TVector<T,d>& X() const { return MPlaneConcrete.X(); }
79 const TVector<T,d>& Normal() const { return MPlaneConcrete.Normal(); }
80 const TVector<T, d>& Normal(const TVector<T, d>&) const { return MPlaneConcrete.Normal(); }
81
83 {
85 MPlaneConcrete.Serialize(Ar);
86 }
87
88 virtual void Serialize(FChaosArchive& Ar) override
89 {
91 SerializeImp(Ar);
92 }
93
94 virtual void Serialize(FArchive& Ar) override
95 {
96 SerializeImp(Ar);
97 }
98
99 virtual uint32 GetTypeHash() const override
100 {
101 return MPlaneConcrete.GetTypeHash();
102 }
103
104 const TPlaneConcrete<T>& PlaneConcrete() const { return MPlaneConcrete; }
105
106 private:
107 TPlaneConcrete<T> MPlaneConcrete;
108};
109
110template<typename T, int d>
112{
113 TVector<T, 2> Bary;
114 TVector<T, d> P10 = P1 - P0;
115 TVector<T, d> P20 = P2 - P0;
116 TVector<T, d> PP0 = P - P0;
117 T Size10 = P10.SizeSquared();
118 T Size20 = P20.SizeSquared();
123 using FVec2Real = decltype(Bary.X);
124 Bary.X = FVec2Real((Size20 * ProjP1 - ProjSides * ProjP2) / Denom);
125 Bary.Y = FVec2Real((Size10 * ProjP2 - ProjSides * ProjP1) / Denom);
126 return Bary;
127}
128
129template<typename T, int d>
131{
132 const TVector<T, d> P10 = P1 - P0;
133 const TVector<T, d> PP0 = P - P0;
135 if (Proj < (T)0) //first check we're not behind
136 {
137 OutAlpha = (T)0;
138 return P0;
139 }
140
141 const T Denom2 = P10.SizeSquared();
142 if (Denom2 < (T)1e-4)
143 {
144 OutAlpha = (T)0;
145 return P0;
146 }
147
148 //do proper projection
149 const T NormalProj = Proj / Denom2;
150 if (NormalProj > (T)1) //too far forward
151 {
152 OutAlpha = (T)1;
153 return P1;
154 }
155
157 return P0 + NormalProj * P10; //somewhere on the line
158}
159
160template<typename T, int d>
166
167template<typename T, int d>
169{
170 const T Epsilon = 1e-4f;
171
173
174 if (Bary[0] >= -Epsilon && Bary[0] <= 1 + Epsilon && Bary[1] >= -Epsilon && Bary[1] <= 1 + Epsilon && (Bary[0] + Bary[1]) <= (1 + Epsilon))
175 {
176 return ClosestPointOnPlane;
177 }
178
182
183 const T P10Dist2 = (P - P10Closest).SizeSquared();
184 const T P20Dist2 = (P - P20Closest).SizeSquared();
185 const T P21Dist2 = (P - P21Closest).SizeSquared();
186
187 if (P10Dist2 < P20Dist2)
188 {
189 if (P10Dist2 < P21Dist2)
190 {
191 return P10Closest;
192 }
193 else
194 {
195 return P21Closest;
196 }
197 }
198 else
199 {
200 if (P20Dist2 < P21Dist2)
201 {
202 return P20Closest;
203 }
204 else
205 {
206 return P21Closest;
207 }
208 }
209}
210
211template<typename T, int d>
213{
214 const TVector<T, d> PointOnPlane = TrianglePlane.FindClosestPoint(P);
215 return FindClosestPointOnTriangle(PointOnPlane, P0, P1, P2, P);
216}
217
218// This method follows FindClosestPointOnTriangle but does less duplicate work and can handle degenerate triangles. It also returns the barycentric coordinates for the returned point.
219template<typename T, int d>
221{
222 const TVector<T, d> P10 = P1 - P0;
223 const TVector<T, d> P20 = P2 - P0;
224 const TVector<T, d> P21 = P2 - P1;
225 const TVector<T, d> PP0 = P - P0;
226
227 const T Size10 = P10.SizeSquared();
228 const T Size20 = P20.SizeSquared();
229 const T Size21 = P21.SizeSquared();
230
231 const T ProjP1 = PP0.Dot(P10);
232 const T ProjP2 = PP0.Dot(P20);
233
234
235 auto ProjectToP01 = [&Bary, &P0, &P1, Size10, ProjP1]() -> TVector<T,d>
236 {
237 Bary.Z = 0.f;
238 Bary.Y = FMath::Clamp(ProjP1 / Size10, (T)0., (T)1.);
239 Bary.X = 1.f - Bary.Y;
240 const TVector<T,d> Result = Bary.X * P0 + Bary.Y * P1;
241 return Result;
242 };
243
244 auto ProjectToP02 = [&Bary, &P0, &P2, Size20, ProjP2]() -> TVector<T, d>
245 {
246 Bary.Y = 0.f;
247 Bary.Z = FMath::Clamp(ProjP2 / Size20, (T)0., (T)1.);
248 Bary.X = 1.f - Bary.Z;
249 const TVector<T, d> Result = Bary.X * P0 + Bary.Z * P2;
250 return Result;
251 };
252
253 auto ProjectToP12 = [&Bary, &P1, &P2, &P]() -> TVector<T, d>
254 {
255 const TVector<T,d> P2P1 = P2 - P1;
256
257 Bary.X = 0.f;
258 Bary.Z = FMath::Clamp(P2P1.Dot(P - P1) / P2P1.SizeSquared(), (T)0., (T)1.);
259 Bary.Y = 1.f - Bary.Z;
260 const TVector<T, d> Result = Bary.Y * P1 + Bary.Z * P2;
261 return Result;
262 };
263
264
265 // Degenerate triangles
267 {
269 {
270 // Triangle is (nearly) a single point.
271 Bary.X = (T)1.;
272 Bary.Y = Bary.Z = (T)0.;
273 return P0;
274 }
275
276 // Triangle is a line segment from P0(=P1) to P2. Project to that line segment.
277 return ProjectToP02();
278 }
280 {
281 // Triangle is a line segment from P0(=P2) to P1. Project to that line segment.
282 return ProjectToP01();
283 }
284
285
286 const T ProjSides = P10.Dot(P20);
287 const T Denom = Size10 * Size20 - ProjSides * ProjSides;
288
290 {
291 // Triangle is a line segment from P0 to P1(=P2), or otherwise the 3 points are (nearly) colinear. Project to the longest edge.
292 if (Size21 > Size20)
293 {
294 return ProjectToP12();
295 }
296 else if (Size20 > Size10)
297 {
298 return ProjectToP02();
299 }
300 else
301 {
302 return ProjectToP01();
303 }
304 }
305
306 // Non-degenerate triangle
307
308 // Numerators of barycentric coordinates if P is inside triangle
309 const T BaryYNum = (Size20 * ProjP1 - ProjSides * ProjP2);
310 const T BaryZNum = (Size10 * ProjP2 - ProjSides * ProjP1);
311
312 // Using this specific epsilon to have parity with FindClosestPointOnTriangle
313 constexpr T Epsilon = (T)1e-4;
314 const T EpsilonScaledByDenom = Epsilon * Denom;
315
316 if (BaryYNum + BaryZNum > Denom * (1 + Epsilon)) // i.e., Bary.X < -Epsilon.
317 {
319 {
320 // Bary.X < 0, Bary.Y < 0, (Bary.Z > 1)
321
322 // We're outside the triangle in the region opposite angle P2. (if angle at P2 is > 90 degrees, closest point could be on one of these segments)
323 // Should project onto line segment P02 or P12
324 if (ProjP2 < Size20)
325 {
326 // Closer to P02
327 // Project to line segment from P02
328 return ProjectToP02();
329 }
330 }
331 else if (BaryZNum < -EpsilonScaledByDenom)
332 {
333 // Bary.X < 0, Bary.Y > 1, Bary.Z < 0
334
335 // We're outside the triangle in the region opposite the angle P1.
336 // Should project onto line segment P01 or P12
337 if (ProjP1 < Size10)
338 {
339 // Closer to P01.
340 // Project to line segment from P01
341 return ProjectToP01();
342 }
343 }
344
345 // Bary.X < 0, Bary.Y >=0, Bary.Z >= 0
346
347 // We're outside the triangle in the region closest to P12
348 // Project to line segment from P12
349 return ProjectToP12();
350 }
351 else if (BaryYNum < -EpsilonScaledByDenom)
352 {
354 {
355 // Bary.X > 1, Bary.Y < 0, Bary.Z < 0
356
357 // We're outside the triangle in the region opposite P0.
358 // Should project onto line segment P01 or P02
359 if (ProjP1 > 0.f)
360 {
361 // Closer to P01.
362 // Project to line segment from P01
363 return ProjectToP01();
364 }
365 }
366
367 // Bary.X >= 0, Bary.Y < 0, Bary.Z >= 0
368 // We're outside the triangle in region closest to P02.
369 // Project to line segment from P02
370 return ProjectToP02();
371 }
372 else if (BaryZNum < -EpsilonScaledByDenom)
373 {
374 // Bary.X >=0, Bary.Y >=0, Bary.Z < 0
375 // We're outside the triangle in the region closest to P01
376 // Project to line segment from P0 to P1
377 return ProjectToP01();
378 }
379
380 // Bary.X >= 0, Bary.Y >= 0, Bary.Z >= 0
381 // Interior of triangle!
382 Bary.Y = BaryYNum / Denom;
383 Bary.Z = BaryZNum / Denom;
384 Bary.X = (T)1. - Bary.Y - Bary.Z;
385 const TVector<T,d> Result = Bary.X * P0 + Bary.Y * P1 + Bary.Z * P2;
386 return Result;
387}
388
389template<typename T, int d>
391{
392 FVector LI = I, LD = D;
393 FPlane LP1(P1.X(), P1.Normal()), LP2(P2.X(), P2.Normal());
395 I = LI; D = LD;
396 return RetVal;
397}
398
399}
#define FORCEINLINE
Definition AndroidPlatform.h:140
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define UE_DOUBLE_SMALL_NUMBER
Definition UnrealMathUtility.h:139
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition ChaosArchive.h:364
Definition ChaosArchive.h:167
Definition ImplicitObject.h:111
virtual FName GetTypeName() const
Definition ImplicitObject.h:414
CHAOS_API void SerializeImp(FArchive &Ar)
Definition ImplicitObject.cpp:337
Definition CorePlane.h:12
Definition Plane.h:14
virtual FReal GetRadius() const override
Definition Plane.h:42
TVector< T, d > FindClosestPoint(const TVector< T, d > &x, const T Thickness=(T) 0) const
Definition Plane.h:63
virtual uint32 GetTypeHash() const override
Definition Plane.h:99
virtual void Serialize(FChaosArchive &Ar) override
Definition Plane.h:88
virtual Pair< FVec3, bool > FindClosestIntersectionImp(const FVec3 &StartPoint, const FVec3 &EndPoint, const FReal Thickness) const override
Definition Plane.h:73
TPlane(const TVector< T, d > &InX, const TVector< T, d > &InNormal)
Definition Plane.h:20
virtual ~TPlane()
Definition Plane.h:35
const TVector< T, d > & Normal(const TVector< T, d > &) const
Definition Plane.h:80
virtual FName GetTypeName() const
Definition ImplicitObject.h:414
T SignedDistance(const TVector< T, d > &x) const
Definition Plane.h:50
virtual void Serialize(FArchive &Ar) override
Definition Plane.h:94
const TPlaneConcrete< T > & PlaneConcrete() const
Definition Plane.h:104
TPlane(TPlane< T, d > &&Other)
Definition Plane.h:30
virtual FReal PhiWithNormal(const FVec3 &x, FVec3 &Normal) const override
Definition Plane.h:58
const TVector< T, d > & Normal() const
Definition Plane.h:79
TPlane(const TPlane< T, d > &Other)
Definition Plane.h:25
static constexpr EImplicitObjectType StaticType()
Definition Plane.h:37
FORCEINLINE void SerializeImp(FArchive &Ar)
Definition Plane.h:82
TPlane()
Definition Plane.h:19
virtual bool Raycast(const FVec3 &StartPoint, const FVec3 &Dir, const FReal Length, const FReal Thickness, FReal &OutTime, FVec3 &OutPosition, FVec3 &OutNormal, int32 &OutFaceIndex) const override
Definition Plane.h:68
const TVector< T, d > & X() const
Definition Plane.h:78
Definition Vector.h:41
Definition Archive.h:1208
@ Plane
Definition ImplicitObjectType.h:15
Definition SkeletalMeshComponent.h:307
uint8 EImplicitObjectType
Definition ImplicitObjectType.h:41
const TVector< T, d > FindClosestPointAndAlphaOnLineSegment(const TVector< T, d > &P0, const TVector< T, d > &P1, const TVector< T, d > &P, T &OutAlpha)
Definition Plane.h:130
FRealDouble FReal
Definition Real.h:22
TVector< T, d > FindClosestPointOnTriangle(const TVector< T, d > &ClosestPointOnPlane, const TVector< T, d > &P0, const TVector< T, d > &P1, const TVector< T, d > &P2, const TVector< T, d > &P)
Definition Plane.h:168
TVector< T, d > FindClosestPointAndBaryOnTriangle(const TVector< T, d > &P0, const TVector< T, d > &P1, const TVector< T, d > &P2, const TVector< T, d > &P, TVector< T, 3 > &Bary)
Definition Plane.h:220
const TVector< T, d > FindClosestPointOnLineSegment(const TVector< T, d > &P0, const TVector< T, d > &P1, const TVector< T, d > &P)
Definition Plane.h:161
bool IntersectPlanes2(TVector< T, d > &I, TVector< T, d > &D, const TPlane< T, d > &P1, const TPlane< T, d > &P2)
Definition Plane.h:390
TVector< T, 2 > ComputeBarycentricInPlane(const TVector< T, d > &P0, const TVector< T, d > &P1, const TVector< T, d > &P2, const TVector< T, d > &P)
Definition Plane.h:111
Definition Pair.h:8
static bool IntersectPlanes2(UE::Math::TVector< FReal > &I, UE::Math::TVector< FReal > &D, const UE::Math::TPlane< FReal > &P1, const UE::Math::TPlane< FReal > &P2)
static constexpr UE_FORCEINLINE_HINT T Clamp(const T X, const T MinValue, const T MaxValue)
Definition UnrealMathUtility.h:592