UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
IntrRay3Triangle3.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3// Port of WildMagic IntrRay3Triangle3
4
5#pragma once
6
7#include "VectorTypes.h"
8#include "TriangleTypes.h"
9#include "VectorUtil.h"
10#include "Math/Ray.h"
11
13
14namespace UE
15{
16namespace Geometry
17{
18
19using namespace UE::Math;
20
21// Ray representation with additional data to support 'watertight' raycasts, i.e. raycasts that cannot slip between adjacent triangles w/ floating point error
22template<typename Real>
24{
29
30 TWatertightRay3() = default;
36 {
37 Init(InRay.Origin, InRay.Direction);
38 }
39
41 {
42 // By convention, remap the max dimension to 'Z', and the other two to X and Y
43 static int32 NextDim[3]{ 1, 2, 0 };
47 // Preserve winding
48 if (InDirection[DimRemap.Z] < 0)
49 {
51 }
52 // Direction of ray must not be a zero vector
53 checkSlow(InDirection[DimRemap.Z] != (Real)0.0);
54 // Compute transform to ray space
56 // Copy standard origin/direction (unchanged)
59 }
60};
61
65template <typename Real, typename RayType = TRay<Real>>
67{
68public:
69 // Input
72
73 // Output
77
78
84
85 // watertight intersection test
92
94 {
95 // Compute the offset origin, edges, and normal.
96 TVector<Real> Diff = InRay.Origin - InTriangle.V[0];
100
101 // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
102 // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
103 // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
104 // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
105 // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
106 Real DdN = InRay.Direction.Dot(Normal);
107 Real Sign;
109 {
110 Sign = (Real)1;
111 }
113 {
114 Sign = (Real)-1;
115 DdN = -DdN;
116 }
117 else
118 {
119 // Ray and triangle are parallel, call it a "no intersection"
120 // even if the ray does intersect.
122 return false;
123 }
124
125 Real DdQxE2 = Sign * InRay.Direction.Dot(Diff.Cross(Edge2));
126 if (DdQxE2 >= (Real)0)
127 {
128 Real DdE1xQ = Sign * InRay.Direction.Dot(Edge1.Cross(Diff));
129 if (DdE1xQ >= (Real)0)
130 {
131 if (DdQxE2 + DdE1xQ <= DdN)
132 {
133 // Line intersects triangle, check if ray does.
134 Real QdN = -Sign * Diff.Dot(Normal);
135 if (QdN >= (Real)0)
136 {
137 // Ray intersects triangle.
139 return true;
140 }
141 // else: t < 0, no intersection
142 }
143 // else: b1+b2 > 1, no intersection
144 }
145 // else: b2 < 0, no intersection
146 }
147 // else: b1 < 0, no intersection
148
150 return false;
151 }
152
153
157 bool Test()
158 {
160 }
161
162
169 {
170 // Compute the offset origin, edges, and normal.
171 TVector<Real> Diff = InRay.Origin - InTriangle.V[0];
175
176 // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
177 // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
178 // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
179 // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
180 // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
181 Real DdN = InRay.Direction.Dot(Normal);
182 Real Sign;
184 {
185 Sign = (Real)1;
186 }
188 {
189 Sign = (Real)-1;
190 DdN = -DdN;
191 }
192 else
193 {
194 // Ray and triangle are parallel, call it a "no intersection"
195 // even if the ray does intersect.
197 return false;
198 }
199
200 Real DdQxE2 = Sign * InRay.Direction.Dot(Diff.Cross(Edge2));
201 if (DdQxE2 >= (Real)0)
202 {
203 Real DdE1xQ = Sign * InRay.Direction.Dot(Edge1.Cross(Diff));
204 if (DdE1xQ >= (Real)0)
205 {
206 if (DdQxE2 + DdE1xQ <= DdN)
207 {
208 // Line intersects triangle, check if ray does.
209 Real QdN = -Sign * Diff.Dot(Normal);
210 if (QdN >= (Real)0)
211 {
212 // Ray intersects triangle.
213 Real Inv = ((Real)1) / DdN;
219 return true;
220 }
221 // else: t < 0, no intersection
222 }
223 // else: b1+b2 > 1, no intersection
224 }
225 // else: b2 < 0, no intersection
226 }
227 // else: b1 < 0, no intersection
228
230 return false;
231 }
232
233
234 // Find intersection point in a 'consistent' way, such that rays should not 'leak' between adjacent triangles.
235 // Note this may return true but report an intersection point slightly outside the triangle, due to numerical precision.
236 // Rays parallel to the triangle are still considered not intersecting.
237 // @return true if ray intersects triangle
243
248
249
250private:
251 // Watertight raycast implementation
252 template<bool bNeedResult> // if bNeedResult is false, we will not compute the OutRayParameter and OutTriangleBaryCoords
253 static bool FindWatertightIntersectionInternal(const TWatertightRay3<Real>& InRay, const TTriangle3<Real>& InTriangle,
255 {
257
258 // transform the input triangle to sheared space w/ the ray through the origin the along Z axis,
259 // so the line of the ray intersects the triangle if the 2D projection of the triangle touches the origin
260 TTriangle3<Real> OriginRelTri(InTriangle.V[0] - InRay.Origin, InTriangle.V[1] - InRay.Origin, InTriangle.V[2] - InRay.Origin);
262 for (int32 Idx = 0; Idx < 3; ++Idx)
263 {
264 TVector<Real> V = OriginRelTri.V[Idx];
265 Tri2D.V[Idx] = TVector2<Real>(V[InRay.DimRemap.X] - InRay.Shear.X * V[InRay.DimRemap.Z], V[InRay.DimRemap.Y] - InRay.Shear.Y * V[InRay.DimRemap.Z]);
266 }
267
268 // Use exact predicate for orientation test of triangle segments vs the origin
269 // Note: This is just A.X*B.Y-A.Y*B.X, with some special handling when the result is zero to ensure the sign of the result is accurate
274 );
275
276 if ((BaryScaled.X < 0 || BaryScaled.Y < 0 || BaryScaled.Z < 0) &&
277 (BaryScaled.X > 0 || BaryScaled.Y > 0 || BaryScaled.Z > 0))
278 {
279 return false;
280 }
281
282 Real Det = BaryScaled.X + BaryScaled.Y + BaryScaled.Z;
283 if (Det == 0)
284 {
285 return false;
286 }
287
288 Real ScaledZ[3];
289 for (int32 Idx = 0; Idx < 3; ++Idx)
290 {
291 ScaledZ[Idx] = InRay.Shear.Z * OriginRelTri.V[Idx][InRay.DimRemap.Z];
292 }
293 // T parameter in scaled space
294 Real ScaledT =
295 BaryScaled.X * ScaledZ[0] +
296 BaryScaled.Y * ScaledZ[1] +
297 BaryScaled.Z * ScaledZ[2];
298
299 if ((ScaledT < 0 && Det > 0) || (ScaledT > 0 && Det < 0))
300 {
301 return false;
302 }
303 if constexpr (bNeedResult)
304 {
305 Real InvDet = (Real)1.0 / Det;
306
309 }
311 return true;
312 }
313
314};
315
320
321} // end namespace UE::Geometry
322} // end namespace UE
@ Normal
Definition AndroidInputInterface.h:116
#define checkSlow(expr)
Definition AssertionMacros.h:332
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
void Init()
Definition LockFreeList.h:4
EIntersectionType
Definition VectorUtil.h:18
Definition MathUtil.h:150
Definition IntrRay3Triangle3.h:67
TTriangle3< Real > Triangle
Definition IntrRay3Triangle3.h:71
static bool FindIntersection(const TWatertightRay3< Real > &InRay, const TTriangle3< Real > &InTriangle, Real &OutRayParameter, FVector3d &OutTriangleBaryCoords, EIntersectionType &OutIntersectionType)
Definition IntrRay3Triangle3.h:238
EIntersectionType IntersectionType
Definition IntrRay3Triangle3.h:76
static bool TestIntersection(const TWatertightRay3< Real > &InRay, const TTriangle3< Real > &InTriangle, EIntersectionType &OutIntersectionType)
Definition IntrRay3Triangle3.h:86
bool Test()
Definition IntrRay3Triangle3.h:157
Real RayParameter
Definition IntrRay3Triangle3.h:74
static bool FindIntersection(const TRay< Real > &InRay, const TTriangle3< Real > &InTriangle, Real &OutRayParameter, FVector3d &OutTriangleBaryCoords, EIntersectionType &OutIntersectionType)
Definition IntrRay3Triangle3.h:167
TIntrRay3Triangle3(const RayType &RayIn, const TTriangle3< Real > &TriangleIn)
Definition IntrRay3Triangle3.h:79
FVector3d TriangleBaryCoords
Definition IntrRay3Triangle3.h:75
static bool TestIntersection(const TRay< Real > &InRay, const TTriangle3< Real > &InTriangle, EIntersectionType &OutIntersectionType)
Definition IntrRay3Triangle3.h:93
bool Find()
Definition IntrRay3Triangle3.h:244
RayType Ray
Definition IntrRay3Triangle3.h:70
RealType Orient2Origin(const TVector2< RealType > &A, const TVector2< RealType > &B)
Definition ExactPredicates.h:80
int Max3Index(const ValueVecType &Vector3)
Definition VectorUtil.h:194
TWatertightRay3< double > FWatertightRay3d
Definition IntrRay3Triangle3.h:317
TIntrRay3Triangle3< double > FIntrRay3Triangle3d
Definition IntrRay3Triangle3.h:319
TWatertightRay3< float > FWatertightRay3f
Definition IntrRay3Triangle3.h:316
TIntrRay3Triangle3< float > FIntrRay3Triangle3f
Definition IntrRay3Triangle3.h:318
Definition Sphere.cpp:10
Definition AdvancedWidgetsModule.cpp:13
Definition TriangleTypes.h:39
Definition TriangleTypes.h:263
Definition IntrRay3Triangle3.h:24
void Init(const TVector< Real > &InOrigin, const TVector< Real > &InDirection)
Definition IntrRay3Triangle3.h:40
TVector< Real > Shear
Definition IntrRay3Triangle3.h:26
FIntVector3 DimRemap
Definition IntrRay3Triangle3.h:25
TVector< Real > Origin
Definition IntrRay3Triangle3.h:27
TWatertightRay3(const TRay< Real > &InRay)
Definition IntrRay3Triangle3.h:35
TVector< Real > Direction
Definition IntrRay3Triangle3.h:28
TWatertightRay3(const TVector< Real > &InOrigin, const TVector< Real > &InDirection)
Definition IntrRay3Triangle3.h:31
IntType Y
Definition IntVector.h:34
IntType X
Definition IntVector.h:31
IntType Z
Definition IntVector.h:37
Definition Ray.h:19
Definition Vector2D.h:38
Definition Vector.h:51
UE_FORCEINLINE_HINT TVector< T > Cross(const TVector< T > &V2) const
Definition Vector.h:1535
UE_FORCEINLINE_HINT T Dot(const TVector< T > &V) const
Definition Vector.h:1553