Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

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