PhysicsWorld.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Physics/PhysicsWorld.h>
  6. #include <AnKi/Util/System.h>
  7. #include <AnKi/Core/StatsSet.h>
  8. #include <AnKi/Util/HighRezTimer.h>
  9. #include <AnKi/Util/Tracer.h>
  10. #include <Jolt/Renderer/DebugRendererSimple.h>
  11. #include <Jolt/ConfigurationString.h>
  12. namespace anki {
  13. static StatCounter g_physicsBodiesCreatedStatVar(StatCategory::kMisc, "Phys bodies created", StatFlag::kZeroEveryFrame);
  14. static StatCounter g_physicsJointsCreatedStatVar(StatCategory::kMisc, "Phys joints created", StatFlag::kZeroEveryFrame);
  15. static StatCounter g_physicsUpdateTimeStatVar(StatCategory::kTime, "Phys update",
  16. StatFlag::kMilisecond | StatFlag::kShowAverage | StatFlag::kMainThreadUpdates);
  17. class BroadphaseLayer
  18. {
  19. public:
  20. static constexpr JPH::BroadPhaseLayer kStatic{0};
  21. static constexpr JPH::BroadPhaseLayer kDynamic{1};
  22. static constexpr JPH::BroadPhaseLayer kDebris{2};
  23. static constexpr U32 kCount = 3;
  24. };
  25. static JPH::BroadPhaseLayer objectLayerToBroadphaseLayer(PhysicsLayer objectLayer)
  26. {
  27. switch(PhysicsLayer(objectLayer))
  28. {
  29. case PhysicsLayer::kStatic:
  30. return BroadphaseLayer::kStatic;
  31. case PhysicsLayer::kDebris:
  32. return BroadphaseLayer::kDebris;
  33. default:
  34. return BroadphaseLayer::kDynamic;
  35. }
  36. }
  37. class BPLayerInterfaceImpl final : public JPH::BroadPhaseLayerInterface
  38. {
  39. public:
  40. U32 GetNumBroadPhaseLayers() const override
  41. {
  42. return BroadphaseLayer::kCount;
  43. }
  44. JPH::BroadPhaseLayer GetBroadPhaseLayer(JPH::ObjectLayer objLayer) const override
  45. {
  46. return objectLayerToBroadphaseLayer(PhysicsLayer(objLayer));
  47. }
  48. #if defined(JPH_EXTERNAL_PROFILE) || defined(JPH_PROFILE_ENABLED)
  49. const char* GetBroadPhaseLayerName(JPH::BroadPhaseLayer inLayer) const override
  50. {
  51. if(inLayer == BroadphaseLayer::kStatic)
  52. {
  53. return "Static";
  54. }
  55. else if(inLayer == BroadphaseLayer::kDynamic)
  56. {
  57. return "Dynamic";
  58. }
  59. else
  60. {
  61. ANKI_ASSERT(inLayer == BroadphaseLayer::kDebris);
  62. return "Debris";
  63. }
  64. }
  65. #endif
  66. };
  67. // Class that determines if an object layer can collide with a broadphase layer
  68. class ObjectVsBroadPhaseLayerFilterImpl final : public JPH::ObjectVsBroadPhaseLayerFilter
  69. {
  70. public:
  71. Bool ShouldCollide(JPH::ObjectLayer layer1, JPH::BroadPhaseLayer layer2) const override
  72. {
  73. switch(PhysicsLayer(layer1))
  74. {
  75. case PhysicsLayer::kStatic:
  76. return layer2 != BroadphaseLayer::kStatic; // Static doesn't collide with static
  77. case PhysicsLayer::kDebris:
  78. return layer2 == BroadphaseLayer::kStatic; // Debris only collides with static
  79. default:
  80. return true;
  81. }
  82. }
  83. };
  84. /// Class that determines if two object layers can collide
  85. class ObjectLayerPairFilterImpl final : public JPH::ObjectLayerPairFilter
  86. {
  87. public:
  88. Bool ShouldCollide(JPH::ObjectLayer layer1, JPH::ObjectLayer layer2) const override
  89. {
  90. const PhysicsLayerBit layer1Bit = PhysicsLayerBit(1u << layer1);
  91. const PhysicsLayerBit layer2Bit = PhysicsLayerBit(1u << layer2);
  92. const PhysicsLayerBit layer1Mask = kPhysicsLayerCollisionTable[layer1];
  93. const PhysicsLayerBit layer2Mask = kPhysicsLayerCollisionTable[layer2];
  94. return !!(layer1Bit & layer2Mask) && !!(layer2Bit & layer1Mask);
  95. }
  96. };
  97. class MaskBroadPhaseLayerFilter final : public JPH::BroadPhaseLayerFilter
  98. {
  99. public:
  100. PhysicsLayerBit m_layerMask;
  101. Bool ShouldCollide(JPH::BroadPhaseLayer inLayer) const override
  102. {
  103. for(PhysicsLayer layer : EnumBitsIterable<PhysicsLayer, PhysicsLayerBit>(m_layerMask))
  104. {
  105. if(objectLayerToBroadphaseLayer(layer) == inLayer)
  106. {
  107. return true;
  108. }
  109. }
  110. return false;
  111. }
  112. };
  113. class MaskObjectLayerFilter final : public JPH::ObjectLayerFilter
  114. {
  115. public:
  116. PhysicsLayerBit m_layerMask;
  117. Bool ShouldCollide(JPH::ObjectLayer inLayer) const override
  118. {
  119. const PhysicsLayerBit inMask = PhysicsLayerBit(1u << inLayer);
  120. return !!(m_layerMask & inMask);
  121. }
  122. };
  123. class PhysicsWorld::MyBodyActivationListener final : public JPH::BodyActivationListener
  124. {
  125. public:
  126. void OnBodyActivated([[maybe_unused]] const JPH::BodyID& inBodyID, U64 bodyUserData) override
  127. {
  128. PhysicsObjectBase* base = numberToPtr<PhysicsObjectBase*>(bodyUserData);
  129. if(base->getType() == PhysicsObjectType::kBody)
  130. {
  131. static_cast<PhysicsBody*>(base)->m_activated = 1;
  132. }
  133. else
  134. {
  135. // Don't care
  136. }
  137. }
  138. void OnBodyDeactivated([[maybe_unused]] const JPH::BodyID& inBodyID, U64 bodyUserData) override
  139. {
  140. PhysicsObjectBase* base = numberToPtr<PhysicsObjectBase*>(bodyUserData);
  141. if(base->getType() == PhysicsObjectType::kBody)
  142. {
  143. static_cast<PhysicsBody*>(base)->m_activated = 0;
  144. }
  145. else
  146. {
  147. // Don't care
  148. }
  149. }
  150. };
  151. class PhysicsWorld::MyContactListener final : public JPH::ContactListener
  152. {
  153. public:
  154. void gatherObjects(U64 body1UserData, U64 body2UserData, PhysicsBody*& trigger, PhysicsObjectBase*& receiver)
  155. {
  156. trigger = nullptr;
  157. receiver = nullptr;
  158. PhysicsObjectBase* obj1 = numberToPtr<PhysicsObjectBase*>(body1UserData);
  159. PhysicsObjectBase* obj2 = numberToPtr<PhysicsObjectBase*>(body2UserData);
  160. if(!obj1 || !obj2)
  161. {
  162. // Possibly a body was removed and Jolt tried to remove the contact, that body doesn't have user data
  163. return;
  164. }
  165. if(obj1->getType() == PhysicsObjectType::kBody && static_cast<PhysicsBody*>(obj1)->m_triggerCallbacks)
  166. {
  167. ANKI_ASSERT(obj2->getType() == PhysicsObjectType::kBody || obj2->getType() == PhysicsObjectType::kPlayerController);
  168. trigger = static_cast<PhysicsBody*>(obj1);
  169. receiver = obj2;
  170. }
  171. else if(obj2->getType() == PhysicsObjectType::kBody && static_cast<PhysicsBody*>(obj2)->m_triggerCallbacks)
  172. {
  173. ANKI_ASSERT(obj1->getType() == PhysicsObjectType::kBody || obj1->getType() == PhysicsObjectType::kPlayerController);
  174. trigger = static_cast<PhysicsBody*>(obj2);
  175. receiver = obj1;
  176. }
  177. else
  178. {
  179. // Do nothing
  180. }
  181. }
  182. void OnContactAdded(const JPH::Body& inBody1, const JPH::Body& inBody2, [[maybe_unused]] const JPH::ContactManifold& inManifold,
  183. [[maybe_unused]] JPH::ContactSettings& ioSettings) override
  184. {
  185. // You can practically do nothing with the bodies so stash them
  186. PhysicsBody* trigger;
  187. PhysicsObjectBase* receiver;
  188. gatherObjects(inBody1.GetUserData(), inBody2.GetUserData(), trigger, receiver);
  189. if(!trigger)
  190. {
  191. return;
  192. }
  193. const Contact contact = {trigger, receiver};
  194. PhysicsWorld& world = PhysicsWorld::getSingleton();
  195. LockGuard lock(world.m_insertedContactsMtx);
  196. world.m_insertedContacts.emplaceBack(contact);
  197. }
  198. void OnContactRemoved(const JPH::SubShapeIDPair& pair) override
  199. {
  200. // You can practically do nothing with the bodies so stash them
  201. PhysicsWorld& world = PhysicsWorld::getSingleton();
  202. PhysicsBody* trigger;
  203. PhysicsObjectBase* receiver;
  204. gatherObjects(world.m_jphPhysicsSystem->GetBodyInterfaceNoLock().GetUserData(pair.GetBody1ID()),
  205. world.m_jphPhysicsSystem->GetBodyInterfaceNoLock().GetUserData(pair.GetBody2ID()), trigger, receiver);
  206. if(!trigger)
  207. {
  208. return;
  209. }
  210. const Contact contact = {trigger, receiver};
  211. LockGuard lock(world.m_deletedContactsMtx);
  212. world.m_deletedContacts.emplaceBack(contact);
  213. }
  214. };
  215. // Globals
  216. static BPLayerInterfaceImpl g_bPLayerInterfaceImpl;
  217. static ObjectVsBroadPhaseLayerFilterImpl g_objectVsBroadPhaseLayerFilterImpl;
  218. static ObjectLayerPairFilterImpl g_objectLayerPairFilterImpl;
  219. PhysicsWorld::MyBodyActivationListener PhysicsWorld::m_bodyActivationListener;
  220. PhysicsWorld::MyContactListener PhysicsWorld::m_contactListener;
  221. void PhysicsCollisionShapePtrDeleter::operator()(PhysicsCollisionShape* ptr)
  222. {
  223. ANKI_ASSERT(ptr);
  224. PhysicsWorld& world = PhysicsWorld::getSingleton();
  225. LockGuard lock(world.m_collisionShapes.m_mtx);
  226. world.m_collisionShapes.m_array.erase(ptr->m_blockArrayIndex);
  227. }
  228. void PhysicsBodyPtrDeleter::operator()(PhysicsBody* ptr)
  229. {
  230. ANKI_ASSERT(ptr);
  231. PhysicsWorld& world = PhysicsWorld::getSingleton();
  232. world.m_jphPhysicsSystem->GetBodyInterface().RemoveBody(ptr->m_jphBody->GetID());
  233. world.m_jphPhysicsSystem->GetBodyInterface().DestroyBody(ptr->m_jphBody->GetID());
  234. LockGuard lock(world.m_bodies.m_mtx);
  235. world.m_bodies.m_array.erase(ptr->m_blockArrayIndex);
  236. world.m_optimizeBroadphase = true;
  237. }
  238. void PhysicsJointPtrDeleter::operator()(PhysicsJoint* ptr)
  239. {
  240. ANKI_ASSERT(ptr);
  241. PhysicsWorld& world = PhysicsWorld::getSingleton();
  242. world.m_jphPhysicsSystem->RemoveConstraint(&(*ptr->m_base));
  243. LockGuard lock(world.m_joints.m_mtx);
  244. world.m_joints.m_array.erase(ptr->m_blockArrayIndex);
  245. }
  246. void PhysicsPlayerControllerPtrDeleter::operator()(PhysicsPlayerController* ptr)
  247. {
  248. ANKI_ASSERT(ptr);
  249. PhysicsWorld& world = PhysicsWorld::getSingleton();
  250. LockGuard lock(world.m_characters.m_mtx);
  251. world.m_characters.m_array.erase(ptr->m_blockArrayIndex);
  252. }
  253. class PhysicsWorld::MyDebugRenderer final : public JPH::DebugRendererSimple
  254. {
  255. public:
  256. PhysicsDebugDrawerInterface* m_interface = nullptr;
  257. void DrawLine(JPH::RVec3Arg inFrom, JPH::RVec3Arg inTo, JPH::ColorArg inColor) override
  258. {
  259. const Array<Vec3, 2> line = {toAnKi(inFrom), toAnKi(inTo)};
  260. m_interface->drawLines(line, {inColor.r, inColor.g, inColor.b, inColor.a});
  261. }
  262. void DrawTriangle(JPH::RVec3Arg inV1, JPH::RVec3Arg inV2, JPH::RVec3Arg inV3, JPH::ColorArg inColor,
  263. [[maybe_unused]] ECastShadow inCastShadow) override
  264. {
  265. Array<Vec3, 6> line = {toAnKi(inV1), toAnKi(inV2), toAnKi(inV2), toAnKi(inV3), toAnKi(inV3), toAnKi(inV1)};
  266. m_interface->drawLines(line, {inColor.r, inColor.g, inColor.b, inColor.a});
  267. }
  268. void DrawText3D([[maybe_unused]] JPH::RVec3Arg inPosition, [[maybe_unused]] const std::string_view& inString,
  269. [[maybe_unused]] JPH::ColorArg inColor, [[maybe_unused]] F32 inHeight) override
  270. {
  271. // Nothing for now
  272. }
  273. };
  274. PhysicsWorld::PhysicsWorld()
  275. {
  276. }
  277. PhysicsWorld::~PhysicsWorld()
  278. {
  279. ANKI_ASSERT(m_collisionShapes.m_array.getSize() == 0);
  280. ANKI_ASSERT(m_bodies.m_array.getSize() == 0);
  281. ANKI_ASSERT(m_joints.m_array.getSize() == 0);
  282. ANKI_ASSERT(m_characters.m_array.getSize() == 0);
  283. m_jobSystem.destroy();
  284. m_jphPhysicsSystem.destroy();
  285. m_tempAllocator.destroy();
  286. JPH::UnregisterTypes();
  287. delete JPH::Factory::sInstance;
  288. JPH::Factory::sInstance = nullptr;
  289. PhysicsMemoryPool::freeSingleton();
  290. }
  291. Error PhysicsWorld::init(AllocAlignedCallback allocCb, void* allocCbData)
  292. {
  293. ANKI_PHYS_LOGI("Initializing physics. Jolt config: %s", JPH::GetConfigurationString());
  294. PhysicsMemoryPool::allocateSingleton(allocCb, allocCbData);
  295. JPH::Allocate = [](PtrSize size) -> void* {
  296. return PhysicsMemoryPool::getSingleton().allocate(size, 16);
  297. };
  298. JPH::Reallocate = []([[maybe_unused]] void* in, [[maybe_unused]] PtrSize oldSize, PtrSize newSize) -> void* {
  299. void* out;
  300. if(newSize > 0)
  301. {
  302. out = PhysicsMemoryPool::getSingleton().allocate(newSize, 16);
  303. }
  304. else
  305. {
  306. out = nullptr;
  307. }
  308. if(in && out)
  309. {
  310. ANKI_ASSERT(oldSize > 0 && newSize > 0);
  311. memcpy(out, in, min(oldSize, newSize));
  312. }
  313. PhysicsMemoryPool::getSingleton().free(in);
  314. return out;
  315. };
  316. JPH::Free = [](void* ptr) {
  317. PhysicsMemoryPool::getSingleton().free(ptr);
  318. };
  319. JPH::AlignedAllocate = [](PtrSize size, PtrSize alignment) -> void* {
  320. return PhysicsMemoryPool::getSingleton().allocate(size, alignment);
  321. };
  322. JPH::AlignedFree = [](void* ptr) {
  323. PhysicsMemoryPool::getSingleton().free(ptr);
  324. };
  325. #if ANKI_ASSERTIONS_ENABLED
  326. JPH::AssertFailed = [](const Char* inExpression, [[maybe_unused]] const Char* inMessage, const Char* inFile, U32 inLine) -> Bool {
  327. Logger::getSingleton().write(inFile, inLine, "?", "JOLT", LoggerMessageType::kFatal, "?", inExpression);
  328. return true;
  329. };
  330. #endif
  331. JPH::Factory::sInstance = new JPH::Factory();
  332. JPH::RegisterTypes();
  333. m_jphPhysicsSystem.construct();
  334. constexpr U32 maxBodies = kMaxU16;
  335. constexpr U32 mutexCount = 0;
  336. constexpr U32 maxBodyPairs = kMaxU16;
  337. constexpr U32 maxConstraints = 10 * 1024;
  338. m_jphPhysicsSystem->Init(maxBodies, mutexCount, maxBodyPairs, maxConstraints, g_bPLayerInterfaceImpl, g_objectVsBroadPhaseLayerFilterImpl,
  339. g_objectLayerPairFilterImpl);
  340. m_jphPhysicsSystem->SetGravity(toJPH(Vec3(0.0f, -9.81f, 0.0f)));
  341. m_jphPhysicsSystem->SetBodyActivationListener(&m_bodyActivationListener);
  342. m_jphPhysicsSystem->SetContactListener(&m_contactListener);
  343. const U32 threadCount = min(8u, getCpuCoresCount() - 1);
  344. m_jobSystem.construct(JPH::cMaxPhysicsJobs, JPH::cMaxPhysicsBarriers, threadCount);
  345. m_tempAllocator.construct(U32(10_MB));
  346. return Error::kNone;
  347. }
  348. void PhysicsWorld::update(Second dt)
  349. {
  350. ANKI_TRACE_SCOPED_EVENT(Physics);
  351. #if ANKI_STATS_ENABLED
  352. const Second startTime = HighRezTimer::getCurrentTime();
  353. #endif
  354. // Pre-update work
  355. {
  356. for(PhysicsPlayerController& charController : m_characters.m_array)
  357. {
  358. charController.prePhysicsUpdate(dt);
  359. }
  360. if(m_optimizeBroadphase)
  361. {
  362. m_optimizeBroadphase = false;
  363. m_jphPhysicsSystem->OptimizeBroadPhase();
  364. }
  365. }
  366. constexpr I32 collisionSteps = 2;
  367. m_jphPhysicsSystem->Update(F32(dt), collisionSteps, &m_tempAllocator, &m_jobSystem);
  368. // Post-update work
  369. {
  370. for(PhysicsBody& body : m_bodies.m_array)
  371. {
  372. body.postPhysicsUpdate();
  373. }
  374. for(PhysicsPlayerController& charController : m_characters.m_array)
  375. {
  376. charController.postPhysicsUpdate();
  377. }
  378. for(Contact& contact : m_insertedContacts)
  379. {
  380. contact.m_trigger->m_triggerCallbacks->onTriggerEnter(*contact.m_trigger, *contact.m_receiver);
  381. }
  382. m_insertedContacts.destroy();
  383. for(Contact& contact : m_deletedContacts)
  384. {
  385. contact.m_trigger->m_triggerCallbacks->onTriggerExit(*contact.m_trigger, *contact.m_receiver);
  386. }
  387. m_deletedContacts.destroy();
  388. }
  389. #if ANKI_STATS_ENABLED
  390. g_physicsUpdateTimeStatVar.set((HighRezTimer::getCurrentTime() - startTime) * 1000.0);
  391. #endif
  392. }
  393. template<typename TJPHCollisionShape, typename... TArgs>
  394. PhysicsCollisionShapePtr PhysicsWorld::newCollisionShape(TArgs&&... args)
  395. {
  396. typename decltype(m_collisionShapes.m_array)::Iterator it;
  397. {
  398. LockGuard lock(m_collisionShapes.m_mtx);
  399. it = m_collisionShapes.m_array.emplace();
  400. }
  401. ClassWrapper<TJPHCollisionShape>& classw = reinterpret_cast<ClassWrapper<TJPHCollisionShape>&>(it->m_shapeBase);
  402. classw.construct(std::forward<TArgs>(args)...);
  403. classw->SetEmbedded();
  404. it->setBlockArrayIndex(it.getArrayIndex());
  405. return PhysicsCollisionShapePtr(&(*it));
  406. }
  407. PhysicsCollisionShapePtr PhysicsWorld::newSphereCollisionShape(F32 radius)
  408. {
  409. return newCollisionShape<JPH::SphereShape>(radius);
  410. }
  411. PhysicsCollisionShapePtr PhysicsWorld::newBoxCollisionShape(Vec3 extend)
  412. {
  413. return newCollisionShape<JPH::BoxShape>(toJPH(extend));
  414. }
  415. PhysicsCollisionShapePtr PhysicsWorld::newCapsuleCollisionShape(F32 height, F32 radius)
  416. {
  417. return newCollisionShape<JPH::CapsuleShape>(height / 2.0f, radius);
  418. }
  419. PhysicsCollisionShapePtr PhysicsWorld::newConvexHullShape(ConstWeakArray<Vec3> positions)
  420. {
  421. JPH::Array<JPH::Vec3> verts;
  422. verts.resize(positions.getSize());
  423. for(U32 i = 0; i < positions.getSize(); ++i)
  424. {
  425. verts[i] = toJPH(positions[i]);
  426. }
  427. JPH::ConvexHullShapeSettings settings(std::move(verts));
  428. settings.SetEmbedded();
  429. JPH::Shape::ShapeResult outResult;
  430. PhysicsCollisionShapePtr out = newCollisionShape<JPH::ConvexHullShape>(settings, outResult);
  431. ANKI_ASSERT(outResult.IsValid());
  432. return out;
  433. }
  434. PhysicsCollisionShapePtr PhysicsWorld::newStaticMeshShape(ConstWeakArray<Vec3> positions, ConstWeakArray<U32> indices)
  435. {
  436. ANKI_ASSERT(positions.getSize() && indices.getSize() && indices.getSize() % 3 == 0);
  437. JPH::VertexList verts;
  438. verts.resize(positions.getSize());
  439. for(U32 i = 0; i < positions.getSize(); ++i)
  440. {
  441. verts[i] = {positions[i].x(), positions[i].y(), positions[i].z()};
  442. }
  443. JPH::IndexedTriangleList idx;
  444. idx.resize(indices.getSize() / 3);
  445. for(U32 i = 0; i < indices.getSize(); i += 3)
  446. {
  447. const U32 material = 0;
  448. idx[i / 3] = JPH::IndexedTriangle(indices[i], indices[i + 1], indices[i + 2], material);
  449. }
  450. JPH::MeshShapeSettings settings(std::move(verts), std::move(idx));
  451. settings.SetEmbedded();
  452. JPH::Shape::ShapeResult outResult;
  453. PhysicsCollisionShapePtr out = newCollisionShape<JPH::MeshShape>(settings, outResult);
  454. ANKI_ASSERT(outResult.IsValid());
  455. return out;
  456. }
  457. PhysicsCollisionShapePtr PhysicsWorld::newScaleCollisionObject(const Vec3& scale, PhysicsCollisionShape* baseShape)
  458. {
  459. return newCollisionShape<JPH::ScaledShape>(&baseShape->m_shapeBase, toJPH(scale));
  460. }
  461. PhysicsBodyPtr PhysicsWorld::newPhysicsBody(const PhysicsBodyInitInfo& init)
  462. {
  463. g_physicsBodiesCreatedStatVar.increment(1);
  464. PhysicsBody* newBody;
  465. {
  466. LockGuard lock(m_bodies.m_mtx);
  467. m_optimizeBroadphase = true;
  468. auto it = m_bodies.m_array.emplace();
  469. newBody = &(*it);
  470. newBody->setBlockArrayIndex(it.getArrayIndex());
  471. }
  472. newBody->init(init);
  473. return PhysicsBodyPtr(newBody);
  474. }
  475. template<typename TJPHJoint, typename... TArgs>
  476. PhysicsJointPtr PhysicsWorld::newJoint(PhysicsBody* body1, PhysicsBody* body2, TArgs&&... args)
  477. {
  478. ANKI_ASSERT(body1 && body2);
  479. g_physicsJointsCreatedStatVar.increment(1);
  480. typename decltype(m_joints.m_array)::Iterator it;
  481. {
  482. LockGuard lock(m_joints.m_mtx);
  483. it = m_joints.m_array.emplace();
  484. }
  485. ClassWrapper<TJPHJoint>& classw = reinterpret_cast<ClassWrapper<TJPHJoint>&>(it->m_base);
  486. classw.construct(*body1->m_jphBody, *body2->m_jphBody, std::forward<TArgs>(args)...);
  487. classw->SetEmbedded();
  488. it->m_body1.reset(body1);
  489. it->m_body2.reset(body2);
  490. it->setBlockArrayIndex(it.getArrayIndex());
  491. m_jphPhysicsSystem->AddConstraint(&it->m_base); // It's thread-safe
  492. return PhysicsJointPtr(&(*it));
  493. }
  494. PhysicsJointPtr PhysicsWorld::newPointJoint(PhysicsBody* body1, PhysicsBody* body2, const Vec3& pivot)
  495. {
  496. ANKI_ASSERT(body1 && body2);
  497. JPH::PointConstraintSettings settings;
  498. settings.SetEmbedded();
  499. settings.mPoint1 = settings.mPoint2 = toJPH(pivot);
  500. return newJoint<JPH::PointConstraint>(body1, body2, settings);
  501. }
  502. PhysicsJointPtr PhysicsWorld::newHingeJoint(PhysicsBody* body1, PhysicsBody* body2, const Transform& pivot)
  503. {
  504. ANKI_ASSERT(body1 && body2);
  505. JPH::HingeConstraintSettings settings;
  506. settings.SetEmbedded();
  507. settings.mPoint1 = settings.mPoint2 = toJPH(pivot.getOrigin().xyz());
  508. settings.mHingeAxis1 = settings.mHingeAxis2 = toJPH(pivot.getRotation().getXAxis());
  509. settings.mNormalAxis1 = settings.mNormalAxis2 = toJPH(pivot.getRotation().getYAxis());
  510. return newJoint<JPH::HingeConstraint>(body1, body2, settings);
  511. }
  512. PhysicsPlayerControllerPtr PhysicsWorld::newPlayerController(const PhysicsPlayerControllerInitInfo& init)
  513. {
  514. PhysicsPlayerController* newChar;
  515. {
  516. LockGuard lock(m_characters.m_mtx);
  517. auto it = m_characters.m_array.emplace();
  518. newChar = &(*it);
  519. newChar->setBlockArrayIndex(it.getArrayIndex());
  520. }
  521. newChar->init(init);
  522. return PhysicsPlayerControllerPtr(newChar);
  523. }
  524. RayHitResult PhysicsWorld::jphToAnKi(const JPH::RRayCast& ray, const JPH::RayCastResult& hit)
  525. {
  526. RayHitResult result;
  527. const JPH::RVec3 hitPosJph = ray.GetPointOnRay(hit.mFraction);
  528. result.m_hitPosition = toAnKi(hitPosJph);
  529. const U64 userData = m_jphPhysicsSystem->GetBodyInterfaceNoLock().GetUserData(hit.mBodyID);
  530. result.m_object = numberToPtr<PhysicsObjectBase*>(userData);
  531. JPH::BodyLockRead lock(m_jphPhysicsSystem->GetBodyLockInterfaceNoLock(), hit.mBodyID);
  532. if(lock.Succeeded())
  533. {
  534. result.m_normal = toAnKi(lock.GetBody().GetWorldSpaceSurfaceNormal(hit.mSubShapeID2, hitPosJph));
  535. }
  536. return result;
  537. }
  538. Bool PhysicsWorld::castRayClosestHit(const Vec3& rayStart, const Vec3& rayEnd, PhysicsLayerBit layers, RayHitResult& result)
  539. {
  540. MaskBroadPhaseLayerFilter broadphaseFilter;
  541. broadphaseFilter.m_layerMask = layers;
  542. MaskObjectLayerFilter objectFilter;
  543. objectFilter.m_layerMask = layers;
  544. JPH::RRayCast ray;
  545. ray.mOrigin = toJPH(rayStart);
  546. ray.mDirection = toJPH(rayEnd - rayStart); // Not exactly a direction if it's not normalized but anyway
  547. JPH::RayCastResult hit;
  548. const Bool success = m_jphPhysicsSystem->GetNarrowPhaseQueryNoLock().CastRay(ray, hit, broadphaseFilter, objectFilter);
  549. if(success)
  550. {
  551. result = jphToAnKi(ray, hit);
  552. }
  553. else
  554. {
  555. result = {};
  556. }
  557. return success;
  558. }
  559. Bool PhysicsWorld::castRayAllHitsInternal(const Vec3& rayStart, const Vec3& rayEnd, PhysicsLayerBit layers,
  560. PhysicsDynamicArray<RayHitResult>& results)
  561. {
  562. MaskBroadPhaseLayerFilter broadphaseFilter;
  563. broadphaseFilter.m_layerMask = layers;
  564. MaskObjectLayerFilter objectFilter;
  565. objectFilter.m_layerMask = layers;
  566. JPH::RRayCast ray;
  567. ray.mOrigin = toJPH(rayStart);
  568. ray.mDirection = toJPH(rayEnd - rayStart); // Not exactly a direction if it's not normalized but anyway
  569. JPH::RayCastResult hit;
  570. JPH::RayCastSettings settings;
  571. class MyCastRayCollector final : public JPH::CastRayCollector
  572. {
  573. public:
  574. PhysicsDynamicArray<RayHitResult>* m_resArray;
  575. JPH::RRayCast m_ray;
  576. PhysicsWorld* m_world;
  577. void AddHit(const JPH::RayCastResult& hit) override
  578. {
  579. const RayHitResult result = m_world->jphToAnKi(m_ray, hit);
  580. m_resArray->emplaceBack(result);
  581. }
  582. } collector;
  583. collector.m_resArray = &results;
  584. collector.m_ray = ray;
  585. collector.m_world = this;
  586. m_jphPhysicsSystem->GetNarrowPhaseQueryNoLock().CastRay(ray, settings, collector, broadphaseFilter, objectFilter);
  587. return results.getSize() > 0;
  588. }
  589. void PhysicsWorld::debugDraw(PhysicsDebugDrawerInterface& interface)
  590. {
  591. MyDebugRenderer renderer;
  592. renderer.m_interface = &interface;
  593. JPH::BodyManager::DrawSettings settings;
  594. settings.mDrawShapeWireframe = true;
  595. m_jphPhysicsSystem->DrawBodies(settings, &renderer);
  596. m_jphPhysicsSystem->DrawConstraints(&renderer);
  597. }
  598. } // end namespace anki