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