You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BulletCharacterController.h 9.8 KiB

преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net>
  5. // (c) 2009-2012 Benjamin Huet <huet.benjamin@gmail.com>
  6. // This program is free software; you can redistribute it and/or
  7. // modify it under the terms of the Do What The Fuck You Want To
  8. // Public License, Version 2, as published by Sam Hocevar. See
  9. // http://sam.zoy.org/projects/COPYING.WTFPL for more details.
  10. //
  11. //
  12. // The BulletCharacterController class
  13. // ------------------
  14. // This class is a equivalent of btKinematicCharacterController, but more useful for Lol.
  15. //
  16. #if !defined __BULLETCHARACTERCONTROLLER_BULLETCHARACTERCONTROLLER_H__
  17. #define __BULLETCHARACTERCONTROLLER_BULLETCHARACTERCONTROLLER_H__
  18. #ifdef HAVE_PHYS_USE_BULLET
  19. #include "core.h"
  20. #include "EasyPhysics.h"
  21. //#include "BulletDynamics\Character\btCharacterControllerInterface.h"
  22. #endif
  23. #define USE_LOL_CTRLR_CHARAC
  24. namespace lol
  25. {
  26. namespace phys
  27. {
  28. #ifdef USE_LOL_CTRLR_CHARAC
  29. #ifdef HAVE_PHYS_USE_BULLET
  30. //SweepCallback used for Swweep Tests.
  31. class ClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
  32. {
  33. public:
  34. ClosestNotMeConvexResultCallback(btCollisionObject* NewMe, const vec3& NewUp, float MinSlopeDot) :
  35. btCollisionWorld::ClosestConvexResultCallback(LOL2BTU_VEC3(vec3(.0f)), LOL2BTU_VEC3(vec3(.0f))),
  36. m_me(NewMe),
  37. m_up(NewUp),
  38. m_min_slope_dot(MinSlopeDot) { }
  39. virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& ConvexResult, bool NormalInWorld)
  40. {
  41. //We hit ourselves, FAIL
  42. if (ConvexResult.m_hitCollisionObject == m_me)
  43. return btScalar(1.f);
  44. vec3 WorldHitNomal(.0f);
  45. if (NormalInWorld)
  46. WorldHitNomal = BT2LOL_VEC3(ConvexResult.m_hitNormalLocal);
  47. else //need to transform Normal into worldspace
  48. {
  49. btVector3 TmpWorldHitNormal = ConvexResult.m_hitCollisionObject->getWorldTransform().getBasis() * ConvexResult.m_hitNormalLocal;
  50. WorldHitNomal = BT2LOL_VEC3(TmpWorldHitNormal);
  51. }
  52. float DotUp = dot(m_up, WorldHitNomal);
  53. //We hit below the accepted slope_dot, FAIL
  54. if (DotUp < m_min_slope_dot)
  55. return btScalar(1.f);
  56. //Continue to next.
  57. return ClosestConvexResultCallback::addSingleResult(ConvexResult, NormalInWorld);
  58. }
  59. protected:
  60. btCollisionObject* m_me;
  61. const vec3 m_up;
  62. float m_min_slope_dot;
  63. };
  64. ///BulletKinematicCharacterController is an object that supports a sliding motion in a world.
  65. ///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations.
  66. ///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user.
  67. class BulletKinematicCharacterController : public btActionInterface
  68. {
  69. public:
  70. BulletKinematicCharacterController(btPairCachingGhostObject* NewGhostObject, btConvexShape* NewConvexShape, float NewStepHeight, int NewUpAxis=1)
  71. {
  72. m_convex_shape = NewConvexShape;
  73. m_i_up_axis = NewUpAxis;
  74. m_ghost_object = NewGhostObject;
  75. m_step_height = NewStepHeight;
  76. m_added_margin = 0.02f;
  77. m_walk_direction = vec3(.0f, .0f, .0f);
  78. m_do_gobject_sweep_test = true;
  79. m_turn_angle = .0f;
  80. m_use_walk_direction = false; // Should remove walk direction, this doesn't work correctly.
  81. m_velocity_time_interval = .0f;
  82. m_vertical_velocity = .0f;
  83. m_vertical_offset = .0f;
  84. m_f_gravity = 9.8f * 3.f; // 3G acceleration.
  85. m_fall_speed = 55.f; // Terminal velocity of a sky diver in m/s.
  86. m_jump_speed = 10.f; // ?
  87. m_was_on_ground = false;
  88. m_was_jumping = false;
  89. SetMaxSlope(45.f);
  90. }
  91. ~BulletKinematicCharacterController() { }
  92. protected:
  93. static vec3* GetUpAxisDirections()
  94. {
  95. static vec3 sUpAxisDirection[3] = { vec3(1.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f), vec3(0.0f, 0.0f, 1.0f) };
  96. return sUpAxisDirection;
  97. }
  98. //--------------------------
  99. //CONVENIENCE FUNCTIONS
  100. //--
  101. //Returns the reflection Direction of a ray going 'Direction' hitting a surface with Normal 'Normal' from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html
  102. vec3 GetReflectedDir(const vec3& Direction, const vec3& Normal)
  103. {
  104. return Direction - (2.f * dot(Direction, Normal) * Normal);
  105. }
  106. //Returns the portion of 'direction' that is parallel to 'normal'
  107. vec3 ProjectDirOnNorm(const vec3& Direction, const vec3& Normal)
  108. {
  109. return Normal * dot(Direction, Normal);
  110. }
  111. //Returns the portion of 'Direction' that is perpindicular to 'Normal'
  112. vec3 ProjectDirOnNormPerpindicular(const vec3& Direction, const vec3& Normal)
  113. {
  114. return Direction - ProjectDirOnNorm(Direction, Normal);
  115. }
  116. //Returns Ghost Object. -duh-
  117. btPairCachingGhostObject* GetGhostObject()
  118. {
  119. return m_ghost_object;
  120. }
  121. //"Real" war functions
  122. bool RecoverFromPenetration(btCollisionWorld* CollisionWorld);
  123. void UpdateTargetOnHit(const vec3& hit_normal, float TangentMag = .0f, float NormalMag = 1.f);
  124. void DoMove(btCollisionWorld* CollisionWorld, const vec3& MoveStep, float DeltaTime);
  125. public:
  126. ///btActionInterface interface : KEEP IN camelCase
  127. virtual void updateAction(btCollisionWorld* CollisionWorld, float deltaTime)
  128. {
  129. PreStep(CollisionWorld);
  130. PlayerStep(CollisionWorld, deltaTime);
  131. }
  132. //not in the interface, but called above
  133. void PreStep(btCollisionWorld* CollisionWorld);
  134. void PlayerStep(btCollisionWorld* CollisionWorld, float DeltaTime);
  135. ///btActionInterface interface : KEEP IN camelCase
  136. void debugDraw(btIDebugDraw* debugDrawer) { }
  137. void SetUpAxis(int NewAxis)
  138. {
  139. if (NewAxis < 0)
  140. NewAxis = 0;
  141. if (NewAxis > 2)
  142. NewAxis = 2;
  143. m_i_up_axis = NewAxis;
  144. }
  145. //!!!!!! SHOULD DITCH THAT !!!!!!
  146. //This should probably be called setPositionIncrementPerSimulatorStep.
  147. //This is neither a Direction nor a velocity, but the amount to
  148. //increment the position each simulation iteration, regardless
  149. //of DeltaTime.
  150. //This call will Reset any velocity set by SetVelocityForTimeInterval().
  151. virtual void SetWalkDirection(const vec3& walkDirection)
  152. {
  153. m_use_walk_direction = true;
  154. m_walk_direction = walkDirection;
  155. m_normalized_direction = normalize(m_walk_direction);
  156. }
  157. //Caller provides a velocity with which the character should MoveStep for
  158. //the given time period. After the time period, velocity is Reset
  159. //to zero.
  160. //This call will Reset any walk Direction set by SetWalkDirection().
  161. //Negative time intervals will result in no motion.
  162. virtual void SetVelocityForTimeInterval(const vec3& velocity, float timeInterval)
  163. {
  164. m_use_walk_direction = false;
  165. m_walk_direction = velocity;
  166. m_normalized_direction = normalize(m_walk_direction);
  167. m_velocity_time_interval = timeInterval;
  168. }
  169. //Usefulness ?
  170. void Reset() { }
  171. void Warp(const vec3& NewOrigin)
  172. {
  173. btTransform NewTransform;
  174. NewTransform.setIdentity();
  175. NewTransform.setOrigin(LOL2BTU_VEC3(NewOrigin));
  176. m_ghost_object->setWorldTransform(NewTransform);
  177. }
  178. //External Setup
  179. //--
  180. void SetFallSpeed(float NewFallSpeed) { m_fall_speed = NewFallSpeed; }
  181. void SetJumpSpeed(float NewJumpSpeed) { m_jump_speed = NewJumpSpeed; }
  182. void SetMaxJumpHeight(float NewMaxJumpHeight) { m_max_jump_height = NewMaxJumpHeight; }
  183. //Jump logic will go in EasyCC
  184. bool CanJump() const { return OnGround(); }
  185. void Jump();
  186. //NewGravity functions
  187. void SetGravity(float NewGravity) { m_f_gravity = NewGravity; }
  188. float GetGravity() const { return m_f_gravity; }
  189. //The max slope determines the maximum angle that the controller can walk up.
  190. //The slope angle is measured in radians.
  191. void SetMaxSlope(float NewSlopeRadians) { m_max_slope_radians = NewSlopeRadians; m_max_slope_cosine = lol::cos(NewSlopeRadians); }
  192. float GetMaxSlope() const { return m_max_slope_radians; }
  193. void SetUseGhostSweepTest(bool UseGObjectSweepTest) { m_do_gobject_sweep_test = UseGObjectSweepTest; }
  194. bool OnGround() const { return m_vertical_velocity == .0f && m_vertical_offset == .0f; }
  195. private:
  196. btPairCachingGhostObject* m_ghost_object;
  197. btConvexShape* m_convex_shape; //is also in m_ghost_object, but it needs to be convex, so we store it here to avoid upcast
  198. //keep track of the contact manifolds
  199. btManifoldArray m_manifold_array;
  200. float m_half_height;
  201. float m_velocity_time_interval;
  202. float m_vertical_velocity;
  203. float m_vertical_offset;
  204. float m_fall_speed;
  205. float m_jump_speed;
  206. float m_max_jump_height;
  207. float m_max_slope_radians; // Slope angle that is set (used for returning the exact value)
  208. float m_max_slope_cosine; // Cosine equivalent of m_max_slope_radians (calculated once when set, for optimization)
  209. float m_f_gravity;
  210. float m_turn_angle;
  211. float m_step_height;
  212. float m_added_margin;//@todo: remove this and fix the code
  213. ///this is the desired walk Direction, set by the user
  214. vec3 m_walk_direction;
  215. vec3 m_normalized_direction;
  216. //some internal variables
  217. vec3 m_current_position;
  218. float m_current_step_offset;
  219. vec3 m_target_position;
  220. vec3 m_touching_normal;
  221. bool m_touching_contact;
  222. bool m_was_on_ground;
  223. bool m_was_jumping;
  224. bool m_do_gobject_sweep_test;
  225. bool m_use_walk_direction;
  226. int m_i_up_axis;
  227. //---------------------------------------------------------------------
  228. //NEW INTERNAL VARS
  229. //---------------------------------------------------------------------
  230. //Gravity in vec3
  231. vec3 m_gravity;
  232. //Current Velocity
  233. vec3 m_velocity;
  234. };
  235. #endif // HAVE_PHYS_USE_BULLET
  236. #endif // USE_LOL_CTRLR_CHARAC
  237. } /* namespace phys */
  238. } /* namespace lol */
  239. #endif /* __BULLETCHARACTERCONTROLLER_BULLETCHARACTERCONTROLLER_H__ */