Browse Source

Made Body constructor/destructor private

- Added more documentation on AddBody/RemoveBody
- Added information to assert when AddBody/RemoveBody is not called correctly
Jorrit Rouwe 1 year ago
parent
commit
e371cbf5e7

+ 12 - 1
Docs/Architecture.md

@@ -19,7 +19,18 @@ Moving bodies have a [MotionProperties](@ref MotionProperties) object that conta
 
 
 ## Creating Bodies {#creating-bodies}
 ## Creating Bodies {#creating-bodies}
 
 
-Bodies are inserted into the [PhysicsSystem](@ref PhysicsSystem) and interacted with through the [BodyInterface](@ref BodyInterface). 
+Bodies are inserted into the [PhysicsSystem](@ref PhysicsSystem) and interacted with through the [BodyInterface](@ref BodyInterface).
+
+The general life cycle of a body is:
+
+- BodyInterface::CreateBody - Construct a Body object and initialize it. You cannot use `new` to create a Body.
+- BodyInterface::AddBody - Add the body to the PhysicsSystem and make it participate in the simulation.
+- BodyInterface::RemoveBody - Remove it from the PhysicsSystem.
+- BodyInterface::DestroyBody - Deinitialize and destruct the Body. You cannot use `delete` to delete a Body. This function will not automatically remove the Body from the PhysicsSystem.
+
+The BodyInterface also contains functionality to add many bodies to the simulation at the same time. It is important to use these functions when inserting many Bodies, you get a performance penalty if you don't.
+
+You can call AddBody, RemoveBody, AddBody, RemoveBody to temporarily remove and later reinsert a body into the simulation.
 
 
 ## Multithreaded Access 
 ## Multithreaded Access 
 
 

+ 6 - 6
Jolt/Physics/Body/Body.h

@@ -36,12 +36,6 @@ class alignas(JPH_RVECTOR_ALIGNMENT) JPH_EXPORT_GCC_BUG_WORKAROUND Body : public
 public:
 public:
 	JPH_OVERRIDE_NEW_DELETE
 	JPH_OVERRIDE_NEW_DELETE
 
 
-	/// Default constructor
-							Body() = default;
-
-	/// Destructor
-							~Body()															{ JPH_ASSERT(mMotionProperties == nullptr); }
-
 	/// Get the id of this body
 	/// Get the id of this body
 	inline const BodyID &	GetID() const													{ return mID; }
 	inline const BodyID &	GetID() const													{ return mID; }
 
 
@@ -336,9 +330,15 @@ public:
 
 
 private:
 private:
 	friend class BodyManager;
 	friend class BodyManager;
+	friend class BodyWithMotionProperties;
+	friend class SoftBodyWithMotionPropertiesAndShape;
+
+							Body() = default;												///< Bodies must be created through BodyInterface::CreateBody
 
 
 	explicit				Body(bool);														///< Alternative constructor that initializes all members
 	explicit				Body(bool);														///< Alternative constructor that initializes all members
 
 
+							~Body()															{ JPH_ASSERT(mMotionProperties == nullptr); } ///< Bodies must be destroyed through BodyInterface::DestroyBody
+
 	inline void				GetSleepTestPoints(RVec3 *outPoints) const;						///< Determine points to test for checking if body is sleeping: COM, COM + largest bounding box axis, COM + second largest bounding box axis
 	inline void				GetSleepTestPoints(RVec3 *outPoints) const;						///< Determine points to test for checking if body is sleeping: COM, COM + largest bounding box axis, COM + second largest bounding box axis
 
 
 	enum class EFlags : uint8
 	enum class EFlags : uint8

+ 3 - 1
Jolt/Physics/Body/BodyInterface.h

@@ -83,10 +83,12 @@ public:
 	/// @param outBodies If not null on input, this will contain a list of body pointers corresponding to inBodyIDs that can be destroyed afterwards (caller assumes ownership over these).
 	/// @param outBodies If not null on input, this will contain a list of body pointers corresponding to inBodyIDs that can be destroyed afterwards (caller assumes ownership over these).
 	void						UnassignBodyIDs(const BodyID *inBodyIDs, int inNumber, Body **outBodies);
 	void						UnassignBodyIDs(const BodyID *inBodyIDs, int inNumber, Body **outBodies);
 
 
-	/// Destroy a body
+	/// Destroy a body.
+	/// Make sure that you remove the body from the physics system using BodyInterface::RemoveBody before calling this function.
 	void						DestroyBody(const BodyID &inBodyID);
 	void						DestroyBody(const BodyID &inBodyID);
 
 
 	/// Destroy multiple bodies
 	/// Destroy multiple bodies
+	/// Make sure that you remove the bodies from the physics system using BodyInterface::RemoveBody before calling this function.
 	void						DestroyBodies(const BodyID *inBodyIDs, int inNumber);
 	void						DestroyBodies(const BodyID *inBodyIDs, int inNumber);
 
 
 	/// Add body to the physics system.
 	/// Add body to the physics system.

+ 3 - 3
Jolt/Physics/Body/BodyManager.cpp

@@ -403,7 +403,7 @@ Body *BodyManager::RemoveBodyInternal(const BodyID &inBodyID)
 	// Validate that it can be removed
 	// Validate that it can be removed
 	JPH_ASSERT(body->GetID() == inBodyID);
 	JPH_ASSERT(body->GetID() == inBodyID);
 	JPH_ASSERT(!body->IsActive());
 	JPH_ASSERT(!body->IsActive());
-	JPH_ASSERT(!body->IsInBroadPhase());
+	JPH_ASSERT(!body->IsInBroadPhase(), "Use BodyInterface::RemoveBody to remove this body first!");
 
 
 	// Push the id onto the freelist
 	// Push the id onto the freelist
 	mBodies[idx] = (Body *)mBodyIDFreeListStart;
 	mBodies[idx] = (Body *)mBodyIDFreeListStart;
@@ -554,7 +554,7 @@ void BodyManager::ActivateBodies(const BodyID *inBodyIDs, int inNumber)
 			Body &body = *mBodies[body_id.GetIndex()];
 			Body &body = *mBodies[body_id.GetIndex()];
 
 
 			JPH_ASSERT(body.GetID() == body_id);
 			JPH_ASSERT(body.GetID() == body_id);
-			JPH_ASSERT(body.IsInBroadPhase());
+			JPH_ASSERT(body.IsInBroadPhase(), "Use BodyInterface::AddBody to add the body first!");
 
 
 			if (!body.IsStatic())
 			if (!body.IsStatic())
 			{
 			{
@@ -591,7 +591,7 @@ void BodyManager::DeactivateBodies(const BodyID *inBodyIDs, int inNumber)
 			Body &body = *mBodies[body_id.GetIndex()];
 			Body &body = *mBodies[body_id.GetIndex()];
 
 
 			JPH_ASSERT(body.GetID() == body_id);
 			JPH_ASSERT(body.GetID() == body_id);
-			JPH_ASSERT(body.IsInBroadPhase());
+			JPH_ASSERT(body.IsInBroadPhase(), "Use BodyInterface::AddBody to add the body first!");
 
 
 			if (body.mMotionProperties != nullptr
 			if (body.mMotionProperties != nullptr
 				&& body.mMotionProperties->mIndexInActiveBodies != Body::cInactiveIndex)
 				&& body.mMotionProperties->mIndexInActiveBodies != Body::cInactiveIndex)