BodyInterface.cpp 22 KB

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