PhysicsWorld.cpp 21 KB

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