Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/patches/0006-backport-upstream-commit-63765d1.patch
59211 views
1
diff --git a/thirdparty/jolt_physics/Jolt/Physics/PhysicsSystem.cpp b/thirdparty/jolt_physics/Jolt/Physics/PhysicsSystem.cpp
2
index d972dd2c..0a3f21b8 100644
3
--- a/thirdparty/jolt_physics/Jolt/Physics/PhysicsSystem.cpp
4
+++ b/thirdparty/jolt_physics/Jolt/Physics/PhysicsSystem.cpp
5
@@ -26,6 +26,7 @@
6
#include <Jolt/Physics/DeterminismLog.h>
7
#include <Jolt/Physics/SoftBody/SoftBodyMotionProperties.h>
8
#include <Jolt/Physics/SoftBody/SoftBodyShape.h>
9
+#include <Jolt/Physics/SoftBody/SoftBodyContactListener.h>
10
#include <Jolt/Geometry/RayAABox.h>
11
#include <Jolt/Geometry/ClosestPoint.h>
12
#include <Jolt/Core/JobSystem.h>
13
@@ -1833,9 +1834,10 @@ void PhysicsSystem::JobFindCCDContacts(const PhysicsUpdateContext *ioContext, Ph
14
class CCDNarrowPhaseCollector : public CastShapeCollector
15
{
16
public:
17
- CCDNarrowPhaseCollector(const BodyManager &inBodyManager, ContactConstraintManager &inContactConstraintManager, CCDBody &inCCDBody, ShapeCastResult &inResult, float inDeltaTime) :
18
+ CCDNarrowPhaseCollector(const BodyManager &inBodyManager, ContactConstraintManager &inContactConstraintManager, SoftBodyContactListener *inSoftBodyContactListener, CCDBody &inCCDBody, ShapeCastResult &inResult, float inDeltaTime) :
19
mBodyManager(inBodyManager),
20
mContactConstraintManager(inContactConstraintManager),
21
+ mSoftBodyContactListener(inSoftBodyContactListener),
22
mCCDBody(inCCDBody),
23
mResult(inResult),
24
mDeltaTime(inDeltaTime)
25
@@ -1871,26 +1873,53 @@ void PhysicsSystem::JobFindCCDContacts(const PhysicsUpdateContext *ioContext, Ph
26
{
27
// Validate the contact result
28
const Body &body1 = mBodyManager.GetBody(mCCDBody.mBodyID1);
29
- ValidateResult validate_result = mContactConstraintManager.ValidateContactPoint(body1, body2, body1.GetCenterOfMassPosition(), inResult); // Note that the center of mass of body 1 is the start of the sweep and is used as base offset below
30
- switch (validate_result)
31
+ if (body2.IsRigidBody())
32
{
33
- case ValidateResult::AcceptContact:
34
- // Just continue
35
- break;
36
-
37
- case ValidateResult::AcceptAllContactsForThisBodyPair:
38
- // Accept this and all following contacts from this body
39
- mValidateBodyPair = false;
40
- break;
41
-
42
- case ValidateResult::RejectContact:
43
- return;
44
-
45
- case ValidateResult::RejectAllContactsForThisBodyPair:
46
- // Reject this and all following contacts from this body
47
- mRejectAll = true;
48
- ForceEarlyOut();
49
- return;
50
+ ValidateResult validate_result = mContactConstraintManager.ValidateContactPoint(body1, body2, body1.GetCenterOfMassPosition(), inResult); // Note that the center of mass of body 1 is the start of the sweep and is used as base offset below
51
+ switch (validate_result)
52
+ {
53
+ case ValidateResult::AcceptContact:
54
+ // Just continue
55
+ break;
56
+
57
+ case ValidateResult::AcceptAllContactsForThisBodyPair:
58
+ // Accept this and all following contacts from this body
59
+ mValidateBodyPair = false;
60
+ break;
61
+
62
+ case ValidateResult::RejectContact:
63
+ return;
64
+
65
+ case ValidateResult::RejectAllContactsForThisBodyPair:
66
+ // Reject this and all following contacts from this body
67
+ mRejectAll = true;
68
+ ForceEarlyOut();
69
+ return;
70
+ }
71
+ }
72
+ else
73
+ {
74
+ SoftBodyContactSettings sb_settings;
75
+ sb_settings.mIsSensor = false;
76
+ if ((mSoftBodyContactListener == nullptr
77
+ || mSoftBodyContactListener->OnSoftBodyContactValidate(body2, body1, sb_settings) == SoftBodyValidateResult::AcceptContact) // Note reversal, soft body needs to be first parameter
78
+ && !sb_settings.mIsSensor) // If the contact listener turned this into a sensor, we want to ignore it
79
+ {
80
+ // Convert the soft body contact settings (note bodies are swapped)
81
+ mCCDBody.mContactSettings.mInvMassScale1 = sb_settings.mInvMassScale2;
82
+ mCCDBody.mContactSettings.mInvMassScale2 = sb_settings.mInvMassScale1;
83
+ mCCDBody.mContactSettings.mInvInertiaScale1 = sb_settings.mInvInertiaScale2;
84
+
85
+ // Accept this and all following contacts from this body
86
+ mValidateBodyPair = false;
87
+ }
88
+ else
89
+ {
90
+ // Reject this and all following contacts from this body
91
+ mRejectAll = true;
92
+ ForceEarlyOut();
93
+ return;
94
+ }
95
}
96
}
97
98
@@ -1927,6 +1956,7 @@ void PhysicsSystem::JobFindCCDContacts(const PhysicsUpdateContext *ioContext, Ph
99
private:
100
const BodyManager & mBodyManager;
101
ContactConstraintManager & mContactConstraintManager;
102
+ SoftBodyContactListener * mSoftBodyContactListener;
103
CCDBody & mCCDBody;
104
ShapeCastResult & mResult;
105
float mDeltaTime;
106
@@ -1935,7 +1965,7 @@ void PhysicsSystem::JobFindCCDContacts(const PhysicsUpdateContext *ioContext, Ph
107
108
// Narrowphase collector
109
ShapeCastResult cast_shape_result;
110
- CCDNarrowPhaseCollector np_collector(mBodyManager, mContactManager, ccd_body, cast_shape_result, ioContext->mStepDeltaTime);
111
+ CCDNarrowPhaseCollector np_collector(mBodyManager, mContactManager, mSoftBodyContactListener, ccd_body, cast_shape_result, ioContext->mStepDeltaTime);
112
113
// This collector wraps the narrowphase collector and collects the closest hit
114
class CCDBroadPhaseCollector : public CastShapeBodyCollector
115
@@ -2058,7 +2088,15 @@ void PhysicsSystem::JobFindCCDContacts(const PhysicsUpdateContext *ioContext, Ph
116
manifold.mWorldSpaceNormal = ccd_body.mContactNormal;
117
118
// Call contact point callbacks
119
- mContactManager.OnCCDContactAdded(contact_allocator, body, body2, manifold, ccd_body.mContactSettings);
120
+ if (body2.IsRigidBody())
121
+ mContactManager.OnCCDContactAdded(contact_allocator, body, body2, manifold, ccd_body.mContactSettings);
122
+ else
123
+ {
124
+ // We already have mass and inertia scale from the OnSoftBodyContactValidate callback, but we need to fill in the rest of the contact settings
125
+ ccd_body.mContactSettings.mCombinedFriction = 0.0f; // Soft bodies CCD contacts don't apply friction
126
+ ccd_body.mContactSettings.mCombinedRestitution = mContactManager.GetCombineRestitution()(body, SubShapeID(), body2, SubShapeID()); // Soft bodies don't pass sub shape IDs because the restitution is uniform across the entire body
127
+ ccd_body.mContactSettings.mIsSensor = false; // We've filtered out sensors already
128
+ }
129
130
if (ccd_body.mContactSettings.mIsSensor)
131
{
132
@@ -2281,6 +2319,19 @@ void PhysicsSystem::JobResolveCCDContacts(PhysicsUpdateContext *ioContext, Physi
133
vtx0.mVelocity += delta_v2 * vtx0.mInvMass;
134
vtx1.mVelocity += delta_v2 * vtx1.mInvMass;
135
vtx2.mVelocity += delta_v2 * vtx2.mInvMass;
136
+
137
+ // If there's a contact listener, we need to flag this vertex as having had collision and force a contact callback.
138
+ // Note that during the soft body update that follows this, it is likely that a new collision will be found and that this will be overwritten.
139
+ if (mSoftBodyContactListener != nullptr)
140
+ {
141
+ BodyID body_id = ccd_body->mBodyID1;
142
+ Vec3 local_normal = inv_body2_transform.Multiply3x3(ccd_body->mContactNormal);
143
+ Plane contact_plane = Plane::sFromPointAndNormal(local_contact, local_normal);
144
+ vtx0.MarkCCDContact(body_id, contact_plane);
145
+ vtx1.MarkCCDContact(body_id, contact_plane);
146
+ vtx2.MarkCCDContact(body_id, contact_plane);
147
+ soft_mp->RequestContactCallback();
148
+ }
149
}
150
151
// Clamp velocity of body 1
152
diff --git a/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyManifold.h b/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyManifold.h
153
index de21ec50..57a244ad 100644
154
--- a/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyManifold.h
155
+++ b/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyManifold.h
156
@@ -36,7 +36,15 @@ public:
157
/// Get the body with which the vertex has collided in this update
158
JPH_INLINE BodyID GetContactBodyID(const SoftBodyVertex &inVertex) const
159
{
160
- return inVertex.mHasContact? mCollidingShapes[inVertex.mCollidingShapeIndex].mBodyID : BodyID();
161
+ if (!inVertex.mHasContact)
162
+ return BodyID();
163
+
164
+ // If this is a CCD contact, the BodyID is encoded in mCollidingShapeIndex
165
+ if (inVertex.mCollidingShapeIndex & int(BodyID::cBroadPhaseBit))
166
+ return BodyID(uint32(inVertex.mCollidingShapeIndex) ^ BodyID::cBroadPhaseBit);
167
+
168
+ // Otherwise we can get it from mCollidingShapes
169
+ return mCollidingShapes[inVertex.mCollidingShapeIndex].mBodyID;
170
}
171
172
/// Get the number of sensors that are in contact with the soft body
173
diff --git a/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.cpp b/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.cpp
174
index 4aa88d20..327145ed 100644
175
--- a/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.cpp
176
+++ b/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.cpp
177
@@ -121,15 +121,13 @@ void SoftBodyMotionProperties::DetermineCollidingShapes(const SoftBodyUpdateCont
178
{
179
JPH_PROFILE_FUNCTION();
180
181
- // Reset flag prior to collision detection
182
- mNeedContactCallback.store(false, memory_order_relaxed);
183
-
184
struct Collector : public CollideShapeBodyCollector
185
{
186
- Collector(const SoftBodyUpdateContext &inContext, const PhysicsSystem &inSystem, const BodyLockInterface &inBodyLockInterface, const AABox &inLocalBounds, SimShapeFilterWrapper &inShapeFilter, Array<CollidingShape> &ioHits, Array<CollidingSensor> &ioSensors) :
187
+ Collector(const SoftBodyUpdateContext &inContext, const PhysicsSystem &inSystem, const BodyLockInterface &inBodyLockInterface, const AABox &inLocalBounds, const AABox &inWorldBounds, SimShapeFilterWrapper &inShapeFilter, Array<CollidingShape> &ioHits, Array<CollidingSensor> &ioSensors) :
188
mContext(inContext),
189
mInverseTransform(inContext.mCenterOfMassTransform.InversedRotationTranslation()),
190
mLocalBounds(inLocalBounds),
191
+ mWorldBounds(inWorldBounds),
192
mBodyLockInterface(inBodyLockInterface),
193
mCombineFriction(inSystem.GetCombineFriction()),
194
mCombineRestitution(inSystem.GetCombineRestitution()),
195
@@ -147,7 +145,8 @@ void SoftBodyMotionProperties::DetermineCollidingShapes(const SoftBodyUpdateCont
196
const Body &soft_body = *mContext.mBody;
197
const Body &body = lock.GetBody();
198
if (body.IsRigidBody() // TODO: We should support soft body vs soft body
199
- && soft_body.GetCollisionGroup().CanCollide(body.GetCollisionGroup()))
200
+ && soft_body.GetCollisionGroup().CanCollide(body.GetCollisionGroup())
201
+ && mWorldBounds.Overlaps(body.GetWorldSpaceBounds())) // In the broadphase we widen the bounding box when a body moves, do a final check to see if the bounding boxes actually overlap
202
{
203
SoftBodyContactSettings settings;
204
settings.mIsSensor = body.IsSensor();
205
@@ -227,6 +226,7 @@ void SoftBodyMotionProperties::DetermineCollidingShapes(const SoftBodyUpdateCont
206
const SoftBodyUpdateContext &mContext;
207
RMat44 mInverseTransform;
208
AABox mLocalBounds;
209
+ AABox mWorldBounds;
210
const BodyLockInterface & mBodyLockInterface;
211
ContactConstraintManager::CombineFunction mCombineFriction;
212
ContactConstraintManager::CombineFunction mCombineRestitution;
213
@@ -246,7 +246,7 @@ void SoftBodyMotionProperties::DetermineCollidingShapes(const SoftBodyUpdateCont
214
// Create shape filter
215
SimShapeFilterWrapper shape_filter(inContext.mSimShapeFilter, inContext.mBody);
216
217
- Collector collector(inContext, inSystem, inBodyLockInterface, local_bounds, shape_filter, mCollidingShapes, mCollidingSensors);
218
+ Collector collector(inContext, inSystem, inBodyLockInterface, local_bounds, world_bounds, shape_filter, mCollidingShapes, mCollidingSensors);
219
ObjectLayer layer = inContext.mBody->GetObjectLayer();
220
DefaultBroadPhaseLayerFilter broadphase_layer_filter = inSystem.GetDefaultBroadPhaseLayerFilter(layer);
221
DefaultObjectLayerFilter object_layer_filter = inSystem.GetDefaultLayerFilter(layer);
222
@@ -285,7 +285,7 @@ void SoftBodyMotionProperties::DetermineSensorCollisions(CollidingSensor &ioSens
223
224
// We need a contact callback if one of the sensors collided
225
if (ioSensor.mHasContact)
226
- mNeedContactCallback.store(true, memory_order_relaxed);
227
+ RequestContactCallback();
228
}
229
230
void SoftBodyMotionProperties::ApplyPressure(const SoftBodyUpdateContext &inContext)
231
@@ -714,6 +714,7 @@ void SoftBodyMotionProperties::ApplyCollisionConstraintsAndUpdateVelocities(cons
232
v.mVelocity = (v.mPosition - v.mPreviousPosition) / dt;
233
234
// Satisfy collision constraint
235
+ static_assert(int(BodyID::cBroadPhaseBit) < 0); // CCD contacts should be negative too (see: SoftBodyVertex::MarkCCDContact)
236
if (v.mCollidingShapeIndex >= 0)
237
{
238
// Check if there is a collision
239
@@ -724,7 +725,7 @@ void SoftBodyMotionProperties::ApplyCollisionConstraintsAndUpdateVelocities(cons
240
v.mHasContact = true;
241
242
// We need a contact callback if one of the vertices collided
243
- mNeedContactCallback.store(true, memory_order_relaxed);
244
+ RequestContactCallback();
245
246
// Note that we already calculated the velocity, so this does not affect the velocity (next iteration starts by setting previous position to current position)
247
CollidingShape &cs = mCollidingShapes[v.mCollidingShapeIndex];
248
@@ -839,6 +840,8 @@ void SoftBodyMotionProperties::UpdateSoftBodyState(SoftBodyUpdateContext &ioCont
249
}
250
251
ioContext.mContactListener->OnSoftBodyContactAdded(*ioContext.mBody, SoftBodyManifold(this));
252
+
253
+ mNeedContactCallback.store(false, memory_order_relaxed);
254
}
255
256
// Loop through vertices once more to update the global state
257
diff --git a/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.h b/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.h
258
index 8768efd6..918ce366 100644
259
--- a/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.h
260
+++ b/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.h
261
@@ -176,6 +176,9 @@ public:
262
/// Update the velocities of all rigid bodies that we collided with. Not part of the public API.
263
void UpdateRigidBodyVelocities(const SoftBodyUpdateContext &inContext, BodyInterface &inBodyInterface);
264
265
+ /// Set a flag to indicate that the ContactListener::OnSoftBodyContactAdded should be called
266
+ inline void RequestContactCallback() { mNeedContactCallback.store(true, memory_order_relaxed); }
267
+
268
private:
269
// SoftBodyManifold needs to have access to CollidingShape
270
friend class SoftBodyManifold;
271
diff --git a/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyVertex.h b/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyVertex.h
272
index 72d4291e..261362ef 100644
273
--- a/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyVertex.h
274
+++ b/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyVertex.h
275
@@ -23,6 +23,14 @@ public:
276
mHasContact = false;
277
}
278
279
+ /// Mark this vertex as being in contact with inBodyID
280
+ inline void MarkCCDContact(const BodyID &inBodyID, const Plane &inContactPlane)
281
+ {
282
+ mCollisionPlane = inContactPlane;
283
+ mCollidingShapeIndex = int(inBodyID.GetIndexAndSequenceNumber() | BodyID::cBroadPhaseBit); // We reuse the broad phase bit to indicate this is a CCD contact
284
+ mHasContact = true;
285
+ }
286
+
287
Vec3 mPreviousPosition; ///< Internal use only. Position at the previous time step
288
Vec3 mPosition; ///< Position, relative to the center of mass of the soft body
289
Vec3 mVelocity; ///< Velocity, relative to the center of mass of the soft body
290
291