PhysCharacter.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. #include "PhysCharacter.h"
  2. #include "PhysicsScene.h"
  3. class UserControllerHitReport : public NxUserControllerHitReport
  4. {
  5. public:
  6. virtual NxControllerAction onShapeHit(const NxControllerShapeHit& hit)
  7. {
  8. //return NX_ACTION_NONE;
  9. if(hit.shape)
  10. {
  11. NxActor& actor = hit.shape->getActor();
  12. if(actor.isDynamic())
  13. {
  14. NxCollisionGroup group = hit.shape->getGroup();
  15. if(group == phys_ragdoll)
  16. {
  17. if(hit.dir.y < -0.8f)
  18. {
  19. NxVec3 vec = hit.dir*Clampf(hit.length, -0.01f, 0.01f);
  20. vec.x = 0.0f;
  21. vec.z = 0.0f;
  22. //actor.addForceAtLocalPos(vec, NxVec3(0,0,0), NX_IMPULSE);
  23. //actor.addForceAtLocalPos(vec, NxVec3(0,0,0), NX_FORCE);
  24. }
  25. }
  26. NxActor* ControllerActor = hit.controller->getActor();
  27. PhysCharacter* pChar = (PhysCharacter*)ControllerActor->userData;
  28. bool bKinematic = actor.readBodyFlag(NX_BF_KINEMATIC);
  29. if(group != phys_ragdoll && pChar->isApplyForce && !bKinematic)
  30. {
  31. NxVec3 vec = hit.dir* pChar->force;
  32. vec.y = 0.0f;
  33. NxActor& actor = hit.shape->getActor();
  34. actor.addForceAtLocalPos(vec, NxVec3(0,0,0), NX_FORCE );
  35. }
  36. }
  37. }
  38. return NX_ACTION_NONE;
  39. };
  40. virtual NxControllerAction onControllerHit(const NxControllersHit& hit)
  41. {
  42. // NxVec3 p = hit.controller->getPosition();
  43. // NxVec3 e = hit.other->getPosition();
  44. return NX_ACTION_NONE;
  45. };
  46. static UserControllerHitReport report;
  47. };
  48. UserControllerHitReport UserControllerHitReport::report;
  49. PhysCharacter::PhysCharacter(const char * filename, long fileline, float r, float h, IPhysicsScene * _scene) :
  50. IPhysCharacter(_scene)
  51. {
  52. SetFileLine(filename, fileline);
  53. controller = null;
  54. desc.radius = r;
  55. desc.height = 1.0f;
  56. //#ifndef _XBOX
  57. // //desc.stepOffset = 0.015f;
  58. // //desc.skinWidth = 0.01f;
  59. // desc.stepOffset = 0.1f;
  60. // desc.skinWidth = 0.05f;
  61. //#else
  62. desc.stepOffset = 0.23f;
  63. desc.skinWidth = 0.1f;
  64. //#endif
  65. desc.upDirection = NX_Y;
  66. static float slopeLimit = cosf(NxMath::degToRad(65.0f));
  67. desc.slopeLimit = slopeLimit;
  68. desc.userData = this;
  69. desc.position = NxExtendedVec3(0.0f, 0.0f, 0.0f);
  70. desc.callback = &UserControllerHitReport::report;
  71. isApplyForce = false;
  72. force = 0.0f;
  73. move_collisionflags = 0;
  74. SetHeight(h);
  75. Activate(true);
  76. sceneChangedIndex = 0xFFFFFFFF;
  77. }
  78. PhysCharacter::~PhysCharacter()
  79. {
  80. if(controller)
  81. {
  82. ((PhysicsScene *)scene)->CtrManager().releaseController(*controller);
  83. controller = null;
  84. }
  85. }
  86. //Установить радиус персонажу
  87. void PhysCharacter::SetRadius(float v)
  88. {
  89. desc.radius = v;
  90. if(controller)
  91. {
  92. controller->setRadius(v);
  93. }
  94. }
  95. //Получить радиус персонажа
  96. float PhysCharacter::GetRadius()
  97. {
  98. return desc.radius;
  99. }
  100. //Установить высоту персонажу
  101. void PhysCharacter::SetHeight(float v)
  102. {
  103. float r = GetRadius();
  104. v -= r*2.0f;
  105. if(v < 0.0001f) v = 0.0001f;
  106. desc.height = v;
  107. if(controller)
  108. {
  109. controller->setHeight(v);
  110. }
  111. }
  112. //Получить высоту персонажа
  113. float PhysCharacter::GetHeight()
  114. {
  115. return desc.height + desc.radius*2.0f;
  116. }
  117. //Установить позицию
  118. void PhysCharacter::SetPosition(const Vector & pos)
  119. {
  120. desc.position = Nxe(pos);
  121. desc.position.y += desc.skinWidth * 1.1f;
  122. if(controller)
  123. {
  124. controller->setPosition(desc.position);
  125. }
  126. }
  127. //Получить позицию
  128. Vector PhysCharacter::GetPosition()
  129. {
  130. if(controller)
  131. {
  132. desc.position = controller->getFilteredPosition();
  133. desc.position.y -= desc.skinWidth;
  134. }
  135. return Nxe(desc.position);
  136. }
  137. //Передвинуть персонажа
  138. dword PhysCharacter::Move(const Vector & move, dword collisionGroups)
  139. {
  140. if(!controller) return 0;
  141. NxU32 flags;
  142. NxVec3 m = Nx(move);
  143. if(fabs(m.y) < 1e-35f)
  144. {
  145. if(m.y <= 0.0f)
  146. {
  147. m.y = -1e-20f;
  148. }else{
  149. m.y = 1e-20f;
  150. }
  151. }
  152. dword newSceneChangedIndex = scene->GetSceneChangedIndex();
  153. if (newSceneChangedIndex != sceneChangedIndex)
  154. {
  155. sceneChangedIndex = newSceneChangedIndex;
  156. controller->reportSceneChanged();
  157. }
  158. controller->move(m, collisionGroups, 0.001f, flags, 1.0f);
  159. move_collisionflags = flags;
  160. /*IPhysicsScene::RaycastResult detail;
  161. IPhysBase* ragdoll = scene->Raycast(GetPosition(),GetPosition()+Vector(0,-desc.height-0.2f,0),phys_mask(phys_ragdoll),&detail);
  162. if (ragdoll)
  163. {
  164. Vector velocity = move;
  165. velocity *= 60.0f * 10.0f * 0.4f;
  166. velocity.y = 5.0f;
  167. //VANO изменил, тут баг, может быть IPhysMesh*, IPhysPlane* и так далее
  168. //((IPhysRagdoll*)ragdoll)->ApplyForce(velocity);
  169. if (ragdoll->UserNumber() == 666)
  170. {
  171. //((IPhysRagdoll*)ragdoll)->ApplyForce(velocity);
  172. }
  173. }*/
  174. return (dword)flags;
  175. }
  176. //Активировать/деактивировать персонажа
  177. void PhysCharacter::Activate(bool isActive)
  178. {
  179. if(isActive)
  180. {
  181. if (!controller)
  182. {
  183. controller = (NxCapsuleController *)((PhysicsScene *)scene)->CtrManager().createController(&((PhysicsScene *)scene)->Scene(), desc);
  184. NxActor * controllerActor = controller->getActor();
  185. // VANO:: TEMP CHANGE {
  186. if (controllerActor)
  187. {
  188. // VANO:: TEMP CHANGE }
  189. controllerActor->userData = this;
  190. controllerActor->setGroup((NxActorGroup)phys_player);
  191. NxU32 count = controllerActor->getNbShapes();
  192. NxShape * const * shapes = controllerActor->getShapes();
  193. for(NxU32 i = 0; i < count; i++)
  194. {
  195. shapes[i]->setGroup((NxCollisionGroup)phys_playerctrl);
  196. }
  197. //desc.position.y += desc.skinWidth;
  198. controller->setPosition(desc.position);
  199. // коллизим контроллеры строго по маске
  200. controller->setInteraction(NXIF_INTERACTION_USE_FILTER);
  201. // VANO:: TEMP CHANGE {
  202. }
  203. else
  204. {
  205. ((PhysicsScene *)scene)->CtrManager().releaseController(*controller);
  206. controller = null;
  207. }
  208. // VANO:: TEMP CHANGE }
  209. }
  210. }
  211. else
  212. {
  213. if(controller)
  214. {
  215. ((PhysicsScene *)scene)->CtrManager().releaseController(*controller);
  216. controller = null;
  217. }
  218. }
  219. }
  220. //Если не 0.0f, то на все объекты при столкновении будет приложена сила v
  221. void PhysCharacter::ApplyForceToObjects(float v)
  222. {
  223. force = v;
  224. isApplyForce = (fabs(force) > 1e-30f);
  225. }
  226. //Возвращает коллижн флаги с последнего выполненого Move
  227. dword PhysCharacter::GetMoveCollisionFlags()
  228. {
  229. return dword(move_collisionflags);
  230. }