Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Body/BodyManager.h
21730 views
1
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3
// SPDX-License-Identifier: MIT
4
5
#pragma once
6
7
#include <Jolt/Physics/Body/Body.h>
8
#include <Jolt/Core/Mutex.h>
9
#include <Jolt/Core/MutexArray.h>
10
11
JPH_NAMESPACE_BEGIN
12
13
// Classes
14
class BodyCreationSettings;
15
class SoftBodyCreationSettings;
16
class BodyActivationListener;
17
class StateRecorderFilter;
18
struct PhysicsSettings;
19
#ifdef JPH_DEBUG_RENDERER
20
class DebugRenderer;
21
class BodyDrawFilter;
22
#endif // JPH_DEBUG_RENDERER
23
24
#ifdef JPH_DEBUG_RENDERER
25
26
/// Defines how to color soft body constraints
27
enum class ESoftBodyConstraintColor
28
{
29
ConstraintType, /// Draw different types of constraints in different colors
30
ConstraintGroup, /// Draw constraints in the same group in the same color, non-parallel group will be red
31
ConstraintOrder, /// Draw constraints in the same group in the same color, non-parallel group will be red, and order within each group will be indicated with gradient
32
};
33
34
#endif // JPH_DEBUG_RENDERER
35
36
/// Array of bodies
37
using BodyVector = Array<Body *>;
38
39
/// Array of body ID's
40
using BodyIDVector = Array<BodyID>;
41
42
/// Class that contains all bodies
43
class JPH_EXPORT BodyManager : public NonCopyable
44
{
45
public:
46
JPH_OVERRIDE_NEW_DELETE
47
48
/// Destructor
49
~BodyManager();
50
51
/// Initialize the manager
52
void Init(uint inMaxBodies, uint inNumBodyMutexes, const BroadPhaseLayerInterface &inLayerInterface);
53
54
/// Gets the current amount of bodies that are in the body manager
55
uint GetNumBodies() const;
56
57
/// Gets the max bodies that we can support
58
uint GetMaxBodies() const { return uint(mBodies.capacity()); }
59
60
/// Helper struct that counts the number of bodies of each type
61
struct BodyStats
62
{
63
uint mNumBodies = 0; ///< Total number of bodies in the body manager
64
uint mMaxBodies = 0; ///< Max allowed number of bodies in the body manager (as configured in Init(...))
65
66
uint mNumBodiesStatic = 0; ///< Number of static bodies
67
68
uint mNumBodiesDynamic = 0; ///< Number of dynamic bodies
69
uint mNumActiveBodiesDynamic = 0; ///< Number of dynamic bodies that are currently active
70
71
uint mNumBodiesKinematic = 0; ///< Number of kinematic bodies
72
uint mNumActiveBodiesKinematic = 0; ///< Number of kinematic bodies that are currently active
73
74
uint mNumSoftBodies = 0; ///< Number of soft bodies
75
uint mNumActiveSoftBodies = 0; ///< Number of soft bodies that are currently active
76
};
77
78
/// Get stats about the bodies in the body manager (slow, iterates through all bodies)
79
BodyStats GetBodyStats() const;
80
81
/// Create a body using creation settings. The returned body will not be part of the body manager yet.
82
Body * AllocateBody(const BodyCreationSettings &inBodyCreationSettings) const;
83
84
/// Create a soft body using creation settings. The returned body will not be part of the body manager yet.
85
Body * AllocateSoftBody(const SoftBodyCreationSettings &inSoftBodyCreationSettings) const;
86
87
/// Free a body that has not been added to the body manager yet (if it has, use DestroyBodies).
88
void FreeBody(Body *inBody) const;
89
90
/// Add a body to the body manager, assigning it the next available ID. Returns false if no more IDs are available.
91
bool AddBody(Body *ioBody);
92
93
/// Add a body to the body manager, assigning it a custom ID. Returns false if the ID is not valid.
94
bool AddBodyWithCustomID(Body *ioBody, const BodyID &inBodyID);
95
96
/// Remove a list of bodies from the body manager
97
void RemoveBodies(const BodyID *inBodyIDs, int inNumber, Body **outBodies);
98
99
/// Remove a set of bodies from the body manager and frees them.
100
void DestroyBodies(const BodyID *inBodyIDs, int inNumber);
101
102
/// Activate a list of bodies.
103
/// This function should only be called when an exclusive lock for the bodies are held.
104
void ActivateBodies(const BodyID *inBodyIDs, int inNumber);
105
106
/// Deactivate a list of bodies.
107
/// This function should only be called when an exclusive lock for the bodies are held.
108
void DeactivateBodies(const BodyID *inBodyIDs, int inNumber);
109
110
/// Update the motion quality for a body
111
void SetMotionQuality(Body &ioBody, EMotionQuality inMotionQuality);
112
113
/// Get copy of the list of active bodies under protection of a lock.
114
void GetActiveBodies(EBodyType inType, BodyIDVector &outBodyIDs) const;
115
116
/// Get the list of active bodies. Note: Not thread safe. The active bodies list can change at any moment.
117
const BodyID * GetActiveBodiesUnsafe(EBodyType inType) const { return mActiveBodies[int(inType)]; }
118
119
/// Get the number of active bodies.
120
uint32 GetNumActiveBodies(EBodyType inType) const { return mNumActiveBodies[int(inType)].load(memory_order_acquire); }
121
122
/// Get the number of active bodies that are using continuous collision detection
123
uint32 GetNumActiveCCDBodies() const { return mNumActiveCCDBodies; }
124
125
/// Listener that is notified whenever a body is activated/deactivated
126
void SetBodyActivationListener(BodyActivationListener *inListener);
127
BodyActivationListener * GetBodyActivationListener() const { return mActivationListener; }
128
129
/// Check if this is a valid body pointer. When a body is freed the memory that the pointer occupies is reused to store a freelist.
130
static inline bool sIsValidBodyPointer(const Body *inBody) { return (uintptr_t(inBody) & cIsFreedBody) == 0; }
131
132
/// Get all bodies. Note that this can contain invalid body pointers, call sIsValidBodyPointer to check.
133
const BodyVector & GetBodies() const { return mBodies; }
134
135
/// Get all bodies. Note that this can contain invalid body pointers, call sIsValidBodyPointer to check.
136
BodyVector & GetBodies() { return mBodies; }
137
138
/// Get all body IDs under the protection of a lock
139
void GetBodyIDs(BodyIDVector &outBodies) const;
140
141
/// Access a body (not protected by lock)
142
const Body & GetBody(const BodyID &inID) const { return *mBodies[inID.GetIndex()]; }
143
144
/// Access a body (not protected by lock)
145
Body & GetBody(const BodyID &inID) { return *mBodies[inID.GetIndex()]; }
146
147
/// Access a body, will return a nullptr if the body ID is no longer valid (not protected by lock)
148
const Body * TryGetBody(const BodyID &inID) const
149
{
150
uint32 idx = inID.GetIndex();
151
if (idx >= mBodies.size())
152
return nullptr;
153
154
const Body *body = mBodies[idx];
155
if (sIsValidBodyPointer(body) && body->GetID() == inID)
156
return body;
157
158
return nullptr;
159
}
160
161
/// Access a body, will return a nullptr if the body ID is no longer valid (not protected by lock)
162
Body * TryGetBody(const BodyID &inID)
163
{
164
uint32 idx = inID.GetIndex();
165
if (idx >= mBodies.size())
166
return nullptr;
167
168
Body *body = mBodies[idx];
169
if (sIsValidBodyPointer(body) && body->GetID() == inID)
170
return body;
171
172
return nullptr;
173
}
174
175
/// Access the mutex for a single body
176
SharedMutex & GetMutexForBody(const BodyID &inID) const { return mBodyMutexes.GetMutexByObjectIndex(inID.GetIndex()); }
177
178
/// Bodies are protected using an array of mutexes (so a fixed number, not 1 per body). Each bit in this mask indicates a locked mutex.
179
using MutexMask = uint64;
180
181
///@name Batch body mutex access (do not use directly)
182
///@{
183
MutexMask GetAllBodiesMutexMask() const { return mBodyMutexes.GetNumMutexes() == sizeof(MutexMask) * 8? ~MutexMask(0) : (MutexMask(1) << mBodyMutexes.GetNumMutexes()) - 1; }
184
MutexMask GetMutexMask(const BodyID *inBodies, int inNumber) const;
185
void LockRead(MutexMask inMutexMask) const;
186
void UnlockRead(MutexMask inMutexMask) const;
187
void LockWrite(MutexMask inMutexMask) const;
188
void UnlockWrite(MutexMask inMutexMask) const;
189
///@}
190
191
/// Lock all bodies. This should only be done during PhysicsSystem::Update().
192
void LockAllBodies() const;
193
194
/// Unlock all bodies. This should only be done during PhysicsSystem::Update().
195
void UnlockAllBodies() const;
196
197
/// Function to update body's layer (should only be called by the BodyInterface since it also requires updating the broadphase)
198
inline void SetBodyObjectLayerInternal(Body &ioBody, ObjectLayer inLayer) const { ioBody.mObjectLayer = inLayer; ioBody.mBroadPhaseLayer = mBroadPhaseLayerInterface->GetBroadPhaseLayer(inLayer); }
199
200
/// Set the Body::EFlags::InvalidateContactCache flag for the specified body. This means that the collision cache is invalid for any body pair involving that body until the next physics step.
201
void InvalidateContactCacheForBody(Body &ioBody);
202
203
/// Reset the Body::EFlags::InvalidateContactCache flag for all bodies. All contact pairs in the contact cache will now by valid again.
204
void ValidateContactCacheForAllBodies();
205
206
/// Saving state for replay
207
void SaveState(StateRecorder &inStream, const StateRecorderFilter *inFilter) const;
208
209
/// Restoring state for replay. Returns false if failed.
210
bool RestoreState(StateRecorder &inStream);
211
212
/// Save the state of a single body for replay
213
void SaveBodyState(const Body &inBody, StateRecorder &inStream) const;
214
215
/// Save the state of a single body for replay
216
void RestoreBodyState(Body &inBody, StateRecorder &inStream);
217
218
#ifdef JPH_DEBUG_RENDERER
219
enum class EShapeColor
220
{
221
InstanceColor, ///< Random color per instance
222
ShapeTypeColor, ///< Convex = green, scaled = yellow, compound = orange, mesh = red
223
MotionTypeColor, ///< Static = grey, keyframed = green, dynamic = random color per instance
224
SleepColor, ///< Static = grey, keyframed = green, dynamic = yellow, sleeping = red
225
IslandColor, ///< Static = grey, active = random color per island, sleeping = light grey
226
MaterialColor, ///< Color as defined by the PhysicsMaterial of the shape
227
};
228
229
/// Draw settings
230
struct DrawSettings
231
{
232
bool mDrawGetSupportFunction = false; ///< Draw the GetSupport() function, used for convex collision detection
233
bool mDrawSupportDirection = false; ///< When drawing the support function, also draw which direction mapped to a specific support point
234
bool mDrawGetSupportingFace = false; ///< Draw the faces that were found colliding during collision detection
235
bool mDrawShape = true; ///< Draw the shapes of all bodies
236
bool mDrawShapeWireframe = false; ///< When mDrawShape is true and this is true, the shapes will be drawn in wireframe instead of solid.
237
EShapeColor mDrawShapeColor = EShapeColor::MotionTypeColor; ///< Coloring scheme to use for shapes
238
bool mDrawBoundingBox = false; ///< Draw a bounding box per body
239
bool mDrawCenterOfMassTransform = false; ///< Draw the center of mass for each body
240
bool mDrawWorldTransform = false; ///< Draw the world transform (which can be different than the center of mass) for each body
241
bool mDrawVelocity = false; ///< Draw the velocity vector for each body
242
bool mDrawMassAndInertia = false; ///< Draw the mass and inertia (as the box equivalent) for each body
243
bool mDrawSleepStats = false; ///< Draw stats regarding the sleeping algorithm of each body
244
bool mDrawSoftBodyVertices = false; ///< Draw the vertices of soft bodies
245
bool mDrawSoftBodyVertexVelocities = false; ///< Draw the velocities of the vertices of soft bodies
246
bool mDrawSoftBodyEdgeConstraints = false; ///< Draw the edge constraints of soft bodies
247
bool mDrawSoftBodyBendConstraints = false; ///< Draw the bend constraints of soft bodies
248
bool mDrawSoftBodyVolumeConstraints = false; ///< Draw the volume constraints of soft bodies
249
bool mDrawSoftBodySkinConstraints = false; ///< Draw the skin constraints of soft bodies
250
bool mDrawSoftBodyLRAConstraints = false; ///< Draw the LRA constraints of soft bodies
251
bool mDrawSoftBodyRods = false; ///< Draw the rods of soft bodies
252
bool mDrawSoftBodyRodStates = false; ///< Draw the rod states (orientation and angular velocity) of soft bodies
253
bool mDrawSoftBodyRodBendTwistConstraints = false; ///< Draw the rod bend twist constraints of soft bodies
254
bool mDrawSoftBodyPredictedBounds = false; ///< Draw the predicted bounds of soft bodies
255
ESoftBodyConstraintColor mDrawSoftBodyConstraintColor = ESoftBodyConstraintColor::ConstraintType; ///< Coloring scheme to use for soft body constraints
256
};
257
258
/// Draw the state of the bodies (debugging purposes)
259
void Draw(const DrawSettings &inSettings, const PhysicsSettings &inPhysicsSettings, DebugRenderer *inRenderer, const BodyDrawFilter *inBodyFilter = nullptr);
260
#endif // JPH_DEBUG_RENDERER
261
262
#ifdef JPH_ENABLE_ASSERTS
263
/// Lock the active body list, asserts when Activate/DeactivateBody is called.
264
void SetActiveBodiesLocked(bool inLocked) { mActiveBodiesLocked = inLocked; }
265
266
/// Per thread override of the locked state, to be used by the PhysicsSystem only!
267
class GrantActiveBodiesAccess
268
{
269
public:
270
inline GrantActiveBodiesAccess(bool inAllowActivation, bool inAllowDeactivation)
271
{
272
JPH_ASSERT(!sGetOverrideAllowActivation());
273
sSetOverrideAllowActivation(inAllowActivation);
274
275
JPH_ASSERT(!sGetOverrideAllowDeactivation());
276
sSetOverrideAllowDeactivation(inAllowDeactivation);
277
}
278
279
inline ~GrantActiveBodiesAccess()
280
{
281
sSetOverrideAllowActivation(false);
282
sSetOverrideAllowDeactivation(false);
283
}
284
};
285
#endif
286
287
#ifdef JPH_DEBUG
288
/// Validate if the cached bounding boxes are correct for all active bodies
289
void ValidateActiveBodyBounds();
290
#endif // JPH_DEBUG
291
292
private:
293
/// Increment and get the sequence number of the body
294
#ifdef JPH_COMPILER_CLANG
295
__attribute__((no_sanitize("implicit-conversion"))) // We intentionally overflow the uint8 sequence number
296
#endif
297
inline uint8 GetNextSequenceNumber(int inBodyIndex) { return ++mBodySequenceNumbers[inBodyIndex]; }
298
299
/// Add a single body to mActiveBodies, note doesn't lock the active body mutex!
300
inline void AddBodyToActiveBodies(Body &ioBody);
301
302
/// Remove a single body from mActiveBodies, note doesn't lock the active body mutex!
303
inline void RemoveBodyFromActiveBodies(Body &ioBody);
304
305
/// Helper function to remove a body from the manager
306
JPH_INLINE Body * RemoveBodyInternal(const BodyID &inBodyID);
307
308
/// Helper function to delete a body (which could actually be a BodyWithMotionProperties)
309
inline static void sDeleteBody(Body *inBody);
310
311
#if defined(JPH_DEBUG) && defined(JPH_ENABLE_ASSERTS)
312
/// Function to check that the free list is not corrupted
313
void ValidateFreeList() const;
314
#endif // defined(JPH_DEBUG) && _defined(JPH_ENABLE_ASSERTS)
315
316
/// List of pointers to all bodies. Contains invalid pointers for deleted bodies, check with sIsValidBodyPointer. Note that this array is reserved to the max bodies that is passed in the Init function so that adding bodies will not reallocate the array.
317
BodyVector mBodies;
318
319
/// Current number of allocated bodies
320
uint mNumBodies = 0;
321
322
/// Indicates that there are no more freed body IDs
323
static constexpr uintptr_t cBodyIDFreeListEnd = ~uintptr_t(0);
324
325
/// Bit that indicates a pointer in mBodies is actually the index of the next freed body. We use the lowest bit because we know that Bodies need to be 16 byte aligned so addresses can never end in a 1 bit.
326
static constexpr uintptr_t cIsFreedBody = uintptr_t(1);
327
328
/// Amount of bits to shift to get an index to the next freed body
329
static constexpr uint cFreedBodyIndexShift = 1;
330
331
/// Index of first entry in mBodies that is unused
332
uintptr_t mBodyIDFreeListStart = cBodyIDFreeListEnd;
333
334
/// Protects mBodies array (but not the bodies it points to), mNumBodies and mBodyIDFreeListStart
335
mutable Mutex mBodiesMutex;
336
337
/// An array of mutexes protecting the bodies in the mBodies array
338
using BodyMutexes = MutexArray<SharedMutex>;
339
mutable BodyMutexes mBodyMutexes;
340
341
/// List of next sequence number for a body ID
342
Array<uint8> mBodySequenceNumbers;
343
344
/// Mutex that protects the mActiveBodies array
345
mutable Mutex mActiveBodiesMutex;
346
347
/// List of all active dynamic bodies (size is equal to max amount of bodies)
348
BodyID * mActiveBodies[cBodyTypeCount] = { };
349
350
/// How many bodies there are in the list of active bodies
351
atomic<uint32> mNumActiveBodies[cBodyTypeCount] = { };
352
353
/// How many of the active bodies have continuous collision detection enabled
354
uint32 mNumActiveCCDBodies = 0;
355
356
/// Mutex that protects the mBodiesCacheInvalid array
357
mutable Mutex mBodiesCacheInvalidMutex;
358
359
/// List of all bodies that should have their cache invalidated
360
BodyIDVector mBodiesCacheInvalid;
361
362
/// Listener that is notified whenever a body is activated/deactivated
363
BodyActivationListener * mActivationListener = nullptr;
364
365
/// Cached broadphase layer interface
366
const BroadPhaseLayerInterface *mBroadPhaseLayerInterface = nullptr;
367
368
#ifdef JPH_ENABLE_ASSERTS
369
static bool sGetOverrideAllowActivation();
370
static void sSetOverrideAllowActivation(bool inValue);
371
372
static bool sGetOverrideAllowDeactivation();
373
static void sSetOverrideAllowDeactivation(bool inValue);
374
375
/// Debug system that tries to limit changes to active bodies during the PhysicsSystem::Update()
376
bool mActiveBodiesLocked = false;
377
#endif
378
};
379
380
JPH_NAMESPACE_END
381
382