BsPhysX.cpp 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063
  1. #include "BsPhysX.h"
  2. #include "PxPhysicsAPI.h"
  3. #include "BsPhysXMaterial.h"
  4. #include "BsPhysXMesh.h"
  5. #include "BsPhysXRigidbody.h"
  6. #include "BsPhysXBoxCollider.h"
  7. #include "BsPhysXSphereCollider.h"
  8. #include "BsPhysXPlaneCollider.h"
  9. #include "BsPhysXCapsuleCollider.h"
  10. #include "BsPhysXMeshCollider.h"
  11. #include "BsPhysXFixedJoint.h"
  12. #include "BsPhysXDistanceJoint.h"
  13. #include "BsPhysXHingeJoint.h"
  14. #include "BsPhysXSphericalJoint.h"
  15. #include "BsPhysXSliderJoint.h"
  16. #include "BsPhysXD6Joint.h"
  17. #include "BsPhysXCharacterController.h"
  18. #include "BsTaskScheduler.h"
  19. #include "BsCCollider.h"
  20. #include "BsTime.h"
  21. #include "Bsvector3.h"
  22. #include "BsAABox.h"
  23. #include "BsCapsule.h"
  24. #include "foundation\PxTransform.h"
  25. using namespace physx;
  26. namespace BansheeEngine
  27. {
  28. class PhysXAllocator : public PxAllocatorCallback
  29. {
  30. public:
  31. void* allocate(size_t size, const char*, const char*, int) override
  32. {
  33. void* ptr = bs_alloc_aligned16((UINT32)size);
  34. PX_ASSERT((reinterpret_cast<size_t>(ptr) & 15) == 0);
  35. return ptr;
  36. }
  37. void deallocate(void* ptr) override
  38. {
  39. bs_free_aligned16(ptr);
  40. }
  41. };
  42. class PhysXErrorCallback : public PxErrorCallback
  43. {
  44. public:
  45. void reportError(PxErrorCode::Enum code, const char* message, const char* file, int line) override
  46. {
  47. {
  48. const char* errorCode = nullptr;
  49. UINT32 severity = 0;
  50. switch (code)
  51. {
  52. case PxErrorCode::eNO_ERROR:
  53. errorCode = "No error";
  54. break;
  55. case PxErrorCode::eINVALID_PARAMETER:
  56. errorCode = "Invalid parameter";
  57. severity = 2;
  58. break;
  59. case PxErrorCode::eINVALID_OPERATION:
  60. errorCode = "Invalid operation";
  61. severity = 2;
  62. break;
  63. case PxErrorCode::eOUT_OF_MEMORY:
  64. errorCode = "Out of memory";
  65. severity = 2;
  66. break;
  67. case PxErrorCode::eDEBUG_INFO:
  68. errorCode = "Info";
  69. break;
  70. case PxErrorCode::eDEBUG_WARNING:
  71. errorCode = "Warning";
  72. severity = 1;
  73. break;
  74. case PxErrorCode::ePERF_WARNING:
  75. errorCode = "Performance warning";
  76. severity = 1;
  77. break;
  78. case PxErrorCode::eABORT:
  79. errorCode = "Abort";
  80. severity = 2;
  81. break;
  82. case PxErrorCode::eINTERNAL_ERROR:
  83. errorCode = "Internal error";
  84. severity = 2;
  85. break;
  86. case PxErrorCode::eMASK_ALL:
  87. default:
  88. errorCode = "Unknown error";
  89. severity = 2;
  90. break;
  91. }
  92. StringStream ss;
  93. switch(severity)
  94. {
  95. case 0:
  96. ss << "PhysX info (" << errorCode << "): " << message << " at " << file << ":" << line;
  97. LOGDBG(ss.str());
  98. break;
  99. case 1:
  100. ss << "PhysX warning (" << errorCode << "): " << message << " at " << file << ":" << line;
  101. LOGWRN(ss.str());
  102. break;
  103. case 2:
  104. ss << "PhysX error (" << errorCode << "): " << message << " at " << file << ":" << line;
  105. LOGERR(ss.str());
  106. BS_ASSERT(false); // Halt execution on debug builds when error occurrs
  107. break;
  108. }
  109. }
  110. }
  111. };
  112. class PhysXEventCallback : public PxSimulationEventCallback
  113. {
  114. void onWake(PxActor** actors, PxU32 count) override { /* Do nothing */ }
  115. void onSleep(PxActor** actors, PxU32 count) override { /* Do nothing */ }
  116. void onTrigger(PxTriggerPair* pairs, PxU32 count) override
  117. {
  118. for (PxU32 i = 0; i < count; i++)
  119. {
  120. const PxTriggerPair& pair = pairs[i];
  121. PhysX::ContactEventType type;
  122. bool ignoreContact = false;
  123. switch ((UINT32)pair.status)
  124. {
  125. case PxPairFlag::eNOTIFY_TOUCH_FOUND:
  126. type = PhysX::ContactEventType::ContactBegin;
  127. break;
  128. case PxPairFlag::eNOTIFY_TOUCH_PERSISTS:
  129. type = PhysX::ContactEventType::ContactStay;
  130. break;
  131. case PxPairFlag::eNOTIFY_TOUCH_LOST:
  132. type = PhysX::ContactEventType::ContactEnd;
  133. break;
  134. default:
  135. ignoreContact = true;
  136. break;
  137. }
  138. if (ignoreContact)
  139. continue;
  140. PhysX::TriggerEvent event;
  141. event.trigger = (Collider*)pair.triggerShape->userData;
  142. event.other = (Collider*)pair.otherShape->userData;
  143. event.type = type;
  144. gPhysX()._reportTriggerEvent(event);
  145. }
  146. }
  147. void onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, PxU32 count) override
  148. {
  149. for (PxU32 i = 0; i < count; i++)
  150. {
  151. const PxContactPair& pair = pairs[i];
  152. PhysX::ContactEventType type;
  153. bool ignoreContact = false;
  154. switch((UINT32)pair.events)
  155. {
  156. case PxPairFlag::eNOTIFY_TOUCH_FOUND:
  157. type = PhysX::ContactEventType::ContactBegin;
  158. break;
  159. case PxPairFlag::eNOTIFY_TOUCH_PERSISTS:
  160. type = PhysX::ContactEventType::ContactStay;
  161. break;
  162. case PxPairFlag::eNOTIFY_TOUCH_LOST:
  163. type = PhysX::ContactEventType::ContactEnd;
  164. break;
  165. default:
  166. ignoreContact = true;
  167. break;
  168. }
  169. if (ignoreContact)
  170. continue;
  171. PhysX::ContactEvent event;
  172. event.colliderA = (Collider*)pair.shapes[0]->userData;
  173. event.colliderB = (Collider*)pair.shapes[1]->userData;
  174. event.type = type;
  175. PxU32 contactCount = pair.contactCount;
  176. const PxU8* stream = pair.contactStream;
  177. PxU16 streamSize = pair.contactStreamSize;
  178. if (contactCount > 0 && streamSize > 0)
  179. {
  180. PxU32 contactIdx = 0;
  181. PxContactStreamIterator iter((PxU8*)stream, streamSize);
  182. stream += ((streamSize + 15) & ~15);
  183. const PxReal* impulses = reinterpret_cast<const PxReal*>(stream);
  184. PxU32 hasImpulses = (pair.flags & PxContactPairFlag::eINTERNAL_HAS_IMPULSES);
  185. while (iter.hasNextPatch())
  186. {
  187. iter.nextPatch();
  188. while (iter.hasNextContact())
  189. {
  190. iter.nextContact();
  191. ContactPoint point;
  192. point.position = fromPxVector(iter.getContactPoint());
  193. point.separation = iter.getSeparation();
  194. point.normal = fromPxVector(iter.getContactNormal());
  195. if (hasImpulses)
  196. point.impulse = impulses[contactIdx];
  197. else
  198. point.impulse = 0.0f;
  199. event.points.push_back(point);
  200. contactIdx++;
  201. }
  202. }
  203. }
  204. gPhysX()._reportContactEvent(event);
  205. }
  206. }
  207. void onConstraintBreak(PxConstraintInfo* constraints, PxU32 count) override
  208. {
  209. for (UINT32 i = 0; i < count; i++)
  210. {
  211. PxConstraintInfo& constraintInfo = constraints[i];
  212. if (constraintInfo.type != PxConstraintExtIDs::eJOINT)
  213. continue;
  214. PxJoint* pxJoint = (PxJoint*)constraintInfo.externalReference;
  215. Joint* joint = (Joint*)pxJoint->userData;
  216. }
  217. }
  218. };
  219. class PhysXCPUDispatcher : public PxCpuDispatcher
  220. {
  221. public:
  222. void submitTask(PxBaseTask& physxTask) override
  223. {
  224. // Note: Banshee's task scheduler is pretty low granularity. Consider a better task manager in case PhysX ends
  225. // up submitting many tasks.
  226. // - PhysX's task manager doesn't seem much lighter either. But perhaps I can at least create a task pool to
  227. // avoid allocating them constantly.
  228. auto runTask = [&]() { physxTask.run(); physxTask.release(); };
  229. TaskPtr task = Task::create("PhysX", runTask);
  230. TaskScheduler::instance().addTask(task);
  231. }
  232. PxU32 getWorkerCount() const override
  233. {
  234. return (PxU32)TaskScheduler::instance().getNumWorkers();
  235. }
  236. };
  237. class PhysXBroadPhaseCallback : public PxBroadPhaseCallback
  238. {
  239. void onObjectOutOfBounds(PxShape& shape, PxActor& actor) override
  240. {
  241. Collider* collider = (Collider*)shape.userData;
  242. if (collider != nullptr)
  243. LOGWRN("Physics object out of bounds. Consider increasing broadphase region!");
  244. }
  245. void onObjectOutOfBounds(PxAggregate& aggregate) override { /* Do nothing */ }
  246. };
  247. PxFilterFlags PhysXFilterShader(PxFilterObjectAttributes attr0, PxFilterData data0, PxFilterObjectAttributes attr1,
  248. PxFilterData data1, PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize)
  249. {
  250. if (PxFilterObjectIsTrigger(attr0) || PxFilterObjectIsTrigger(attr1))
  251. {
  252. pairFlags = PxPairFlag::eTRIGGER_DEFAULT;
  253. return PxFilterFlags();
  254. }
  255. UINT64 groupA = *(UINT64*)&data0.word0;
  256. UINT64 groupB = *(UINT64*)&data1.word0;
  257. bool canCollide = gPhysics().isCollisionEnabled(groupA, groupB);
  258. if (!canCollide)
  259. return PxFilterFlag::eSUPPRESS;
  260. pairFlags = PxPairFlag::eCONTACT_DEFAULT;
  261. return PxFilterFlags();
  262. }
  263. void parseHit(const PxRaycastHit& input, PhysicsQueryHit& output)
  264. {
  265. output.point = fromPxVector(input.position);
  266. output.normal = fromPxVector(input.normal);
  267. output.distance = input.distance;
  268. output.triangleIdx = input.faceIndex;
  269. output.uv = Vector2(input.u, input.v);
  270. output.colliderRaw = (Collider*)input.shape->userData;
  271. if (output.colliderRaw != nullptr)
  272. {
  273. CCollider* component = (CCollider*)output.colliderRaw->_getOwner(PhysicsOwnerType::Component);
  274. if (component != nullptr)
  275. output.collider = component->getHandle();
  276. }
  277. }
  278. void parseHit(const PxSweepHit& input, PhysicsQueryHit& output)
  279. {
  280. output.point = fromPxVector(input.position);
  281. output.normal = fromPxVector(input.normal);
  282. output.distance = input.distance;
  283. output.triangleIdx = input.faceIndex;
  284. output.colliderRaw = (Collider*)input.shape->userData;
  285. if (output.colliderRaw != nullptr)
  286. {
  287. CCollider* component = (CCollider*)output.colliderRaw->_getOwner(PhysicsOwnerType::Component);
  288. if (component != nullptr)
  289. output.collider = component->getHandle();
  290. }
  291. }
  292. struct PhysXRaycastQueryCallback : PxRaycastCallback
  293. {
  294. Vector<PhysicsQueryHit> data;
  295. PhysXRaycastQueryCallback()
  296. :PxRaycastCallback(nullptr, 0)
  297. { }
  298. PxAgain processTouches(const PxRaycastHit* buffer, PxU32 nbHits) override
  299. {
  300. for (PxU32 i = 0; i < nbHits; i++)
  301. {
  302. data.push_back(PhysicsQueryHit());
  303. parseHit(buffer[i], data.back());
  304. }
  305. return true;
  306. }
  307. };
  308. struct PhysXSweepQueryCallback : PxSweepCallback
  309. {
  310. Vector<PhysicsQueryHit> data;
  311. PhysXSweepQueryCallback()
  312. :PxSweepCallback(nullptr, 0)
  313. { }
  314. PxAgain processTouches(const PxSweepHit* buffer, PxU32 nbHits) override
  315. {
  316. for (PxU32 i = 0; i < nbHits; i++)
  317. {
  318. data.push_back(PhysicsQueryHit());
  319. parseHit(buffer[i], data.back());
  320. }
  321. return true;
  322. }
  323. };
  324. struct PhysXOverlapQueryCallback : PxOverlapCallback
  325. {
  326. Vector<Collider*> data;
  327. PhysXOverlapQueryCallback()
  328. :PxOverlapCallback(nullptr, 0)
  329. { }
  330. PxAgain processTouches(const PxOverlapHit* buffer, PxU32 nbHits) override
  331. {
  332. for (PxU32 i = 0; i < nbHits; i++)
  333. data.push_back((Collider*)buffer[i].shape->userData);
  334. return true;
  335. }
  336. };
  337. static PhysXAllocator gPhysXAllocator;
  338. static PhysXErrorCallback gPhysXErrorHandler;
  339. static PhysXCPUDispatcher gPhysXCPUDispatcher;
  340. static PhysXEventCallback gPhysXEventCallback;
  341. static PhysXBroadPhaseCallback gPhysXBroadphaseCallback;
  342. PhysX::PhysX(const PHYSICS_INIT_DESC& input)
  343. :Physics(input)
  344. {
  345. mScale.length = input.typicalLength;
  346. mScale.speed = input.typicalSpeed;
  347. mFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gPhysXAllocator, gPhysXErrorHandler);
  348. mPhysics = PxCreateBasePhysics(PX_PHYSICS_VERSION, *mFoundation, mScale);
  349. PxRegisterArticulations(*mPhysics);
  350. if (input.initCooking)
  351. {
  352. // Note: PhysX supports cooking for specific platforms to make the generated results better. Consider
  353. // allowing the meshes to be re-cooked when target platform is changed. Right now we just use the default value.
  354. PxCookingParams cookingParams(mScale);
  355. mCooking = PxCreateCooking(PX_PHYSICS_VERSION, *mFoundation, cookingParams);
  356. }
  357. PxSceneDesc sceneDesc(mScale); // TODO - Test out various other parameters provided by scene desc
  358. sceneDesc.gravity = toPxVector(input.gravity);
  359. sceneDesc.cpuDispatcher = &gPhysXCPUDispatcher;
  360. sceneDesc.filterShader = PhysXFilterShader;
  361. sceneDesc.simulationEventCallback = &gPhysXEventCallback;
  362. sceneDesc.broadPhaseCallback = &gPhysXBroadphaseCallback;
  363. // Optionally: eENABLE_CCD, eENABLE_KINEMATIC_STATIC_PAIRS, eENABLE_KINEMATIC_PAIRS, eENABLE_PCM
  364. sceneDesc.flags = PxSceneFlag::eENABLE_ACTIVETRANSFORMS;
  365. // Optionally: eMBP
  366. sceneDesc.broadPhaseType = PxBroadPhaseType::eSAP;
  367. mScene = mPhysics->createScene(sceneDesc);
  368. // Character controller
  369. mCharManager = PxCreateControllerManager(*mScene);
  370. mSimulationStep = input.timeStep;
  371. mDefaultMaterial = mPhysics->createMaterial(0.0f, 0.0f, 0.0f);
  372. }
  373. PhysX::~PhysX()
  374. {
  375. mCharManager->release();
  376. mScene->release();
  377. if (mCooking != nullptr)
  378. mCooking->release();
  379. mPhysics->release();
  380. mFoundation->release();
  381. }
  382. void PhysX::update()
  383. {
  384. mUpdateInProgress = true;
  385. float nextFrameTime = mLastSimulationTime + mSimulationStep;
  386. float curFrameTime = gTime().getTime();
  387. if(curFrameTime < nextFrameTime)
  388. {
  389. // TODO - Interpolate rigidbodies but perform no actual simulation
  390. return;
  391. }
  392. float simulationAmount = curFrameTime - mLastSimulationTime;
  393. while (simulationAmount >= mSimulationStep) // In case we're running really slow multiple updates might be needed
  394. {
  395. // Note: Consider delaying fetchResults one frame. This could improve performance because Physics update would be
  396. // able to run parallel to the simulation thread, but at a cost to input latency.
  397. // TODO - Provide a scratch buffer for the simulation (use the frame allocator, but I must extend it so it allocates
  398. // on a 16 byte boundary).
  399. mScene->simulate(mSimulationStep);
  400. mScene->fetchResults(true);
  401. // Update rigidbodies with new transforms
  402. PxU32 numActiveTransforms;
  403. const PxActiveTransform* activeTransforms = mScene->getActiveTransforms(numActiveTransforms);
  404. for (PxU32 i = 0; i < numActiveTransforms; i++)
  405. {
  406. Rigidbody* rigidbody = static_cast<Rigidbody*>(activeTransforms[i].userData);
  407. const PxTransform& transform = activeTransforms[i].actor2World;
  408. // Note: Make this faster, avoid dereferencing Rigidbody and attempt to access pos/rot destination directly,
  409. // use non-temporal writes
  410. rigidbody->_setTransform(fromPxVector(transform.p), fromPxQuaternion(transform.q));
  411. }
  412. simulationAmount -= mSimulationStep;
  413. }
  414. // TODO - Consider extrapolating for the remaining "simulationAmount" value
  415. mLastSimulationTime = curFrameTime;
  416. mUpdateInProgress = false;
  417. triggerEvents();
  418. }
  419. void PhysX::_reportContactEvent(const ContactEvent& event)
  420. {
  421. mContactEvents.push_back(event);
  422. }
  423. void PhysX::_reportTriggerEvent(const TriggerEvent& event)
  424. {
  425. mTriggerEvents.push_back(event);
  426. }
  427. void PhysX::_reportJointBreakEvent(const JointBreakEvent& event)
  428. {
  429. mJointBreakEvents.push_back(event);
  430. }
  431. void PhysX::triggerEvents()
  432. {
  433. CollisionData data;
  434. for(auto& entry : mTriggerEvents)
  435. {
  436. data.collidersRaw[0] = entry.trigger;
  437. data.collidersRaw[1] = entry.other;
  438. switch (entry.type)
  439. {
  440. case ContactEventType::ContactBegin:
  441. entry.trigger->onCollisionBegin(data);
  442. break;
  443. case ContactEventType::ContactStay:
  444. entry.trigger->onCollisionStay(data);
  445. break;
  446. case ContactEventType::ContactEnd:
  447. entry.trigger->onCollisionEnd(data);
  448. break;
  449. }
  450. }
  451. auto notifyContact = [&](Collider* obj, Collider* other, ContactEventType type,
  452. const Vector<ContactPoint>& points, bool flipNormals = false)
  453. {
  454. data.collidersRaw[0] = obj;
  455. data.collidersRaw[1] = other;
  456. data.contactPoints = points;
  457. if(flipNormals)
  458. {
  459. for (auto& point : data.contactPoints)
  460. point.normal = -point.normal;
  461. }
  462. SPtr<Rigidbody> rigidbody = obj->getRigidbody();
  463. if(rigidbody != nullptr)
  464. {
  465. switch (type)
  466. {
  467. case ContactEventType::ContactBegin:
  468. rigidbody->onCollisionBegin(data);
  469. break;
  470. case ContactEventType::ContactStay:
  471. rigidbody->onCollisionStay(data);
  472. break;
  473. case ContactEventType::ContactEnd:
  474. rigidbody->onCollisionEnd(data);
  475. break;
  476. }
  477. }
  478. else
  479. {
  480. switch (type)
  481. {
  482. case ContactEventType::ContactBegin:
  483. obj->onCollisionBegin(data);
  484. break;
  485. case ContactEventType::ContactStay:
  486. obj->onCollisionStay(data);
  487. break;
  488. case ContactEventType::ContactEnd:
  489. obj->onCollisionEnd(data);
  490. break;
  491. }
  492. }
  493. };
  494. for (auto& entry : mContactEvents)
  495. {
  496. notifyContact(entry.colliderA, entry.colliderB, entry.type, entry.points, true);
  497. notifyContact(entry.colliderB, entry.colliderA, entry.type, entry.points, false);
  498. }
  499. for(auto& entry : mJointBreakEvents)
  500. {
  501. entry.joint->onJointBreak();
  502. }
  503. mTriggerEvents.clear();
  504. mContactEvents.clear();
  505. mJointBreakEvents.clear();
  506. }
  507. SPtr<PhysicsMaterial> PhysX::createMaterial(float staticFriction, float dynamicFriction, float restitution)
  508. {
  509. return bs_shared_ptr_new<PhysXMaterial>(mPhysics, staticFriction, dynamicFriction, restitution);
  510. }
  511. SPtr<PhysicsMesh> PhysX::createMesh(const MeshDataPtr& meshData, PhysicsMeshType type)
  512. {
  513. return bs_shared_ptr_new<PhysXMesh>(meshData, type);
  514. }
  515. SPtr<Rigidbody> PhysX::createRigidbody(const HSceneObject& linkedSO)
  516. {
  517. return bs_shared_ptr_new<PhysXRigidbody>(mPhysics, mScene, linkedSO);
  518. }
  519. SPtr<BoxCollider> PhysX::createBoxCollider(const Vector3& extents, const Vector3& position,
  520. const Quaternion& rotation)
  521. {
  522. return bs_shared_ptr_new<PhysXBoxCollider>(mPhysics, position, rotation, extents);
  523. }
  524. SPtr<SphereCollider> PhysX::createSphereCollider(float radius, const Vector3& position, const Quaternion& rotation)
  525. {
  526. return bs_shared_ptr_new<PhysXSphereCollider>(mPhysics, position, rotation, radius);
  527. }
  528. SPtr<PlaneCollider> PhysX::createPlaneCollider(const Vector3& position, const Quaternion& rotation)
  529. {
  530. return bs_shared_ptr_new<PhysXPlaneCollider>(mPhysics, position, rotation);
  531. }
  532. SPtr<CapsuleCollider> PhysX::createCapsuleCollider(float radius, float halfHeight, const Vector3& position,
  533. const Quaternion& rotation)
  534. {
  535. return bs_shared_ptr_new<PhysXCapsuleCollider>(mPhysics, position, rotation, radius, halfHeight);
  536. }
  537. SPtr<MeshCollider> PhysX::createMeshCollider(const Vector3& position, const Quaternion& rotation)
  538. {
  539. return bs_shared_ptr_new<PhysXMeshCollider>(mPhysics, position, rotation);
  540. }
  541. SPtr<FixedJoint> PhysX::createFixedJoint()
  542. {
  543. return bs_shared_ptr_new<PhysXFixedJoint>(mPhysics);
  544. }
  545. SPtr<DistanceJoint> PhysX::createDistanceJoint()
  546. {
  547. return bs_shared_ptr_new<PhysXDistanceJoint>(mPhysics);
  548. }
  549. SPtr<HingeJoint> PhysX::createHingeJoint()
  550. {
  551. return bs_shared_ptr_new<PhysXHingeJoint>(mPhysics);
  552. }
  553. SPtr<SphericalJoint> PhysX::createSphericalJoint()
  554. {
  555. return bs_shared_ptr_new<PhysXSphericalJoint>(mPhysics);
  556. }
  557. SPtr<SliderJoint> PhysX::createSliderJoint()
  558. {
  559. return bs_shared_ptr_new<PhysXSliderJoint>(mPhysics);
  560. }
  561. SPtr<D6Joint> PhysX::createD6Joint()
  562. {
  563. return bs_shared_ptr_new<PhysXD6Joint>(mPhysics);
  564. }
  565. SPtr<CharacterController> PhysX::createCharacterController(const CHAR_CONTROLLER_DESC& desc)
  566. {
  567. return bs_shared_ptr_new<PhysXCharacterController>(mCharManager, desc);
  568. }
  569. Vector<PhysicsQueryHit> PhysX::sweepAll(const PxGeometry& geometry, const PxTransform& tfrm, const Vector3& unitDir,
  570. UINT64 layer, float maxDist) const
  571. {
  572. PhysXSweepQueryCallback output;
  573. PxQueryFilterData filterData;
  574. memcpy(&filterData.data.word0, &layer, sizeof(layer));
  575. mScene->sweep(geometry, tfrm, toPxVector(unitDir), maxDist, output,
  576. PxHitFlag::eDEFAULT | PxHitFlag::eUV, filterData);
  577. return output.data;
  578. }
  579. bool PhysX::sweepAny(const PxGeometry& geometry, const PxTransform& tfrm, const Vector3& unitDir, UINT64 layer,
  580. float maxDist) const
  581. {
  582. PxSweepBuffer output;
  583. PxQueryFilterData filterData;
  584. filterData.flags |= PxQueryFlag::eANY_HIT;
  585. memcpy(&filterData.data.word0, &layer, sizeof(layer));
  586. return mScene->sweep(geometry, tfrm, toPxVector(unitDir), maxDist, output,
  587. PxHitFlag::eDEFAULT | PxHitFlag::eUV | PxHitFlag::eMESH_ANY, filterData);
  588. }
  589. bool PhysX::rayCast(const Vector3& origin, const Vector3& unitDir, PhysicsQueryHit& hit, UINT64 layer, float max)
  590. {
  591. PxRaycastBuffer output;
  592. PxQueryFilterData filterData;
  593. memcpy(&filterData.data.word0, &layer, sizeof(layer));
  594. bool wasHit = mScene->raycast(toPxVector(origin),
  595. toPxVector(unitDir), max, output, PxHitFlag::eDEFAULT | PxHitFlag::eUV, filterData);
  596. if (wasHit)
  597. parseHit(output.block, hit);
  598. return wasHit;
  599. }
  600. bool PhysX::boxCast(const AABox& box, const Quaternion& rotation, const Vector3& unitDir, PhysicsQueryHit& hit,
  601. UINT64 layer, float max)
  602. {
  603. PxBoxGeometry geometry(toPxVector(box.getHalfSize()));
  604. PxTransform transform = toPxTransform(box.getCenter(), rotation);
  605. return sweep(geometry, transform, unitDir, hit, layer, max);
  606. }
  607. bool PhysX::sphereCast(const Sphere& sphere, const Vector3& unitDir, PhysicsQueryHit& hit,
  608. UINT64 layer, float max)
  609. {
  610. PxSphereGeometry geometry(sphere.getRadius());
  611. PxTransform transform = toPxTransform(sphere.getCenter(), Quaternion::IDENTITY);
  612. return sweep(geometry, transform, unitDir, hit, layer, max);
  613. }
  614. bool PhysX::capsuleCast(const Capsule& capsule, const Quaternion& rotation, const Vector3& unitDir,
  615. PhysicsQueryHit& hit, UINT64 layer, float max)
  616. {
  617. PxCapsuleGeometry geometry(capsule.getRadius(), capsule.getHeight() * 0.5f);
  618. PxTransform transform = toPxTransform(capsule.getCenter(), Quaternion::IDENTITY);
  619. return sweep(geometry, transform, unitDir, hit, layer, max);
  620. }
  621. bool PhysX::convexCast(const HPhysicsMesh& mesh, const Vector3& position, const Quaternion& rotation,
  622. const Vector3& unitDir, PhysicsQueryHit& hit, UINT64 layer, float max)
  623. {
  624. if (mesh == nullptr)
  625. return false;
  626. PhysXMesh* physxMesh = static_cast<PhysXMesh*>(mesh.get());
  627. if (physxMesh->getType() != PhysicsMeshType::Convex)
  628. return false;
  629. PxConvexMeshGeometry geometry(physxMesh->_getConvex());
  630. PxTransform transform = toPxTransform(position, rotation);
  631. return sweep(geometry, transform, unitDir, hit, layer, max);
  632. }
  633. Vector<PhysicsQueryHit> PhysX::rayCastAll(const Vector3& origin, const Vector3& unitDir,
  634. UINT64 layer, float max)
  635. {
  636. PhysXRaycastQueryCallback output;
  637. PxQueryFilterData filterData;
  638. memcpy(&filterData.data.word0, &layer, sizeof(layer));
  639. mScene->raycast(toPxVector(origin), toPxVector(unitDir), max, output,
  640. PxHitFlag::eDEFAULT | PxHitFlag::eUV | PxHitFlag::eMESH_MULTIPLE, filterData);
  641. return output.data;
  642. }
  643. Vector<PhysicsQueryHit> PhysX::boxCastAll(const AABox& box, const Quaternion& rotation,
  644. const Vector3& unitDir, UINT64 layer, float max)
  645. {
  646. PxBoxGeometry geometry(toPxVector(box.getHalfSize()));
  647. PxTransform transform = toPxTransform(box.getCenter(), rotation);
  648. return sweepAll(geometry, transform, unitDir, layer, max);
  649. }
  650. Vector<PhysicsQueryHit> PhysX::sphereCastAll(const Sphere& sphere, const Vector3& unitDir,
  651. UINT64 layer, float max)
  652. {
  653. PxSphereGeometry geometry(sphere.getRadius());
  654. PxTransform transform = toPxTransform(sphere.getCenter(), Quaternion::IDENTITY);
  655. return sweepAll(geometry, transform, unitDir, layer, max);
  656. }
  657. Vector<PhysicsQueryHit> PhysX::capsuleCastAll(const Capsule& capsule, const Quaternion& rotation,
  658. const Vector3& unitDir, UINT64 layer, float max)
  659. {
  660. PxCapsuleGeometry geometry(capsule.getRadius(), capsule.getHeight() * 0.5f);
  661. PxTransform transform = toPxTransform(capsule.getCenter(), Quaternion::IDENTITY);
  662. return sweepAll(geometry, transform, unitDir, layer, max);
  663. }
  664. Vector<PhysicsQueryHit> PhysX::convexCastAll(const HPhysicsMesh& mesh, const Vector3& position,
  665. const Quaternion& rotation, const Vector3& unitDir, UINT64 layer, float max)
  666. {
  667. if (mesh == nullptr)
  668. return Vector<PhysicsQueryHit>(0);
  669. PhysXMesh* physxMesh = static_cast<PhysXMesh*>(mesh.get());
  670. if (physxMesh->getType() != PhysicsMeshType::Convex)
  671. return Vector<PhysicsQueryHit>(0);
  672. PxConvexMeshGeometry geometry(physxMesh->_getConvex());
  673. PxTransform transform = toPxTransform(position, rotation);
  674. return sweepAll(geometry, transform, unitDir, layer, max);
  675. }
  676. bool PhysX::rayCastAny(const Vector3& origin, const Vector3& unitDir,
  677. UINT64 layer, float max)
  678. {
  679. PxRaycastBuffer output;
  680. PxQueryFilterData filterData;
  681. filterData.flags |= PxQueryFlag::eANY_HIT;
  682. memcpy(&filterData.data.word0, &layer, sizeof(layer));
  683. return mScene->raycast(toPxVector(origin),
  684. toPxVector(unitDir), max, output, PxHitFlag::eDEFAULT | PxHitFlag::eUV | PxHitFlag::eMESH_ANY, filterData);
  685. }
  686. bool PhysX::boxCastAny(const AABox& box, const Quaternion& rotation, const Vector3& unitDir,
  687. UINT64 layer, float max)
  688. {
  689. PxBoxGeometry geometry(toPxVector(box.getHalfSize()));
  690. PxTransform transform = toPxTransform(box.getCenter(), rotation);
  691. return sweepAny(geometry, transform, unitDir, layer, max);
  692. }
  693. bool PhysX::sphereCastAny(const Sphere& sphere, const Vector3& unitDir,
  694. UINT64 layer, float max)
  695. {
  696. PxSphereGeometry geometry(sphere.getRadius());
  697. PxTransform transform = toPxTransform(sphere.getCenter(), Quaternion::IDENTITY);
  698. return sweepAny(geometry, transform, unitDir, layer, max);
  699. }
  700. bool PhysX::capsuleCastAny(const Capsule& capsule, const Quaternion& rotation, const Vector3& unitDir,
  701. UINT64 layer, float max)
  702. {
  703. PxCapsuleGeometry geometry(capsule.getRadius(), capsule.getHeight() * 0.5f);
  704. PxTransform transform = toPxTransform(capsule.getCenter(), Quaternion::IDENTITY);
  705. return sweepAny(geometry, transform, unitDir, layer, max);
  706. }
  707. bool PhysX::convexCastAny(const HPhysicsMesh& mesh, const Vector3& position, const Quaternion& rotation,
  708. const Vector3& unitDir, UINT64 layer, float max)
  709. {
  710. if (mesh == nullptr)
  711. return false;
  712. PhysXMesh* physxMesh = static_cast<PhysXMesh*>(mesh.get());
  713. if (physxMesh->getType() != PhysicsMeshType::Convex)
  714. return false;
  715. PxConvexMeshGeometry geometry(physxMesh->_getConvex());
  716. PxTransform transform = toPxTransform(position, rotation);
  717. return sweepAny(geometry, transform, unitDir, layer, max);
  718. }
  719. Vector<Collider*> PhysX::_boxOverlap(const AABox& box, const Quaternion& rotation,
  720. UINT64 layer)
  721. {
  722. PxBoxGeometry geometry(toPxVector(box.getHalfSize()));
  723. PxTransform transform = toPxTransform(box.getCenter(), rotation);
  724. return overlap(geometry, transform, layer);
  725. }
  726. Vector<Collider*> PhysX::_sphereOverlap(const Sphere& sphere, UINT64 layer)
  727. {
  728. PxSphereGeometry geometry(sphere.getRadius());
  729. PxTransform transform = toPxTransform(sphere.getCenter(), Quaternion::IDENTITY);
  730. return overlap(geometry, transform, layer);
  731. }
  732. Vector<Collider*> PhysX::_capsuleOverlap(const Capsule& capsule, const Quaternion& rotation,
  733. UINT64 layer)
  734. {
  735. PxCapsuleGeometry geometry(capsule.getRadius(), capsule.getHeight() * 0.5f);
  736. PxTransform transform = toPxTransform(capsule.getCenter(), Quaternion::IDENTITY);
  737. return overlap(geometry, transform, layer);
  738. }
  739. Vector<Collider*> PhysX::_convexOverlap(const HPhysicsMesh& mesh, const Vector3& position,
  740. const Quaternion& rotation, UINT64 layer)
  741. {
  742. if (mesh == nullptr)
  743. return Vector<Collider*>(0);
  744. PhysXMesh* physxMesh = static_cast<PhysXMesh*>(mesh.get());
  745. if (physxMesh->getType() != PhysicsMeshType::Convex)
  746. return Vector<Collider*>(0);
  747. PxConvexMeshGeometry geometry(physxMesh->_getConvex());
  748. PxTransform transform = toPxTransform(position, rotation);
  749. return overlap(geometry, transform, layer);
  750. }
  751. bool PhysX::boxOverlapAny(const AABox& box, const Quaternion& rotation, UINT64 layer)
  752. {
  753. PxBoxGeometry geometry(toPxVector(box.getHalfSize()));
  754. PxTransform transform = toPxTransform(box.getCenter(), rotation);
  755. return overlapAny(geometry, transform, layer);
  756. }
  757. bool PhysX::sphereOverlapAny(const Sphere& sphere, UINT64 layer)
  758. {
  759. PxSphereGeometry geometry(sphere.getRadius());
  760. PxTransform transform = toPxTransform(sphere.getCenter(), Quaternion::IDENTITY);
  761. return overlapAny(geometry, transform, layer);
  762. }
  763. bool PhysX::capsuleOverlapAny(const Capsule& capsule, const Quaternion& rotation,
  764. UINT64 layer)
  765. {
  766. PxCapsuleGeometry geometry(capsule.getRadius(), capsule.getHeight() * 0.5f);
  767. PxTransform transform = toPxTransform(capsule.getCenter(), Quaternion::IDENTITY);
  768. return overlapAny(geometry, transform, layer);
  769. }
  770. bool PhysX::convexOverlapAny(const HPhysicsMesh& mesh, const Vector3& position, const Quaternion& rotation,
  771. UINT64 layer)
  772. {
  773. if (mesh == nullptr)
  774. return false;
  775. PhysXMesh* physxMesh = static_cast<PhysXMesh*>(mesh.get());
  776. if (physxMesh->getType() != PhysicsMeshType::Convex)
  777. return false;
  778. PxConvexMeshGeometry geometry(physxMesh->_getConvex());
  779. PxTransform transform = toPxTransform(position, rotation);
  780. return overlapAny(geometry, transform, layer);
  781. }
  782. bool PhysX::sweep(const PxGeometry& geometry, const PxTransform& tfrm, const Vector3& unitDir,
  783. PhysicsQueryHit& hit, UINT64 layer, float maxDist) const
  784. {
  785. PxSweepBuffer output;
  786. PxQueryFilterData filterData;
  787. memcpy(&filterData.data.word0, &layer, sizeof(layer));
  788. bool wasHit = mScene->sweep(geometry, tfrm, toPxVector(unitDir), maxDist, output,
  789. PxHitFlag::eDEFAULT | PxHitFlag::eUV, filterData);
  790. if (wasHit)
  791. parseHit(output.block, hit);
  792. return wasHit;
  793. }
  794. bool PhysX::overlapAny(const PxGeometry& geometry, const PxTransform& tfrm, UINT64 layer) const
  795. {
  796. PxOverlapBuffer output;
  797. PxQueryFilterData filterData;
  798. memcpy(&filterData.data.word0, &layer, sizeof(layer));
  799. return mScene->overlap(geometry, tfrm, output, filterData);
  800. }
  801. Vector<Collider*> PhysX::overlap(const PxGeometry& geometry, const PxTransform& tfrm, UINT64 layer) const
  802. {
  803. PhysXOverlapQueryCallback output;
  804. PxQueryFilterData filterData;
  805. memcpy(&filterData.data.word0, &layer, sizeof(layer));
  806. mScene->overlap(geometry, tfrm, output, filterData);
  807. return output.data;
  808. }
  809. void PhysX::setFlag(PhysicsFlags flag, bool enabled)
  810. {
  811. Physics::setFlag(flag, enabled);
  812. mCharManager->setOverlapRecoveryModule(mFlags.isSet(PhysicsFlag::CCT_OverlapRecovery));
  813. mCharManager->setPreciseSweeps(mFlags.isSet(PhysicsFlag::CCT_PreciseSweeps));
  814. mCharManager->setTessellation(mFlags.isSet(PhysicsFlag::CCT_Tesselation), mTesselationLength);
  815. }
  816. Vector3 PhysX::getGravity() const
  817. {
  818. return fromPxVector(mScene->getGravity());
  819. }
  820. void PhysX::setGravity(const Vector3& gravity)
  821. {
  822. mScene->setGravity(toPxVector(gravity));
  823. }
  824. void PhysX::setMaxTesselationEdgeLength(float length)
  825. {
  826. mTesselationLength = length;
  827. mCharManager->setTessellation(mFlags.isSet(PhysicsFlag::CCT_Tesselation), mTesselationLength);
  828. }
  829. UINT32 PhysX::addBroadPhaseRegion(const AABox& region)
  830. {
  831. UINT32 id = mNextRegionIdx++;
  832. PxBroadPhaseRegion pxRegion;
  833. pxRegion.bounds = PxBounds3(toPxVector(region.getMin()), toPxVector(region.getMax()));
  834. pxRegion.userData = (void*)(UINT64)id;
  835. UINT32 handle = mScene->addBroadPhaseRegion(pxRegion, true);
  836. mBroadPhaseRegionHandles[id] = handle;
  837. return handle;
  838. }
  839. void PhysX::removeBroadPhaseRegion(UINT32 regionId)
  840. {
  841. auto iterFind = mBroadPhaseRegionHandles.find(regionId);
  842. if (iterFind == mBroadPhaseRegionHandles.end())
  843. return;
  844. mScene->removeBroadPhaseRegion(iterFind->second);
  845. mBroadPhaseRegionHandles.erase(iterFind);
  846. }
  847. void PhysX::clearBroadPhaseRegions()
  848. {
  849. for(auto& entry : mBroadPhaseRegionHandles)
  850. mScene->removeBroadPhaseRegion(entry.second);
  851. mBroadPhaseRegionHandles.clear();
  852. }
  853. PhysX& gPhysX()
  854. {
  855. return static_cast<PhysX&>(PhysX::instance());
  856. }
  857. }