UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
PhysicsSolverBaseImpl.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreMinimal.h"
7#include "UObject/GCObject.h"
8
17
18#include <type_traits>
19
20namespace Chaos
21{
22 namespace Private
23 {
24 // This lets us add support for performing per-proxy operations in PullPhysicsStateForEachDirtyProxy_External
25 // without the need to keep adding function parameters to keep taking in lambdas. We assume that the incoming
26 // user-specified TDispatcher has various operator() overridden to take in a specific proxy pointer. We require
27 // the TPullPhysicsStateDispatchHelper then to wrap the TDispatcher so that we can check if the incoming TDispatcher
28 // has a override for the proxy we want to pass to it. If it does not, we do nothing. This lets us maintain backward
29 // compatability as we keep adding in new proxy types while not requiring any additional computation at runtime since
30 // this dispatch is all done at compile time.
31 template<typename TDispatcher>
33 {
34 template<typename TProxy>
35 static void Apply(TDispatcher& Dispatcher, TProxy* Proxy)
36 {
37 if constexpr (std::is_invocable_v<TDispatcher, TProxy*>)
38 {
39 Dispatcher(Proxy);
40 }
41 }
42 };
43 }
44
45 template<typename TDispatcher>
47 {
48 using namespace Chaos;
49
52 {
54
56 //we want to interpolate between prev and next. There are a few cases to consider:
57 //case 1: dirty data exists in both prev and next. In this case continuous data is interpolated, state data is a step function from prev to next
58 //case 2: prev has dirty data and next doesn't. in this case take prev as it means nothing to interpolate, just a constant value
59 //case 3: prev has dirty data and next has overwritten data. In this case we do nothing as the overwritten data wins (came from GT), and also particle may be deleted
60 //case 4: prev has no dirty data and next does. In this case interpolate from gt data to next
61 //case 5: prev has no dirty data and next was overwritten. In this case do nothing as the overwritten data wins, and also particle may be deleted
62
64
65 {
67 ResultsPerChannel = PullResultsManager->PullAsyncPhysicsResults_External(ResultsTime);
68 }
69
70 for (int32 ChannelIdx = 0; ChannelIdx < ResultsPerChannel.Num(); ++ChannelIdx)
71 {
72 const FChaosInterpolationResults& Results = *ResultsPerChannel[ChannelIdx];
73 LatestData = Results.Next;
74 //todo: go wide
75 const int32 SolverTimestamp = Results.Next ? Results.Next->SolverTimestamp : INDEX_NONE;
76
77 // single particles
78 {
81 {
82 if (FSingleParticlePhysicsProxy* Proxy = RigidInterp.Prev.GetProxy())
83 {
84 const FDirtyRigidParticleReplicationErrorData* ErrorData = LatestData->DirtyRigidErrors.Find(Proxy);
85 if (Proxy->PullFromPhysicsState(RigidInterp.Prev, SolverTimestamp, &RigidInterp.Next, &Results.Alpha, ErrorData, GetAsyncDeltaTime()))
86 {
88 }
89 LatestData->DirtyRigidErrors.Remove(Proxy);
90 }
91 }
92 }
93
94 // geometry collections
95 {
98 {
99 if (FGeometryCollectionPhysicsProxy* Proxy = GCInterp.Prev.GetProxy())
100 {
101 const FDirtyRigidParticleReplicationErrorData* ErrorData = LatestData->DirtyRigidErrors.Find(Proxy);
102 if (Proxy->PullFromPhysicsState(GCInterp.Prev, SolverTimestamp, &GCInterp.Next, &Results.Alpha, ErrorData, GetAsyncDeltaTime()))
103 {
105 }
106 LatestData->DirtyRigidErrors.Remove(Proxy);
107 }
108 }
109 }
110
111 // cluster unions
112 {
115 {
116 if(FClusterUnionPhysicsProxy* Proxy = ClusterInterp.Prev.GetProxy())
117 {
118 const FDirtyRigidParticleReplicationErrorData* ErrorData = LatestData->DirtyRigidErrors.Find(Proxy);
119 if (Proxy->PullFromPhysicsState(ClusterInterp.Prev, SolverTimestamp, &ClusterInterp.Next, &Results.Alpha, ErrorData, GetAsyncDeltaTime()))
120 {
122 }
123 LatestData->DirtyRigidErrors.Remove(Proxy);
124 }
125 }
126 }
127 }
128 }
129 else
130 {
132
133 //no interpolation so just use latest, in non-substepping modes this will just be the next result
134 // available in the queue - however if we substepped externally we need to consume the whole
135 // queue by telling the sync pull that we expect multiple results.
136
137 const FChaosInterpolationResults& Results = PullResultsManager->PullSyncPhysicsResults_External();
138 LatestData = Results.Next;
139 //todo: go wide
140 const int32 SolverTimestamp = Results.Next ? Results.Next->SolverTimestamp : INDEX_NONE;
141
142 // Single particles
143 {
146 {
147 if(FSingleParticlePhysicsProxy* Proxy = RigidInterp.Prev.GetProxy())
148 {
149 if(Proxy->PullFromPhysicsState(RigidInterp.Next, SolverTimestamp))
150 {
152 }
153 }
154 }
155 }
156
157 // geometry collections
158 {
161 {
162 if(FGeometryCollectionPhysicsProxy* Proxy = GCInterp.Prev.GetProxy())
163 {
164 if(Proxy->PullFromPhysicsState(GCInterp.Next, SolverTimestamp))
165 {
167 }
168 }
169 }
170 }
171
172 // cluster unions
173 {
176 {
177 if(FClusterUnionPhysicsProxy* Proxy = ClusterInterp.Prev.GetProxy())
178 {
179 if(Proxy->PullFromPhysicsState(ClusterInterp.Prev, SolverTimestamp))
180 {
182 }
183 }
184 }
185 }
186 }
187
188 //no interpolation for GC or joints at the moment
189 if (LatestData)
190 {
192 const int32 SyncTimestamp = LatestData->SolverTimestamp;
193
194 //
195 // @todo(chaos) : Add Dirty Constraints Support
196 //
197 // This is temporary constraint code until the DirtyParticleBuffer
198 // can be updated to support constraints. In summary : The
199 // FDirtyPropertiesManager is going to be updated to support a
200 // FDirtySet that is specific to a TConstraintProperties class.
201 //
202 for (const FDirtyJointConstraintData& DirtyData : LatestData->DirtyJointConstraints)
203 {
204 if (auto Proxy = DirtyData.GetProxy())
205 {
206 if (Proxy->PullFromPhysicsState(DirtyData, SyncTimestamp))
207 {
209 }
210
211 }
212 }
213
214 //latest data may be used multiple times during interpolation, so for non interpolated joints we clear it
215 LatestData->DirtyJointConstraints.Reset();
216
217 for (const FDirtyCharacterGroundConstraintData& DirtyData : LatestData->DirtyCharacterGroundConstraints)
218 {
219 if (auto Proxy = DirtyData.GetProxy())
220 {
221 // todo: Do we need to add a callback?
222 Proxy->PullFromPhysicsState(DirtyData, SyncTimestamp);
223 }
224 }
225 LatestData->DirtyCharacterGroundConstraints.Reset();
226 }
227 }
228
229 // Pulls physics state for each dirty particle and allows caller to do additional work if needed
230 template <typename RigidLambda, typename ConstraintLambda, typename GeometryCollectionLambda>
232 {
233 struct FDispatcher
234 {
235 void operator()(FSingleParticlePhysicsProxy* Proxy)
236 {
237 RigidFunc(Proxy);
238 }
239
240 void operator()(FJointConstraintPhysicsProxy* Proxy)
241 {
242 ConstraintFunc(Proxy);
243 }
244
245 void operator()(FGeometryCollectionPhysicsProxy* Proxy)
246 {
248 }
249 } Dispatcher;
251 }
252
253 template <typename RigidLambda, typename ConstraintLambda>
255 {
256 struct FDispatcher
257 {
258 void operator()(FSingleParticlePhysicsProxy* Proxy)
259 {
260 RigidFunc(Proxy);
261 }
262
263 void operator()(FJointConstraintPhysicsProxy* Proxy)
264 {
265 ConstraintFunc(Proxy);
266 }
267 } Dispatcher;
269 }
270}
@ INDEX_NONE
Definition CoreMiscDefines.h:150
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define SCOPE_CYCLE_COUNTER(Stat)
Definition Stats.h:650
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
Definition ClusterUnionPhysicsProxy.h:63
Definition JointConstraintProxy.h:33
FReal GetPhysicsResultsTime_External() const
Definition PhysicsSolverBase.h:738
TUniquePtr< FChaosResultsManager > PullResultsManager
Definition PhysicsSolverBase.h:916
FReal GetAsyncDeltaTime() const
Definition PhysicsSolverBase.h:590
void PullPhysicsStateForEachDirtyProxy_External(TDispatcher &Dispatcher)
Definition PhysicsSolverBaseImpl.h:46
bool IsUsingAsyncResults() const
Definition PhysicsSolverBase.h:681
Definition PullPhysicsDataImp.h:166
int32 SolverTimestamp
Definition PullPhysicsDataImp.h:175
Definition SingleParticlePhysicsProxy.h:58
Definition GeometryCollectionPhysicsProxy.h:143
Definition Array.h:670
Definition SkeletalMeshComponent.h:307
FRealDouble FReal
Definition Real.h:22
CHAOS_API int32 UseAsyncInterpolation
Definition PhysicsSolverBase.cpp:193
Definition OverriddenPropertySet.cpp:45
Definition ChaosResultsManager.h:26
Definition ChaosResultsManager.h:20
Definition ChaosResultsManager.h:32
TArray< FChaosGeometryCollectionInterpolationData > GeometryCollectionInterpolations
Definition ChaosResultsManager.h:55
FRealSingle Alpha
Definition ChaosResultsManager.h:59
TArray< FChaosRigidInterpolationData > RigidInterpolations
Definition ChaosResultsManager.h:54
TArray< FChaosClusterUnionInterpolationData > ClusterUnionInterpolations
Definition ChaosResultsManager.h:56
FPullPhysicsData * Next
Definition ChaosResultsManager.h:58
Definition ChaosResultsManager.h:14
Definition PullPhysicsDataImp.h:153
Definition PullPhysicsDataImp.h:148
Definition PullPhysicsDataImp.h:62
Definition PhysicsSolverBaseImpl.h:33
static void Apply(TDispatcher &Dispatcher, TProxy *Proxy)
Definition PhysicsSolverBaseImpl.h:35