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