|
@@ -5,6 +5,7 @@
|
|
|
|
|
|
#include <Jolt/Physics/PhysicsScene.h>
|
|
|
#include <Jolt/Physics/PhysicsSystem.h>
|
|
|
+#include <Jolt/Physics/Body/BodyLockMulti.h>
|
|
|
#include <Jolt/ObjectStream/TypeDeclarations.h>
|
|
|
|
|
|
JPH_NAMESPACE_BEGIN
|
|
@@ -12,6 +13,14 @@ JPH_NAMESPACE_BEGIN
|
|
|
JPH_IMPLEMENT_SERIALIZABLE_NON_VIRTUAL(PhysicsScene)
|
|
|
{
|
|
|
JPH_ADD_ATTRIBUTE(PhysicsScene, mBodies)
|
|
|
+ JPH_ADD_ATTRIBUTE(PhysicsScene, mConstraints)
|
|
|
+}
|
|
|
+
|
|
|
+JPH_IMPLEMENT_SERIALIZABLE_NON_VIRTUAL(PhysicsScene::ConnectedConstraint)
|
|
|
+{
|
|
|
+ JPH_ADD_ATTRIBUTE(PhysicsScene::ConnectedConstraint, mSettings)
|
|
|
+ JPH_ADD_ATTRIBUTE(PhysicsScene::ConnectedConstraint, mBody1)
|
|
|
+ JPH_ADD_ATTRIBUTE(PhysicsScene::ConnectedConstraint, mBody2)
|
|
|
}
|
|
|
|
|
|
void PhysicsScene::AddBody(const BodyCreationSettings &inBody)
|
|
@@ -19,6 +28,11 @@ void PhysicsScene::AddBody(const BodyCreationSettings &inBody)
|
|
|
mBodies.push_back(inBody);
|
|
|
}
|
|
|
|
|
|
+void PhysicsScene::AddConstraint(const TwoBodyConstraintSettings *inConstraint, uint32 inBody1, uint32 inBody2)
|
|
|
+{
|
|
|
+ mConstraints.emplace_back(inConstraint, inBody1, inBody2);
|
|
|
+}
|
|
|
+
|
|
|
bool PhysicsScene::FixInvalidScales()
|
|
|
{
|
|
|
const Vec3 unit_scale = Vec3::sReplicate(1.0f);
|
|
@@ -52,16 +66,30 @@ bool PhysicsScene::CreateBodies(PhysicsSystem *inSystem) const
|
|
|
{
|
|
|
const Body *body = bi.CreateBody(b);
|
|
|
if (body == nullptr)
|
|
|
- break; // Out of bodies
|
|
|
+ break;
|
|
|
body_ids.push_back(body->GetID());
|
|
|
}
|
|
|
|
|
|
// Batch add bodies
|
|
|
- BodyInterface::AddState add_state = bi.AddBodiesPrepare(body_ids.data(), (int)body_ids.size());
|
|
|
- bi.AddBodiesFinalize(body_ids.data(), (int)body_ids.size(), add_state, EActivation::Activate);
|
|
|
+ BodyIDVector temp_body_ids = body_ids; // Body ID's get shuffled by AddBodiesPrepare
|
|
|
+ BodyInterface::AddState add_state = bi.AddBodiesPrepare(temp_body_ids.data(), (int)temp_body_ids.size());
|
|
|
+ bi.AddBodiesFinalize(temp_body_ids.data(), (int)temp_body_ids.size(), add_state, EActivation::Activate);
|
|
|
+
|
|
|
+ // If not all bodies are created, creating constraints will be unreliable
|
|
|
+ if (body_ids.size() != mBodies.size())
|
|
|
+ return false;
|
|
|
+
|
|
|
+ // Create constraints
|
|
|
+ for (const ConnectedConstraint &cc : mConstraints)
|
|
|
+ {
|
|
|
+ BodyID body1_id = cc.mBody1 == cFixedToWorld? BodyID() : body_ids[cc.mBody1];
|
|
|
+ BodyID body2_id = cc.mBody2 == cFixedToWorld? BodyID() : body_ids[cc.mBody2];
|
|
|
+ Constraint *c = bi.CreateConstraint(cc.mSettings, body1_id, body2_id);
|
|
|
+ inSystem->AddConstraint(c);
|
|
|
+ }
|
|
|
|
|
|
- // Return true if all bodies were added
|
|
|
- return body_ids.size() == mBodies.size();
|
|
|
+ // Everything was created
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
void PhysicsScene::SaveBinaryState(StreamOut &inStream, bool inSaveShapes, bool inSaveGroupFilter) const
|
|
@@ -74,6 +102,15 @@ void PhysicsScene::SaveBinaryState(StreamOut &inStream, bool inSaveShapes, bool
|
|
|
inStream.Write((uint32)mBodies.size());
|
|
|
for (const BodyCreationSettings &b : mBodies)
|
|
|
b.SaveWithChildren(inStream, inSaveShapes? &shape_to_id : nullptr, inSaveShapes? &material_to_id : nullptr, inSaveGroupFilter? &group_filter_to_id : nullptr);
|
|
|
+
|
|
|
+ // Save constraints
|
|
|
+ inStream.Write((uint32)mConstraints.size());
|
|
|
+ for (const ConnectedConstraint &cc : mConstraints)
|
|
|
+ {
|
|
|
+ cc.mSettings->SaveBinaryState(inStream);
|
|
|
+ inStream.Write(cc.mBody1);
|
|
|
+ inStream.Write(cc.mBody2);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
PhysicsScene::PhysicsSceneResult PhysicsScene::sRestoreFromBinaryState(StreamIn &inStream)
|
|
@@ -108,8 +145,72 @@ PhysicsScene::PhysicsSceneResult PhysicsScene::sRestoreFromBinaryState(StreamIn
|
|
|
b = bcs_result.Get();
|
|
|
}
|
|
|
|
|
|
+ // Read constraints
|
|
|
+ len = 0;
|
|
|
+ inStream.Read(len);
|
|
|
+ scene->mConstraints.resize(len);
|
|
|
+ for (ConnectedConstraint &cc : scene->mConstraints)
|
|
|
+ {
|
|
|
+ ConstraintSettings::ConstraintResult c_result = ConstraintSettings::sRestoreFromBinaryState(inStream);
|
|
|
+ if (c_result.HasError())
|
|
|
+ {
|
|
|
+ result.SetError(c_result.GetError());
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ cc.mSettings = static_cast<const TwoBodyConstraintSettings *>(c_result.Get().GetPtr());
|
|
|
+ inStream.Read(cc.mBody1);
|
|
|
+ inStream.Read(cc.mBody2);
|
|
|
+ }
|
|
|
+
|
|
|
result.Set(scene);
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+void PhysicsScene::FromPhysicsSystem(const PhysicsSystem *inSystem)
|
|
|
+{
|
|
|
+ // This map will track where each body went in mBodies
|
|
|
+ using BodyIDToIdxMap = unordered_map<BodyID, uint32>;
|
|
|
+ BodyIDToIdxMap body_id_to_idx;
|
|
|
+
|
|
|
+ // Map invalid ID
|
|
|
+ body_id_to_idx[BodyID()] = cFixedToWorld;
|
|
|
+
|
|
|
+ // Get all bodies
|
|
|
+ BodyIDVector body_ids;
|
|
|
+ inSystem->GetBodies(body_ids);
|
|
|
+
|
|
|
+ // Loop over all bodies
|
|
|
+ const BodyLockInterface &bli = inSystem->GetBodyLockInterface();
|
|
|
+ for (const BodyID &id : body_ids)
|
|
|
+ {
|
|
|
+ BodyLockRead lock(bli, id);
|
|
|
+ if (lock.Succeeded())
|
|
|
+ {
|
|
|
+ // Store location of body
|
|
|
+ body_id_to_idx[id] = (uint32)mBodies.size();
|
|
|
+
|
|
|
+ // Convert to body creation settings
|
|
|
+ AddBody(lock.GetBody().GetBodyCreationSettings());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Loop over all constraints
|
|
|
+ Constraints constraints = inSystem->GetConstraints();
|
|
|
+ for (const Constraint *c : constraints)
|
|
|
+ if (c->GetType() == EConstraintType::TwoBodyConstraint)
|
|
|
+ {
|
|
|
+ // Cast to two body constraint
|
|
|
+ const TwoBodyConstraint *tbc = static_cast<const TwoBodyConstraint *>(c);
|
|
|
+
|
|
|
+ // Find the body indices
|
|
|
+ BodyIDToIdxMap::const_iterator b1 = body_id_to_idx.find(tbc->GetBody1()->GetID());
|
|
|
+ BodyIDToIdxMap::const_iterator b2 = body_id_to_idx.find(tbc->GetBody2()->GetID());
|
|
|
+ JPH_ASSERT(b1 != body_id_to_idx.end() && b2 != body_id_to_idx.end());
|
|
|
+
|
|
|
+ // Create constraint settings and add the constraint
|
|
|
+ Ref<ConstraintSettings> settings = c->GetConstraintSettings();
|
|
|
+ AddConstraint(static_cast<const TwoBodyConstraintSettings *>(settings.GetPtr()), b1->second, b2->second);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
JPH_NAMESPACE_END
|