Jolt Physics
A multi core friendly Game Physics Engine
Loading...
Searching...
No Matches
BodyManager.h
Go to the documentation of this file.
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
8#include <Jolt/Core/Mutex.h>
10
12
13// Classes
18struct PhysicsSettings;
19#ifdef JPH_DEBUG_RENDERER
20class DebugRenderer;
21class BodyDrawFilter;
22#endif // JPH_DEBUG_RENDERER
23
24#ifdef JPH_DEBUG_RENDERER
25
28{
32};
33
34#endif // JPH_DEBUG_RENDERER
35
38
41
44{
45public:
47
50
52 void Init(uint inMaxBodies, uint inNumBodyMutexes, const BroadPhaseLayerInterface &inLayerInterface);
53
55 uint GetNumBodies() const;
56
58 uint GetMaxBodies() const { return uint(mBodies.capacity()); }
59
61 struct BodyStats
62 {
63 uint mNumBodies = 0;
64 uint mMaxBodies = 0;
65
66 uint mNumBodiesStatic = 0;
67
68 uint mNumBodiesDynamic = 0;
69 uint mNumActiveBodiesDynamic = 0;
70
71 uint mNumBodiesKinematic = 0;
72 uint mNumActiveBodiesKinematic = 0;
73
74 uint mNumSoftBodies = 0;
75 uint mNumActiveSoftBodies = 0;
76 };
77
79 BodyStats GetBodyStats() const;
80
82 Body * AllocateBody(const BodyCreationSettings &inBodyCreationSettings) const;
83
85 Body * AllocateSoftBody(const SoftBodyCreationSettings &inSoftBodyCreationSettings) const;
86
88 void FreeBody(Body *inBody) const;
89
91 bool AddBody(Body *ioBody);
92
94 bool AddBodyWithCustomID(Body *ioBody, const BodyID &inBodyID);
95
97 void RemoveBodies(const BodyID *inBodyIDs, int inNumber, Body **outBodies);
98
100 void DestroyBodies(const BodyID *inBodyIDs, int inNumber);
101
104 void ActivateBodies(const BodyID *inBodyIDs, int inNumber);
105
108 void DeactivateBodies(const BodyID *inBodyIDs, int inNumber);
109
111 void SetMotionQuality(Body &ioBody, EMotionQuality inMotionQuality);
112
114 void GetActiveBodies(EBodyType inType, BodyIDVector &outBodyIDs) const;
115
117 const BodyID * GetActiveBodiesUnsafe(EBodyType inType) const { return mActiveBodies[int(inType)]; }
118
120 uint32 GetNumActiveBodies(EBodyType inType) const { return mNumActiveBodies[int(inType)].load(memory_order_acquire); }
121
123 uint32 GetNumActiveCCDBodies() const { return mNumActiveCCDBodies; }
124
126 void SetBodyActivationListener(BodyActivationListener *inListener);
127 BodyActivationListener * GetBodyActivationListener() const { return mActivationListener; }
128
130 static inline bool sIsValidBodyPointer(const Body *inBody) { return (uintptr_t(inBody) & cIsFreedBody) == 0; }
131
133 const BodyVector & GetBodies() const { return mBodies; }
134
136 BodyVector & GetBodies() { return mBodies; }
137
139 void GetBodyIDs(BodyIDVector &outBodies) const;
140
142 const Body & GetBody(const BodyID &inID) const { return *mBodies[inID.GetIndex()]; }
143
145 Body & GetBody(const BodyID &inID) { return *mBodies[inID.GetIndex()]; }
146
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
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
176 SharedMutex & GetMutexForBody(const BodyID &inID) const { return mBodyMutexes.GetMutexByObjectIndex(inID.GetIndex()); }
177
180
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;
190
192 void LockAllBodies() const;
193
195 void UnlockAllBodies() const;
196
198 inline void SetBodyObjectLayerInternal(Body &ioBody, ObjectLayer inLayer) const { ioBody.mObjectLayer = inLayer; ioBody.mBroadPhaseLayer = mBroadPhaseLayerInterface->GetBroadPhaseLayer(inLayer); }
199
201 void InvalidateContactCacheForBody(Body &ioBody);
202
204 void ValidateContactCacheForAllBodies();
205
207 void SaveState(StateRecorder &inStream, const StateRecorderFilter *inFilter) const;
208
210 bool RestoreState(StateRecorder &inStream);
211
213 void SaveBodyState(const Body &inBody, StateRecorder &inStream) const;
214
216 void RestoreBodyState(Body &inBody, StateRecorder &inStream);
217
218#ifdef JPH_DEBUG_RENDERER
219 enum class EShapeColor
220 {
221 InstanceColor,
222 ShapeTypeColor,
223 MotionTypeColor,
224 SleepColor,
225 IslandColor,
226 MaterialColor,
227 };
228
231 {
232 bool mDrawGetSupportFunction = false;
233 bool mDrawSupportDirection = false;
234 bool mDrawGetSupportingFace = false;
235 bool mDrawShape = true;
236 bool mDrawShapeWireframe = false;
237 EShapeColor mDrawShapeColor = EShapeColor::MotionTypeColor;
238 bool mDrawBoundingBox = false;
239 bool mDrawCenterOfMassTransform = false;
240 bool mDrawWorldTransform = false;
241 bool mDrawVelocity = false;
242 bool mDrawMassAndInertia = false;
243 bool mDrawSleepStats = false;
244 bool mDrawSoftBodyVertices = false;
245 bool mDrawSoftBodyVertexVelocities = false;
246 bool mDrawSoftBodyEdgeConstraints = false;
247 bool mDrawSoftBodyBendConstraints = false;
248 bool mDrawSoftBodyVolumeConstraints = false;
249 bool mDrawSoftBodySkinConstraints = false;
250 bool mDrawSoftBodyLRAConstraints = false;
251 bool mDrawSoftBodyPredictedBounds = false;
252 ESoftBodyConstraintColor mDrawSoftBodyConstraintColor = ESoftBodyConstraintColor::ConstraintType;
253 };
254
256 void Draw(const DrawSettings &inSettings, const PhysicsSettings &inPhysicsSettings, DebugRenderer *inRenderer, const BodyDrawFilter *inBodyFilter = nullptr);
257#endif // JPH_DEBUG_RENDERER
258
259#ifdef JPH_ENABLE_ASSERTS
261 void SetActiveBodiesLocked(bool inLocked) { mActiveBodiesLocked = inLocked; }
262
264 class GrantActiveBodiesAccess
265 {
266 public:
267 inline GrantActiveBodiesAccess(bool inAllowActivation, bool inAllowDeactivation)
268 {
269 JPH_ASSERT(!sGetOverrideAllowActivation());
270 sSetOverrideAllowActivation(inAllowActivation);
271
272 JPH_ASSERT(!sGetOverrideAllowDeactivation());
273 sSetOverrideAllowDeactivation(inAllowDeactivation);
274 }
275
276 inline ~GrantActiveBodiesAccess()
277 {
278 sSetOverrideAllowActivation(false);
279 sSetOverrideAllowDeactivation(false);
280 }
281 };
282#endif
283
284#ifdef JPH_DEBUG
286 void ValidateActiveBodyBounds();
287#endif // JPH_DEBUG
288
289private:
291#ifdef JPH_COMPILER_CLANG
292 __attribute__((no_sanitize("implicit-conversion"))) // We intentionally overflow the uint8 sequence number
293#endif
294 inline uint8 GetNextSequenceNumber(int inBodyIndex) { return ++mBodySequenceNumbers[inBodyIndex]; }
295
297 inline void AddBodyToActiveBodies(Body &ioBody);
298
300 inline void RemoveBodyFromActiveBodies(Body &ioBody);
301
303 JPH_INLINE Body * RemoveBodyInternal(const BodyID &inBodyID);
304
306 inline static void sDeleteBody(Body *inBody);
307
308#if defined(JPH_DEBUG) && defined(JPH_ENABLE_ASSERTS)
310 void ValidateFreeList() const;
311#endif // defined(JPH_DEBUG) && _defined(JPH_ENABLE_ASSERTS)
312
314 BodyVector mBodies;
315
317 uint mNumBodies = 0;
318
320 static constexpr uintptr_t cBodyIDFreeListEnd = ~uintptr_t(0);
321
323 static constexpr uintptr_t cIsFreedBody = uintptr_t(1);
324
326 static constexpr uint cFreedBodyIndexShift = 1;
327
329 uintptr_t mBodyIDFreeListStart = cBodyIDFreeListEnd;
330
332 mutable Mutex mBodiesMutex;
333
335 using BodyMutexes = MutexArray<SharedMutex>;
336 mutable BodyMutexes mBodyMutexes;
337
339 Array<uint8> mBodySequenceNumbers;
340
342 mutable Mutex mActiveBodiesMutex;
343
345 BodyID * mActiveBodies[cBodyTypeCount] = { };
346
348 atomic<uint32> mNumActiveBodies[cBodyTypeCount] = { };
349
351 uint32 mNumActiveCCDBodies = 0;
352
354 mutable Mutex mBodiesCacheInvalidMutex;
355
357 BodyIDVector mBodiesCacheInvalid;
358
360 BodyActivationListener * mActivationListener = nullptr;
361
363 const BroadPhaseLayerInterface *mBroadPhaseLayerInterface = nullptr;
364
365#ifdef JPH_ENABLE_ASSERTS
366 static bool sGetOverrideAllowActivation();
367 static void sSetOverrideAllowActivation(bool inValue);
368
369 static bool sGetOverrideAllowDeactivation();
370 static void sSetOverrideAllowDeactivation(bool inValue);
371
373 bool mActiveBodiesLocked = false;
374#endif
375};
376
ESoftBodyConstraintColor
Defines how to color soft body constraints.
Definition: BodyManager.h:28
@ ConstraintGroup
Draw different types of constraints in different colors.
@ ConstraintOrder
Draw constraints in the same group in the same color, non-parallel group will be red.
EBodyType
Type of body.
Definition: BodyType.h:11
std::uint8_t uint8
Definition: Core.h:453
#define JPH_EXPORT
Definition: Core.h:236
std::uint64_t uint64
Definition: Core.h:456
unsigned int uint
Definition: Core.h:452
#define JPH_NAMESPACE_END
Definition: Core.h:378
std::uint32_t uint32
Definition: Core.h:455
#define JPH_NAMESPACE_BEGIN
Definition: Core.h:372
#define JPH_ASSERT(...)
Definition: IssueReporting.h:33
#define JPH_OVERRIDE_NEW_DELETE
Macro to override the new and delete functions.
Definition: Memory.h:31
EMotionQuality
Motion quality, or how well it detects collisions when it has a high velocity.
Definition: MotionQuality.h:11
uint16 ObjectLayer
Definition: ObjectLayer.h:16
Definition: BodyActivationListener.h:14
Settings for constructing a rigid body.
Definition: BodyCreationSettings.h:31
Class function to filter out bodies for debug rendering, returns true if body should be rendered.
Definition: BodyFilter.h:117
Definition: Body.h:35
JPH_OVERRIDE_NEW_DELETE const BodyID & GetID() const
Get the id of this body.
Definition: Body.h:40
ID of a body. This is a way of reasoning about bodies in a multithreaded simulation while avoiding ra...
Definition: BodyID.h:13
uint32 GetIndex() const
Get index in body array.
Definition: BodyID.h:43
Class that contains all bodies.
Definition: BodyManager.h:44
static bool sIsValidBodyPointer(const Body *inBody)
Check if this is a valid body pointer. When a body is freed the memory that the pointer occupies is r...
Definition: BodyManager.h:130
Body & GetBody(const BodyID &inID)
Access a body (not protected by lock)
Definition: BodyManager.h:145
BodyActivationListener * GetBodyActivationListener() const
Definition: BodyManager.h:127
uint32 GetNumActiveCCDBodies() const
Get the number of active bodies that are using continuous collision detection.
Definition: BodyManager.h:123
MutexMask GetAllBodiesMutexMask() const
Definition: BodyManager.h:183
Body * TryGetBody(const BodyID &inID)
Access a body, will return a nullptr if the body ID is no longer valid (not protected by lock)
Definition: BodyManager.h:162
SharedMutex & GetMutexForBody(const BodyID &inID) const
Access the mutex for a single body.
Definition: BodyManager.h:176
const Body * TryGetBody(const BodyID &inID) const
Access a body, will return a nullptr if the body ID is no longer valid (not protected by lock)
Definition: BodyManager.h:148
const BodyID * GetActiveBodiesUnsafe(EBodyType inType) const
Get the list of active bodies. Note: Not thread safe. The active bodies list can change at any moment...
Definition: BodyManager.h:117
const BodyVector & GetBodies() const
Get all bodies. Note that this can contain invalid body pointers, call sIsValidBodyPointer to check.
Definition: BodyManager.h:133
BodyVector & GetBodies()
Get all bodies. Note that this can contain invalid body pointers, call sIsValidBodyPointer to check.
Definition: BodyManager.h:136
uint GetMaxBodies() const
Gets the max bodies that we can support.
Definition: BodyManager.h:58
EShapeColor
Definition: BodyManager.h:220
void SetBodyObjectLayerInternal(Body &ioBody, ObjectLayer inLayer) const
Function to update body's layer (should only be called by the BodyInterface since it also requires up...
Definition: BodyManager.h:198
const Body & GetBody(const BodyID &inID) const
Access a body (not protected by lock)
Definition: BodyManager.h:142
uint64 MutexMask
Bodies are protected using an array of mutexes (so a fixed number, not 1 per body)....
Definition: BodyManager.h:179
uint32 GetNumActiveBodies(EBodyType inType) const
Get the number of active bodies.
Definition: BodyManager.h:120
Interface that the application should implement to allow mapping object layers to broadphase layers.
Definition: BroadPhaseLayer.h:61
Definition: DebugRenderer.h:47
Definition: MutexArray.h:17
Definition: Mutex.h:122
Class that makes another class non-copyable. Usage: Inherit from NonCopyable.
Definition: NonCopyable.h:11
Definition: Mutex.h:166
Definition: SoftBodyCreationSettings.h:18
User callbacks that allow determining which parts of the simulation should be saved by a StateRecorde...
Definition: StateRecorder.h:74
Definition: StateRecorder.h:105
Helper struct that counts the number of bodies of each type.
Definition: BodyManager.h:62
Draw settings.
Definition: BodyManager.h:231
Definition: PhysicsSettings.h:28