243 rivejä
8.3 KiB

  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. ///BulletKinematicCharacterController is an object that supports a sliding motion in a world.
  31. ///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.
  32. ///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user.
  33. class BulletKinematicCharacterController : public btActionInterface
  34. {
  35. public:
  36. BulletKinematicCharacterController(btPairCachingGhostObject* NewGhostObject, btConvexShape* NewConvexShape, float NewStepHeight, int NewUpAxis=1)
  37. {
  38. m_convex_shape = NewConvexShape;
  39. m_up_axis = NewUpAxis;
  40. m_ghost_object = NewGhostObject;
  41. m_step_height = NewStepHeight;
  42. m_added_margin = 0.02f;
  43. m_walk_direction = vec3(.0f, .0f, .0f);
  44. m_do_gobject_sweep_test = true;
  45. m_turn_angle = .0f;
  46. m_use_walk_direction = false; // Should remove walk direction, this doesn't work correctly.
  47. m_velocity_time_interval = .0f;
  48. m_vertical_velocity = .0f;
  49. m_vertical_offset = .0f;
  50. m_gravity = 9.8f * 3.f; // 3G acceleration.
  51. m_fall_speed = 55.f; // Terminal velocity of a sky diver in m/s.
  52. m_jump_speed = 10.f; // ?
  53. m_was_on_ground = false;
  54. m_was_jumping = false;
  55. SetMaxSlope(45.f);
  56. }
  57. ~BulletKinematicCharacterController() { }
  58. protected:
  59. static vec3* GetUpAxisDirections()
  60. {
  61. 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) };
  62. return sUpAxisDirection;
  63. }
  64. //--------------------------
  65. //CONVENIENCE FUNCTIONS
  66. //--
  67. //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
  68. vec3 GetReflectedDir(const vec3& Direction, const vec3& Normal)
  69. {
  70. return Direction - (2.f * dot(Direction, Normal) * Normal);
  71. }
  72. //Returns the portion of 'direction' that is parallel to 'normal'
  73. vec3 ProjectDirOnNorm(const vec3& Direction, const vec3& Normal)
  74. {
  75. return Normal * dot(Direction, Normal);
  76. }
  77. //Returns the portion of 'Direction' that is perpindicular to 'Normal'
  78. vec3 ProjectDirOnNormPerpindicular(const vec3& Direction, const vec3& Normal)
  79. {
  80. return Direction - ProjectDirOnNorm(Direction, Normal);
  81. }
  82. //Returns Ghost Object. -duh-
  83. btPairCachingGhostObject* GetGhostObject()
  84. {
  85. return m_ghost_object;
  86. }
  87. //"Real" war functions
  88. bool RecoverFromPenetration(btCollisionWorld* CollisionWorld);
  89. void UpdateTargetOnHit(const vec3& hit_normal, float TangentMag = .0f, float NormalMag = 1.f);
  90. void StepUp(btCollisionWorld* CollisionWorld);
  91. void StepForwardAndStrafe(btCollisionWorld* CollisionWorld, const vec3& MoveStep);
  92. void StepDown(btCollisionWorld* CollisionWorld, float DeltaTime);
  93. public:
  94. ///btActionInterface interface : KEEP IN camelCase
  95. virtual void updateAction(btCollisionWorld* CollisionWorld, float deltaTime)
  96. {
  97. PreStep(CollisionWorld);
  98. PlayerStep(CollisionWorld, deltaTime);
  99. }
  100. //not in the interface, but called above
  101. void PreStep(btCollisionWorld* CollisionWorld);
  102. void PlayerStep(btCollisionWorld* CollisionWorld, float DeltaTime);
  103. ///btActionInterface interface : KEEP IN camelCase
  104. void debugDraw(btIDebugDraw* debugDrawer) { }
  105. void SetUpAxis(int NewAxis)
  106. {
  107. if (NewAxis < 0)
  108. NewAxis = 0;
  109. if (NewAxis > 2)
  110. NewAxis = 2;
  111. m_up_axis = NewAxis;
  112. }
  113. //!!!!!! SHOULD DITCH THAT !!!!!!
  114. //This should probably be called setPositionIncrementPerSimulatorStep.
  115. //This is neither a Direction nor a velocity, but the amount to
  116. //increment the position each simulation iteration, regardless
  117. //of DeltaTime.
  118. //This call will Reset any velocity set by SetVelocityForTimeInterval().
  119. virtual void SetWalkDirection(const vec3& walkDirection)
  120. {
  121. m_use_walk_direction = true;
  122. m_walk_direction = walkDirection;
  123. m_normalized_direction = normalize(m_walk_direction);
  124. }
  125. //Caller provides a velocity with which the character should MoveStep for
  126. //the given time period. After the time period, velocity is Reset
  127. //to zero.
  128. //This call will Reset any walk Direction set by SetWalkDirection().
  129. //Negative time intervals will result in no motion.
  130. virtual void SetVelocityForTimeInterval(const vec3& velocity, float timeInterval)
  131. {
  132. m_use_walk_direction = false;
  133. m_walk_direction = velocity;
  134. m_normalized_direction = normalize(m_walk_direction);
  135. m_velocity_time_interval = timeInterval;
  136. }
  137. //Usefulness ?
  138. void Reset() { }
  139. void Warp(const vec3& NewOrigin)
  140. {
  141. btTransform NewTransform;
  142. NewTransform.setIdentity();
  143. NewTransform.setOrigin(LOL2BTU_VEC3(NewOrigin));
  144. m_ghost_object->setWorldTransform(NewTransform);
  145. }
  146. //External Setup
  147. //--
  148. void SetFallSpeed(float NewFallSpeed) { m_fall_speed = NewFallSpeed; }
  149. void SetJumpSpeed(float NewJumpSpeed) { m_jump_speed = NewJumpSpeed; }
  150. void SetMaxJumpHeight(float NewMaxJumpHeight) { m_max_jump_height = NewMaxJumpHeight; }
  151. //Jump logic will go in EasyCC
  152. bool CanJump() const { return OnGround(); }
  153. void Jump();
  154. //NewGravity functions
  155. void SetGravity(float NewGravity) { m_gravity = NewGravity; }
  156. float GetGravity() const { return m_gravity; }
  157. //The max slope determines the maximum angle that the controller can walk up.
  158. //The slope angle is measured in radians.
  159. void SetMaxSlope(float NewSlopeRadians) { m_max_slope_radians = NewSlopeRadians; m_max_slope_cosine = lol::cos(NewSlopeRadians); }
  160. float GetMaxSlope() const { return m_max_slope_radians; }
  161. void SetUseGhostSweepTest(bool UseGObjectSweepTest) { m_do_gobject_sweep_test = UseGObjectSweepTest; }
  162. bool OnGround() const { return m_vertical_velocity == .0f && m_vertical_offset == .0f; }
  163. private:
  164. btPairCachingGhostObject* m_ghost_object;
  165. btConvexShape* m_convex_shape; //is also in m_ghost_object, but it needs to be convex, so we store it here to avoid upcast
  166. //keep track of the contact manifolds
  167. btManifoldArray m_manifold_array;
  168. float m_half_height;
  169. float m_velocity_time_interval;
  170. float m_vertical_velocity;
  171. float m_vertical_offset;
  172. float m_fall_speed;
  173. float m_jump_speed;
  174. float m_max_jump_height;
  175. float m_max_slope_radians; // Slope angle that is set (used for returning the exact value)
  176. float m_max_slope_cosine; // Cosine equivalent of m_max_slope_radians (calculated once when set, for optimization)
  177. float m_gravity;
  178. float m_turn_angle;
  179. float m_step_height;
  180. float m_added_margin;//@todo: remove this and fix the code
  181. ///this is the desired walk Direction, set by the user
  182. vec3 m_walk_direction;
  183. vec3 m_normalized_direction;
  184. //some internal variables
  185. vec3 m_current_position;
  186. float m_current_step_offset;
  187. vec3 m_target_position;
  188. vec3 m_touching_normal;
  189. bool m_touching_contact;
  190. bool m_was_on_ground;
  191. bool m_was_jumping;
  192. bool m_do_gobject_sweep_test;
  193. bool m_use_walk_direction;
  194. int m_up_axis;
  195. };
  196. #endif // HAVE_PHYS_USE_BULLET
  197. #endif // USE_LOL_CTRLR_CHARAC
  198. } /* namespace phys */
  199. } /* namespace lol */
  200. #endif /* __BULLETCHARACTERCONTROLLER_BULLETCHARACTERCONTROLLER_H__ */