BodyInterface.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #include <Jolt/Jolt.h>
  5. #include <Jolt/Physics/Collision/BroadPhase/BroadPhase.h>
  6. #include <Jolt/Physics/Body/Body.h>
  7. #include <Jolt/Physics/Body/BodyManager.h>
  8. #include <Jolt/Physics/Body/BodyInterface.h>
  9. #include <Jolt/Physics/Body/BodyCreationSettings.h>
  10. #include <Jolt/Physics/Body/BodyLock.h>
  11. #include <Jolt/Physics/Body/BodyLockMulti.h>
  12. #include <Jolt/Physics/Collision/PhysicsMaterial.h>
  13. #include <Jolt/Physics/Constraints/TwoBodyConstraint.h>
  14. JPH_NAMESPACE_BEGIN
  15. Body *BodyInterface::CreateBody(const BodyCreationSettings &inSettings)
  16. {
  17. Body *body = mBodyManager->AllocateBody(inSettings);
  18. if (!mBodyManager->AddBody(body))
  19. {
  20. mBodyManager->FreeBody(body);
  21. return nullptr;
  22. }
  23. return body;
  24. }
  25. Body *BodyInterface::CreateBodyWithID(const BodyID &inBodyID, const BodyCreationSettings &inSettings)
  26. {
  27. Body *body = mBodyManager->AllocateBody(inSettings);
  28. if (!mBodyManager->AddBodyWithCustomID(body, inBodyID))
  29. {
  30. mBodyManager->FreeBody(body);
  31. return nullptr;
  32. }
  33. return body;
  34. }
  35. Body *BodyInterface::CreateBodyWithoutID(const BodyCreationSettings &inSettings) const
  36. {
  37. return mBodyManager->AllocateBody(inSettings);
  38. }
  39. void BodyInterface::DestroyBodyWithoutID(Body *inBody) const
  40. {
  41. mBodyManager->FreeBody(inBody);
  42. }
  43. bool BodyInterface::AssignBodyID(Body *ioBody)
  44. {
  45. return mBodyManager->AddBody(ioBody);
  46. }
  47. bool BodyInterface::AssignBodyID(Body *ioBody, const BodyID &inBodyID)
  48. {
  49. return mBodyManager->AddBodyWithCustomID(ioBody, inBodyID);
  50. }
  51. Body *BodyInterface::UnassignBodyID(const BodyID &inBodyID)
  52. {
  53. Body *body = nullptr;
  54. mBodyManager->RemoveBodies(&inBodyID, 1, &body);
  55. return body;
  56. }
  57. void BodyInterface::UnassignBodyIDs(const BodyID *inBodyIDs, int inNumber, Body **outBodies)
  58. {
  59. mBodyManager->RemoveBodies(inBodyIDs, inNumber, outBodies);
  60. }
  61. void BodyInterface::DestroyBody(const BodyID &inBodyID)
  62. {
  63. mBodyManager->DestroyBodies(&inBodyID, 1);
  64. }
  65. void BodyInterface::DestroyBodies(const BodyID *inBodyIDs, int inNumber)
  66. {
  67. mBodyManager->DestroyBodies(inBodyIDs, inNumber);
  68. }
  69. void BodyInterface::AddBody(const BodyID &inBodyID, EActivation inActivationMode)
  70. {
  71. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  72. if (lock.Succeeded())
  73. {
  74. const Body &body = lock.GetBody();
  75. // Add to broadphase
  76. BodyID id = inBodyID;
  77. BroadPhase::AddState add_state = mBroadPhase->AddBodiesPrepare(&id, 1);
  78. mBroadPhase->AddBodiesFinalize(&id, 1, add_state);
  79. // Optionally activate body
  80. if (inActivationMode == EActivation::Activate && !body.IsStatic())
  81. mBodyManager->ActivateBodies(&inBodyID, 1);
  82. }
  83. }
  84. void BodyInterface::RemoveBody(const BodyID &inBodyID)
  85. {
  86. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  87. if (lock.Succeeded())
  88. {
  89. const Body &body = lock.GetBody();
  90. // Deactivate body
  91. if (body.IsActive())
  92. mBodyManager->DeactivateBodies(&inBodyID, 1);
  93. // Remove from broadphase
  94. BodyID id = inBodyID;
  95. mBroadPhase->RemoveBodies(&id, 1);
  96. }
  97. }
  98. bool BodyInterface::IsAdded(const BodyID &inBodyID) const
  99. {
  100. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  101. return lock.SucceededAndIsInBroadPhase();
  102. }
  103. BodyID BodyInterface::CreateAndAddBody(const BodyCreationSettings &inSettings, EActivation inActivationMode)
  104. {
  105. const Body *b = CreateBody(inSettings);
  106. if (b == nullptr)
  107. return BodyID(); // Out of bodies
  108. AddBody(b->GetID(), inActivationMode);
  109. return b->GetID();
  110. }
  111. BodyInterface::AddState BodyInterface::AddBodiesPrepare(BodyID *ioBodies, int inNumber)
  112. {
  113. return mBroadPhase->AddBodiesPrepare(ioBodies, inNumber);
  114. }
  115. void BodyInterface::AddBodiesFinalize(BodyID *ioBodies, int inNumber, AddState inAddState, EActivation inActivationMode)
  116. {
  117. BodyLockMultiWrite lock(*mBodyLockInterface, ioBodies, inNumber);
  118. // Add to broadphase
  119. mBroadPhase->AddBodiesFinalize(ioBodies, inNumber, inAddState);
  120. // Optionally activate bodies
  121. if (inActivationMode == EActivation::Activate)
  122. mBodyManager->ActivateBodies(ioBodies, inNumber);
  123. }
  124. void BodyInterface::AddBodiesAbort(BodyID *ioBodies, int inNumber, AddState inAddState)
  125. {
  126. mBroadPhase->AddBodiesAbort(ioBodies, inNumber, inAddState);
  127. }
  128. void BodyInterface::RemoveBodies(BodyID *ioBodies, int inNumber)
  129. {
  130. BodyLockMultiWrite lock(*mBodyLockInterface, ioBodies, inNumber);
  131. // Deactivate bodies
  132. mBodyManager->DeactivateBodies(ioBodies, inNumber);
  133. // Remove from broadphase
  134. mBroadPhase->RemoveBodies(ioBodies, inNumber);
  135. }
  136. void BodyInterface::ActivateBody(const BodyID &inBodyID)
  137. {
  138. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  139. if (lock.Succeeded())
  140. {
  141. const Body &body = lock.GetBody();
  142. if (!body.IsActive())
  143. mBodyManager->ActivateBodies(&inBodyID, 1);
  144. }
  145. }
  146. void BodyInterface::ActivateBodies(const BodyID *inBodyIDs, int inNumber)
  147. {
  148. BodyLockMultiWrite lock(*mBodyLockInterface, inBodyIDs, inNumber);
  149. mBodyManager->ActivateBodies(inBodyIDs, inNumber);
  150. }
  151. void BodyInterface::DeactivateBody(const BodyID &inBodyID)
  152. {
  153. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  154. if (lock.Succeeded())
  155. {
  156. const Body &body = lock.GetBody();
  157. if (body.IsActive())
  158. mBodyManager->DeactivateBodies(&inBodyID, 1);
  159. }
  160. }
  161. void BodyInterface::DeactivateBodies(const BodyID *inBodyIDs, int inNumber)
  162. {
  163. BodyLockMultiWrite lock(*mBodyLockInterface, inBodyIDs, inNumber);
  164. mBodyManager->DeactivateBodies(inBodyIDs, inNumber);
  165. }
  166. bool BodyInterface::IsActive(const BodyID &inBodyID) const
  167. {
  168. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  169. return lock.Succeeded() && lock.GetBody().IsActive();
  170. }
  171. TwoBodyConstraint *BodyInterface::CreateConstraint(const TwoBodyConstraintSettings *inSettings, const BodyID &inBodyID1, const BodyID &inBodyID2)
  172. {
  173. BodyID constraint_bodies[] = { inBodyID1, inBodyID2 };
  174. BodyLockMultiWrite lock(*mBodyLockInterface, constraint_bodies, 2);
  175. Body *body1 = lock.GetBody(0);
  176. Body *body2 = lock.GetBody(1);
  177. JPH_ASSERT(body1 != body2);
  178. JPH_ASSERT(body1 != nullptr || body2 != nullptr);
  179. return inSettings->Create(body1 != nullptr? *body1 : Body::sFixedToWorld, body2 != nullptr? *body2 : Body::sFixedToWorld);
  180. }
  181. void BodyInterface::ActivateConstraint(const TwoBodyConstraint *inConstraint)
  182. {
  183. BodyID bodies[] = { inConstraint->GetBody1()->GetID(), inConstraint->GetBody2()->GetID() };
  184. ActivateBodies(bodies, 2);
  185. }
  186. RefConst<Shape> BodyInterface::GetShape(const BodyID &inBodyID) const
  187. {
  188. RefConst<Shape> shape;
  189. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  190. if (lock.Succeeded())
  191. shape = lock.GetBody().GetShape();
  192. return shape;
  193. }
  194. void BodyInterface::SetShape(const BodyID &inBodyID, const Shape *inShape, bool inUpdateMassProperties, EActivation inActivationMode) const
  195. {
  196. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  197. if (lock.Succeeded())
  198. {
  199. Body &body = lock.GetBody();
  200. // Check if shape actually changed
  201. if (body.GetShape() != inShape)
  202. {
  203. // Update the shape
  204. body.SetShapeInternal(inShape, inUpdateMassProperties);
  205. // Flag collision cache invalid for this body
  206. mBodyManager->InvalidateContactCacheForBody(body);
  207. // Notify broadphase of change
  208. if (body.IsInBroadPhase())
  209. {
  210. BodyID id = body.GetID();
  211. mBroadPhase->NotifyBodiesAABBChanged(&id, 1);
  212. }
  213. // Optionally activate body
  214. if (inActivationMode == EActivation::Activate && !body.IsStatic())
  215. mBodyManager->ActivateBodies(&inBodyID, 1);
  216. }
  217. }
  218. }
  219. void BodyInterface::NotifyShapeChanged(const BodyID &inBodyID, Vec3Arg inPreviousCenterOfMass, bool inUpdateMassProperties, EActivation inActivationMode) const
  220. {
  221. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  222. if (lock.Succeeded())
  223. {
  224. Body &body = lock.GetBody();
  225. // Update center of mass, mass and inertia
  226. body.UpdateCenterOfMassInternal(inPreviousCenterOfMass, inUpdateMassProperties);
  227. // Recalculate bounding box
  228. body.CalculateWorldSpaceBoundsInternal();
  229. // Flag collision cache invalid for this body
  230. mBodyManager->InvalidateContactCacheForBody(body);
  231. // Notify broadphase of change
  232. if (body.IsInBroadPhase())
  233. {
  234. BodyID id = body.GetID();
  235. mBroadPhase->NotifyBodiesAABBChanged(&id, 1);
  236. }
  237. // Optionally activate body
  238. if (inActivationMode == EActivation::Activate && !body.IsStatic())
  239. mBodyManager->ActivateBodies(&inBodyID, 1);
  240. }
  241. }
  242. void BodyInterface::SetObjectLayer(const BodyID &inBodyID, ObjectLayer inLayer)
  243. {
  244. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  245. if (lock.Succeeded())
  246. {
  247. Body &body = lock.GetBody();
  248. // Check if layer actually changed, updating the broadphase is rather expensive
  249. if (body.GetObjectLayer() != inLayer)
  250. {
  251. // Update the layer on the body
  252. mBodyManager->SetBodyObjectLayerInternal(body, inLayer);
  253. // Notify broadphase of change
  254. if (body.IsInBroadPhase())
  255. {
  256. BodyID id = body.GetID();
  257. mBroadPhase->NotifyBodiesLayerChanged(&id, 1);
  258. }
  259. }
  260. }
  261. }
  262. ObjectLayer BodyInterface::GetObjectLayer(const BodyID &inBodyID) const
  263. {
  264. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  265. if (lock.Succeeded())
  266. return lock.GetBody().GetObjectLayer();
  267. else
  268. return cObjectLayerInvalid;
  269. }
  270. void BodyInterface::SetPositionAndRotation(const BodyID &inBodyID, RVec3Arg inPosition, QuatArg inRotation, EActivation inActivationMode)
  271. {
  272. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  273. if (lock.Succeeded())
  274. {
  275. Body &body = lock.GetBody();
  276. // Update the position
  277. body.SetPositionAndRotationInternal(inPosition, inRotation);
  278. // Notify broadphase of change
  279. if (body.IsInBroadPhase())
  280. {
  281. BodyID id = body.GetID();
  282. mBroadPhase->NotifyBodiesAABBChanged(&id, 1);
  283. }
  284. // Optionally activate body
  285. if (inActivationMode == EActivation::Activate && !body.IsStatic())
  286. mBodyManager->ActivateBodies(&inBodyID, 1);
  287. }
  288. }
  289. void BodyInterface::SetPositionAndRotationWhenChanged(const BodyID &inBodyID, RVec3Arg inPosition, QuatArg inRotation, EActivation inActivationMode)
  290. {
  291. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  292. if (lock.Succeeded())
  293. {
  294. Body &body = lock.GetBody();
  295. // Check if there is enough change
  296. if (!body.GetPosition().IsClose(inPosition)
  297. || !body.GetRotation().IsClose(inRotation))
  298. {
  299. // Update the position
  300. body.SetPositionAndRotationInternal(inPosition, inRotation);
  301. // Notify broadphase of change
  302. if (body.IsInBroadPhase())
  303. {
  304. BodyID id = body.GetID();
  305. mBroadPhase->NotifyBodiesAABBChanged(&id, 1);
  306. }
  307. // Optionally activate body
  308. if (inActivationMode == EActivation::Activate && !body.IsStatic())
  309. mBodyManager->ActivateBodies(&inBodyID, 1);
  310. }
  311. }
  312. }
  313. void BodyInterface::GetPositionAndRotation(const BodyID &inBodyID, RVec3 &outPosition, Quat &outRotation) const
  314. {
  315. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  316. if (lock.Succeeded())
  317. {
  318. const Body &body = lock.GetBody();
  319. outPosition = body.GetPosition();
  320. outRotation = body.GetRotation();
  321. }
  322. else
  323. {
  324. outPosition = RVec3::sZero();
  325. outRotation = Quat::sIdentity();
  326. }
  327. }
  328. void BodyInterface::SetPosition(const BodyID &inBodyID, RVec3Arg inPosition, EActivation inActivationMode)
  329. {
  330. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  331. if (lock.Succeeded())
  332. {
  333. Body &body = lock.GetBody();
  334. // Update the position
  335. body.SetPositionAndRotationInternal(inPosition, body.GetRotation());
  336. // Notify broadphase of change
  337. if (body.IsInBroadPhase())
  338. {
  339. BodyID id = body.GetID();
  340. mBroadPhase->NotifyBodiesAABBChanged(&id, 1);
  341. }
  342. // Optionally activate body
  343. if (inActivationMode == EActivation::Activate && !body.IsStatic())
  344. mBodyManager->ActivateBodies(&inBodyID, 1);
  345. }
  346. }
  347. RVec3 BodyInterface::GetPosition(const BodyID &inBodyID) const
  348. {
  349. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  350. if (lock.Succeeded())
  351. return lock.GetBody().GetPosition();
  352. else
  353. return RVec3::sZero();
  354. }
  355. RVec3 BodyInterface::GetCenterOfMassPosition(const BodyID &inBodyID) const
  356. {
  357. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  358. if (lock.Succeeded())
  359. return lock.GetBody().GetCenterOfMassPosition();
  360. else
  361. return RVec3::sZero();
  362. }
  363. void BodyInterface::SetRotation(const BodyID &inBodyID, QuatArg inRotation, EActivation inActivationMode)
  364. {
  365. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  366. if (lock.Succeeded())
  367. {
  368. Body &body = lock.GetBody();
  369. // Update the position
  370. body.SetPositionAndRotationInternal(body.GetPosition(), inRotation);
  371. // Notify broadphase of change
  372. if (body.IsInBroadPhase())
  373. {
  374. BodyID id = body.GetID();
  375. mBroadPhase->NotifyBodiesAABBChanged(&id, 1);
  376. }
  377. // Optionally activate body
  378. if (inActivationMode == EActivation::Activate && !body.IsStatic())
  379. mBodyManager->ActivateBodies(&inBodyID, 1);
  380. }
  381. }
  382. Quat BodyInterface::GetRotation(const BodyID &inBodyID) const
  383. {
  384. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  385. if (lock.Succeeded())
  386. return lock.GetBody().GetRotation();
  387. else
  388. return Quat::sIdentity();
  389. }
  390. RMat44 BodyInterface::GetWorldTransform(const BodyID &inBodyID) const
  391. {
  392. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  393. if (lock.Succeeded())
  394. return lock.GetBody().GetWorldTransform();
  395. else
  396. return RMat44::sIdentity();
  397. }
  398. RMat44 BodyInterface::GetCenterOfMassTransform(const BodyID &inBodyID) const
  399. {
  400. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  401. if (lock.Succeeded())
  402. return lock.GetBody().GetCenterOfMassTransform();
  403. else
  404. return RMat44::sIdentity();
  405. }
  406. void BodyInterface::MoveKinematic(const BodyID &inBodyID, RVec3Arg inTargetPosition, QuatArg inTargetRotation, float inDeltaTime)
  407. {
  408. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  409. if (lock.Succeeded())
  410. {
  411. Body &body = lock.GetBody();
  412. body.MoveKinematic(inTargetPosition, inTargetRotation, inDeltaTime);
  413. if (!body.IsActive() && (!body.GetLinearVelocity().IsNearZero() || !body.GetAngularVelocity().IsNearZero()))
  414. mBodyManager->ActivateBodies(&inBodyID, 1);
  415. }
  416. }
  417. void BodyInterface::SetLinearAndAngularVelocity(const BodyID &inBodyID, Vec3Arg inLinearVelocity, Vec3Arg inAngularVelocity)
  418. {
  419. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  420. if (lock.Succeeded())
  421. {
  422. Body &body = lock.GetBody();
  423. if (!body.IsStatic())
  424. {
  425. body.SetLinearVelocityClamped(inLinearVelocity);
  426. body.SetAngularVelocityClamped(inAngularVelocity);
  427. if (!body.IsActive() && (!inLinearVelocity.IsNearZero() || !inAngularVelocity.IsNearZero()))
  428. mBodyManager->ActivateBodies(&inBodyID, 1);
  429. }
  430. }
  431. }
  432. void BodyInterface::GetLinearAndAngularVelocity(const BodyID &inBodyID, Vec3 &outLinearVelocity, Vec3 &outAngularVelocity) const
  433. {
  434. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  435. if (lock.Succeeded())
  436. {
  437. const Body &body = lock.GetBody();
  438. if (!body.IsStatic())
  439. {
  440. outLinearVelocity = body.GetLinearVelocity();
  441. outAngularVelocity = body.GetAngularVelocity();
  442. return;
  443. }
  444. }
  445. outLinearVelocity = outAngularVelocity = Vec3::sZero();
  446. }
  447. void BodyInterface::SetLinearVelocity(const BodyID &inBodyID, Vec3Arg inLinearVelocity)
  448. {
  449. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  450. if (lock.Succeeded())
  451. {
  452. Body &body = lock.GetBody();
  453. if (!body.IsStatic())
  454. {
  455. body.SetLinearVelocityClamped(inLinearVelocity);
  456. if (!body.IsActive() && !inLinearVelocity.IsNearZero())
  457. mBodyManager->ActivateBodies(&inBodyID, 1);
  458. }
  459. }
  460. }
  461. Vec3 BodyInterface::GetLinearVelocity(const BodyID &inBodyID) const
  462. {
  463. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  464. if (lock.Succeeded())
  465. {
  466. const Body &body = lock.GetBody();
  467. if (!body.IsStatic())
  468. return body.GetLinearVelocity();
  469. }
  470. return Vec3::sZero();
  471. }
  472. void BodyInterface::AddLinearVelocity(const BodyID &inBodyID, Vec3Arg inLinearVelocity)
  473. {
  474. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  475. if (lock.Succeeded())
  476. {
  477. Body &body = lock.GetBody();
  478. if (!body.IsStatic())
  479. {
  480. body.SetLinearVelocityClamped(body.GetLinearVelocity() + inLinearVelocity);
  481. if (!body.IsActive() && !body.GetLinearVelocity().IsNearZero())
  482. mBodyManager->ActivateBodies(&inBodyID, 1);
  483. }
  484. }
  485. }
  486. void BodyInterface::AddLinearAndAngularVelocity(const BodyID &inBodyID, Vec3Arg inLinearVelocity, Vec3Arg inAngularVelocity)
  487. {
  488. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  489. if (lock.Succeeded())
  490. {
  491. Body &body = lock.GetBody();
  492. if (!body.IsStatic())
  493. {
  494. body.SetLinearVelocityClamped(body.GetLinearVelocity() + inLinearVelocity);
  495. body.SetAngularVelocityClamped(body.GetAngularVelocity() + inAngularVelocity);
  496. if (!body.IsActive() && (!body.GetLinearVelocity().IsNearZero() || !body.GetAngularVelocity().IsNearZero()))
  497. mBodyManager->ActivateBodies(&inBodyID, 1);
  498. }
  499. }
  500. }
  501. void BodyInterface::SetAngularVelocity(const BodyID &inBodyID, Vec3Arg inAngularVelocity)
  502. {
  503. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  504. if (lock.Succeeded())
  505. {
  506. Body &body = lock.GetBody();
  507. if (!body.IsStatic())
  508. {
  509. body.SetAngularVelocityClamped(inAngularVelocity);
  510. if (!body.IsActive() && !inAngularVelocity.IsNearZero())
  511. mBodyManager->ActivateBodies(&inBodyID, 1);
  512. }
  513. }
  514. }
  515. Vec3 BodyInterface::GetAngularVelocity(const BodyID &inBodyID) const
  516. {
  517. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  518. if (lock.Succeeded())
  519. {
  520. const Body &body = lock.GetBody();
  521. if (!body.IsStatic())
  522. return body.GetAngularVelocity();
  523. }
  524. return Vec3::sZero();
  525. }
  526. Vec3 BodyInterface::GetPointVelocity(const BodyID &inBodyID, RVec3Arg inPoint) const
  527. {
  528. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  529. if (lock.Succeeded())
  530. {
  531. const Body &body = lock.GetBody();
  532. if (!body.IsStatic())
  533. return body.GetPointVelocity(inPoint);
  534. }
  535. return Vec3::sZero();
  536. }
  537. void BodyInterface::AddForce(const BodyID &inBodyID, Vec3Arg inForce)
  538. {
  539. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  540. if (lock.Succeeded())
  541. {
  542. Body &body = lock.GetBody();
  543. if (body.IsDynamic())
  544. {
  545. body.AddForce(inForce);
  546. if (!body.IsActive())
  547. mBodyManager->ActivateBodies(&inBodyID, 1);
  548. }
  549. }
  550. }
  551. void BodyInterface::AddForce(const BodyID &inBodyID, Vec3Arg inForce, RVec3Arg inPoint)
  552. {
  553. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  554. if (lock.Succeeded())
  555. {
  556. Body &body = lock.GetBody();
  557. if (body.IsDynamic())
  558. {
  559. body.AddForce(inForce, inPoint);
  560. if (!body.IsActive())
  561. mBodyManager->ActivateBodies(&inBodyID, 1);
  562. }
  563. }
  564. }
  565. void BodyInterface::AddTorque(const BodyID &inBodyID, Vec3Arg inTorque)
  566. {
  567. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  568. if (lock.Succeeded())
  569. {
  570. Body &body = lock.GetBody();
  571. if (body.IsDynamic())
  572. {
  573. body.AddTorque(inTorque);
  574. if (!body.IsActive())
  575. mBodyManager->ActivateBodies(&inBodyID, 1);
  576. }
  577. }
  578. }
  579. void BodyInterface::AddForceAndTorque(const BodyID &inBodyID, Vec3Arg inForce, Vec3Arg inTorque)
  580. {
  581. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  582. if (lock.Succeeded())
  583. {
  584. Body &body = lock.GetBody();
  585. if (body.IsDynamic())
  586. {
  587. body.AddForce(inForce);
  588. body.AddTorque(inTorque);
  589. if (!body.IsActive())
  590. mBodyManager->ActivateBodies(&inBodyID, 1);
  591. }
  592. }
  593. }
  594. void BodyInterface::AddImpulse(const BodyID &inBodyID, Vec3Arg inImpulse)
  595. {
  596. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  597. if (lock.Succeeded())
  598. {
  599. Body &body = lock.GetBody();
  600. if (body.IsDynamic())
  601. {
  602. body.AddImpulse(inImpulse);
  603. if (!body.IsActive())
  604. mBodyManager->ActivateBodies(&inBodyID, 1);
  605. }
  606. }
  607. }
  608. void BodyInterface::AddImpulse(const BodyID &inBodyID, Vec3Arg inImpulse, RVec3Arg inPoint)
  609. {
  610. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  611. if (lock.Succeeded())
  612. {
  613. Body &body = lock.GetBody();
  614. if (body.IsDynamic())
  615. {
  616. body.AddImpulse(inImpulse, inPoint);
  617. if (!body.IsActive())
  618. mBodyManager->ActivateBodies(&inBodyID, 1);
  619. }
  620. }
  621. }
  622. void BodyInterface::AddAngularImpulse(const BodyID &inBodyID, Vec3Arg inAngularImpulse)
  623. {
  624. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  625. if (lock.Succeeded())
  626. {
  627. Body &body = lock.GetBody();
  628. if (body.IsDynamic())
  629. {
  630. body.AddAngularImpulse(inAngularImpulse);
  631. if (!body.IsActive())
  632. mBodyManager->ActivateBodies(&inBodyID, 1);
  633. }
  634. }
  635. }
  636. void BodyInterface::SetPositionRotationAndVelocity(const BodyID &inBodyID, RVec3Arg inPosition, QuatArg inRotation, Vec3Arg inLinearVelocity, Vec3Arg inAngularVelocity)
  637. {
  638. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  639. if (lock.Succeeded())
  640. {
  641. Body &body = lock.GetBody();
  642. // Update the position
  643. body.SetPositionAndRotationInternal(inPosition, inRotation);
  644. // Notify broadphase of change
  645. if (body.IsInBroadPhase())
  646. {
  647. BodyID id = body.GetID();
  648. mBroadPhase->NotifyBodiesAABBChanged(&id, 1);
  649. }
  650. if (!body.IsStatic())
  651. {
  652. body.SetLinearVelocityClamped(inLinearVelocity);
  653. body.SetAngularVelocityClamped(inAngularVelocity);
  654. // Optionally activate body
  655. if (!body.IsActive() && (!inLinearVelocity.IsNearZero() || !inAngularVelocity.IsNearZero()))
  656. mBodyManager->ActivateBodies(&inBodyID, 1);
  657. }
  658. }
  659. }
  660. void BodyInterface::SetMotionType(const BodyID &inBodyID, EMotionType inMotionType, EActivation inActivationMode)
  661. {
  662. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  663. if (lock.Succeeded())
  664. {
  665. Body &body = lock.GetBody();
  666. // Deactivate if we're making the body static
  667. if (body.IsActive() && inMotionType == EMotionType::Static)
  668. mBodyManager->DeactivateBodies(&inBodyID, 1);
  669. body.SetMotionType(inMotionType);
  670. // Activate body if requested
  671. if (inMotionType != EMotionType::Static && inActivationMode == EActivation::Activate && !body.IsActive())
  672. mBodyManager->ActivateBodies(&inBodyID, 1);
  673. }
  674. }
  675. EMotionType BodyInterface::GetMotionType(const BodyID &inBodyID) const
  676. {
  677. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  678. if (lock.Succeeded())
  679. return lock.GetBody().GetMotionType();
  680. else
  681. return EMotionType::Static;
  682. }
  683. void BodyInterface::SetMotionQuality(const BodyID &inBodyID, EMotionQuality inMotionQuality)
  684. {
  685. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  686. if (lock.Succeeded())
  687. mBodyManager->SetMotionQuality(lock.GetBody(), inMotionQuality);
  688. }
  689. EMotionQuality BodyInterface::GetMotionQuality(const BodyID &inBodyID) const
  690. {
  691. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  692. if (lock.Succeeded() && !lock.GetBody().IsStatic())
  693. return lock.GetBody().GetMotionProperties()->GetMotionQuality();
  694. else
  695. return EMotionQuality::Discrete;
  696. }
  697. Mat44 BodyInterface::GetInverseInertia(const BodyID &inBodyID) const
  698. {
  699. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  700. if (lock.Succeeded())
  701. return lock.GetBody().GetInverseInertia();
  702. else
  703. return Mat44::sIdentity();
  704. }
  705. void BodyInterface::SetRestitution(const BodyID &inBodyID, float inRestitution)
  706. {
  707. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  708. if (lock.Succeeded())
  709. lock.GetBody().SetRestitution(inRestitution);
  710. }
  711. float BodyInterface::GetRestitution(const BodyID &inBodyID) const
  712. {
  713. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  714. if (lock.Succeeded())
  715. return lock.GetBody().GetRestitution();
  716. else
  717. return 0.0f;
  718. }
  719. void BodyInterface::SetFriction(const BodyID &inBodyID, float inFriction)
  720. {
  721. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  722. if (lock.Succeeded())
  723. lock.GetBody().SetFriction(inFriction);
  724. }
  725. float BodyInterface::GetFriction(const BodyID &inBodyID) const
  726. {
  727. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  728. if (lock.Succeeded())
  729. return lock.GetBody().GetFriction();
  730. else
  731. return 0.0f;
  732. }
  733. void BodyInterface::SetGravityFactor(const BodyID &inBodyID, float inGravityFactor)
  734. {
  735. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  736. if (lock.Succeeded() && lock.GetBody().GetMotionPropertiesUnchecked() != nullptr)
  737. lock.GetBody().GetMotionPropertiesUnchecked()->SetGravityFactor(inGravityFactor);
  738. }
  739. float BodyInterface::GetGravityFactor(const BodyID &inBodyID) const
  740. {
  741. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  742. if (lock.Succeeded() && lock.GetBody().GetMotionPropertiesUnchecked() != nullptr)
  743. return lock.GetBody().GetMotionPropertiesUnchecked()->GetGravityFactor();
  744. else
  745. return 1.0f;
  746. }
  747. TransformedShape BodyInterface::GetTransformedShape(const BodyID &inBodyID) const
  748. {
  749. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  750. if (lock.Succeeded())
  751. return lock.GetBody().GetTransformedShape();
  752. else
  753. return TransformedShape();
  754. }
  755. uint64 BodyInterface::GetUserData(const BodyID &inBodyID) const
  756. {
  757. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  758. if (lock.Succeeded())
  759. return lock.GetBody().GetUserData();
  760. else
  761. return 0;
  762. }
  763. const PhysicsMaterial *BodyInterface::GetMaterial(const BodyID &inBodyID, const SubShapeID &inSubShapeID) const
  764. {
  765. BodyLockRead lock(*mBodyLockInterface, inBodyID);
  766. if (lock.Succeeded())
  767. return lock.GetBody().GetShape()->GetMaterial(inSubShapeID);
  768. else
  769. return PhysicsMaterial::sDefault;
  770. }
  771. void BodyInterface::InvalidateContactCache(const BodyID &inBodyID)
  772. {
  773. BodyLockWrite lock(*mBodyLockInterface, inBodyID);
  774. if (lock.Succeeded())
  775. mBodyManager->InvalidateContactCacheForBody(lock.GetBody());
  776. }
  777. JPH_NAMESPACE_END