UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
TaperedCylinder.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
5#include "Chaos/Cylinder.h"
6#include "Chaos/Plane.h"
7
8namespace Chaos
9{
10 struct FTaperedCylinderSpecializeSamplingHelper;
11
13 {
14 public:
16 : FImplicitObject(EImplicitObject::FiniteConvex, ImplicitObjectType::TaperedCylinder)
17 {
18 this->bIsConvex = true;
19 }
20 FTaperedCylinder(const FVec3& x1, const FVec3& x2, const FReal Radius1, const FReal Radius2)
21 : FImplicitObject(EImplicitObject::FiniteConvex, ImplicitObjectType::TaperedCylinder)
22 , MPlane1(x1, (x2 - x1).GetSafeNormal())
23 , MPlane2(x2, -MPlane1.Normal())
24 , MHeight((FRealSingle)((x2 - x1).Size()))
25 , MRadius1((FRealSingle)Radius1)
26 , MRadius2((FRealSingle)Radius2)
27 , MLocalBoundingBox(x1, x1)
28 {
29 this->bIsConvex = true;
30 MLocalBoundingBox.GrowToInclude(x2);
31 FRealSingle MaxRadius = MRadius1;
32 if (MaxRadius < MRadius2)
33 MaxRadius = MRadius2;
34 MLocalBoundingBox = FAABB3(MLocalBoundingBox.Min() - FVec3(MaxRadius), MLocalBoundingBox.Max() + FVec3(MaxRadius));
35 }
37 : FImplicitObject(EImplicitObject::FiniteConvex, ImplicitObjectType::TaperedCylinder)
38 , MPlane1(Other.MPlane1)
39 , MPlane2(Other.MPlane2)
40 , MHeight(Other.MHeight)
41 , MRadius1(Other.MRadius1)
42 , MRadius2(Other.MRadius2)
43 , MLocalBoundingBox(Other.MLocalBoundingBox)
44 {
45 this->bIsConvex = true;
46 }
48 : FImplicitObject(EImplicitObject::FiniteConvex, ImplicitObjectType::TaperedCylinder)
49 , MPlane1(MoveTemp(Other.MPlane1))
50 , MPlane2(MoveTemp(Other.MPlane2))
51 , MHeight(Other.MHeight)
52 , MRadius1(Other.MRadius1)
53 , MRadius2(Other.MRadius2)
54 , MLocalBoundingBox(MoveTemp(Other.MLocalBoundingBox))
55 {
56 this->bIsConvex = true;
57 }
59
61
69 TArray<FVec3> ComputeLocalSamplePoints(const int32 NumPoints, const bool IncludeEndCaps = true) const;
70
79 TArray<FVec3> ComputeLocalSamplePoints(const FReal PointsPerUnitArea, const bool IncludeEndCaps = true, const int32 MinPoints = 0, const int32 MaxPoints = 1000) const
80 { return ComputeLocalSamplePoints(FMath::Clamp(static_cast<int32>(ceil(PointsPerUnitArea * GetArea(IncludeEndCaps))), MinPoints, MaxPoints), IncludeEndCaps); }
81
89 TArray<FVec3> ComputeSamplePoints(const int32 NumPoints, const bool IncludeEndCaps = true) const;
90
99 TArray<FVec3> ComputeSamplePoints(const FReal PointsPerUnitArea, const bool IncludeEndCaps = true, const int32 MinPoints = 0, const int32 MaxPoints = 1000) const
100 { return ComputeSamplePoints(FMath::Clamp(static_cast<int32>(ceil(PointsPerUnitArea * GetArea(IncludeEndCaps))), MinPoints, MaxPoints), IncludeEndCaps); }
101
102 virtual const FAABB3 BoundingBox() const override { return MLocalBoundingBox; }
103
105 {
106 const FVec3f Xf(x);
107 const FVec3f& Normal1 = MPlane1.Normal();
108 const FRealSingle Distance1 = MPlane1.SignedDistance(Xf);
110 {
111 ensure(MPlane2.SignedDistance(Xf) > (FRealSingle)0.);
112 const FVec3f v = x - FVec3f(Normal1 * Distance1 + MPlane1.X());
113 if (v.Size() > MRadius1)
114 {
115 const FVec3f Corner = FVec3f(v.GetSafeNormal()) * MRadius1 + MPlane1.X();
116 const FVec3f CornerVector = x - Corner;
117 Normal = CornerVector.GetSafeNormal();
118 return CornerVector.Size();
119 }
120 else
121 {
122 Normal = -Normal1;
123 return -Distance1;
124 }
125 }
126 const FVec3f& Normal2 = MPlane2.Normal(); // Used to be Distance2 = MPlane2.PhiWithNormal(x, Normal2); but that would trigger
127 const FRealSingle Distance2 = MHeight - Distance1; // the ensure on Distance2 being slightly larger than MHeight in some border cases
129 {
130 const FVec3f v = Xf - FVec3f(Normal2 * Distance2 + MPlane2.X());
131 if (v.Size() > MRadius2)
132 {
133 const FVec3f Corner = FVec3f(v.GetSafeNormal()) * MRadius2 + MPlane2.X();
134 const FVec3f CornerVector = Xf - Corner;
135 Normal = CornerVector.GetSafeNormal();
136 return CornerVector.Size();
137 }
138 else
139 {
140 Normal = -Normal2;
141 return -Distance2;
142 }
143 }
144 ensure(Distance1 <= MHeight && Distance2 <= MHeight);
145 const FVec3f SideVector = (Xf - FVec3f(Normal1 * Distance1 + MPlane1.X()));
146 const FRealSingle SideDistance = SideVector.Size() - GetRadiusAtDistance(Distance1);
147 if (SideDistance < 0.)
148 {
151 {
153 return -TopDistance;
154 }
155 }
156 Normal = SideVector.GetSafeNormal();
157 return SideDistance;
158 }
159
160 Pair<FVec3, bool> FindClosestIntersection(const FVec3& StartPoint, const FVec3& EndPoint, const FReal Thickness)
161 {
162 TArray<Pair<FReal, FVec3>> Intersections;
163 FReal DeltaRadius = FGenericPlatformMath::Abs(MRadius2 - MRadius1);
164 if (DeltaRadius == 0)
165 return FCylinder(MPlane1.X(), MPlane2.X(), MRadius1).FindClosestIntersection(StartPoint, EndPoint, Thickness);
169 if (MRadius2 > MRadius1)
170 {
171 BaseNormal = MPlane2.Normal();
172 BaseRadius = MRadius2 + Thickness;
173 BaseCenter = MPlane2.X();
174 }
175 else
176 {
177 BaseNormal = MPlane1.Normal();
178 BaseRadius = MRadius1 + Thickness;
179 BaseCenter = MPlane1.X();
180 }
185 check(theta > 0 && theta < UE_PI / 2);
186 FVec3 Direction = EndPoint - StartPoint;
187 FReal Length = Direction.Size();
188 Direction = Direction.GetSafeNormal();
189 auto DDotN = FVec3::DotProduct(Direction, -BaseNormal);
190 auto SMT = StartPoint - Top;
191 auto SMTDotN = FVec3::DotProduct(SMT, -BaseNormal);
192 FReal a = DDotN * DDotN - cossqtheta;
193 FReal b = 2 * (DDotN * SMTDotN - FVec3::DotProduct(Direction, SMT) * cossqtheta);
194 FReal c = SMTDotN * SMTDotN - SMT.SizeSquared() * cossqtheta;
195 FReal Determinant = b * b - 4 * a * c;
196 if (Determinant == 0)
197 {
198 FReal Root = -b / (2 * a);
199 FVec3 RootPoint = Root * Direction + StartPoint;
200 if (Root >= 0 && Root <= Length && FVec3::DotProduct(RootPoint - Top, -BaseNormal) >= 0)
201 {
202 Intersections.Add(MakePair(Root, RootPoint));
203 }
204 }
205 if (Determinant > 0)
206 {
207 FReal Root1 = (-b - sqrt(Determinant)) / (2 * a);
208 FReal Root2 = (-b + sqrt(Determinant)) / (2 * a);
209 FVec3 Root1Point = Root1 * Direction + StartPoint;
210 FVec3 Root2Point = Root2 * Direction + StartPoint;
211 if (Root1 < 0 || Root1 > Length || FVec3::DotProduct(Root1Point - Top, -BaseNormal) < 0)
212 {
213 if (Root2 >= 0 && Root2 <= Length && FVec3::DotProduct(Root2Point - Top, -BaseNormal) >= 0)
214 {
215 Intersections.Add(MakePair(Root2, Root2Point));
216 }
217 }
218 else if (Root2 < 0 || Root2 > Length || FVec3::DotProduct(Root2Point - Top, -BaseNormal) < 0)
219 {
220 Intersections.Add(MakePair(Root1, Root1Point));
221 }
222 else if (Root1 < Root2 && FVec3::DotProduct(Root1Point - Top, -BaseNormal) >= 0)
223 {
224 Intersections.Add(MakePair(Root1, Root1Point));
225 }
226 else if (FVec3::DotProduct(Root2Point - Top, -BaseNormal) >= 0)
227 {
228 Intersections.Add(MakePair(Root2, Root2Point));
229 }
230 }
231 auto Plane1Intersection = MPlane1.FindClosestIntersection(StartPoint, EndPoint, Thickness);
232 if (Plane1Intersection.Second)
233 Intersections.Add(MakePair((FReal)(Plane1Intersection.First - StartPoint).Size(), Plane1Intersection.First));
234 auto Plane2Intersection = MPlane2.FindClosestIntersection(StartPoint, EndPoint, Thickness);
235 if (Plane2Intersection.Second)
236 Intersections.Add(MakePair((FReal)(Plane2Intersection.First - StartPoint).Size(), Plane2Intersection.First));
237 Intersections.Sort([](const Pair<FReal, FVec3>& Elem1, const Pair<FReal, FVec3>& Elem2) { return Elem1.First < Elem2.First; });
238 for (const auto& Elem : Intersections)
239 {
240 if (SignedDistance(Elem.Second) <= (Thickness + 1e-4))
241 {
242 return MakePair(Elem.Second, true);
243 }
244 }
245 return MakePair(FVec3(0), false);
246 }
247
248 FReal GetRadius1() const { return MRadius1; }
249 FReal GetRadius2() const { return MRadius2; }
250 FReal GetHeight() const { return MHeight; }
251 FReal GetSlantHeight() const { const FReal R1mR2 = MRadius1-MRadius2; return FMath::Sqrt(R1mR2*R1mR2 + MHeight*MHeight); }
252 FVec3 GetX1() const { return MPlane1.X(); }
253 const FVec3f& GetX1f() const { return MPlane1.X(); }
254 FVec3 GetX2() const { return MPlane2.X(); }
255 const FVec3f& GetX2f() const { return MPlane2.X(); }
257 FVec3 GetOrigin() const { return MPlane1.X(); }
258 const FVec3f& GetOriginf() const { return MPlane1.X(); }
260 FVec3 GetInsertion() const { return MPlane2.X(); }
261 const FVec3f& GetInsertionf() const { return MPlane2.X(); }
262 FVec3 GetCenter() const { return (MPlane1.X() + MPlane2.X()) * (FReal)0.5; }
264 FVec3 GetCenterOfMass() const // centroid
265 {
266 const FReal R1R1 = MRadius1 * MRadius1;
267 const FReal R2R2 = MRadius2 * MRadius2;
268 const FReal R1R2 = MRadius1 * MRadius2;
269 return FVec3(0, 0, static_cast<FReal>(MHeight*(R1R1 + 2.*R1R2 + 3.*R2R2) / 4.*(R1R1 + R1R2 + R2R2)));
270 }
271 FVec3 GetAxis() const { return (MPlane2.X() - MPlane1.X()).GetSafeNormal(); }
272
273 FReal GetArea(const bool IncludeEndCaps = true) const { return GetArea(MHeight, MRadius1, MRadius2, IncludeEndCaps); }
274 static FReal GetArea(const FReal Height, const FReal Radius1, const FReal Radius2, const bool IncludeEndCaps)
275 {
276 static const FReal TwoPI = UE_PI * 2;
277 if (Radius1 == Radius2)
278 {
279 const FReal TwoPIR1 = TwoPI * Radius1;
280 return IncludeEndCaps ?
281 TwoPIR1 * Height + TwoPIR1 * Radius1 :
282 TwoPIR1 * Height;
283 }
284 else
285 {
286 const FReal R1_R2 = Radius1 - Radius2;
287 const FReal CylArea = UE_PI * (Radius1 + Radius2) * FMath::Sqrt((R1_R2 * R1_R2) + (Height * Height));
288 return IncludeEndCaps ?
289 CylArea + UE_PI * Radius1 * Radius1 + UE_PI * Radius2 * Radius2 :
290 CylArea;
291 }
292 }
293
294 FReal GetVolume() const { return GetVolume(MHeight, MRadius1, MRadius2); }
295 static FReal GetVolume(const FReal Height, const FReal Radius1, const FReal Radius2)
296 {
297 static const FReal PI_3 = UE_PI / 3;
298 return PI_3 * Height * (Radius1 * Radius1 + Radius1 * Radius2 + Radius2 * Radius2);
299 }
300
301 FMatrix33 GetInertiaTensor(const FReal Mass) const { return GetInertiaTensor(Mass, MHeight, MRadius1, MRadius2); }
302 static FMatrix33 GetInertiaTensor(const FReal Mass, const FReal Height, const FReal Radius1, const FReal Radius2)
303 {
304 // https://www.wolframalpha.com/input/?i=conical+frustum
305 const FReal R1 = FMath::Min(Radius1, Radius2);
306 const FReal R2 = FMath::Max(Radius1, Radius2);
307 const FReal HH = Height * Height;
308 const FReal R1R1 = R1 * R1;
309 const FReal R1R2 = R1 * R2;
310 const FReal R2R2 = R2 * R2;
311
312 const FReal Num1 = static_cast<FReal>(2. * HH * (R1R1 + 3. * R1R2 + 6. * R2R2)); // 2H^2 * (R1^2 + 3R1R2 + 6R2^2)
313 const FReal Num2 = static_cast<FReal>(3. * (R1R1 * R1R1 + R1R1 * R1R2 + R1R2 * R1R2 + R1R2 * R2R2 + R2R2 * R2R2)); // 3 * (R1^4 + R1^3R2 + R1^2R2^2 + R1R2^3 + R2^4)
314 const FReal Den1 = UE_PI * (R1R1 + R1R2 + R2R2); // PI * (R1^2 + R1R2 + R2^2)
315
316 const FReal Diag12 = Mass * (Num1 + Num2) / (static_cast<FReal>(20.) * Den1);
317 const FReal Diag3 = Mass * Num2 / (static_cast<FReal>(10.) * Den1);
318
319 return FMatrix33(Diag12, Diag12, Diag3);
320 }
321
324 {
325 // since the cylinder stores an axis and the InertiaTensor is assumed to be along the ZAxis
326 // we need to make sure to return the rotation of the axis from Z
327 return FRotation3::FromRotatedVector(FVec3(0, 0, 1), Axis);
328 }
329
330 virtual uint32 GetTypeHash() const override
331 {
332 const uint32 PlaneHashes = HashCombine(MPlane1.GetTypeHash(), MPlane2.GetTypeHash());
333 const uint32 PropertyHash = HashCombine(::GetTypeHash(MHeight), HashCombine(::GetTypeHash(MRadius1), ::GetTypeHash(MRadius2)));
334
336 }
337
338#if INTEL_ISPC
339 // See PerParticlePBDCollisionConstraint.cpp
340 // ISPC code has matching structs for interpreting FImplicitObjects.
341 // This is used to verify that the structs stay the same.
342 struct FISPCDataVerifier
343 {
344 static constexpr int32 OffsetOfMPlane1() { return offsetof(FTaperedCylinder, MPlane1); }
345 static constexpr int32 SizeOfMPlane1() { return sizeof(FTaperedCylinder::MPlane1); }
346 static constexpr int32 OffsetOfMPlane2() { return offsetof(FTaperedCylinder, MPlane2); }
347 static constexpr int32 SizeOfMPlane2() { return sizeof(FTaperedCylinder::MPlane2); }
348 static constexpr int32 OffsetOfMHeight() { return offsetof(FTaperedCylinder, MHeight); }
349 static constexpr int32 SizeOfMHeight() { return sizeof(FTaperedCylinder::MHeight); }
350 static constexpr int32 OffsetOfMRadius1() { return offsetof(FTaperedCylinder, MRadius1); }
351 static constexpr int32 SizeOfMRadius1() { return sizeof(FTaperedCylinder::MRadius1); }
352 static constexpr int32 OffsetOfMRadius2() { return offsetof(FTaperedCylinder, MRadius2); }
353 static constexpr int32 SizeOfMRadius2() { return sizeof(FTaperedCylinder::MRadius2); }
354 };
355 friend FISPCDataVerifier;
356#endif // #if INTEL_ISPC
357
358 private:
359 //Phi is distance from closest point on plane1
360 FRealSingle GetRadiusAtDistance(const FRealSingle& Phi) const
361 {
362 const FRealSingle Alpha = Phi / MHeight;
363 return MRadius1 * (static_cast<FRealSingle>(1.) - Alpha) + MRadius2 * Alpha;
364 }
365
366 TPlaneConcrete<FRealSingle, 3> MPlane1, MPlane2;
367 FRealSingle MHeight, MRadius1, MRadius2;
368 FAABB3 MLocalBoundingBox;
369 };
370
372 {
375 const int32 NumPoints, const bool IncludeEndCaps = true)
376 {
377 if (NumPoints <= 1 ||
378 (Cylinder.GetRadius1() <= UE_KINDA_SMALL_NUMBER &&
379 Cylinder.GetRadius2() <= UE_KINDA_SMALL_NUMBER))
380 {
381 const int32 Offset = Points.Num();
382 if (Cylinder.GetHeight() <= UE_KINDA_SMALL_NUMBER)
383 {
384 Points.SetNumUninitialized(Offset + 1);
385 Points[Offset] = Cylinder.GetCenter();
386 }
387 else
388 {
389 Points.SetNumUninitialized(Offset + 3);
390 Points[Offset + 0] = Cylinder.GetOrigin();
391 Points[Offset + 1] = Cylinder.GetCenter();
392 Points[Offset + 2] = Cylinder.GetInsertion();
393 }
394 return;
395 }
397 }
398
399 static FORCEINLINE void ComputeGoldenSpiralPoints(TArray<FVec3>& Points, const FTaperedCylinder& Cylinder, const int32 NumPoints, const bool IncludeEndCaps = true)
400 {
401 ComputeGoldenSpiralPoints(Points, Cylinder.GetOrigin(), Cylinder.GetAxis(), Cylinder.GetRadius1(), Cylinder.GetRadius2(), Cylinder.GetHeight(), NumPoints, IncludeEndCaps);
402 }
403
428 static /*FORCEINLINE*/ void ComputeGoldenSpiralPoints(
429 TArray<FVec3>& Points,
430 const FVec3& Origin,
431 const FVec3& Axis,
432 const FReal Radius1,
433 const FReal Radius2,
434 const FReal Height,
435 const int32 NumPoints,
436 const bool IncludeEndCaps = true,
437 int32 SpiralSeed = 0)
438 {
439 // Axis should be normalized.
440 checkSlow(FMath::Abs(Axis.Size() - 1.0) < UE_KINDA_SMALL_NUMBER);
441
442 const int32 Offset = Points.Num();
443 ComputeGoldenSpiralPointsUnoriented(Points, Radius1, Radius2, Height, NumPoints, IncludeEndCaps, SpiralSeed);
444
445 // At this point, Points are centered about the origin (0,0,0), built
446 // along the Z axis. Transform them to where they should be.
447 const FReal HalfHeight = Height / 2;
448 const FRotation3 Rotation = FRotation3::FromRotatedVector(FVec3(0, 0, 1), Axis);
449 checkSlow(((Origin + Axis * Height) - (Rotation.RotateVector(FVec3(0, 0, Height)) + Origin)).Size() < UE_KINDA_SMALL_NUMBER);
450 for (int32 i = Offset; i < Points.Num(); i++)
451 {
452 FVec3& Point = Points[i];
453 const FVec3 PointNew = Rotation.RotateVector(Point + FVec3(0, 0, HalfHeight)) + Origin;
454// checkSlow(FMath::Abs(FTaperedCylinder(Origin, Origin + Axis * Height, Radius1, Radius2).SignedDistance(PointNew)) < KINDA_SMALL_NUMBER);
455 Point = PointNew;
456 }
457 }
458
487 static /*FORCEINLINE*/ void ComputeGoldenSpiralPointsUnoriented(
488 TArray<FVec3>& Points,
489 const FReal Radius1,
490 const FReal Radius2,
491 const FReal Height,
492 const int32 NumPoints,
493 const bool IncludeEndCaps = true,
494 int32 SpiralSeed = 0)
495 {
496 // Evenly distribute points between the cylinder body and the end caps.
500 if (IncludeEndCaps)
501 {
502 const FReal Cap1Area = UE_PI * Radius1 * Radius1;
503 const FReal Cap2Area = UE_PI * Radius2 * Radius2;
504 const FReal CylArea =
505 UE_PI * Radius2 * (Radius2 + FMath::Sqrt(Height * Height + Radius2 * Radius2)) -
506 UE_PI * Radius1 * (Radius1 + FMath::Sqrt(Height * Height + Radius1 * Radius1));
509 {
510 NumPointsEndCap1 = static_cast<int32>(round(Cap1Area / AllArea * static_cast<FReal>(NumPoints)));
511 NumPointsEndCap2 = static_cast<int32>(round(Cap2Area / AllArea * static_cast<FReal>(NumPoints)));
513 }
514 else
515 {
517 NumPointsEndCap1 = NumPointsEndCap2 = (NumPoints - (NumPoints % 2)) / 2;
518 }
519 }
520 else
521 {
522 NumPointsCylinder = NumPoints;
525 }
527 Points.Reserve(Points.Num() + NumPointsToAdd);
528
529 int32 Offset = Points.Num();
530 const FReal HalfHeight = Height / 2;
531 TArray<FVec2> Points2D;
532 Points2D.Reserve(NumPointsEndCap1);
533 if (IncludeEndCaps)
534 {
536 Points2D, FVec2((FReal)0.0), Radius1, NumPointsEndCap1, SpiralSeed);
537 Offset = Points.AddUninitialized(Points2D.Num());
538 for (int32 i = 0; i < Points2D.Num(); i++)
539 {
540 const FVec2& Pt = Points2D[i];
541 checkSlow(Pt.Size() < Radius1 + UE_KINDA_SMALL_NUMBER);
542 Points[i + Offset] = FVec3(Pt[0], Pt[1], -HalfHeight);
543 }
544 // Advance the SpiralSeed by the number of points generated.
545 SpiralSeed += Points2D.Num();
546 }
547
549 if (NumPointsCylinder == 1)
550 {
551 Points[Offset] = FVec3(0, 0, HalfHeight);
552 }
553 else
554 {
555 static const FRealSingle Increment = UE_PI * (1.0f + FMath::Sqrt(5.0f));
556 for (int32 i = 0; i < NumPointsCylinder; i++)
557 {
558 // In the 2D sphere (disc) case, we vary R so it increases monotonically,
559 // which spreads points out across the disc:
560 // const FReal R = FMath::Sqrt((0.5 + Index) / NumPoints) * Radius;
561 // But we're mapping to a cylinder, which means we want to keep R constant.
562 const FReal R = FMath::Lerp(Radius1, Radius2, static_cast<FReal>(i) / static_cast<FReal>(NumPointsCylinder - 1));
563 const FReal Theta = Increment * (0.5f + static_cast<FReal>(i + SpiralSeed));
564
565 // Map polar coordinates to Cartesian, and vary Z by [-HalfHeight, HalfHeight].
566 const FReal Z = FMath::LerpStable(-HalfHeight, HalfHeight, static_cast<FReal>(i) / static_cast<FReal>(NumPointsCylinder - 1));
567 Points[i + Offset] =
568 FVec3(
569 R * FMath::Cos(Theta),
570 R * FMath::Sin(Theta),
571 Z);
572
573 //checkSlow(FMath::Abs(FVec2(Points[i + Offset][0], Points[i + Offset][1]).Size() - Radius) < KINDA_SMALL_NUMBER);
574 }
575 }
576 // Advance the SpiralSeed by the number of points generated.
578
579 if (IncludeEndCaps)
580 {
581 Points2D.Reset();
583 Points2D, FVec2((FReal)0.0), Radius2, NumPointsEndCap2, SpiralSeed);
584 Offset = Points.AddUninitialized(Points2D.Num());
585 for (int32 i = 0; i < Points2D.Num(); i++)
586 {
587 const FVec2& Pt = Points2D[i];
588 checkSlow(Pt.Size() < Radius2 + UE_KINDA_SMALL_NUMBER);
589 Points[i + Offset] = FVec3(Pt[0], Pt[1], HalfHeight);
590 }
591 }
592 }
593 };
594
596 {
597 TArray<FVec3> Points;
598 const FVec3 Mid = GetCenter();
600 Points,
601 FTaperedCylinder(MPlane1.X() - Mid, MPlane2.X() - Mid, GetRadius1(), GetRadius2()),
602 NumPoints, IncludeEndCaps);
603 return Points;
604 }
605
607 {
608 TArray<FVec3> Points;
610 return Points;
611 }
612
613 template<class T>
614 using TTaperedCylinder UE_DEPRECATED(4.27, "Deprecated. this class is to be deleted, use FTaperedCylinder instead") = FTaperedCylinder;
615
616 template<typename T>
617 using TTaperedCylinderSpecializeSamplingHelper UE_DEPRECATED(4.27, "Deprecated. this class is to be deleted, use FTaperedCylinderSpecializeSamplingHelper instead") = FTaperedCylinderSpecializeSamplingHelper;
618
619
620} // namespace Chaos
#define FORCEINLINE
Definition AndroidPlatform.h:140
#define checkSlow(expr)
Definition AssertionMacros.h:332
#define check(expr)
Definition AssertionMacros.h:314
#define ensure( InExpression)
Definition AssertionMacros.h:464
#define UE_DEPRECATED(Version, Message)
Definition CoreMiscDefines.h:302
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
@ Top
Definition MaterialExpressionFunctionInput.h:42
constexpr uint32 HashCombine(uint32 A, uint32 C)
Definition TypeHash.h:36
#define UE_PI
Definition UnrealMathUtility.h:129
#define UE_SMALL_NUMBER
Definition UnrealMathUtility.h:130
#define UE_KINDA_SMALL_NUMBER
Definition UnrealMathUtility.h:131
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
uint32 Offset
Definition VulkanMemory.cpp:4033
uint32 Size
Definition VulkanMemory.cpp:4034
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition Cylinder.h:15
Definition ImplicitObject.h:111
CHAOS_API FReal SignedDistance(const FVec3 &x) const
Definition ImplicitObject.cpp:105
bool bIsConvex
Definition ImplicitObject.h:572
CHAOS_API Pair< FVec3, bool > FindClosestIntersection(const FVec3 &StartPoint, const FVec3 &EndPoint, const FReal Thickness) const
Definition ImplicitObject.cpp:183
Definition TaperedCylinder.h:13
TArray< FVec3 > ComputeLocalSamplePoints(const FReal PointsPerUnitArea, const bool IncludeEndCaps=true, const int32 MinPoints=0, const int32 MaxPoints=1000) const
Definition TaperedCylinder.h:79
FReal GetRadius2() const
Definition TaperedCylinder.h:249
virtual const FAABB3 BoundingBox() const override
Definition TaperedCylinder.h:102
FVec3 GetOrigin() const
Definition TaperedCylinder.h:257
static FReal GetVolume(const FReal Height, const FReal Radius1, const FReal Radius2)
Definition TaperedCylinder.h:295
TArray< FVec3 > ComputeSamplePoints(const FReal PointsPerUnitArea, const bool IncludeEndCaps=true, const int32 MinPoints=0, const int32 MaxPoints=1000) const
Definition TaperedCylinder.h:99
FReal GetArea(const bool IncludeEndCaps=true) const
Definition TaperedCylinder.h:273
TArray< FVec3 > ComputeSamplePoints(const int32 NumPoints, const bool IncludeEndCaps=true) const
Definition TaperedCylinder.h:606
FReal GetRadius1() const
Definition TaperedCylinder.h:248
FReal GetHeight() const
Definition TaperedCylinder.h:250
virtual uint32 GetTypeHash() const override
Definition TaperedCylinder.h:330
FVec3 GetCenter() const
Definition TaperedCylinder.h:262
FTaperedCylinder()
Definition TaperedCylinder.h:15
FVec3 GetX1() const
Definition TaperedCylinder.h:252
TArray< FVec3 > ComputeLocalSamplePoints(const int32 NumPoints, const bool IncludeEndCaps=true) const
Definition TaperedCylinder.h:595
static constexpr EImplicitObjectType StaticType()
Definition TaperedCylinder.h:60
FVec3 GetInsertion() const
Definition TaperedCylinder.h:260
const FVec3f & GetInsertionf() const
Definition TaperedCylinder.h:261
FRotation3 GetRotationOfMass() const
Definition TaperedCylinder.h:322
FVec3 GetX2() const
Definition TaperedCylinder.h:254
const FVec3f & GetOriginf() const
Definition TaperedCylinder.h:258
FVec3 GetAxis() const
Definition TaperedCylinder.h:271
static FRotation3 GetRotationOfMass(const FVec3 &Axis)
Definition TaperedCylinder.h:323
static FReal GetArea(const FReal Height, const FReal Radius1, const FReal Radius2, const bool IncludeEndCaps)
Definition TaperedCylinder.h:274
FTaperedCylinder(const FTaperedCylinder &Other)
Definition TaperedCylinder.h:36
const FVec3f & GetX1f() const
Definition TaperedCylinder.h:253
Pair< FVec3, bool > FindClosestIntersection(const FVec3 &StartPoint, const FVec3 &EndPoint, const FReal Thickness)
Definition TaperedCylinder.h:160
FTaperedCylinder(const FVec3 &x1, const FVec3 &x2, const FReal Radius1, const FReal Radius2)
Definition TaperedCylinder.h:20
const FVec3f & GetX2f() const
Definition TaperedCylinder.h:255
FMatrix33 GetInertiaTensor(const FReal Mass) const
Definition TaperedCylinder.h:301
FVec3 GetCenterOfMass() const
Definition TaperedCylinder.h:264
FReal GetSlantHeight() const
Definition TaperedCylinder.h:251
~FTaperedCylinder()
Definition TaperedCylinder.h:58
static FMatrix33 GetInertiaTensor(const FReal Mass, const FReal Height, const FReal Radius1, const FReal Radius2)
Definition TaperedCylinder.h:302
FReal GetVolume() const
Definition TaperedCylinder.h:294
FTaperedCylinder(FTaperedCylinder &&Other)
Definition TaperedCylinder.h:47
FReal PhiWithNormal(const FVec3 &x, FVec3 &Normal) const
Definition TaperedCylinder.h:104
FORCEINLINE const TVector< T, d > & Max() const
Definition AABB.h:596
FORCEINLINE void GrowToInclude(const TVector< T, d > &V)
Definition AABB.h:393
FORCEINLINE const TVector< T, d > & Min() const
Definition AABB.h:595
Definition Vector.h:407
Definition Array.h:670
UE_FORCEINLINE_HINT SizeType AddUninitialized()
Definition Array.h:1664
UE_REWRITE SizeType Num() const
Definition Array.h:1144
void Reset(SizeType NewSize=0)
Definition Array.h:2246
UE_NODEBUG UE_FORCEINLINE_HINT SizeType Add(ElementType &&Item)
Definition Array.h:2696
void SetNumUninitialized(SizeType NewNum, EAllowShrinking AllowShrinking=UE::Core::Private::AllowShrinkingByDefault< AllocatorType >())
Definition Array.h:2369
UE_NODEBUG void Sort()
Definition Array.h:3418
UE_FORCEINLINE_HINT void Reserve(SizeType Number)
Definition Array.h:3016
@ TaperedCylinder
Definition ImplicitObjectType.h:22
Definition SkeletalMeshComponent.h:307
TVector< FRealSingle, 3 > FVec3f
Definition Core.h:27
uint8 EImplicitObjectType
Definition ImplicitObjectType.h:41
FRealDouble FReal
Definition Real.h:22
PMatrix< FReal, 3, 3 > FMatrix33
Definition Core.h:20
Pair< T1, T2 > MakePair(const T1 &First, const T2 &Second)
Definition Pair.h:45
float FRealSingle
Definition Real.h:14
TVector< FReal, 3 > FVec3
Definition Core.h:17
TAABB< FReal, 3 > FAABB3
Definition ImplicitObject.h:34
TVector< FReal, 2 > FVec2
Definition Core.h:16
float v
Definition radaudio_mdct.cpp:62
Definition TaperedCylinder.h:372
static void ComputeGoldenSpiralPoints(TArray< FVec3 > &Points, const FVec3 &Origin, const FVec3 &Axis, const FReal Radius1, const FReal Radius2, const FReal Height, const int32 NumPoints, const bool IncludeEndCaps=true, int32 SpiralSeed=0)
Definition TaperedCylinder.h:428
static void ComputeGoldenSpiralPointsUnoriented(TArray< FVec3 > &Points, const FReal Radius1, const FReal Radius2, const FReal Height, const int32 NumPoints, const bool IncludeEndCaps=true, int32 SpiralSeed=0)
Definition TaperedCylinder.h:487
static FORCEINLINE void ComputeSamplePoints(TArray< FVec3 > &Points, const FTaperedCylinder &Cylinder, const int32 NumPoints, const bool IncludeEndCaps=true)
Definition TaperedCylinder.h:373
static FORCEINLINE void ComputeGoldenSpiralPoints(TArray< FVec3 > &Points, const FTaperedCylinder &Cylinder, const int32 NumPoints, const bool IncludeEndCaps=true)
Definition TaperedCylinder.h:399
Definition Pair.h:8
static constexpr UE_FORCEINLINE_HINT T Abs(const T A)
Definition GenericPlatformMath.h:949
static constexpr UE_FORCEINLINE_HINT T Lerp(const T &A, const T &B, const U &Alpha)
Definition UnrealMathUtility.h:1116
static constexpr UE_FORCEINLINE_HINT T Clamp(const T X, const T MinValue, const T MaxValue)
Definition UnrealMathUtility.h:592
static constexpr UE_FORCEINLINE_HINT T LerpStable(const T &A, const T &B, double Alpha)
Definition UnrealMathUtility.h:1147
T Size() const
Definition Vector.h:1716