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 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
  5. // (c) 2009-2013 Cdric Lecacheur <jordx@free.fr>
  6. // (c) 2009-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
  7. // This program is free software; you can redistribute it and/or
  8. // modify it under the terms of the Do What The Fuck You Want To
  9. // Public License, Version 2, as published by Sam Hocevar. See
  10. // http://www.wtfpl.net/ for more details.
  11. //
  12. #if defined HAVE_CONFIG_H
  13. # include "config.h"
  14. #endif
  15. #include "../Include/LolBtPhysicsIntegration.h"
  16. #include "../Include/LolPhysics.h"
  17. namespace lol
  18. {
  19. namespace phys
  20. {
  21. #ifdef HAVE_PHYS_USE_BULLET
  22. //-------------------------------------------------------------------------
  23. //EASY_PHYSIC
  24. //--
  25. EasyPhysic::EasyPhysic(WorldEntity* NewOwnerEntity) :
  26. m_collision_object(NULL),
  27. m_ghost_object(NULL),
  28. m_rigid_body(NULL),
  29. m_local_inertia(btVector3(.0f, .0f, .0f)),
  30. m_collision_shape(NULL),
  31. m_convex_shape(NULL),
  32. m_motion_state(NULL),
  33. m_mass(.0f),
  34. m_collision_group(1),
  35. m_collision_mask(1),
  36. m_owner_entity(NewOwnerEntity),
  37. m_owner_simulation(NULL),
  38. m_base_physic(NULL)
  39. {
  40. }
  41. EasyPhysic::~EasyPhysic()
  42. {
  43. m_rigid_body = NULL;
  44. delete m_collision_object;
  45. delete m_collision_shape;
  46. delete m_motion_state;
  47. }
  48. //-------------------------------------------------------------------------
  49. //Set Shape functions
  50. //--
  51. void EasyPhysic::SetShapeTo(btCollisionShape* collision_shape)
  52. {
  53. bool bReinitToRigidBody = false;
  54. if (m_rigid_body)
  55. {
  56. bReinitToRigidBody = true;
  57. delete m_rigid_body;
  58. }
  59. if (m_collision_shape)
  60. delete m_collision_shape;
  61. m_collision_shape = collision_shape;
  62. if (bReinitToRigidBody)
  63. InitBodyToRigid();
  64. }
  65. //Box Shape support
  66. void EasyPhysic::SetShapeToBox(lol::vec3& box_size)
  67. {
  68. vec3 new_box_size = box_size * LOL2BT_UNIT * LOL2BT_SIZE;
  69. m_convex_shape = new btBoxShape(LOL2BT_VEC3(new_box_size));
  70. SetShapeTo(m_convex_shape);
  71. }
  72. void EasyPhysic::SetShapeToSphere(float radius)
  73. {
  74. m_convex_shape = new btSphereShape(radius * LOL2BT_UNIT * LOL2BT_SIZE);
  75. SetShapeTo(m_convex_shape);
  76. }
  77. void EasyPhysic::SetShapeToCone(float radius, float height)
  78. {
  79. m_convex_shape = new btConeShape( radius * LOL2BT_UNIT,
  80. height * LOL2BT_UNIT);
  81. SetShapeTo(m_convex_shape);
  82. }
  83. void EasyPhysic::SetShapeToCylinder(lol::vec3& cyl_size)
  84. {
  85. vec3 new_cyl_size = cyl_size * LOL2BT_UNIT;
  86. new_cyl_size.y *= LOL2BT_SIZE;
  87. m_convex_shape = new btCylinderShape(LOL2BT_VEC3(new_cyl_size));
  88. SetShapeTo(m_convex_shape);
  89. }
  90. void EasyPhysic::SetShapeToCapsule(float radius, float height)
  91. {
  92. m_convex_shape = new btCapsuleShape(radius * LOL2BT_UNIT * LOL2BT_SIZE,
  93. height * LOL2BT_UNIT * LOL2BT_SIZE);
  94. SetShapeTo(m_convex_shape);
  95. }
  96. //-------------------------------------------------------------------------
  97. //Base Location/Rotation setup
  98. //--
  99. //Getter
  100. mat4 EasyPhysic::GetTransform()
  101. {
  102. m_local_to_world = lol::mat4(1.0f);
  103. if (m_rigid_body && m_motion_state)
  104. {
  105. btTransform CurTransform;
  106. m_motion_state->getWorldTransform(CurTransform);
  107. CurTransform.getOpenGLMatrix(&m_local_to_world[0][0]);
  108. }
  109. else if (m_collision_object)
  110. m_collision_object->getWorldTransform().getOpenGLMatrix(&m_local_to_world[0][0]);
  111. return m_local_to_world;
  112. }
  113. //Setter
  114. void EasyPhysic::SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation)
  115. {
  116. lol::mat4 PreviousMatrix = m_local_to_world;
  117. m_local_to_world = lol::mat4::translate(base_location) * lol::mat4(base_rotation);
  118. if (m_ghost_object)
  119. m_ghost_object->setWorldTransform(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(LOL2BT_UNIT * base_location)));
  120. else
  121. {
  122. if (m_motion_state)
  123. m_motion_state->setWorldTransform(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(LOL2BT_UNIT * base_location)));
  124. else
  125. m_motion_state = new btDefaultMotionState(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(LOL2BT_UNIT * base_location)));
  126. }
  127. for (int i = 0; i < m_based_physic_list.Count(); i++)
  128. {
  129. if (m_based_physic_list[i])
  130. m_based_physic_list[i]->BaseTransformChanged(PreviousMatrix, m_local_to_world);
  131. else
  132. m_based_physic_list.Remove(i--);
  133. }
  134. }
  135. //Internal callback when Base transform has changed.
  136. void EasyPhysic::BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix)
  137. {
  138. mat4 PreviousMatrixLoc = ((m_base_lock_location)?(PreviousMatrix):(lol::mat4::translate(PreviousMatrix.v3.xyz)));
  139. mat4 PreviousMatrixRot = ((m_base_lock_rotation)?(lol::mat4(lol::quat(PreviousMatrix))):(lol::mat4(1.f)));
  140. mat4 NewMatrixLoc = ((m_base_lock_location)?(NewMatrix):(lol::mat4::translate(NewMatrix.v3.xyz)));
  141. mat4 NewMatrixRot = ((m_base_lock_rotation)?(lol::mat4(lol::quat(NewMatrix))):(lol::mat4(1.f)));
  142. if (m_ghost_object || (m_rigid_body->getCollisionFlags() & btCollisionObject::CF_KINEMATIC_OBJECT))
  143. {
  144. mat4 ThisMatrixLoc = NewMatrixLoc * inverse(PreviousMatrixLoc) * lol::mat4::translate(m_local_to_world.v3.xyz);
  145. mat4 ThisMatrixRot = NewMatrixRot * inverse(PreviousMatrixRot) * lol::mat4(lol::quat(m_local_to_world));
  146. SetTransform(ThisMatrixLoc.v3.xyz, lol::mat4(lol::quat(ThisMatrixRot)));
  147. }
  148. }
  149. //-------------------------------------------------------------------------
  150. //Mass related functions
  151. //--
  152. //Set Shape functions
  153. void EasyPhysic::SetMass(float mass)
  154. {
  155. m_mass = mass;
  156. if (m_rigid_body)
  157. {
  158. SetLocalInertia(m_mass);
  159. m_rigid_body->setMassProps(mass, m_local_inertia);
  160. }
  161. }
  162. //-------------------------------------------------------------------------
  163. //Final conversion pass functons : Body related
  164. //--
  165. //Init to rigid body
  166. void EasyPhysic::InitBodyToRigid(bool SetToKinematic)
  167. {
  168. if (m_collision_object)
  169. delete m_collision_object;
  170. if (!m_motion_state)
  171. SetTransform(vec3(.0f));
  172. btRigidBody::btRigidBodyConstructionInfo NewInfos(m_mass, m_motion_state, m_collision_shape, m_local_inertia);
  173. m_rigid_body = new btRigidBody(NewInfos);
  174. m_collision_object = m_rigid_body;
  175. m_collision_object->setUserPointer(this);
  176. if (m_mass == .0f)
  177. {
  178. if (SetToKinematic)
  179. {
  180. m_rigid_body->setActivationState(DISABLE_DEACTIVATION);
  181. m_rigid_body->setCollisionFlags(m_rigid_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
  182. }
  183. }
  184. else
  185. SetMass(m_mass);
  186. }
  187. //Return correct Ghost Object
  188. btGhostObject* EasyPhysic::GetGhostObjectInstance()
  189. {
  190. return new btGhostObject();
  191. }
  192. //Init to Ghost object, for Overlap/Sweep Test/Touching logic
  193. void EasyPhysic::InitBodyToGhost()
  194. {
  195. if (m_collision_object)
  196. delete m_collision_object;
  197. m_ghost_object = GetGhostObjectInstance();
  198. m_ghost_object->setCollisionShape(m_collision_shape);
  199. m_collision_object = m_ghost_object;
  200. m_collision_object->setUserPointer(this);
  201. SetTransform(m_local_to_world.v3.xyz, lol::quat(m_local_to_world));
  202. m_ghost_object->setCollisionFlags(m_ghost_object->getCollisionFlags());
  203. }
  204. //-------------
  205. //Touch logic
  206. //-------------
  207. // btManifoldArray manifoldArray;
  208. // btBroadphasePairArray& pairArray = ghostObject->getOverlappingPairCache()->getOverlappingPairArray();
  209. // int numPairs = pairArray.size();
  210. // for (int i=0;i<numPairs;i++)
  211. // {
  212. // manifoldArray.clear();
  213. // const btBroadphasePair& pair = pairArray[i];
  214. //
  215. // //unless we manually perform collision detection on this pair, the contacts are in the dynamics world paircache:
  216. // btBroadphasePair* collisionPair = dynamicsWorld->getPairCache()->findPair(pair.m_pProxy0,pair.m_pProxy1);
  217. // if (!collisionPair)
  218. // continue;
  219. // if (collisionPair->m_algorithm)
  220. // collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
  221. // for (int j=0;j<manifoldArray.size();j++)
  222. // {
  223. // btPersistentManifold* manifold = manifoldArray[j];
  224. // btScalar directionSign = manifold->getBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0);
  225. // for (int p=0;p<manifold->getNumContacts();p++)
  226. // {
  227. // const btManifoldPoint&pt = manifold->getContactPoint(p);
  228. // if (pt.getDistance()<0.f)
  229. //{
  230. // const btVector3& ptA = pt.getPositionWorldOnA();
  231. // const btVector3& ptB = pt.getPositionWorldOnB();
  232. // const btVector3& normalOnB = pt.m_normalWorldOnB;
  233. // /// work here
  234. //}
  235. // }
  236. // }
  237. // }
  238. //Add Physic object to the simulation
  239. void EasyPhysic::AddToSimulation(class Simulation* current_simulation)
  240. {
  241. btDiscreteDynamicsWorld* dynamics_world = current_simulation->GetWorld();
  242. if (dynamics_world)
  243. {
  244. if (m_ghost_object)
  245. {
  246. dynamics_world->addCollisionObject(m_ghost_object, m_collision_group, m_collision_mask);
  247. current_simulation->ObjectRegistration(true, this, Simulation::EEPT_Ghost);
  248. }
  249. else if (m_rigid_body)
  250. {
  251. dynamics_world->addRigidBody(m_rigid_body, m_collision_group, m_collision_mask);
  252. if (m_mass != .0f)
  253. current_simulation->ObjectRegistration(true, this, Simulation::EEPT_Dynamic);
  254. else
  255. current_simulation->ObjectRegistration(true, this, Simulation::EEPT_Static);
  256. }
  257. else
  258. {
  259. dynamics_world->addCollisionObject(m_collision_object, m_collision_group, m_collision_mask);
  260. current_simulation->ObjectRegistration(true, this, Simulation::EEPT_CollisionObject);
  261. }
  262. }
  263. }
  264. //Remove Physic object to the simulation
  265. void EasyPhysic::RemoveFromSimulation(class Simulation* current_simulation)
  266. {
  267. btDiscreteDynamicsWorld* dynamics_world = current_simulation->GetWorld();
  268. if (dynamics_world)
  269. {
  270. if (m_rigid_body)
  271. {
  272. dynamics_world->removeRigidBody(m_rigid_body);
  273. if (m_mass != .0f)
  274. current_simulation->ObjectRegistration(false, this, Simulation::EEPT_Dynamic);
  275. else
  276. current_simulation->ObjectRegistration(false, this, Simulation::EEPT_Static);
  277. }
  278. else
  279. {
  280. dynamics_world->removeCollisionObject(m_collision_object);
  281. if (m_ghost_object)
  282. current_simulation->ObjectRegistration(false, this, Simulation::EEPT_Ghost);
  283. current_simulation->ObjectRegistration(false, this, Simulation::EEPT_CollisionObject);
  284. }
  285. }
  286. }
  287. //Set Local Inertia
  288. void EasyPhysic::SetLocalInertia(float mass)
  289. {
  290. if (mass != .0f)
  291. m_collision_shape->calculateLocalInertia(mass, m_local_inertia);
  292. else
  293. m_local_inertia = btVector3(.0f, .0f, .0f);
  294. }
  295. #endif // HAVE_PHYS_USE_BULLET
  296. } /* namespace phys */
  297. } /* namespace lol */