Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Body/BodyInterface.cpp
9912 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/Body/BodyInterface.h>7#include <Jolt/Physics/Collision/BroadPhase/BroadPhase.h>8#include <Jolt/Physics/Collision/CollisionCollectorImpl.h>9#include <Jolt/Physics/Body/Body.h>10#include <Jolt/Physics/Body/BodyManager.h>11#include <Jolt/Physics/Body/BodyCreationSettings.h>12#include <Jolt/Physics/Body/BodyLock.h>13#include <Jolt/Physics/Body/BodyLockMulti.h>14#include <Jolt/Physics/Collision/PhysicsMaterial.h>15#include <Jolt/Physics/Constraints/TwoBodyConstraint.h>1617JPH_NAMESPACE_BEGIN1819void BodyInterface::ActivateBodyInternal(Body &ioBody) const20{21// Activate body or reset its sleep timer.22// Note that BodyManager::ActivateBodies also resets the sleep timer internally, but we avoid a mutex lock if the body is already active by calling ResetSleepTimer directly.23if (!ioBody.IsActive())24mBodyManager->ActivateBodies(&ioBody.GetID(), 1);25else26ioBody.ResetSleepTimer();27}2829Body *BodyInterface::CreateBody(const BodyCreationSettings &inSettings)30{31Body *body = mBodyManager->AllocateBody(inSettings);32if (!mBodyManager->AddBody(body))33{34mBodyManager->FreeBody(body);35return nullptr;36}37return body;38}3940Body *BodyInterface::CreateSoftBody(const SoftBodyCreationSettings &inSettings)41{42Body *body = mBodyManager->AllocateSoftBody(inSettings);43if (!mBodyManager->AddBody(body))44{45mBodyManager->FreeBody(body);46return nullptr;47}48return body;49}5051Body *BodyInterface::CreateBodyWithID(const BodyID &inBodyID, const BodyCreationSettings &inSettings)52{53Body *body = mBodyManager->AllocateBody(inSettings);54if (!mBodyManager->AddBodyWithCustomID(body, inBodyID))55{56mBodyManager->FreeBody(body);57return nullptr;58}59return body;60}6162Body *BodyInterface::CreateSoftBodyWithID(const BodyID &inBodyID, const SoftBodyCreationSettings &inSettings)63{64Body *body = mBodyManager->AllocateSoftBody(inSettings);65if (!mBodyManager->AddBodyWithCustomID(body, inBodyID))66{67mBodyManager->FreeBody(body);68return nullptr;69}70return body;71}7273Body *BodyInterface::CreateBodyWithoutID(const BodyCreationSettings &inSettings) const74{75return mBodyManager->AllocateBody(inSettings);76}7778Body *BodyInterface::CreateSoftBodyWithoutID(const SoftBodyCreationSettings &inSettings) const79{80return mBodyManager->AllocateSoftBody(inSettings);81}8283void BodyInterface::DestroyBodyWithoutID(Body *inBody) const84{85mBodyManager->FreeBody(inBody);86}8788bool BodyInterface::AssignBodyID(Body *ioBody)89{90return mBodyManager->AddBody(ioBody);91}9293bool BodyInterface::AssignBodyID(Body *ioBody, const BodyID &inBodyID)94{95return mBodyManager->AddBodyWithCustomID(ioBody, inBodyID);96}9798Body *BodyInterface::UnassignBodyID(const BodyID &inBodyID)99{100Body *body = nullptr;101mBodyManager->RemoveBodies(&inBodyID, 1, &body);102return body;103}104105void BodyInterface::UnassignBodyIDs(const BodyID *inBodyIDs, int inNumber, Body **outBodies)106{107mBodyManager->RemoveBodies(inBodyIDs, inNumber, outBodies);108}109110void BodyInterface::DestroyBody(const BodyID &inBodyID)111{112mBodyManager->DestroyBodies(&inBodyID, 1);113}114115void BodyInterface::DestroyBodies(const BodyID *inBodyIDs, int inNumber)116{117mBodyManager->DestroyBodies(inBodyIDs, inNumber);118}119120void BodyInterface::AddBody(const BodyID &inBodyID, EActivation inActivationMode)121{122BodyLockWrite lock(*mBodyLockInterface, inBodyID);123if (lock.Succeeded())124{125const Body &body = lock.GetBody();126127// Add to broadphase128BodyID id = inBodyID;129BroadPhase::AddState add_state = mBroadPhase->AddBodiesPrepare(&id, 1);130mBroadPhase->AddBodiesFinalize(&id, 1, add_state);131132// Optionally activate body133if (inActivationMode == EActivation::Activate && !body.IsStatic())134mBodyManager->ActivateBodies(&inBodyID, 1);135}136}137138void BodyInterface::RemoveBody(const BodyID &inBodyID)139{140BodyLockWrite lock(*mBodyLockInterface, inBodyID);141if (lock.Succeeded())142{143const Body &body = lock.GetBody();144145// Deactivate body146if (body.IsActive())147mBodyManager->DeactivateBodies(&inBodyID, 1);148149// Remove from broadphase150BodyID id = inBodyID;151mBroadPhase->RemoveBodies(&id, 1);152}153}154155bool BodyInterface::IsAdded(const BodyID &inBodyID) const156{157BodyLockRead lock(*mBodyLockInterface, inBodyID);158return lock.SucceededAndIsInBroadPhase();159}160161BodyID BodyInterface::CreateAndAddBody(const BodyCreationSettings &inSettings, EActivation inActivationMode)162{163const Body *b = CreateBody(inSettings);164if (b == nullptr)165return BodyID(); // Out of bodies166AddBody(b->GetID(), inActivationMode);167return b->GetID();168}169170BodyID BodyInterface::CreateAndAddSoftBody(const SoftBodyCreationSettings &inSettings, EActivation inActivationMode)171{172const Body *b = CreateSoftBody(inSettings);173if (b == nullptr)174return BodyID(); // Out of bodies175AddBody(b->GetID(), inActivationMode);176return b->GetID();177}178179BodyInterface::AddState BodyInterface::AddBodiesPrepare(BodyID *ioBodies, int inNumber)180{181return mBroadPhase->AddBodiesPrepare(ioBodies, inNumber);182}183184void BodyInterface::AddBodiesFinalize(BodyID *ioBodies, int inNumber, AddState inAddState, EActivation inActivationMode)185{186BodyLockMultiWrite lock(*mBodyLockInterface, ioBodies, inNumber);187188// Add to broadphase189mBroadPhase->AddBodiesFinalize(ioBodies, inNumber, inAddState);190191// Optionally activate bodies192if (inActivationMode == EActivation::Activate)193mBodyManager->ActivateBodies(ioBodies, inNumber);194}195196void BodyInterface::AddBodiesAbort(BodyID *ioBodies, int inNumber, AddState inAddState)197{198mBroadPhase->AddBodiesAbort(ioBodies, inNumber, inAddState);199}200201void BodyInterface::RemoveBodies(BodyID *ioBodies, int inNumber)202{203BodyLockMultiWrite lock(*mBodyLockInterface, ioBodies, inNumber);204205// Deactivate bodies206mBodyManager->DeactivateBodies(ioBodies, inNumber);207208// Remove from broadphase209mBroadPhase->RemoveBodies(ioBodies, inNumber);210}211212void BodyInterface::ActivateBody(const BodyID &inBodyID)213{214BodyLockWrite lock(*mBodyLockInterface, inBodyID);215if (lock.Succeeded())216{217Body &body = lock.GetBody();218ActivateBodyInternal(body);219}220}221222void BodyInterface::ActivateBodies(const BodyID *inBodyIDs, int inNumber)223{224BodyLockMultiWrite lock(*mBodyLockInterface, inBodyIDs, inNumber);225226mBodyManager->ActivateBodies(inBodyIDs, inNumber);227}228229void BodyInterface::ActivateBodiesInAABox(const AABox &inBox, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter)230{231AllHitCollisionCollector<CollideShapeBodyCollector> collector;232mBroadPhase->CollideAABox(inBox, collector, inBroadPhaseLayerFilter, inObjectLayerFilter);233ActivateBodies(collector.mHits.data(), (int)collector.mHits.size());234}235236void BodyInterface::DeactivateBody(const BodyID &inBodyID)237{238BodyLockWrite lock(*mBodyLockInterface, inBodyID);239if (lock.Succeeded())240{241const Body &body = lock.GetBody();242243if (body.IsActive())244mBodyManager->DeactivateBodies(&inBodyID, 1);245}246}247248void BodyInterface::DeactivateBodies(const BodyID *inBodyIDs, int inNumber)249{250BodyLockMultiWrite lock(*mBodyLockInterface, inBodyIDs, inNumber);251252mBodyManager->DeactivateBodies(inBodyIDs, inNumber);253}254255bool BodyInterface::IsActive(const BodyID &inBodyID) const256{257BodyLockRead lock(*mBodyLockInterface, inBodyID);258return lock.Succeeded() && lock.GetBody().IsActive();259}260261void BodyInterface::ResetSleepTimer(const BodyID &inBodyID)262{263BodyLockWrite lock(*mBodyLockInterface, inBodyID);264if (lock.Succeeded())265lock.GetBody().ResetSleepTimer();266}267268TwoBodyConstraint *BodyInterface::CreateConstraint(const TwoBodyConstraintSettings *inSettings, const BodyID &inBodyID1, const BodyID &inBodyID2)269{270BodyID constraint_bodies[] = { inBodyID1, inBodyID2 };271BodyLockMultiWrite lock(*mBodyLockInterface, constraint_bodies, 2);272273Body *body1 = lock.GetBody(0);274Body *body2 = lock.GetBody(1);275276JPH_ASSERT(body1 != body2);277JPH_ASSERT(body1 != nullptr || body2 != nullptr);278279return inSettings->Create(body1 != nullptr? *body1 : Body::sFixedToWorld, body2 != nullptr? *body2 : Body::sFixedToWorld);280}281282void BodyInterface::ActivateConstraint(const TwoBodyConstraint *inConstraint)283{284BodyID bodies[] = { inConstraint->GetBody1()->GetID(), inConstraint->GetBody2()->GetID() };285ActivateBodies(bodies, 2);286}287288RefConst<Shape> BodyInterface::GetShape(const BodyID &inBodyID) const289{290RefConst<Shape> shape;291BodyLockRead lock(*mBodyLockInterface, inBodyID);292if (lock.Succeeded())293shape = lock.GetBody().GetShape();294return shape;295}296297void BodyInterface::SetShape(const BodyID &inBodyID, const Shape *inShape, bool inUpdateMassProperties, EActivation inActivationMode) const298{299BodyLockWrite lock(*mBodyLockInterface, inBodyID);300if (lock.Succeeded())301{302Body &body = lock.GetBody();303304// Check if shape actually changed305if (body.GetShape() != inShape)306{307// Update the shape308body.SetShapeInternal(inShape, inUpdateMassProperties);309310// Flag collision cache invalid for this body311mBodyManager->InvalidateContactCacheForBody(body);312313// Notify broadphase of change314if (body.IsInBroadPhase())315{316BodyID id = body.GetID();317mBroadPhase->NotifyBodiesAABBChanged(&id, 1);318319// Optionally activate body320if (inActivationMode == EActivation::Activate && !body.IsStatic())321ActivateBodyInternal(body);322}323}324}325}326327void BodyInterface::NotifyShapeChanged(const BodyID &inBodyID, Vec3Arg inPreviousCenterOfMass, bool inUpdateMassProperties, EActivation inActivationMode) const328{329BodyLockWrite lock(*mBodyLockInterface, inBodyID);330if (lock.Succeeded())331{332Body &body = lock.GetBody();333334// Update center of mass, mass and inertia335body.UpdateCenterOfMassInternal(inPreviousCenterOfMass, inUpdateMassProperties);336337// Recalculate bounding box338body.CalculateWorldSpaceBoundsInternal();339340// Flag collision cache invalid for this body341mBodyManager->InvalidateContactCacheForBody(body);342343// Notify broadphase of change344if (body.IsInBroadPhase())345{346BodyID id = body.GetID();347mBroadPhase->NotifyBodiesAABBChanged(&id, 1);348349// Optionally activate body350if (inActivationMode == EActivation::Activate && !body.IsStatic())351ActivateBodyInternal(body);352}353}354}355356void BodyInterface::SetObjectLayer(const BodyID &inBodyID, ObjectLayer inLayer)357{358BodyLockWrite lock(*mBodyLockInterface, inBodyID);359if (lock.Succeeded())360{361Body &body = lock.GetBody();362363// Check if layer actually changed, updating the broadphase is rather expensive364if (body.GetObjectLayer() != inLayer)365{366// Update the layer on the body367mBodyManager->SetBodyObjectLayerInternal(body, inLayer);368369// Notify broadphase of change370if (body.IsInBroadPhase())371{372BodyID id = body.GetID();373mBroadPhase->NotifyBodiesLayerChanged(&id, 1);374}375}376}377}378379ObjectLayer BodyInterface::GetObjectLayer(const BodyID &inBodyID) const380{381BodyLockRead lock(*mBodyLockInterface, inBodyID);382if (lock.Succeeded())383return lock.GetBody().GetObjectLayer();384else385return cObjectLayerInvalid;386}387388void BodyInterface::SetPositionAndRotation(const BodyID &inBodyID, RVec3Arg inPosition, QuatArg inRotation, EActivation inActivationMode)389{390BodyLockWrite lock(*mBodyLockInterface, inBodyID);391if (lock.Succeeded())392{393Body &body = lock.GetBody();394395// Update the position396body.SetPositionAndRotationInternal(inPosition, inRotation);397398// Notify broadphase of change399if (body.IsInBroadPhase())400{401BodyID id = body.GetID();402mBroadPhase->NotifyBodiesAABBChanged(&id, 1);403404// Optionally activate body405if (inActivationMode == EActivation::Activate && !body.IsStatic())406ActivateBodyInternal(body);407}408}409}410411void BodyInterface::SetPositionAndRotationWhenChanged(const BodyID &inBodyID, RVec3Arg inPosition, QuatArg inRotation, EActivation inActivationMode)412{413BodyLockWrite lock(*mBodyLockInterface, inBodyID);414if (lock.Succeeded())415{416Body &body = lock.GetBody();417418// Check if there is enough change419if (!body.GetPosition().IsClose(inPosition)420|| !body.GetRotation().IsClose(inRotation))421{422// Update the position423body.SetPositionAndRotationInternal(inPosition, inRotation);424425// Notify broadphase of change426if (body.IsInBroadPhase())427{428BodyID id = body.GetID();429mBroadPhase->NotifyBodiesAABBChanged(&id, 1);430431// Optionally activate body432if (inActivationMode == EActivation::Activate && !body.IsStatic())433ActivateBodyInternal(body);434}435}436}437}438439void BodyInterface::GetPositionAndRotation(const BodyID &inBodyID, RVec3 &outPosition, Quat &outRotation) const440{441BodyLockRead lock(*mBodyLockInterface, inBodyID);442if (lock.Succeeded())443{444const Body &body = lock.GetBody();445outPosition = body.GetPosition();446outRotation = body.GetRotation();447}448else449{450outPosition = RVec3::sZero();451outRotation = Quat::sIdentity();452}453}454455void BodyInterface::SetPosition(const BodyID &inBodyID, RVec3Arg inPosition, EActivation inActivationMode)456{457BodyLockWrite lock(*mBodyLockInterface, inBodyID);458if (lock.Succeeded())459{460Body &body = lock.GetBody();461462// Update the position463body.SetPositionAndRotationInternal(inPosition, body.GetRotation());464465// Notify broadphase of change466if (body.IsInBroadPhase())467{468BodyID id = body.GetID();469mBroadPhase->NotifyBodiesAABBChanged(&id, 1);470471// Optionally activate body472if (inActivationMode == EActivation::Activate && !body.IsStatic())473ActivateBodyInternal(body);474}475}476}477478RVec3 BodyInterface::GetPosition(const BodyID &inBodyID) const479{480BodyLockRead lock(*mBodyLockInterface, inBodyID);481if (lock.Succeeded())482return lock.GetBody().GetPosition();483else484return RVec3::sZero();485}486487RVec3 BodyInterface::GetCenterOfMassPosition(const BodyID &inBodyID) const488{489BodyLockRead lock(*mBodyLockInterface, inBodyID);490if (lock.Succeeded())491return lock.GetBody().GetCenterOfMassPosition();492else493return RVec3::sZero();494}495496void BodyInterface::SetRotation(const BodyID &inBodyID, QuatArg inRotation, EActivation inActivationMode)497{498BodyLockWrite lock(*mBodyLockInterface, inBodyID);499if (lock.Succeeded())500{501Body &body = lock.GetBody();502503// Update the position504body.SetPositionAndRotationInternal(body.GetPosition(), inRotation);505506// Notify broadphase of change507if (body.IsInBroadPhase())508{509BodyID id = body.GetID();510mBroadPhase->NotifyBodiesAABBChanged(&id, 1);511512// Optionally activate body513if (inActivationMode == EActivation::Activate && !body.IsStatic())514ActivateBodyInternal(body);515}516}517}518519Quat BodyInterface::GetRotation(const BodyID &inBodyID) const520{521BodyLockRead lock(*mBodyLockInterface, inBodyID);522if (lock.Succeeded())523return lock.GetBody().GetRotation();524else525return Quat::sIdentity();526}527528RMat44 BodyInterface::GetWorldTransform(const BodyID &inBodyID) const529{530BodyLockRead lock(*mBodyLockInterface, inBodyID);531if (lock.Succeeded())532return lock.GetBody().GetWorldTransform();533else534return RMat44::sIdentity();535}536537RMat44 BodyInterface::GetCenterOfMassTransform(const BodyID &inBodyID) const538{539BodyLockRead lock(*mBodyLockInterface, inBodyID);540if (lock.Succeeded())541return lock.GetBody().GetCenterOfMassTransform();542else543return RMat44::sIdentity();544}545546void BodyInterface::MoveKinematic(const BodyID &inBodyID, RVec3Arg inTargetPosition, QuatArg inTargetRotation, float inDeltaTime)547{548BodyLockWrite lock(*mBodyLockInterface, inBodyID);549if (lock.Succeeded())550{551Body &body = lock.GetBody();552553body.MoveKinematic(inTargetPosition, inTargetRotation, inDeltaTime);554555if (!body.IsActive() && (!body.GetLinearVelocity().IsNearZero() || !body.GetAngularVelocity().IsNearZero()))556mBodyManager->ActivateBodies(&inBodyID, 1);557}558}559560void BodyInterface::SetLinearAndAngularVelocity(const BodyID &inBodyID, Vec3Arg inLinearVelocity, Vec3Arg inAngularVelocity)561{562BodyLockWrite lock(*mBodyLockInterface, inBodyID);563if (lock.Succeeded())564{565Body &body = lock.GetBody();566if (!body.IsStatic())567{568body.SetLinearVelocityClamped(inLinearVelocity);569body.SetAngularVelocityClamped(inAngularVelocity);570571if (!body.IsActive() && (!inLinearVelocity.IsNearZero() || !inAngularVelocity.IsNearZero()))572mBodyManager->ActivateBodies(&inBodyID, 1);573}574}575}576577void BodyInterface::GetLinearAndAngularVelocity(const BodyID &inBodyID, Vec3 &outLinearVelocity, Vec3 &outAngularVelocity) const578{579BodyLockRead lock(*mBodyLockInterface, inBodyID);580if (lock.Succeeded())581{582const Body &body = lock.GetBody();583if (!body.IsStatic())584{585outLinearVelocity = body.GetLinearVelocity();586outAngularVelocity = body.GetAngularVelocity();587return;588}589}590591outLinearVelocity = outAngularVelocity = Vec3::sZero();592}593594void BodyInterface::SetLinearVelocity(const BodyID &inBodyID, Vec3Arg inLinearVelocity)595{596BodyLockWrite lock(*mBodyLockInterface, inBodyID);597if (lock.Succeeded())598{599Body &body = lock.GetBody();600if (!body.IsStatic())601{602body.SetLinearVelocityClamped(inLinearVelocity);603604if (!body.IsActive() && !inLinearVelocity.IsNearZero())605mBodyManager->ActivateBodies(&inBodyID, 1);606}607}608}609610Vec3 BodyInterface::GetLinearVelocity(const BodyID &inBodyID) const611{612BodyLockRead lock(*mBodyLockInterface, inBodyID);613if (lock.Succeeded())614{615const Body &body = lock.GetBody();616if (!body.IsStatic())617return body.GetLinearVelocity();618}619620return Vec3::sZero();621}622623void BodyInterface::AddLinearVelocity(const BodyID &inBodyID, Vec3Arg inLinearVelocity)624{625BodyLockWrite lock(*mBodyLockInterface, inBodyID);626if (lock.Succeeded())627{628Body &body = lock.GetBody();629if (!body.IsStatic())630{631body.SetLinearVelocityClamped(body.GetLinearVelocity() + inLinearVelocity);632633if (!body.IsActive() && !body.GetLinearVelocity().IsNearZero())634mBodyManager->ActivateBodies(&inBodyID, 1);635}636}637}638639void BodyInterface::AddLinearAndAngularVelocity(const BodyID &inBodyID, Vec3Arg inLinearVelocity, Vec3Arg inAngularVelocity)640{641BodyLockWrite lock(*mBodyLockInterface, inBodyID);642if (lock.Succeeded())643{644Body &body = lock.GetBody();645if (!body.IsStatic())646{647body.SetLinearVelocityClamped(body.GetLinearVelocity() + inLinearVelocity);648body.SetAngularVelocityClamped(body.GetAngularVelocity() + inAngularVelocity);649650if (!body.IsActive() && (!body.GetLinearVelocity().IsNearZero() || !body.GetAngularVelocity().IsNearZero()))651mBodyManager->ActivateBodies(&inBodyID, 1);652}653}654}655656void BodyInterface::SetAngularVelocity(const BodyID &inBodyID, Vec3Arg inAngularVelocity)657{658BodyLockWrite lock(*mBodyLockInterface, inBodyID);659if (lock.Succeeded())660{661Body &body = lock.GetBody();662if (!body.IsStatic())663{664body.SetAngularVelocityClamped(inAngularVelocity);665666if (!body.IsActive() && !inAngularVelocity.IsNearZero())667mBodyManager->ActivateBodies(&inBodyID, 1);668}669}670}671672Vec3 BodyInterface::GetAngularVelocity(const BodyID &inBodyID) const673{674BodyLockRead lock(*mBodyLockInterface, inBodyID);675if (lock.Succeeded())676{677const Body &body = lock.GetBody();678if (!body.IsStatic())679return body.GetAngularVelocity();680}681682return Vec3::sZero();683}684685Vec3 BodyInterface::GetPointVelocity(const BodyID &inBodyID, RVec3Arg inPoint) const686{687BodyLockRead lock(*mBodyLockInterface, inBodyID);688if (lock.Succeeded())689{690const Body &body = lock.GetBody();691if (!body.IsStatic())692return body.GetPointVelocity(inPoint);693}694695return Vec3::sZero();696}697698void BodyInterface::AddForce(const BodyID &inBodyID, Vec3Arg inForce, EActivation inActivationMode)699{700BodyLockWrite lock(*mBodyLockInterface, inBodyID);701if (lock.Succeeded())702{703Body &body = lock.GetBody();704if (body.IsDynamic() && (inActivationMode == EActivation::Activate || body.IsActive()))705{706body.AddForce(inForce);707708if (inActivationMode == EActivation::Activate)709ActivateBodyInternal(body);710}711}712}713714void BodyInterface::AddForce(const BodyID &inBodyID, Vec3Arg inForce, RVec3Arg inPoint, EActivation inActivationMode)715{716BodyLockWrite lock(*mBodyLockInterface, inBodyID);717if (lock.Succeeded())718{719Body &body = lock.GetBody();720if (body.IsDynamic() && (inActivationMode == EActivation::Activate || body.IsActive()))721{722body.AddForce(inForce, inPoint);723724if (inActivationMode == EActivation::Activate)725ActivateBodyInternal(body);726}727}728}729730void BodyInterface::AddTorque(const BodyID &inBodyID, Vec3Arg inTorque, EActivation inActivationMode)731{732BodyLockWrite lock(*mBodyLockInterface, inBodyID);733if (lock.Succeeded())734{735Body &body = lock.GetBody();736if (body.IsDynamic() && (inActivationMode == EActivation::Activate || body.IsActive()))737{738body.AddTorque(inTorque);739740if (inActivationMode == EActivation::Activate)741ActivateBodyInternal(body);742}743}744}745746void BodyInterface::AddForceAndTorque(const BodyID &inBodyID, Vec3Arg inForce, Vec3Arg inTorque, EActivation inActivationMode)747{748BodyLockWrite lock(*mBodyLockInterface, inBodyID);749if (lock.Succeeded())750{751Body &body = lock.GetBody();752if (body.IsDynamic() && (inActivationMode == EActivation::Activate || body.IsActive()))753{754body.AddForce(inForce);755body.AddTorque(inTorque);756757if (inActivationMode == EActivation::Activate)758ActivateBodyInternal(body);759}760}761}762763void BodyInterface::AddImpulse(const BodyID &inBodyID, Vec3Arg inImpulse)764{765BodyLockWrite lock(*mBodyLockInterface, inBodyID);766if (lock.Succeeded())767{768Body &body = lock.GetBody();769if (body.IsDynamic())770{771body.AddImpulse(inImpulse);772773if (!body.IsActive())774mBodyManager->ActivateBodies(&inBodyID, 1);775}776}777}778779void BodyInterface::AddImpulse(const BodyID &inBodyID, Vec3Arg inImpulse, RVec3Arg inPoint)780{781BodyLockWrite lock(*mBodyLockInterface, inBodyID);782if (lock.Succeeded())783{784Body &body = lock.GetBody();785if (body.IsDynamic())786{787body.AddImpulse(inImpulse, inPoint);788789if (!body.IsActive())790mBodyManager->ActivateBodies(&inBodyID, 1);791}792}793}794795void BodyInterface::AddAngularImpulse(const BodyID &inBodyID, Vec3Arg inAngularImpulse)796{797BodyLockWrite lock(*mBodyLockInterface, inBodyID);798if (lock.Succeeded())799{800Body &body = lock.GetBody();801if (body.IsDynamic())802{803body.AddAngularImpulse(inAngularImpulse);804805if (!body.IsActive())806mBodyManager->ActivateBodies(&inBodyID, 1);807}808}809}810811bool BodyInterface::ApplyBuoyancyImpulse(const BodyID &inBodyID, RVec3Arg inSurfacePosition, Vec3Arg inSurfaceNormal, float inBuoyancy, float inLinearDrag, float inAngularDrag, Vec3Arg inFluidVelocity, Vec3Arg inGravity, float inDeltaTime)812{813BodyLockWrite lock(*mBodyLockInterface, inBodyID);814if (lock.Succeeded())815{816Body &body = lock.GetBody();817if (body.IsDynamic()818&& body.ApplyBuoyancyImpulse(inSurfacePosition, inSurfaceNormal, inBuoyancy, inLinearDrag, inAngularDrag, inFluidVelocity, inGravity, inDeltaTime))819{820ActivateBodyInternal(body);821return true;822}823}824825return false;826}827828void BodyInterface::SetPositionRotationAndVelocity(const BodyID &inBodyID, RVec3Arg inPosition, QuatArg inRotation, Vec3Arg inLinearVelocity, Vec3Arg inAngularVelocity)829{830BodyLockWrite lock(*mBodyLockInterface, inBodyID);831if (lock.Succeeded())832{833Body &body = lock.GetBody();834835// Update the position836body.SetPositionAndRotationInternal(inPosition, inRotation);837838// Notify broadphase of change839if (body.IsInBroadPhase())840{841BodyID id = body.GetID();842mBroadPhase->NotifyBodiesAABBChanged(&id, 1);843}844845if (!body.IsStatic())846{847body.SetLinearVelocityClamped(inLinearVelocity);848body.SetAngularVelocityClamped(inAngularVelocity);849850// Optionally activate body851if (!body.IsActive() && (!inLinearVelocity.IsNearZero() || !inAngularVelocity.IsNearZero()))852mBodyManager->ActivateBodies(&inBodyID, 1);853}854}855}856857void BodyInterface::SetMotionType(const BodyID &inBodyID, EMotionType inMotionType, EActivation inActivationMode)858{859BodyLockWrite lock(*mBodyLockInterface, inBodyID);860if (lock.Succeeded())861{862Body &body = lock.GetBody();863864// Deactivate if we're making the body static865if (body.IsActive() && inMotionType == EMotionType::Static)866mBodyManager->DeactivateBodies(&inBodyID, 1);867868body.SetMotionType(inMotionType);869870// Activate body if requested871if (inMotionType != EMotionType::Static && inActivationMode == EActivation::Activate)872ActivateBodyInternal(body);873}874}875876EBodyType BodyInterface::GetBodyType(const BodyID &inBodyID) const877{878BodyLockRead lock(*mBodyLockInterface, inBodyID);879if (lock.Succeeded())880return lock.GetBody().GetBodyType();881else882return EBodyType::RigidBody;883}884885EMotionType BodyInterface::GetMotionType(const BodyID &inBodyID) const886{887BodyLockRead lock(*mBodyLockInterface, inBodyID);888if (lock.Succeeded())889return lock.GetBody().GetMotionType();890else891return EMotionType::Static;892}893894void BodyInterface::SetMotionQuality(const BodyID &inBodyID, EMotionQuality inMotionQuality)895{896BodyLockWrite lock(*mBodyLockInterface, inBodyID);897if (lock.Succeeded())898mBodyManager->SetMotionQuality(lock.GetBody(), inMotionQuality);899}900901EMotionQuality BodyInterface::GetMotionQuality(const BodyID &inBodyID) const902{903BodyLockRead lock(*mBodyLockInterface, inBodyID);904if (lock.Succeeded() && !lock.GetBody().IsStatic())905return lock.GetBody().GetMotionProperties()->GetMotionQuality();906else907return EMotionQuality::Discrete;908}909910Mat44 BodyInterface::GetInverseInertia(const BodyID &inBodyID) const911{912BodyLockRead lock(*mBodyLockInterface, inBodyID);913if (lock.Succeeded())914return lock.GetBody().GetInverseInertia();915else916return Mat44::sIdentity();917}918919void BodyInterface::SetRestitution(const BodyID &inBodyID, float inRestitution)920{921BodyLockWrite lock(*mBodyLockInterface, inBodyID);922if (lock.Succeeded())923lock.GetBody().SetRestitution(inRestitution);924}925926float BodyInterface::GetRestitution(const BodyID &inBodyID) const927{928BodyLockRead lock(*mBodyLockInterface, inBodyID);929if (lock.Succeeded())930return lock.GetBody().GetRestitution();931else932return 0.0f;933}934935void BodyInterface::SetFriction(const BodyID &inBodyID, float inFriction)936{937BodyLockWrite lock(*mBodyLockInterface, inBodyID);938if (lock.Succeeded())939lock.GetBody().SetFriction(inFriction);940}941942float BodyInterface::GetFriction(const BodyID &inBodyID) const943{944BodyLockRead lock(*mBodyLockInterface, inBodyID);945if (lock.Succeeded())946return lock.GetBody().GetFriction();947else948return 0.0f;949}950951void BodyInterface::SetGravityFactor(const BodyID &inBodyID, float inGravityFactor)952{953BodyLockWrite lock(*mBodyLockInterface, inBodyID);954if (lock.Succeeded() && lock.GetBody().GetMotionPropertiesUnchecked() != nullptr)955lock.GetBody().GetMotionPropertiesUnchecked()->SetGravityFactor(inGravityFactor);956}957958float BodyInterface::GetGravityFactor(const BodyID &inBodyID) const959{960BodyLockRead lock(*mBodyLockInterface, inBodyID);961if (lock.Succeeded() && lock.GetBody().GetMotionPropertiesUnchecked() != nullptr)962return lock.GetBody().GetMotionPropertiesUnchecked()->GetGravityFactor();963else964return 1.0f;965}966967void BodyInterface::SetUseManifoldReduction(const BodyID &inBodyID, bool inUseReduction)968{969BodyLockWrite lock(*mBodyLockInterface, inBodyID);970if (lock.Succeeded())971{972Body &body = lock.GetBody();973if (body.GetUseManifoldReduction() != inUseReduction)974{975body.SetUseManifoldReduction(inUseReduction);976977// Flag collision cache invalid for this body978mBodyManager->InvalidateContactCacheForBody(body);979}980}981}982983bool BodyInterface::GetUseManifoldReduction(const BodyID &inBodyID) const984{985BodyLockRead lock(*mBodyLockInterface, inBodyID);986if (lock.Succeeded())987return lock.GetBody().GetUseManifoldReduction();988else989return true;990}991992void BodyInterface::SetCollisionGroup(const BodyID &inBodyID, const CollisionGroup &inCollisionGroup)993{994BodyLockWrite lock(*mBodyLockInterface, inBodyID);995if (lock.Succeeded())996lock.GetBody().SetCollisionGroup(inCollisionGroup);997}998999const CollisionGroup &BodyInterface::GetCollisionGroup(const BodyID &inBodyID) const1000{1001BodyLockRead lock(*mBodyLockInterface, inBodyID);1002if (lock.Succeeded())1003return lock.GetBody().GetCollisionGroup();1004else1005return CollisionGroup::sInvalid;1006}10071008TransformedShape BodyInterface::GetTransformedShape(const BodyID &inBodyID) const1009{1010BodyLockRead lock(*mBodyLockInterface, inBodyID);1011if (lock.Succeeded())1012return lock.GetBody().GetTransformedShape();1013else1014return TransformedShape();1015}10161017uint64 BodyInterface::GetUserData(const BodyID &inBodyID) const1018{1019BodyLockRead lock(*mBodyLockInterface, inBodyID);1020if (lock.Succeeded())1021return lock.GetBody().GetUserData();1022else1023return 0;1024}10251026void BodyInterface::SetUserData(const BodyID &inBodyID, uint64 inUserData) const1027{1028BodyLockWrite lock(*mBodyLockInterface, inBodyID);1029if (lock.Succeeded())1030lock.GetBody().SetUserData(inUserData);1031}10321033const PhysicsMaterial *BodyInterface::GetMaterial(const BodyID &inBodyID, const SubShapeID &inSubShapeID) const1034{1035BodyLockRead lock(*mBodyLockInterface, inBodyID);1036if (lock.Succeeded())1037return lock.GetBody().GetShape()->GetMaterial(inSubShapeID);1038else1039return PhysicsMaterial::sDefault;1040}10411042void BodyInterface::InvalidateContactCache(const BodyID &inBodyID)1043{1044BodyLockWrite lock(*mBodyLockInterface, inBodyID);1045if (lock.Succeeded())1046mBodyManager->InvalidateContactCacheForBody(lock.GetBody());1047}10481049JPH_NAMESPACE_END105010511052