PhysicsWorld.cpp 21 KB

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