305 wiersze
8.2 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net>
  5. // (c) 2009-2012 Cédric Lecacheur <jordx@free.fr>
  6. // (c) 2009-2012 Benjamin 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://sam.zoy.org/projects/COPYING.WTFPL 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() :
  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. {
  37. }
  38. EasyPhysic::~EasyPhysic()
  39. {
  40. m_rigid_body = NULL;
  41. delete m_collision_object;
  42. delete m_collision_shape;
  43. delete m_motion_state;
  44. }
  45. //-------------------------------------------------------------------------
  46. //Set Shape functions
  47. //--
  48. void EasyPhysic::SetShapeTo(btCollisionShape* collision_shape)
  49. {
  50. bool bReinitToRigidBody = false;
  51. if (m_rigid_body)
  52. {
  53. bReinitToRigidBody = true;
  54. delete m_rigid_body;
  55. }
  56. if (m_collision_shape)
  57. delete m_collision_shape;
  58. m_collision_shape = collision_shape;
  59. if (bReinitToRigidBody)
  60. InitBodyToRigid();
  61. }
  62. //Box Shape support
  63. void EasyPhysic::SetShapeToBox(lol::vec3& box_size)
  64. {
  65. vec3 new_box_size = box_size * LOL2BT_UNIT * LOL2BT_SIZE;
  66. m_convex_shape = new btBoxShape(LOL2BT_VEC3(new_box_size));
  67. SetShapeTo(m_convex_shape);
  68. }
  69. void EasyPhysic::SetShapeToSphere(float radius)
  70. {
  71. m_convex_shape = new btSphereShape(radius * LOL2BT_UNIT * LOL2BT_SIZE);
  72. SetShapeTo(m_convex_shape);
  73. }
  74. void EasyPhysic::SetShapeToCone(float radius, float height)
  75. {
  76. m_convex_shape = new btConeShape( radius * LOL2BT_UNIT,
  77. height * LOL2BT_UNIT);
  78. SetShapeTo(m_convex_shape);
  79. }
  80. void EasyPhysic::SetShapeToCylinder(lol::vec3& cyl_size)
  81. {
  82. vec3 new_cyl_size = cyl_size * LOL2BT_UNIT;
  83. new_cyl_size.y *= LOL2BT_SIZE;
  84. m_convex_shape = new btCylinderShape(LOL2BT_VEC3(new_cyl_size));
  85. SetShapeTo(m_convex_shape);
  86. }
  87. void EasyPhysic::SetShapeToCapsule(float radius, float height)
  88. {
  89. m_convex_shape = new btCapsuleShape(radius * LOL2BT_UNIT * LOL2BT_SIZE,
  90. height * LOL2BT_UNIT * LOL2BT_SIZE);
  91. SetShapeTo(m_convex_shape);
  92. }
  93. //-------------------------------------------------------------------------
  94. //Base Location/Rotation setup
  95. //--
  96. void EasyPhysic::SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation)
  97. {
  98. m_local_to_world = lol::mat4::translate(base_location) * mat4(base_rotation);
  99. if (m_ghost_object)
  100. m_ghost_object->setWorldTransform(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(base_location * LOL2BT_UNIT)));
  101. else
  102. {
  103. if (m_motion_state)
  104. m_motion_state->setWorldTransform(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(base_location * LOL2BT_UNIT)));
  105. else
  106. m_motion_state = new btDefaultMotionState(btTransform(LOL2BT_QUAT(base_rotation), LOL2BT_VEC3(base_location * LOL2BT_UNIT)));
  107. }
  108. }
  109. //-------------------------------------------------------------------------
  110. //Mass related functions
  111. //--
  112. //Set Shape functions
  113. void EasyPhysic::SetMass(float mass)
  114. {
  115. m_mass = mass;
  116. if (m_rigid_body)
  117. {
  118. SetLocalInertia(m_mass);
  119. m_rigid_body->setMassProps(mass, m_local_inertia);
  120. }
  121. }
  122. //-------------------------------------------------------------------------
  123. //Final conversion pass functons : Body related
  124. //--
  125. //Init to rigid body
  126. void EasyPhysic::InitBodyToRigid(bool SetToKinematic)
  127. {
  128. if (m_collision_object)
  129. delete m_collision_object;
  130. if (!m_motion_state)
  131. SetTransform(vec3(.0f));
  132. btRigidBody::btRigidBodyConstructionInfo NewInfos(m_mass, m_motion_state, m_collision_shape, m_local_inertia);
  133. m_rigid_body = new btRigidBody(NewInfos);
  134. m_collision_object = m_rigid_body;
  135. m_collision_object->setUserPointer(this);
  136. if (m_mass == .0f)
  137. {
  138. if (SetToKinematic)
  139. {
  140. m_rigid_body->setActivationState(DISABLE_DEACTIVATION);
  141. m_rigid_body->setCollisionFlags(m_rigid_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
  142. }
  143. }
  144. else
  145. SetMass(m_mass);
  146. }
  147. //Return correct Ghost Object
  148. btGhostObject* EasyPhysic::GetGhostObject()
  149. {
  150. return new btGhostObject();
  151. }
  152. //Init to Ghost object, for Overlap/Sweep Test/Touching logic
  153. void EasyPhysic::InitBodyToGhost()
  154. {
  155. if (m_collision_object)
  156. delete m_collision_object;
  157. m_ghost_object = GetGhostObject();
  158. m_ghost_object->setCollisionShape(m_collision_shape);
  159. m_collision_object = m_ghost_object;
  160. m_collision_object->setUserPointer(this);
  161. SetTransform(m_local_to_world.v3.xyz, lol::quat(m_local_to_world));
  162. m_ghost_object->setCollisionFlags(m_ghost_object->getCollisionFlags());
  163. }
  164. //-------------
  165. //Touch logic
  166. //-------------
  167. // btManifoldArray manifoldArray;
  168. // btBroadphasePairArray& pairArray = ghostObject->getOverlappingPairCache()->getOverlappingPairArray();
  169. // int numPairs = pairArray.size();
  170. // for (int i=0;i<numPairs;i++)
  171. // {
  172. // manifoldArray.clear();
  173. // const btBroadphasePair& pair = pairArray[i];
  174. //
  175. // //unless we manually perform collision detection on this pair, the contacts are in the dynamics world paircache:
  176. // btBroadphasePair* collisionPair = dynamicsWorld->getPairCache()->findPair(pair.m_pProxy0,pair.m_pProxy1);
  177. // if (!collisionPair)
  178. // continue;
  179. // if (collisionPair->m_algorithm)
  180. // collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
  181. // for (int j=0;j<manifoldArray.size();j++)
  182. // {
  183. // btPersistentManifold* manifold = manifoldArray[j];
  184. // btScalar directionSign = manifold->getBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0);
  185. // for (int p=0;p<manifold->getNumContacts();p++)
  186. // {
  187. // const btManifoldPoint&pt = manifold->getContactPoint(p);
  188. // if (pt.getDistance()<0.f)
  189. //{
  190. // const btVector3& ptA = pt.getPositionWorldOnA();
  191. // const btVector3& ptB = pt.getPositionWorldOnB();
  192. // const btVector3& normalOnB = pt.m_normalWorldOnB;
  193. // /// work here
  194. //}
  195. // }
  196. // }
  197. // }
  198. //Add Physic object to the simulation
  199. void EasyPhysic::AddToSimulation(class Simulation* current_simulation)
  200. {
  201. btDiscreteDynamicsWorld* dynamics_world = current_simulation->GetWorld();
  202. if (dynamics_world)
  203. {
  204. if (m_ghost_object)
  205. {
  206. dynamics_world->addCollisionObject(m_ghost_object, m_collision_group, m_collision_mask);
  207. current_simulation->AddToGhost(this);
  208. }
  209. else if (m_rigid_body)
  210. {
  211. dynamics_world->addRigidBody(m_rigid_body, m_collision_group, m_collision_mask);
  212. if (m_mass != .0f)
  213. current_simulation->AddToDynamic(this);
  214. else
  215. current_simulation->AddToStatic(this);
  216. }
  217. else
  218. dynamics_world->addCollisionObject(m_collision_object, m_collision_group, m_collision_mask);
  219. }
  220. }
  221. //Remove Physic object to the simulation
  222. void EasyPhysic::RemoveFromSimulation(class Simulation* current_simulation)
  223. {
  224. btDiscreteDynamicsWorld* dynamics_world = current_simulation->GetWorld();
  225. if (dynamics_world)
  226. {
  227. if (m_rigid_body)
  228. dynamics_world->removeRigidBody(m_rigid_body);
  229. else if (m_collision_object)
  230. dynamics_world->removeCollisionObject(m_collision_object);
  231. }
  232. }
  233. //-------------------------------------------------------------------------
  234. //Getter functons
  235. //--
  236. mat4 EasyPhysic::GetTransform()
  237. {
  238. m_local_to_world = lol::mat4(1.0f);
  239. if (m_rigid_body && m_motion_state)
  240. {
  241. btTransform CurTransform;
  242. m_motion_state->getWorldTransform(CurTransform);
  243. CurTransform.getOpenGLMatrix(&m_local_to_world[0][0]);
  244. }
  245. else if (m_collision_object)
  246. m_collision_object->getWorldTransform().getOpenGLMatrix(&m_local_to_world[0][0]);
  247. return m_local_to_world;
  248. }
  249. //Set Local Inertia
  250. void EasyPhysic::SetLocalInertia(float mass)
  251. {
  252. if (mass != .0f)
  253. m_collision_shape->calculateLocalInertia(mass, m_local_inertia);
  254. else
  255. m_local_inertia = btVector3(.0f, .0f, .0f);
  256. }
  257. #endif // HAVE_PHYS_USE_BULLET
  258. } /* namespace phys */
  259. } /* namespace lol */