|
@@ -157,6 +157,77 @@ Body *BodyManager::CreateBody(const BodyCreationSettings &inBodyCreationSettings
|
|
// Get next sequence number
|
|
// Get next sequence number
|
|
uint8 seq_no = GetNextSequenceNumber(idx);
|
|
uint8 seq_no = GetNextSequenceNumber(idx);
|
|
|
|
|
|
|
|
+ // Do actual creation
|
|
|
|
+ return CreateBodyWithIDInternal(BodyID(idx, seq_no), inBodyCreationSettings);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+Body *BodyManager::CreateBodyWithID(const BodyID &inBodyID, const BodyCreationSettings &inBodyCreationSettings)
|
|
|
|
+{
|
|
|
|
+ {
|
|
|
|
+ UniqueLock lock(mBodiesMutex, EPhysicsLockTypes::BodiesList);
|
|
|
|
+
|
|
|
|
+ // Check if index is beyond the max body ID
|
|
|
|
+ uint32 idx = inBodyID.GetIndex();
|
|
|
|
+ if (idx >= mBodies.capacity())
|
|
|
|
+ return nullptr; // Return error
|
|
|
|
+
|
|
|
|
+ if (idx < mBodies.size())
|
|
|
|
+ {
|
|
|
|
+ // Body array entry has already been allocated, check if there's a free body here
|
|
|
|
+ if (sIsValidBodyPointer(mBodies[idx]))
|
|
|
|
+ return nullptr; // Return error
|
|
|
|
+
|
|
|
|
+ // Remove the entry from the freelist
|
|
|
|
+ uintptr_t idx_start = mBodyIDFreeListStart >> cFreedBodyIndexShift;
|
|
|
|
+ if (idx == idx_start)
|
|
|
|
+ {
|
|
|
|
+ // First entry, easy to remove, the start of the list is our next
|
|
|
|
+ mBodyIDFreeListStart = uintptr_t(mBodies[idx]);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ // Loop over the freelist and find the entry in the freelist pointing to our index
|
|
|
|
+ // TODO: This is O(N), see if this becomes a performance problem (don't want to put the freed bodies in a double linked list)
|
|
|
|
+ uintptr_t cur, next;
|
|
|
|
+ for (cur = idx_start; cur != cBodyIDFreeListEnd >> cFreedBodyIndexShift; cur = next)
|
|
|
|
+ {
|
|
|
|
+ next = uintptr_t(mBodies[cur]) >> cFreedBodyIndexShift;
|
|
|
|
+ if (next == idx)
|
|
|
|
+ {
|
|
|
|
+ mBodies[cur] = mBodies[idx];
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ JPH_ASSERT(cur != cBodyIDFreeListEnd >> cFreedBodyIndexShift);
|
|
|
|
+
|
|
|
|
+ // We're leaving the lock, ensure that we've overwritten this entry (although it's not strictly needed)
|
|
|
|
+ mBodies[idx] = (Body *)cBodyIDFreeListEnd;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ // Ensure that all body IDs up to this body ID have been allocated and added to the free list
|
|
|
|
+ while (idx > mBodies.size())
|
|
|
|
+ {
|
|
|
|
+ // Push the id onto the freelist
|
|
|
|
+ mBodies.push_back((Body *)mBodyIDFreeListStart);
|
|
|
|
+ mBodyIDFreeListStart = (uintptr_t(mBodies.size() - 1) << cFreedBodyIndexShift) | cIsFreedBody;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Add the element that we're going to overwrite to the list
|
|
|
|
+ mBodies.push_back((Body *)cBodyIDFreeListEnd);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Update cached number of bodies
|
|
|
|
+ mNumBodies++;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Do actual creation
|
|
|
|
+ return CreateBodyWithIDInternal(inBodyID, inBodyCreationSettings);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+Body *BodyManager::CreateBodyWithIDInternal(const BodyID &inBodyID, const BodyCreationSettings &inBodyCreationSettings)
|
|
|
|
+{
|
|
// Fill in basic properties
|
|
// Fill in basic properties
|
|
Body *body;
|
|
Body *body;
|
|
if (inBodyCreationSettings.HasMassProperties())
|
|
if (inBodyCreationSettings.HasMassProperties())
|
|
@@ -169,7 +240,7 @@ Body *BodyManager::CreateBody(const BodyCreationSettings &inBodyCreationSettings
|
|
{
|
|
{
|
|
body = new Body;
|
|
body = new Body;
|
|
}
|
|
}
|
|
- body->mID = BodyID(idx, seq_no);
|
|
|
|
|
|
+ body->mID = inBodyID;
|
|
body->mShape = inBodyCreationSettings.GetShape();
|
|
body->mShape = inBodyCreationSettings.GetShape();
|
|
body->mUserData = inBodyCreationSettings.mUserData;
|
|
body->mUserData = inBodyCreationSettings.mUserData;
|
|
body->SetFriction(inBodyCreationSettings.mFriction);
|
|
body->SetFriction(inBodyCreationSettings.mFriction);
|
|
@@ -203,7 +274,7 @@ Body *BodyManager::CreateBody(const BodyCreationSettings &inBodyCreationSettings
|
|
body->SetPositionAndRotationInternal(inBodyCreationSettings.mPosition, inBodyCreationSettings.mRotation);
|
|
body->SetPositionAndRotationInternal(inBodyCreationSettings.mPosition, inBodyCreationSettings.mRotation);
|
|
|
|
|
|
// Add body
|
|
// Add body
|
|
- mBodies[idx] = body;
|
|
|
|
|
|
+ mBodies[inBodyID.GetIndex()] = body;
|
|
return body;
|
|
return body;
|
|
}
|
|
}
|
|
|
|
|