Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/PhysicsScene.cpp
9913 views
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)1// SPDX-FileCopyrightText: 2021 Jorrit Rouwe2// SPDX-License-Identifier: MIT34#include <Jolt/Jolt.h>56#include <Jolt/Physics/PhysicsScene.h>7#include <Jolt/Physics/PhysicsSystem.h>8#include <Jolt/Physics/Body/BodyLockMulti.h>9#include <Jolt/ObjectStream/TypeDeclarations.h>1011JPH_NAMESPACE_BEGIN1213JPH_IMPLEMENT_SERIALIZABLE_NON_VIRTUAL(PhysicsScene)14{15JPH_ADD_ATTRIBUTE(PhysicsScene, mBodies)16JPH_ADD_ATTRIBUTE(PhysicsScene, mConstraints)17JPH_ADD_ATTRIBUTE(PhysicsScene, mSoftBodies)18}1920JPH_IMPLEMENT_SERIALIZABLE_NON_VIRTUAL(PhysicsScene::ConnectedConstraint)21{22JPH_ADD_ATTRIBUTE(PhysicsScene::ConnectedConstraint, mSettings)23JPH_ADD_ATTRIBUTE(PhysicsScene::ConnectedConstraint, mBody1)24JPH_ADD_ATTRIBUTE(PhysicsScene::ConnectedConstraint, mBody2)25}2627void PhysicsScene::AddBody(const BodyCreationSettings &inBody)28{29mBodies.push_back(inBody);30}3132void PhysicsScene::AddConstraint(const TwoBodyConstraintSettings *inConstraint, uint32 inBody1, uint32 inBody2)33{34mConstraints.emplace_back(inConstraint, inBody1, inBody2);35}3637void PhysicsScene::AddSoftBody(const SoftBodyCreationSettings &inSoftBody)38{39mSoftBodies.push_back(inSoftBody);40}4142bool PhysicsScene::FixInvalidScales()43{44const Vec3 unit_scale = Vec3::sOne();4546bool success = true;47for (BodyCreationSettings &b : mBodies)48{49// Test if there is an invalid scale in the shape hierarchy50const Shape *shape = b.GetShape();51if (!shape->IsValidScale(unit_scale))52{53// Fix it up54Shape::ShapeResult result = shape->ScaleShape(unit_scale);55if (result.IsValid())56b.SetShape(result.Get());57else58success = false;59}60}61return success;62}6364bool PhysicsScene::CreateBodies(PhysicsSystem *inSystem) const65{66BodyInterface &bi = inSystem->GetBodyInterface();6768BodyIDVector body_ids;69body_ids.reserve(mBodies.size() + mSoftBodies.size());7071// Create bodies72for (const BodyCreationSettings &b : mBodies)73{74const Body *body = bi.CreateBody(b);75if (body == nullptr)76break;77body_ids.push_back(body->GetID());78}7980// Create soft bodies81for (const SoftBodyCreationSettings &b : mSoftBodies)82{83const Body *body = bi.CreateSoftBody(b);84if (body == nullptr)85break;86body_ids.push_back(body->GetID());87}8889// Batch add bodies90BodyIDVector temp_body_ids = body_ids; // Body ID's get shuffled by AddBodiesPrepare91BodyInterface::AddState add_state = bi.AddBodiesPrepare(temp_body_ids.data(), (int)temp_body_ids.size());92bi.AddBodiesFinalize(temp_body_ids.data(), (int)temp_body_ids.size(), add_state, EActivation::Activate);9394// If not all bodies are created, creating constraints will be unreliable95if (body_ids.size() != mBodies.size() + mSoftBodies.size())96return false;9798// Create constraints99for (const ConnectedConstraint &cc : mConstraints)100{101BodyID body1_id = cc.mBody1 == cFixedToWorld? BodyID() : body_ids[cc.mBody1];102BodyID body2_id = cc.mBody2 == cFixedToWorld? BodyID() : body_ids[cc.mBody2];103Constraint *c = bi.CreateConstraint(cc.mSettings, body1_id, body2_id);104inSystem->AddConstraint(c);105}106107// Everything was created108return true;109}110111void PhysicsScene::SaveBinaryState(StreamOut &inStream, bool inSaveShapes, bool inSaveGroupFilter) const112{113BodyCreationSettings::ShapeToIDMap shape_to_id;114BodyCreationSettings::MaterialToIDMap material_to_id;115BodyCreationSettings::GroupFilterToIDMap group_filter_to_id;116SoftBodyCreationSettings::SharedSettingsToIDMap settings_to_id;117118// Save bodies119inStream.Write((uint32)mBodies.size());120for (const BodyCreationSettings &b : mBodies)121b.SaveWithChildren(inStream, inSaveShapes? &shape_to_id : nullptr, inSaveShapes? &material_to_id : nullptr, inSaveGroupFilter? &group_filter_to_id : nullptr);122123// Save constraints124inStream.Write((uint32)mConstraints.size());125for (const ConnectedConstraint &cc : mConstraints)126{127cc.mSettings->SaveBinaryState(inStream);128inStream.Write(cc.mBody1);129inStream.Write(cc.mBody2);130}131132// Save soft bodies133inStream.Write((uint32)mSoftBodies.size());134for (const SoftBodyCreationSettings &b : mSoftBodies)135b.SaveWithChildren(inStream, &settings_to_id, &material_to_id, inSaveGroupFilter? &group_filter_to_id : nullptr);136}137138PhysicsScene::PhysicsSceneResult PhysicsScene::sRestoreFromBinaryState(StreamIn &inStream)139{140PhysicsSceneResult result;141142// Create scene143Ref<PhysicsScene> scene = new PhysicsScene();144145BodyCreationSettings::IDToShapeMap id_to_shape;146BodyCreationSettings::IDToMaterialMap id_to_material;147BodyCreationSettings::IDToGroupFilterMap id_to_group_filter;148SoftBodyCreationSettings::IDToSharedSettingsMap id_to_settings;149150// Reserve some memory to avoid frequent reallocations151id_to_shape.reserve(1024);152id_to_material.reserve(128);153id_to_group_filter.reserve(128);154155// Read bodies156uint32 len = 0;157inStream.Read(len);158scene->mBodies.resize(len);159for (BodyCreationSettings &b : scene->mBodies)160{161// Read creation settings162BodyCreationSettings::BCSResult bcs_result = BodyCreationSettings::sRestoreWithChildren(inStream, id_to_shape, id_to_material, id_to_group_filter);163if (bcs_result.HasError())164{165result.SetError(bcs_result.GetError());166return result;167}168b = bcs_result.Get();169}170171// Read constraints172len = 0;173inStream.Read(len);174scene->mConstraints.resize(len);175for (ConnectedConstraint &cc : scene->mConstraints)176{177ConstraintSettings::ConstraintResult c_result = ConstraintSettings::sRestoreFromBinaryState(inStream);178if (c_result.HasError())179{180result.SetError(c_result.GetError());181return result;182}183cc.mSettings = StaticCast<TwoBodyConstraintSettings>(c_result.Get());184inStream.Read(cc.mBody1);185inStream.Read(cc.mBody2);186}187188// Read soft bodies189len = 0;190inStream.Read(len);191scene->mSoftBodies.resize(len);192for (SoftBodyCreationSettings &b : scene->mSoftBodies)193{194// Read creation settings195SoftBodyCreationSettings::SBCSResult sbcs_result = SoftBodyCreationSettings::sRestoreWithChildren(inStream, id_to_settings, id_to_material, id_to_group_filter);196if (sbcs_result.HasError())197{198result.SetError(sbcs_result.GetError());199return result;200}201b = sbcs_result.Get();202}203204result.Set(scene);205return result;206}207208void PhysicsScene::FromPhysicsSystem(const PhysicsSystem *inSystem)209{210// This map will track where each body went in mBodies211using BodyIDToIdxMap = UnorderedMap<BodyID, uint32>;212BodyIDToIdxMap body_id_to_idx;213214// Map invalid ID215body_id_to_idx[BodyID()] = cFixedToWorld;216217// Get all bodies218BodyIDVector body_ids;219inSystem->GetBodies(body_ids);220221// Loop over all bodies222const BodyLockInterface &bli = inSystem->GetBodyLockInterface();223for (const BodyID &id : body_ids)224{225BodyLockRead lock(bli, id);226if (lock.Succeeded())227{228// Store location of body229body_id_to_idx[id] = (uint32)mBodies.size();230231const Body &body = lock.GetBody();232233// Convert to body creation settings234if (body.IsRigidBody())235AddBody(body.GetBodyCreationSettings());236else237AddSoftBody(body.GetSoftBodyCreationSettings());238}239}240241// Loop over all constraints242Constraints constraints = inSystem->GetConstraints();243for (const Constraint *c : constraints)244if (c->GetType() == EConstraintType::TwoBodyConstraint)245{246// Cast to two body constraint247const TwoBodyConstraint *tbc = static_cast<const TwoBodyConstraint *>(c);248249// Find the body indices250BodyIDToIdxMap::const_iterator b1 = body_id_to_idx.find(tbc->GetBody1()->GetID());251BodyIDToIdxMap::const_iterator b2 = body_id_to_idx.find(tbc->GetBody2()->GetID());252JPH_ASSERT(b1 != body_id_to_idx.end() && b2 != body_id_to_idx.end());253254// Create constraint settings and add the constraint255Ref<ConstraintSettings> settings = c->GetConstraintSettings();256AddConstraint(StaticCast<TwoBodyConstraintSettings>(settings), b1->second, b2->second);257}258}259260JPH_NAMESPACE_END261262263