BsPhysX.cpp 33 KB

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