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
26
29
32{
33public:
35
38
40 void Init(uint inMaxBodies, uint inNumBodyMutexes, const BroadPhaseLayerInterface &inLayerInterface);
41
43 uint GetNumBodies() const;
44
46 uint GetMaxBodies() const { return uint(mBodies.capacity()); }
47
49 struct BodyStats
50 {
51 uint mNumBodies = 0;
52 uint mMaxBodies = 0;
53
54 uint mNumBodiesStatic = 0;
55
56 uint mNumBodiesDynamic = 0;
57 uint mNumActiveBodiesDynamic = 0;
58
59 uint mNumBodiesKinematic = 0;
60 uint mNumActiveBodiesKinematic = 0;
61
62 uint mNumSoftBodies = 0;
63 uint mNumActiveSoftBodies = 0;
64 };
65
67 BodyStats GetBodyStats() const;
68
70 Body * AllocateBody(const BodyCreationSettings &inBodyCreationSettings) const;
71
73 Body * AllocateSoftBody(const SoftBodyCreationSettings &inSoftBodyCreationSettings) const;
74
76 void FreeBody(Body *inBody) const;
77
79 bool AddBody(Body *ioBody);
80
82 bool AddBodyWithCustomID(Body *ioBody, const BodyID &inBodyID);
83
85 void RemoveBodies(const BodyID *inBodyIDs, int inNumber, Body **outBodies);
86
88 void DestroyBodies(const BodyID *inBodyIDs, int inNumber);
89
92 void ActivateBodies(const BodyID *inBodyIDs, int inNumber);
93
96 void DeactivateBodies(const BodyID *inBodyIDs, int inNumber);
97
99 void SetMotionQuality(Body &ioBody, EMotionQuality inMotionQuality);
100
102 void GetActiveBodies(EBodyType inType, BodyIDVector &outBodyIDs) const;
103
105 const BodyID * GetActiveBodiesUnsafe(EBodyType inType) const { return mActiveBodies[int(inType)]; }
106
108 uint32 GetNumActiveBodies(EBodyType inType) const { return mNumActiveBodies[int(inType)]; }
109
111 uint32 GetNumActiveCCDBodies() const { return mNumActiveCCDBodies; }
112
114 void SetBodyActivationListener(BodyActivationListener *inListener);
115 BodyActivationListener * GetBodyActivationListener() const { return mActivationListener; }
116
118 static inline bool sIsValidBodyPointer(const Body *inBody) { return (uintptr_t(inBody) & cIsFreedBody) == 0; }
119
121 const BodyVector & GetBodies() const { return mBodies; }
122
124 BodyVector & GetBodies() { return mBodies; }
125
127 void GetBodyIDs(BodyIDVector &outBodies) const;
128
130 const Body & GetBody(const BodyID &inID) const { return *mBodies[inID.GetIndex()]; }
131
133 Body & GetBody(const BodyID &inID) { return *mBodies[inID.GetIndex()]; }
134
136 const Body * TryGetBody(const BodyID &inID) const
137 {
138 uint32 idx = inID.GetIndex();
139 if (idx >= mBodies.size())
140 return nullptr;
141
142 const Body *body = mBodies[idx];
143 if (sIsValidBodyPointer(body) && body->GetID() == inID)
144 return body;
145
146 return nullptr;
147 }
148
150 Body * TryGetBody(const BodyID &inID)
151 {
152 uint32 idx = inID.GetIndex();
153 if (idx >= mBodies.size())
154 return nullptr;
155
156 Body *body = mBodies[idx];
157 if (sIsValidBodyPointer(body) && body->GetID() == inID)
158 return body;
159
160 return nullptr;
161 }
162
164 SharedMutex & GetMutexForBody(const BodyID &inID) const { return mBodyMutexes.GetMutexByObjectIndex(inID.GetIndex()); }
165
168
171 MutexMask GetAllBodiesMutexMask() const { return mBodyMutexes.GetNumMutexes() == sizeof(MutexMask) * 8? ~MutexMask(0) : (MutexMask(1) << mBodyMutexes.GetNumMutexes()) - 1; }
172 MutexMask GetMutexMask(const BodyID *inBodies, int inNumber) const;
173 void LockRead(MutexMask inMutexMask) const;
174 void UnlockRead(MutexMask inMutexMask) const;
175 void LockWrite(MutexMask inMutexMask) const;
176 void UnlockWrite(MutexMask inMutexMask) const;
178
180 void LockAllBodies() const;
181
183 void UnlockAllBodies() const;
184
186 inline void SetBodyObjectLayerInternal(Body &ioBody, ObjectLayer inLayer) const { ioBody.mObjectLayer = inLayer; ioBody.mBroadPhaseLayer = mBroadPhaseLayerInterface->GetBroadPhaseLayer(inLayer); }
187
189 void InvalidateContactCacheForBody(Body &ioBody);
190
192 void ValidateContactCacheForAllBodies();
193
195 void SaveState(StateRecorder &inStream, const StateRecorderFilter *inFilter) const;
196
198 bool RestoreState(StateRecorder &inStream);
199
201 void SaveBodyState(const Body &inBody, StateRecorder &inStream) const;
202
204 void RestoreBodyState(Body &inBody, StateRecorder &inStream);
205
206 enum class EShapeColor
207 {
208 InstanceColor,
209 ShapeTypeColor,
210 MotionTypeColor,
211 SleepColor,
212 IslandColor,
213 MaterialColor,
214 };
215
216#ifdef JPH_DEBUG_RENDERER
219 {
220 bool mDrawGetSupportFunction = false;
221 bool mDrawSupportDirection = false;
222 bool mDrawGetSupportingFace = false;
223 bool mDrawShape = true;
224 bool mDrawShapeWireframe = false;
225 EShapeColor mDrawShapeColor = EShapeColor::MotionTypeColor;
226 bool mDrawBoundingBox = false;
227 bool mDrawCenterOfMassTransform = false;
228 bool mDrawWorldTransform = false;
229 bool mDrawVelocity = false;
230 bool mDrawMassAndInertia = false;
231 bool mDrawSleepStats = false;
232 bool mDrawSoftBodyVertices = false;
233 bool mDrawSoftBodyVertexVelocities = false;
234 bool mDrawSoftBodyEdgeConstraints = false;
235 bool mDrawSoftBodyBendConstraints = false;
236 bool mDrawSoftBodyVolumeConstraints = false;
237 bool mDrawSoftBodySkinConstraints = false;
238 bool mDrawSoftBodyLRAConstraints = false;
239 bool mDrawSoftBodyPredictedBounds = false;
240 };
241
243 void Draw(const DrawSettings &inSettings, const PhysicsSettings &inPhysicsSettings, DebugRenderer *inRenderer, const BodyDrawFilter *inBodyFilter = nullptr);
244#endif // JPH_DEBUG_RENDERER
245
246#ifdef JPH_ENABLE_ASSERTS
248 void SetActiveBodiesLocked(bool inLocked) { mActiveBodiesLocked = inLocked; }
249
251 class GrantActiveBodiesAccess
252 {
253 public:
254 inline GrantActiveBodiesAccess(bool inAllowActivation, bool inAllowDeactivation)
255 {
256 JPH_ASSERT(!sGetOverrideAllowActivation());
257 sSetOverrideAllowActivation(inAllowActivation);
258
259 JPH_ASSERT(!sGetOverrideAllowDeactivation());
260 sSetOverrideAllowDeactivation(inAllowDeactivation);
261 }
262
263 inline ~GrantActiveBodiesAccess()
264 {
265 sSetOverrideAllowActivation(false);
266 sSetOverrideAllowDeactivation(false);
267 }
268 };
269#endif
270
271#ifdef _DEBUG
273 void ValidateActiveBodyBounds();
274#endif // _DEBUG
275
276private:
278#ifdef JPH_COMPILER_CLANG
279 __attribute__((no_sanitize("implicit-conversion"))) // We intentionally overflow the uint8 sequence number
280#endif
281 inline uint8 GetNextSequenceNumber(int inBodyIndex) { return ++mBodySequenceNumbers[inBodyIndex]; }
282
284 inline void AddBodyToActiveBodies(Body &ioBody);
285
287 inline void RemoveBodyFromActiveBodies(Body &ioBody);
288
290 JPH_INLINE Body * RemoveBodyInternal(const BodyID &inBodyID);
291
293 inline static void sDeleteBody(Body *inBody);
294
295#if defined(_DEBUG) && defined(JPH_ENABLE_ASSERTS)
297 void ValidateFreeList() const;
298#endif // defined(_DEBUG) && _defined(JPH_ENABLE_ASSERTS)
299
301 BodyVector mBodies;
302
304 uint mNumBodies = 0;
305
307 static constexpr uintptr_t cBodyIDFreeListEnd = ~uintptr_t(0);
308
310 static constexpr uintptr_t cIsFreedBody = uintptr_t(1);
311
313 static constexpr uint cFreedBodyIndexShift = 1;
314
316 uintptr_t mBodyIDFreeListStart = cBodyIDFreeListEnd;
317
319 mutable Mutex mBodiesMutex;
320
322 using BodyMutexes = MutexArray<SharedMutex>;
323 mutable BodyMutexes mBodyMutexes;
324
326 Array<uint8> mBodySequenceNumbers;
327
329 mutable Mutex mActiveBodiesMutex;
330
332 BodyID * mActiveBodies[cBodyTypeCount] = { };
333
335 atomic<uint32> mNumActiveBodies[cBodyTypeCount] = { };
336
338 uint32 mNumActiveCCDBodies = 0;
339
341 mutable Mutex mBodiesCacheInvalidMutex;
342
344 BodyIDVector mBodiesCacheInvalid;
345
347 BodyActivationListener * mActivationListener = nullptr;
348
350 const BroadPhaseLayerInterface *mBroadPhaseLayerInterface = nullptr;
351
352#ifdef JPH_ENABLE_ASSERTS
353 static bool sGetOverrideAllowActivation();
354 static void sSetOverrideAllowActivation(bool inValue);
355
356 static bool sGetOverrideAllowDeactivation();
357 static void sSetOverrideAllowDeactivation(bool inValue);
358
360 bool mActiveBodiesLocked = false;
361#endif
362};
363
Array< Body * > BodyVector
Array of bodies.
Definition: BodyManager.h:25
Array< BodyID > BodyIDVector
Array of body ID's.
Definition: BodyManager.h:28
EBodyType
Type of body.
Definition: BodyType.h:11
std::uint8_t uint8
Definition: Core.h:440
#define JPH_EXPORT
Definition: Core.h:227
std::uint64_t uint64
Definition: Core.h:443
unsigned int uint
Definition: Core.h:439
#define JPH_NAMESPACE_END
Definition: Core.h:367
std::uint32_t uint32
Definition: Core.h:442
#define JPH_NAMESPACE_BEGIN
Definition: Core.h:361
#define JPH_ASSERT(...)
Definition: IssueReporting.h:33
#define JPH_OVERRIDE_NEW_DELETE
Macro to override the new and delete functions.
Definition: Memory.h:29
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
std::vector< T, STLAllocator< T > > Array
Definition: STLAllocator.h:81
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:89
Definition: Body.h:35
const BodyID & GetID() const
Get the id of this body.
Definition: Body.h:46
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:32
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:118
Body & GetBody(const BodyID &inID)
Access a body (not protected by lock)
Definition: BodyManager.h:133
BodyActivationListener * GetBodyActivationListener() const
Definition: BodyManager.h:115
uint32 GetNumActiveCCDBodies() const
Get the number of active bodies that are using continuous collision detection.
Definition: BodyManager.h:111
MutexMask GetAllBodiesMutexMask() const
Definition: BodyManager.h:171
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:150
SharedMutex & GetMutexForBody(const BodyID &inID) const
Access the mutex for a single body.
Definition: BodyManager.h:164
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:136
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:105
const BodyVector & GetBodies() const
Get all bodies. Note that this can contain invalid body pointers, call sIsValidBodyPointer to check.
Definition: BodyManager.h:121
BodyVector & GetBodies()
Get all bodies. Note that this can contain invalid body pointers, call sIsValidBodyPointer to check.
Definition: BodyManager.h:124
uint GetMaxBodies() const
Gets the max bodies that we can support.
Definition: BodyManager.h:46
EShapeColor
Definition: BodyManager.h:207
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:186
const Body & GetBody(const BodyID &inID) const
Access a body (not protected by lock)
Definition: BodyManager.h:130
uint64 MutexMask
Bodies are protected using an array of mutexes (so a fixed number, not 1 per body)....
Definition: BodyManager.h:167
uint32 GetNumActiveBodies(EBodyType inType) const
Get the number of active bodies.
Definition: BodyManager.h:108
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:29
Definition: StateRecorder.h:48
Helper struct that counts the number of bodies of each type.
Definition: BodyManager.h:50
Draw settings.
Definition: BodyManager.h:219
Definition: PhysicsSettings.h:28