123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
- // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
- // SPDX-License-Identifier: MIT
- #include <Jolt/Jolt.h>
- #include <Jolt/Physics/PhysicsScene.h>
- #include <Jolt/Physics/PhysicsSystem.h>
- #include <Jolt/Physics/Body/BodyLockMulti.h>
- #include <Jolt/ObjectStream/TypeDeclarations.h>
- JPH_NAMESPACE_BEGIN
- JPH_IMPLEMENT_SERIALIZABLE_NON_VIRTUAL(PhysicsScene)
- {
- JPH_ADD_ATTRIBUTE(PhysicsScene, mBodies)
- JPH_ADD_ATTRIBUTE(PhysicsScene, mConstraints)
- JPH_ADD_ATTRIBUTE(PhysicsScene, mSoftBodies)
- }
- 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)
- {
- mBodies.push_back(inBody);
- }
- void PhysicsScene::AddConstraint(const TwoBodyConstraintSettings *inConstraint, uint32 inBody1, uint32 inBody2)
- {
- mConstraints.emplace_back(inConstraint, inBody1, inBody2);
- }
- void PhysicsScene::AddSoftBody(const SoftBodyCreationSettings &inSoftBody)
- {
- mSoftBodies.push_back(inSoftBody);
- }
- bool PhysicsScene::FixInvalidScales()
- {
- const Vec3 unit_scale = Vec3::sReplicate(1.0f);
- bool success = true;
- for (BodyCreationSettings &b : mBodies)
- {
- // Test if there is an invalid scale in the shape hierarchy
- const Shape *shape = b.GetShape();
- if (!shape->IsValidScale(unit_scale))
- {
- // Fix it up
- Shape::ShapeResult result = shape->ScaleShape(unit_scale);
- if (result.IsValid())
- b.SetShape(result.Get());
- else
- success = false;
- }
- }
- return success;
- }
- bool PhysicsScene::CreateBodies(PhysicsSystem *inSystem) const
- {
- BodyInterface &bi = inSystem->GetBodyInterface();
- BodyIDVector body_ids;
- body_ids.reserve(mBodies.size() + mSoftBodies.size());
- // Create bodies
- for (const BodyCreationSettings &b : mBodies)
- {
- const Body *body = bi.CreateBody(b);
- if (body == nullptr)
- break;
- body_ids.push_back(body->GetID());
- }
- // Create soft bodies
- for (const SoftBodyCreationSettings &b : mSoftBodies)
- {
- const Body *body = bi.CreateSoftBody(b);
- if (body == nullptr)
- break;
- body_ids.push_back(body->GetID());
- }
- // Batch add bodies
- 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() + mSoftBodies.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);
- }
- // Everything was created
- return true;
- }
- void PhysicsScene::SaveBinaryState(StreamOut &inStream, bool inSaveShapes, bool inSaveGroupFilter) const
- {
- BodyCreationSettings::ShapeToIDMap shape_to_id;
- BodyCreationSettings::MaterialToIDMap material_to_id;
- BodyCreationSettings::GroupFilterToIDMap group_filter_to_id;
- SoftBodyCreationSettings::SharedSettingsToIDMap settings_to_id;
- // Save bodies
- 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);
- }
- // Save soft bodies
- inStream.Write((uint32)mSoftBodies.size());
- for (const SoftBodyCreationSettings &b : mSoftBodies)
- b.SaveWithChildren(inStream, &settings_to_id, &material_to_id, inSaveGroupFilter? &group_filter_to_id : nullptr);
- }
- PhysicsScene::PhysicsSceneResult PhysicsScene::sRestoreFromBinaryState(StreamIn &inStream)
- {
- PhysicsSceneResult result;
- // Create scene
- Ref<PhysicsScene> scene = new PhysicsScene();
- BodyCreationSettings::IDToShapeMap id_to_shape;
- BodyCreationSettings::IDToMaterialMap id_to_material;
- BodyCreationSettings::IDToGroupFilterMap id_to_group_filter;
- SoftBodyCreationSettings::IDToSharedSettingsMap id_to_settings;
- // Reserve some memory to avoid frequent reallocations
- id_to_shape.reserve(1024);
- id_to_material.reserve(128);
- id_to_group_filter.reserve(128);
- // Read bodies
- uint32 len = 0;
- inStream.Read(len);
- scene->mBodies.resize(len);
- for (BodyCreationSettings &b : scene->mBodies)
- {
- // Read creation settings
- BodyCreationSettings::BCSResult bcs_result = BodyCreationSettings::sRestoreWithChildren(inStream, id_to_shape, id_to_material, id_to_group_filter);
- if (bcs_result.HasError())
- {
- result.SetError(bcs_result.GetError());
- return result;
- }
- 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);
- }
- // Read soft bodies
- len = 0;
- inStream.Read(len);
- scene->mSoftBodies.resize(len);
- for (SoftBodyCreationSettings &b : scene->mSoftBodies)
- {
- // Read creation settings
- SoftBodyCreationSettings::SBCSResult sbcs_result = SoftBodyCreationSettings::sRestoreWithChildren(inStream, id_to_settings, id_to_material, id_to_group_filter);
- if (sbcs_result.HasError())
- {
- result.SetError(sbcs_result.GetError());
- return result;
- }
- b = sbcs_result.Get();
- }
- result.Set(scene);
- return result;
- }
- void PhysicsScene::FromPhysicsSystem(const PhysicsSystem *inSystem)
- {
- // This map will track where each body went in mBodies
- using BodyIDToIdxMap = UnorderedMap<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();
- const Body &body = lock.GetBody();
- // Convert to body creation settings
- if (body.IsRigidBody())
- AddBody(body.GetBodyCreationSettings());
- else
- AddSoftBody(body.GetSoftBodyCreationSettings());
- }
- }
- // 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
|