UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
EvolutionResimCache.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
4#include "ResimCacheBase.h"
8
9namespace Chaos
10{
12
14 {
15 public:
17 virtual ~FEvolutionResimCache() = default;
19 {
20 // If the number of cached particles is shrinking, reduce the memory allocation but leave room for 10% growth without needing to reallocate
21 // Memory will be reallocated if the cached particles grow or shrink by 10%, growing reallocation is done automatically, this logic handles shrink reallocation and leaving room for 10% growth.
22 // Example: At 100 particles it's allowed to populate the TMap between 90-110 particles without a memory reallocation.
23 const int32 CurrentSize = ParticleToCachedSolve.Num();
24 const int32 SizeLeniency = FMath::CeilToInt(0.1f * static_cast<float>(CurrentSize)); // 10% leniency
25 ParticleCacheAllocationSize = FMath::Max(CurrentSize, ParticleCacheAllocationSize);
26 const int32 ReallocationLimit = FMath::Max(ParticleCacheAllocationSize - (SizeLeniency * 2), 0);
27
28 if (CurrentSize < ReallocationLimit)
29 {
30 const int32 PreferredSize = CurrentSize + SizeLeniency;
31
32 ParticleToCachedSolve.Empty(PreferredSize);
33 ParticleCacheAllocationSize = PreferredSize;
34 }
35 else
36 {
37 ParticleToCachedSolve.Reset();
38 }
39
40 SavedConstraints.Reset();
41 WeakSinglePointConstraints.Reset();
42 }
43
45 {
46 FPBDSolveCache& Cache = ParticleToCachedSolve.FindOrAdd(Particle.UniqueIdx());
47 Cache.P = Particle.GetP();
48 Cache.Q = Particle.GetQ();
49 Cache.V = Particle.GetV();
50 Cache.W = Particle.GetW();
51 }
52
54 {
55 //if this function is called it means the particle is in sync, which means we should have a cached value
56 const FPBDSolveCache* Cache = ParticleToCachedSolve.Find(Particle.UniqueIdx());
57 if (Cache && (Particle.GetP() != Cache->P || Particle.GetQ() != Cache->Q || Particle.GetV() != Cache->V || Particle.GetW() != Cache->W))
58 {
59 Particle.SetP(Cache->P);
60 Particle.SetQ(Cache->Q);
61 Particle.SetV(Cache->V);
62 Particle.SetW(Cache->W);
63 return true;
64 }
65 return false;
66 }
67
69 {
70 // Copy the constraints into an array
71 SavedConstraints.Reset(CollisionsArray.Num());
73 {
74 SavedConstraints.Emplace(FPBDCollisionConstraint::MakeCopy(*Collision));
75 }
76
77 //Create weak handles so we can make sure everything is alive later
78 auto SaveArrayHelper = [](auto& Constraints,auto& WeakPairs)
79 {
80 WeakPairs.Empty(Constraints.Num());
81 for(FPBDCollisionConstraint& Constraint : Constraints)
82 {
83 WeakPairs.Add(FWeakConstraintPair{Constraint.GetParticle0()->WeakParticleHandle(),Constraint.GetParticle1()->WeakParticleHandle()});
84
85 auto* A = Constraint.GetParticle0();
86 auto* B = Constraint.GetParticle1();
87
88 //Need to do this on save for any new constraints
89 MarkSoftIfDesync(*A,*B);
90 }
91 check(Constraints.Num() == WeakPairs.Num());
92 };
93
94 SaveArrayHelper(SavedConstraints,WeakSinglePointConstraints);
95 }
96
97 //Returns all constraints that are still valid (resim can invalidate constraints by either deleting particles, moving particles, etc...)
99 {
100 auto CleanupArrayHelper = [](auto& Constraints,auto& WeakPairs)
101 {
102 check(Constraints.Num() == WeakPairs.Num());
103 for(int32 Idx = Constraints.Num() - 1; Idx >= 0; --Idx)
104 {
105 FPBDCollisionConstraint& Constraint = Constraints[Idx];
106 FWeakConstraintPair& WeakPair = WeakPairs[Idx];
107
108 TGeometryParticleHandle<FReal,3>* A = WeakPair.A.GetHandleUnsafe();
109 TGeometryParticleHandle<FReal,3>* B = WeakPair.B.GetHandleUnsafe();
110
111 bool bValidConstraint = A != nullptr && B != nullptr;
113 {
114 //must do this on get in case particles are no longer constrained (means we won't see them during save above)
115 bValidConstraint = !MarkSoftIfDesync(*A,*B);
116 }
117
119 {
120 Constraints.RemoveAtSwap(Idx);
121 WeakPairs.RemoveAtSwap(Idx);
122 }
123 }
124 };
125
126 CleanupArrayHelper(SavedConstraints,WeakSinglePointConstraints);
127
128 return SavedConstraints;
129 }
130
131 private:
132
134 {
135 if(A.SyncState() == ESyncState::HardDesync || B.SyncState() == ESyncState::HardDesync)
136 {
137 if(A.SyncState() != ESyncState::HardDesync)
138 {
139 //Need to resim, but may end up still in sync
140 //A.SetSyncState(ESyncState::SoftDesync);
141 }
142
143 if(B.SyncState() != ESyncState::HardDesync)
144 {
145 //Need to resim, but may end up still in sync
146 //B.SetSyncState(ESyncState::SoftDesync);
147 }
148
149 return true;
150 }
151
152 return false;
153 }
154
155 //NOTE: You must sanitize this before using. This can contain dangling pointers or invalid constraints
156 TArray<FPBDCollisionConstraint> SavedConstraints;
157
158 struct FWeakConstraintPair
159 {
160 FWeakParticleHandle A;
161 FWeakParticleHandle B;
162 };
163
164 struct FPBDSolveCache
165 {
166 FVec3 P;
167 FQuat Q;
168 FVec3 V;
169 FVec3 W;
170 };
171
172 //TODO: better way to handle this?
173 TArray<FWeakConstraintPair> WeakSinglePointConstraints;
174 TMap<FUniqueIdx, FPBDSolveCache> ParticleToCachedSolve;
175 int32 ParticleCacheAllocationSize = 0;
176 };
177
178} // namespace Chaos
#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
Definition EvolutionResimCache.h:14
void SaveConstraints(TArrayView< const FPBDCollisionConstraint *const > CollisionsArray)
Definition EvolutionResimCache.h:68
const TArray< FPBDCollisionConstraint > & GetAndSanitizeConstraints()
Definition EvolutionResimCache.h:98
bool ReloadParticlePostSolve(FPBDRigidParticleHandle &Particle) const
Definition EvolutionResimCache.h:53
void ResetCache()
Definition EvolutionResimCache.h:18
virtual ~FEvolutionResimCache()=default
void SaveParticlePostSolve(const FPBDRigidParticleHandle &Particle)
Definition EvolutionResimCache.h:44
FEvolutionResimCache()
Definition EvolutionResimCache.h:16
A contact constraint.
Definition PBDCollisionConstraint.h:225
static CHAOS_API FPBDCollisionConstraint MakeCopy(const FPBDCollisionConstraint &Source)
Return a constraint copied from the Source constraint, for use in the Resim Cache or other system.
Definition PBDCollisionConstraint.cpp:172
Definition ResimCacheBase.h:11
Definition ParticleHandle.h:436
FUniqueIdx UniqueIdx() const
Definition ParticleHandle.h:561
const TVector< T, d > GetW() const
Definition ParticleHandle.h:957
void SetW(const TVector< T, d > &InW, bool bInvalidate=false)
Definition ParticleHandle.h:958
const TVector< T, d > GetV() const
Definition ParticleHandle.h:948
void SetV(const TVector< T, d > &InV, bool bInvalidate=false)
Definition ParticleHandle.h:949
Definition ParticleHandle.h:987
const TRotation< T, d > GetQ() const
Definition ParticleHandle.h:1113
void SetQ(const TRotation< T, d > &InQ)
Definition ParticleHandle.h:1114
void SetP(const TVector< T, d > &InP)
Definition ParticleHandle.h:1107
const TVector< T, d > & GetP() const
Definition ParticleHandle.h:1106
Definition Constraints.Build.cs:6
Definition ArrayView.h:139
Definition Array.h:670
void Reset(SizeType NewSize=0)
Definition Array.h:2246
Definition UnrealString.h.inl:34
Definition SkeletalMeshComponent.h:307
TVector< FReal, 3 > FVec3
Definition Core.h:17
const TCHAR * B(bool b)
Definition SkinnedMeshComponent.cpp:386
int32 P[512]
Definition FieldSystemNoiseAlgo.cpp:11