BsPhysXCharacterController.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsPhysXCharacterController.h"
  4. #include "BsTime.h"
  5. #include "BsPhysX.h"
  6. #include "characterkinematic\PxControllerManager.h"
  7. using namespace physx;
  8. namespace BansheeEngine
  9. {
  10. PxExtendedVec3 toPxExtVector(const Vector3& input)
  11. {
  12. return PxExtendedVec3(input.x, input.y, input.z);
  13. }
  14. Vector3 fromPxExtVector(const PxExtendedVec3& input)
  15. {
  16. return Vector3((float)input.x, (float)input.y, (float)input.z);
  17. }
  18. PxCapsuleClimbingMode::Enum toPxEnum(CharacterClimbingMode value)
  19. {
  20. return value == CharacterClimbingMode::Normal
  21. ? PxCapsuleClimbingMode::eEASY
  22. : PxCapsuleClimbingMode::eCONSTRAINED;
  23. }
  24. PxControllerNonWalkableMode::Enum toPxEnum(CharacterNonWalkableMode value)
  25. {
  26. return value == CharacterNonWalkableMode::Prevent
  27. ? PxControllerNonWalkableMode::ePREVENT_CLIMBING
  28. : PxControllerNonWalkableMode::ePREVENT_CLIMBING_AND_FORCE_SLIDING;
  29. }
  30. CharacterClimbingMode fromPxEnum(PxCapsuleClimbingMode::Enum value)
  31. {
  32. return value == PxCapsuleClimbingMode::eEASY
  33. ? CharacterClimbingMode::Normal
  34. : CharacterClimbingMode::Constrained;
  35. }
  36. CharacterNonWalkableMode fromPxEnum(PxControllerNonWalkableMode::Enum value)
  37. {
  38. return value == PxControllerNonWalkableMode::ePREVENT_CLIMBING
  39. ? CharacterNonWalkableMode::Prevent
  40. : CharacterNonWalkableMode::PreventAndSlide;
  41. }
  42. PxCapsuleControllerDesc toPxDesc(const CHAR_CONTROLLER_DESC& desc)
  43. {
  44. PxCapsuleControllerDesc output;
  45. output.climbingMode = toPxEnum(desc.climbingMode);
  46. output.nonWalkableMode = toPxEnum(desc.nonWalkableMode);
  47. output.contactOffset = desc.contactOffset;
  48. output.stepOffset = desc.stepOffset;
  49. output.slopeLimit = desc.slopeLimit.valueRadians();
  50. output.height = desc.height;
  51. output.radius = desc.radius;
  52. output.upDirection = toPxVector(desc.up);
  53. output.position = toPxExtVector(desc.position);
  54. return output;
  55. }
  56. PhysXCharacterController::PhysXCharacterController(PxControllerManager* manager, const CHAR_CONTROLLER_DESC& desc)
  57. :CharacterController(desc)
  58. {
  59. PxCapsuleControllerDesc pxDesc = toPxDesc(desc);
  60. pxDesc.reportCallback = this;
  61. mController = static_cast<PxCapsuleController*>(manager->createController(pxDesc));
  62. mController->setUserData(this);
  63. }
  64. PhysXCharacterController::~PhysXCharacterController()
  65. {
  66. mController->release();
  67. }
  68. CharacterCollisionFlags PhysXCharacterController::move(const Vector3& displacement)
  69. {
  70. PxControllerFilters filters;
  71. filters.mFilterCallback = this;
  72. filters.mFilterFlags = PxQueryFlag::eANY_HIT | PxQueryFlag::eSTATIC | PxQueryFlag::eDYNAMIC | PxQueryFlag::ePREFILTER;
  73. filters.mCCTFilterCallback = this;
  74. float curTime = gTime().getTime();
  75. float delta = curTime - mLastMoveCall;
  76. mLastMoveCall = curTime;
  77. PxControllerCollisionFlags collisionFlag = mController->move(toPxVector(displacement), mMinMoveDistance, delta, filters);
  78. CharacterCollisionFlags output;
  79. if (collisionFlag.isSet(PxControllerCollisionFlag::eCOLLISION_DOWN))
  80. output.set(CharacterCollisionFlag::Down);
  81. if (collisionFlag.isSet(PxControllerCollisionFlag::eCOLLISION_UP))
  82. output.set(CharacterCollisionFlag::Up);
  83. if (collisionFlag.isSet(PxControllerCollisionFlag::eCOLLISION_SIDES))
  84. output.set(CharacterCollisionFlag::Sides);
  85. return output;
  86. }
  87. Vector3 PhysXCharacterController::getPosition() const
  88. {
  89. return fromPxExtVector(mController->getPosition());
  90. }
  91. void PhysXCharacterController::setPosition(const Vector3& position)
  92. {
  93. mController->setPosition(toPxExtVector(position));
  94. }
  95. Vector3 PhysXCharacterController::getFootPosition() const
  96. {
  97. return fromPxExtVector(mController->getFootPosition());
  98. }
  99. void PhysXCharacterController::setFootPosition(const Vector3& position)
  100. {
  101. mController->setFootPosition(toPxExtVector(position));
  102. }
  103. float PhysXCharacterController::getRadius() const
  104. {
  105. return mController->getRadius();
  106. }
  107. void PhysXCharacterController::setRadius(float radius)
  108. {
  109. mController->setRadius(radius);
  110. }
  111. float PhysXCharacterController::getHeight() const
  112. {
  113. return mController->getHeight();
  114. }
  115. void PhysXCharacterController::setHeight(float height)
  116. {
  117. mController->setHeight(height);
  118. }
  119. Vector3 PhysXCharacterController::getUp() const
  120. {
  121. return fromPxVector(mController->getUpDirection());
  122. }
  123. void PhysXCharacterController::setUp(const Vector3& up)
  124. {
  125. mController->setUpDirection(toPxVector(up));
  126. }
  127. CharacterClimbingMode PhysXCharacterController::getClimbingMode() const
  128. {
  129. return fromPxEnum(mController->getClimbingMode());
  130. }
  131. void PhysXCharacterController::setClimbingMode(CharacterClimbingMode mode)
  132. {
  133. mController->setClimbingMode(toPxEnum(mode));
  134. }
  135. CharacterNonWalkableMode PhysXCharacterController::getNonWalkableMode() const
  136. {
  137. return fromPxEnum(mController->getNonWalkableMode());
  138. }
  139. void PhysXCharacterController::setNonWalkableMode(CharacterNonWalkableMode mode)
  140. {
  141. mController->setNonWalkableMode(toPxEnum(mode));
  142. }
  143. float PhysXCharacterController::getMinMoveDistance()
  144. {
  145. return mMinMoveDistance;
  146. }
  147. void PhysXCharacterController::setMinMoveDistance(float value)
  148. {
  149. mMinMoveDistance = value;
  150. }
  151. float PhysXCharacterController::getContactOffset()
  152. {
  153. return mController->getContactOffset();
  154. }
  155. void PhysXCharacterController::setContactOffset(float value)
  156. {
  157. mController->setContactOffset(value);
  158. }
  159. float PhysXCharacterController::getStepOffset()
  160. {
  161. return mController->getStepOffset();
  162. }
  163. void PhysXCharacterController::setStepOffset(float value)
  164. {
  165. mController->setStepOffset(value);
  166. }
  167. Radian PhysXCharacterController::getSlopeLimit()
  168. {
  169. return Radian(mController->getSlopeLimit());
  170. }
  171. void PhysXCharacterController::setSlopeLimit(Radian value)
  172. {
  173. mController->setSlopeLimit(value.valueRadians());
  174. }
  175. void PhysXCharacterController::onShapeHit(const PxControllerShapeHit& hit)
  176. {
  177. if (onColliderHit.empty())
  178. return;
  179. ControllerColliderCollision collision;
  180. collision.position = fromPxExtVector(hit.worldPos);
  181. collision.normal = fromPxVector(hit.worldNormal);
  182. collision.motionDir = fromPxVector(hit.dir);
  183. collision.motionAmount = hit.length;
  184. collision.triangleIndex = hit.triangleIndex;
  185. collision.collider = (Collider*)hit.shape->userData;
  186. onColliderHit(collision);
  187. }
  188. void PhysXCharacterController::onControllerHit(const PxControllersHit& hit)
  189. {
  190. if (CharacterController::onControllerHit.empty())
  191. return;
  192. ControllerControllerCollision collision;
  193. collision.position = fromPxExtVector(hit.worldPos);
  194. collision.normal = fromPxVector(hit.worldNormal);
  195. collision.motionDir = fromPxVector(hit.dir);
  196. collision.motionAmount = hit.length;
  197. collision.controller = (CharacterController*)hit.controller->getUserData();
  198. CharacterController::onControllerHit(collision);
  199. }
  200. PxQueryHitType::Enum PhysXCharacterController::preFilter(const PxFilterData& filterData, const PxShape* shape,
  201. const PxRigidActor* actor, PxHitFlags& queryFlags)
  202. {
  203. PxFilterData colliderFilterData = shape->getSimulationFilterData();
  204. UINT64 colliderLayer = *(UINT64*)&colliderFilterData.word0;
  205. bool canCollide = gPhysics().isCollisionEnabled(colliderLayer, getLayer());
  206. if(canCollide)
  207. return PxSceneQueryHitType::eBLOCK;
  208. return PxSceneQueryHitType::eNONE;
  209. }
  210. PxQueryHitType::Enum PhysXCharacterController::postFilter(const PxFilterData& filterData,
  211. const PxQueryHit& hit)
  212. {
  213. return PxSceneQueryHitType::eBLOCK;
  214. }
  215. bool PhysXCharacterController::filter(const PxController& a, const PxController& b)
  216. {
  217. CharacterController* controllerA = (CharacterController*)a.getUserData();
  218. CharacterController* controllerB = (CharacterController*)b.getUserData();
  219. bool canCollide = gPhysics().isCollisionEnabled(controllerA->getLayer(), controllerB->getLayer());
  220. return canCollide;
  221. }
  222. }