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.

пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. //
  2. // LolPhysics
  3. //
  4. // Copyright: (c) 2009-2012 Benjamin Huet <huet.benjamin@gmail.com>
  5. // (c) 2012 Sam Hocevar <sam@hocevar.net>
  6. //
  7. #if !defined __LOLPHYSICS_H__
  8. #define __LOLPHYSICS_H__
  9. #ifdef HAVE_PHYS_USE_BULLET
  10. #include <cstring>
  11. #include <bullet/btBulletDynamicsCommon.h>
  12. #include <bullet/btBulletCollisionCommon.h>
  13. #include <BulletDynamics/Character/btKinematicCharacterController.h>
  14. #include "LolBtPhysicsIntegration.h"
  15. #include "EasyPhysics.h"
  16. #include "EasyConstraint.h"
  17. #endif
  18. namespace lol
  19. {
  20. namespace phys
  21. {
  22. enum eRaycastType
  23. {
  24. ERT_Closest,
  25. ERT_AllHit,
  26. ERT_AnyHit, //Will stop at the first hit. Hit data are supposed to be irrelevant
  27. ERT_MAX
  28. };
  29. struct RayCastResult
  30. {
  31. RayCastResult(int CollisionFilterGroup=1, int CollisionFilterMask=(0xFF))
  32. {
  33. memset(this, 0, sizeof(RayCastResult));
  34. m_collision_filter_group = CollisionFilterGroup;
  35. m_collision_filter_mask = CollisionFilterMask;
  36. }
  37. void Reset()
  38. {
  39. m_collider_list.Empty();
  40. m_hit_normal_list.Empty();
  41. m_hit_point_list.Empty();
  42. m_hit_fraction_list.Empty();
  43. }
  44. Array<EasyPhysic*> m_collider_list;
  45. Array<vec3> m_hit_normal_list;
  46. Array<vec3> m_hit_point_list;
  47. Array<float> m_hit_fraction_list;
  48. short int m_collision_filter_group;
  49. short int m_collision_filter_mask;
  50. unsigned int m_flags; //???
  51. };
  52. class Simulation : public Entity
  53. {
  54. public:
  55. Simulation() :
  56. m_broadphase(0),
  57. m_collision_configuration(0),
  58. m_dispatcher(0),
  59. m_solver(0),
  60. m_dynamics_world(0),
  61. m_timestep(1.f/60.f)
  62. {
  63. m_gamegroup = GAMEGROUP_SIMULATION;
  64. }
  65. ~Simulation()
  66. {
  67. Exit();
  68. }
  69. char const *GetName() { return "<Simulation>"; }
  70. #ifdef HAVE_PHYS_USE_BULLET
  71. public:
  72. void Init()
  73. {
  74. // Build the broadphase
  75. if (1)
  76. {
  77. m_Sweep_broadphase = new btAxisSweep3(LOL2BT_VEC3(m_world_min), LOL2BT_VEC3(m_world_max));
  78. m_Sweep_broadphase->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
  79. m_broadphase = m_Sweep_broadphase;
  80. }
  81. else
  82. m_broadphase = new btDbvtBroadphase();
  83. // Set up the collision configuration and dispatcher
  84. m_collision_configuration = new btDefaultCollisionConfiguration();
  85. m_dispatcher = new btCollisionDispatcher(m_collision_configuration);
  86. // The actual physics solver
  87. m_solver = new btSequentialImpulseConstraintSolver;
  88. // The world.
  89. m_dynamics_world = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collision_configuration);
  90. }
  91. virtual void TickGame(float seconds)
  92. {
  93. Entity::TickGame(seconds);
  94. //step the simulation
  95. if (m_dynamics_world)
  96. {
  97. //the "+1" is to have at least one Timestep and to ensure float to int .5f conversion.
  98. int steps = (int)(seconds / m_timestep) + 1;
  99. m_dynamics_world->stepSimulation(seconds, steps, m_timestep);
  100. }
  101. }
  102. //Rip-Off of the btKinematicClosestNotMeRayResultCallback
  103. class ClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
  104. {
  105. public:
  106. ClosestNotMeRayResultCallback(btCollisionObject* Me, const btVector3& rayFromWorld, const btVector3& rayToWorld) :
  107. btCollisionWorld::ClosestRayResultCallback(rayFromWorld, rayToWorld)
  108. {
  109. m_me = Me;
  110. }
  111. virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace)
  112. {
  113. if (rayResult.m_collisionObject == m_me)
  114. return 1.0;
  115. return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
  116. }
  117. protected:
  118. btCollisionObject* m_me;
  119. };
  120. //Will stop at the first hit. Hit data are supposed to be irrelevant
  121. class AnyHitRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
  122. {
  123. public:
  124. AnyHitRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld) :
  125. btCollisionWorld::ClosestRayResultCallback(rayFromWorld, rayToWorld)
  126. {
  127. }
  128. virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace)
  129. {
  130. return .0f;
  131. }
  132. };
  133. //Returns true when hitting something. If SourceCaster is set, it will be ignored by Raycast.
  134. bool RayHits(RayCastResult& HitResult, eRaycastType RaycastType, const vec3& RayFrom, const vec3& RayTo, EasyPhysic* SourceCaster=NULL)
  135. {
  136. bool bResult = false;
  137. btCollisionWorld::RayResultCallback* BtRayResult = NULL;
  138. btCollisionWorld::ClosestRayResultCallback* BtRayResult_Closest;
  139. btCollisionWorld::AllHitsRayResultCallback* BtRayResult_AllHits;
  140. switch (RaycastType)
  141. {
  142. case ERT_Closest:
  143. {
  144. if (SourceCaster)
  145. BtRayResult_Closest = new ClosestNotMeRayResultCallback(SourceCaster->m_collision_object, LOL2BTU_VEC3(RayFrom), LOL2BTU_VEC3(RayTo));
  146. else
  147. BtRayResult_Closest = new btCollisionWorld::ClosestRayResultCallback(LOL2BTU_VEC3(RayFrom), LOL2BTU_VEC3(RayTo));
  148. BtRayResult = BtRayResult_Closest;
  149. break;
  150. }
  151. case ERT_AllHit:
  152. {
  153. BtRayResult_AllHits = new btCollisionWorld::AllHitsRayResultCallback(LOL2BTU_VEC3(RayFrom), LOL2BTU_VEC3(RayTo));
  154. BtRayResult = BtRayResult_AllHits;
  155. break;
  156. }
  157. case ERT_AnyHit:
  158. {
  159. BtRayResult_Closest = new AnyHitRayResultCallback(LOL2BTU_VEC3(RayFrom), LOL2BTU_VEC3(RayTo));
  160. BtRayResult = BtRayResult_Closest;
  161. break;
  162. }
  163. }
  164. m_dynamics_world->rayTest(LOL2BTU_VEC3(RayFrom), LOL2BTU_VEC3(RayTo), *BtRayResult);
  165. if (BtRayResult->hasHit())
  166. {
  167. bResult = true;
  168. switch (RaycastType)
  169. {
  170. case ERT_Closest:
  171. {
  172. HitResult.m_collider_list << (EasyPhysic*)BtRayResult_Closest->m_collisionObject->getUserPointer();
  173. HitResult.m_hit_normal_list << BT2LOLU_VEC3(BtRayResult_Closest->m_hitNormalWorld);
  174. HitResult.m_hit_point_list << BT2LOLU_VEC3(BtRayResult_Closest->m_hitPointWorld);
  175. HitResult.m_hit_fraction_list << BtRayResult_Closest->m_closestHitFraction;
  176. break;
  177. }
  178. case ERT_AllHit:
  179. {
  180. for (int i = 0; i < BtRayResult_AllHits->m_collisionObjects.size(); i++)
  181. {
  182. HitResult.m_collider_list << (EasyPhysic*)BtRayResult_AllHits->m_collisionObjects[i]->getUserPointer();
  183. HitResult.m_hit_normal_list << BT2LOLU_VEC3(BtRayResult_AllHits->m_hitNormalWorld[i]);
  184. HitResult.m_hit_point_list << BT2LOLU_VEC3(BtRayResult_AllHits->m_hitPointWorld[i]);
  185. HitResult.m_hit_fraction_list << BtRayResult_AllHits->m_hitFractions[i];
  186. }
  187. break;
  188. }
  189. }
  190. }
  191. delete BtRayResult;
  192. return bResult;
  193. }
  194. void Exit()
  195. {
  196. delete m_dynamics_world;
  197. delete m_solver;
  198. delete m_dispatcher;
  199. delete m_collision_configuration;
  200. delete m_broadphase;
  201. }
  202. btDiscreteDynamicsWorld* GetWorld()
  203. {
  204. return m_dynamics_world;
  205. }
  206. private:
  207. void CustomSetContinuousDetection(bool ShouldUseCCD)
  208. {
  209. if (m_dynamics_world)
  210. m_dynamics_world->getDispatchInfo().m_useContinuous = ShouldUseCCD;
  211. }
  212. void CustomSetGravity(vec3 &NewGravity)
  213. {
  214. if (m_dynamics_world)
  215. m_dynamics_world->setGravity(LOL2BT_VEC3(NewGravity * LOL2BT_UNIT));
  216. }
  217. void CustomSetWorldLimit(vec3 const &NewWorldMin, vec3 const &NewWorldMax)
  218. {
  219. }
  220. void CustomSetTimestep(float NewTimestep) { }
  221. //broadphase
  222. btBroadphaseInterface* m_broadphase;
  223. btAxisSweep3* m_Sweep_broadphase;
  224. // Set up the collision configuration and dispatc
  225. btDefaultCollisionConfiguration* m_collision_configuration;
  226. btCollisionDispatcher* m_dispatcher;
  227. // The actual physics solver
  228. btSequentialImpulseConstraintSolver* m_solver;
  229. // The world.
  230. btDiscreteDynamicsWorld* m_dynamics_world;
  231. #else // NO PHYSIC IMPLEMENTATION
  232. public:
  233. void Init() { }
  234. void TickGame(float seconds) { }
  235. bool RayHits(RayCastResult& HitResult, eRaycastType RaycastType, const vec3& RayFrom, const vec3& RayTo, EasyPhysic* SourceCaster=NULL) { return false; }
  236. void Exit() { }
  237. private:
  238. void CustomSetContinuousDetection(bool ShouldUseCCD) { }
  239. void CustomSetGravity(vec3 &NewGravity) { }
  240. void CustomSetWorldLimit(vec3 &NewWorldMin, vec3 &NewWorldMax) { }
  241. void CustomSetTimestep(float NewTimestep) { }
  242. #endif // PHYSIC IMPLEMENTATION
  243. public:
  244. //Main logic :
  245. //The Set*() functions do the all-lib-independent data storage.
  246. //And then it calls the CustomSet*() which are the specialized versions.
  247. //Sets the continuous collision detection flag.
  248. void SetContinuousDetection(bool ShouldUseCCD)
  249. {
  250. m_using_CCD = ShouldUseCCD;
  251. CustomSetContinuousDetection(ShouldUseCCD);
  252. }
  253. //Sets the simulation gravity.
  254. void SetGravity(vec3 &NewGravity)
  255. {
  256. m_gravity = NewGravity;
  257. CustomSetGravity(NewGravity);
  258. }
  259. //Sets the simulation gravity.
  260. void SetWorldLimit(vec3 const &NewWorldMin, vec3 const &NewWorldMax)
  261. {
  262. m_world_min = NewWorldMin;
  263. m_world_max = NewWorldMax;
  264. CustomSetWorldLimit(NewWorldMin, NewWorldMax);
  265. }
  266. //Sets the simulation fixed timestep.
  267. void SetTimestep(float NewTimestep)
  268. {
  269. if (NewTimestep > .0f)
  270. {
  271. m_timestep = NewTimestep;
  272. CustomSetTimestep(NewTimestep);
  273. }
  274. }
  275. private:
  276. friend class EasyPhysic;
  277. friend class EasyCharacterController;
  278. friend class EasyConstraint;
  279. enum eEasyPhysicType
  280. {
  281. EEPT_Dynamic,
  282. EEPT_Static,
  283. EEPT_Ghost,
  284. EEPT_CollisionObject,
  285. EEPT_CharacterController,
  286. EEPT_MAX
  287. };
  288. //m_owner_simulation
  289. //Adds the given EasyPhysic to the correct list.
  290. void ObjectRegistration(bool AddObject, EasyPhysic* NewEP, eEasyPhysicType CurType)
  291. {
  292. Array<EasyPhysic*>* SearchList = NULL;
  293. switch(CurType)
  294. {
  295. case EEPT_Dynamic:
  296. {
  297. SearchList = &m_dynamic_list;
  298. break;
  299. }
  300. case EEPT_Static:
  301. {
  302. SearchList = &m_static_list;
  303. break;
  304. }
  305. case EEPT_Ghost:
  306. {
  307. SearchList = &m_ghost_list;
  308. break;
  309. }
  310. case EEPT_CollisionObject:
  311. {
  312. SearchList = &m_collision_object_list;
  313. break;
  314. }
  315. case EEPT_CharacterController:
  316. {
  317. SearchList = &m_character_controller_list;
  318. break;
  319. }
  320. }
  321. if (AddObject)
  322. {
  323. NewEP->m_owner_simulation = this;
  324. (*SearchList) << NewEP;
  325. }
  326. else
  327. {
  328. NewEP->m_owner_simulation = NULL;
  329. for (int i = 0; i < SearchList->Count(); ++i)
  330. {
  331. if ((*SearchList)[i] == NewEP)
  332. {
  333. SearchList->Remove(i--);
  334. break;
  335. }
  336. }
  337. }
  338. }
  339. void ObjectRegistration(bool AddObject, EasyConstraint* NewEC)
  340. {
  341. Array<EasyConstraint*>* SearchList = NULL;
  342. SearchList = &m_constraint_list;
  343. if (AddObject)
  344. {
  345. NewEC->m_owner_simulation = this;
  346. (*SearchList) << NewEC;
  347. }
  348. else
  349. {
  350. NewEC->m_owner_simulation = NULL;
  351. for (int i = 0; i < SearchList->Count(); ++i)
  352. {
  353. if ((*SearchList)[i] == NewEC)
  354. {
  355. SearchList->Remove(i--);
  356. break;
  357. }
  358. }
  359. }
  360. }
  361. //Easy Physics body List
  362. Array<EasyPhysic*> m_dynamic_list;
  363. Array<EasyPhysic*> m_static_list;
  364. Array<EasyPhysic*> m_ghost_list;
  365. Array<EasyPhysic*> m_collision_object_list;
  366. Array<EasyPhysic*> m_character_controller_list;
  367. Array<EasyConstraint*> m_constraint_list;
  368. //Easy Physics data storage
  369. float m_timestep;
  370. bool m_using_CCD;
  371. vec3 m_gravity;
  372. vec3 m_world_min;
  373. vec3 m_world_max;
  374. };
  375. } /* namespace phys */
  376. } /* namespace lol */
  377. #endif // __LOLPHYSICS_H__