UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
PerParticlePBDCCDCollisionConstraint.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
4// HEADER_UNIT_SKIP - Internal
5
6#if UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_4
8#endif
10#include "Chaos/Transform.h"
11#include "Chaos/PBDActiveView.h"
14#include "Chaos/Levelset.h"
15#include "Misc/ScopeLock.h"
16
17namespace Chaos::Softs
18{
19
21{
22public:
46
48 {
49 delete Mutex;
50 }
51
52 inline void ApplyRange(FSolverParticles& Particles, const FSolverReal Dt, const int32 Offset, const int32 Range) const
53 {
54 if (Mutex)
55 {
56 ApplyRangeHelper<true>(Particles, Dt, Offset, Range);
57 }
58 else
59 {
60 ApplyRangeHelper<false>(Particles, Dt, Offset, Range);
61 }
62 }
63
64private:
65 template<bool bLockAndWriteContacts>
66 inline void ApplyRangeHelper(FSolverParticles& Particles, const FSolverReal Dt, const int32 Offset, const int32 Range) const
67 {
68 const uint32 DynamicGroupId = DynamicGroupIds[Offset]; // Particle group Id, must be the same across the entire range
69 const FSolverReal Friction = PerGroupFriction[DynamicGroupId];
70 const FSolverReal Thickness = PerGroupThicknesses[DynamicGroupId];
71
72 PhysicsParallelFor(Range - Offset, [this, &Particles, Offset, DynamicGroupId, Thickness, Friction, Dt](int32 i)
73 {
74 const int32 Index = Offset + i;
75
76 if (Particles.InvM(Index) == (FSolverReal)0.)
77 {
78 return; // Continue
79 }
80
81 CollisionParticlesActiveView.SequentialFor([this, &Particles, &Index, DynamicGroupId, Thickness, Friction, Dt](FSolverCollisionParticles& CollisionParticles, int32 CollisionIndex)
82 {
83 const uint32 KinematicGroupId = KinematicGroupIds[CollisionIndex]; // Collision group Id
84
85 if (KinematicGroupId != (uint32)INDEX_NONE && DynamicGroupId != KinematicGroupId)
86 {
87 return; // Bail out if the collision groups doesn't match the particle group id, or use INDEX_NONE (= global collision that affects all particle)
88 }
89
90 const FSolverRigidTransform3 Frame(CollisionParticles.GetX(CollisionIndex), CollisionParticles.GetR(CollisionIndex));
91
92 const Pair<FVec3, bool> PointPair = CollisionParticles.GetGeometry(CollisionIndex)->FindClosestIntersection( // Geometry operates in FReal
93 FVec3(CollisionTransforms[CollisionIndex].InverseTransformPositionNoScale(Particles.GetX(Index))), // hence the back and forth
94 FVec3(Frame.InverseTransformPositionNoScale(Particles.P(Index))), (FReal)Thickness); // FVec3/FReal conversions
95
96 if (PointPair.Second)
97 {
98 Collided[CollisionIndex] = true;
99
100 const FSolverVec3 Normal = FSolverVec3(CollisionParticles.GetGeometry(CollisionIndex)->Normal(PointPair.First));
101 const FSolverVec3 NormalWorld = Frame.TransformVectorNoScale(Normal);
102 const FSolverVec3 ContactWorld = Frame.TransformPositionNoScale(UE::Math::TVector<FSolverReal>(PointPair.First));
103
105 {
106 check(Mutex);
107 FScopeLock Lock(Mutex);
108 Contacts.Emplace(ContactWorld);
109 Normals.Emplace(NormalWorld);
110 }
111 const FSolverVec3 Direction = ContactWorld - Particles.P(Index);
112 const FSolverReal Penetration = FMath::Max((FSolverReal)0., FSolverVec3::DotProduct(NormalWorld, Direction)) + (FSolverReal)UE_THRESH_POINT_ON_PLANE;
113
114 Particles.P(Index) += Penetration * NormalWorld;
115
116 // Friction
117 const FSolverVec3 VectorToPoint = Particles.P(Index) - CollisionParticles.GetX(CollisionIndex);
118 const FSolverVec3 RelativeDisplacement = (Particles.P(Index) - Particles.GetX(Index)) - (CollisionParticles.V(CollisionIndex) + FSolverVec3::CrossProduct(CollisionParticles.W(CollisionIndex), VectorToPoint)) * Dt; // This corresponds to the tangential velocity multiplied by dt (friction will drive this to zero if it is high enough)
119 const FSolverVec3 RelativeDisplacementTangent = RelativeDisplacement - FSolverVec3::DotProduct(RelativeDisplacement, NormalWorld) * NormalWorld; // Project displacement into the tangential plane
122 {
123 const FSolverReal PositionCorrection = FMath::Min<FSolverReal>(Penetration * Friction, RelativeDisplacementTangentLength);
126 }
127 }
128 });
129 });
130 }
131
132private:
133 // TODO(mlentine): Need a bb hierarchy
134 const TPBDActiveView<FSolverCollisionParticles>& CollisionParticlesActiveView;
135 const TArray<FSolverRigidTransform3>& CollisionTransforms;
136 TArray<bool>& Collided;
137 TArray<FSolverVec3>& Contacts;
139 const TArray<uint32>& DynamicGroupIds;
140 const TArray<uint32>& KinematicGroupIds;
141 const TArray<FSolverReal>& PerGroupThicknesses;
142 const TArray<FSolverReal>& PerGroupFriction;
143 FCriticalSection* const Mutex;
144};
145
146} // End namespace Chaos::Softs
#define check(expr)
Definition AssertionMacros.h:314
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
UE::FPlatformRecursiveMutex FCriticalSection
Definition CriticalSection.h:53
#define UE_SMALL_NUMBER
Definition UnrealMathUtility.h:130
#define UE_THRESH_POINT_ON_PLANE
Definition UnrealMathUtility.h:199
FRWLock Lock
Definition UnversionedPropertySerialization.cpp:921
uint32 Offset
Definition VulkanMemory.cpp:4033
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition PerParticlePBDCCDCollisionConstraint.h:21
void ApplyRange(FSolverParticles &Particles, const FSolverReal Dt, const int32 Offset, const int32 Range) const
Definition PerParticlePBDCCDCollisionConstraint.h:52
FPerParticlePBDCCDCollisionConstraint(const TPBDActiveView< FSolverCollisionParticles > &InCollisionParticlesActiveView, TArray< FSolverRigidTransform3 > &InCollisionTransforms, TArray< bool > &InCollided, TArray< FSolverVec3 > &InContacts, TArray< FSolverVec3 > &InNormals, TArray< uint32 > &InDynamicGroupIds, TArray< uint32 > &InKinematicGroupIds, const TArray< FSolverReal > &InPerGroupThicknesses, const TArray< FSolverReal > &InPerGroupFriction, bool bWriteCCDContacts)
Definition PerParticlePBDCCDCollisionConstraint.h:23
~FPerParticlePBDCCDCollisionConstraint()
Definition PerParticlePBDCCDCollisionConstraint.h:47
Definition SoftsSolverCollisionParticles.h:10
const FSolverVec3 & V(const int32 Index) const
Definition SoftsSolverCollisionParticles.h:42
const FSolverVec3 & W(const int32 Index) const
Definition SoftsSolverCollisionParticles.h:47
Definition PBDSoftsSolverParticles.h:20
const FSolverVec3 & P(const int32 index) const
Definition PBDSoftsSolverParticles.h:36
const T InvM(const int32 Index) const
Definition DynamicParticles.h:48
Definition PBDActiveView.h:47
const TVector< T, d > & GetX(const int32 Index) const
Definition Particles.h:156
Definition Transform.h:115
FORCEINLINE const TRotation< T, d > GetR(const int32 Index) const
Definition SimpleGeometryParticles.h:54
FORCEINLINE const FImplicitObjectPtr & GetGeometry(const int32 Index) const
Definition SimpleGeometryParticles.h:61
Definition Vector.h:1000
FORCEINLINE T Size() const
Definition Vector.h:1055
Definition ScopeLock.h:141
Definition Array.h:670
Definition CollectionEmbeddedSpringConstraintFacade.cpp:6
FRealSingle FSolverReal
Definition PBDSoftsEvolutionFwd.h:31
TVector< FSolverReal, 3 > FSolverVec3
Definition PBDSoftsEvolutionFwd.h:33
void CHAOS_API PhysicsParallelFor(int32 InNum, TFunctionRef< void(int32)> InCallable, bool bForceSingleThreaded=false)
Definition Parallel.cpp:55
FRealDouble FReal
Definition Real.h:22
FRealSingle FSolverReal
Definition SolverBody.h:38
TVector< FReal, 3 > FVec3
Definition Core.h:17
UE::FRecursiveMutex Mutex
Definition MeshPaintVirtualTexture.cpp:164
U16 Index
Definition radfft.cpp:71
Definition Pair.h:8
Definition Vector.h:51