263 satır
6.6 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. #ifdef HAVE_PHYS_USE_BULLET
  16. #include "../Include/EasyPhysics.h"
  17. #endif // HAVE_PHYS_USE_BULLET
  18. namespace lol
  19. {
  20. namespace phys
  21. {
  22. #ifdef HAVE_PHYS_USE_BULLET
  23. //-------------------------------------------------------------------------
  24. //EASY_PHYSIC
  25. //--
  26. EasyPhysic::EasyPhysic() :
  27. m_collision_object(NULL),
  28. m_rigid_body(NULL),
  29. m_ghost_object(NULL),
  30. m_collision_shape(NULL),
  31. m_motion_state(NULL),
  32. m_mass(.0f),
  33. m_local_inertia(btVector3(.0f, .0f, .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. if (m_mass == .0f)
  136. {
  137. if (SetToKinematic)
  138. {
  139. m_rigid_body->setActivationState(DISABLE_DEACTIVATION);
  140. m_rigid_body->setCollisionFlags(m_rigid_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
  141. }
  142. }
  143. else
  144. SetMass(m_mass);
  145. }
  146. //Return correct Ghost Object
  147. btGhostObject* EasyPhysic::GetGhostObject()
  148. {
  149. return new btGhostObject();
  150. }
  151. //Init to Ghost object, for Overlap/Sweep Test/Touching logic
  152. void EasyPhysic::InitBodyToGhost()
  153. {
  154. if (m_collision_object)
  155. delete m_collision_object;
  156. m_ghost_object = GetGhostObject();
  157. m_ghost_object->setCollisionShape(m_collision_shape);
  158. m_collision_object = m_ghost_object;
  159. SetTransform(m_local_to_world.v3.xyz, lol::quat(m_local_to_world));
  160. m_ghost_object->setCollisionFlags(m_ghost_object->getCollisionFlags());
  161. }
  162. //Add Physic object to the simulation
  163. void EasyPhysic::AddToSimulation(class Simulation* current_simulation)
  164. {
  165. btDiscreteDynamicsWorld* dynamics_world = current_simulation->GetWorld();
  166. if (dynamics_world)
  167. {
  168. if (m_ghost_object)
  169. {
  170. dynamics_world->addCollisionObject(m_ghost_object, m_collision_group, m_collision_mask);
  171. current_simulation->AddToGhost(this);
  172. }
  173. else if (m_rigid_body)
  174. {
  175. dynamics_world->addRigidBody(m_rigid_body, m_collision_group, m_collision_mask);
  176. if (m_mass != .0f)
  177. current_simulation->AddToDynamic(this);
  178. else
  179. current_simulation->AddToStatic(this);
  180. }
  181. else
  182. dynamics_world->addCollisionObject(m_collision_object, m_collision_group, m_collision_mask);
  183. }
  184. }
  185. //Remove Physic object to the simulation
  186. void EasyPhysic::RemoveFromSimulation(class Simulation* current_simulation)
  187. {
  188. btDiscreteDynamicsWorld* dynamics_world = current_simulation->GetWorld();
  189. if (dynamics_world)
  190. {
  191. if (m_rigid_body)
  192. dynamics_world->removeRigidBody(m_rigid_body);
  193. else if (m_collision_object)
  194. dynamics_world->removeCollisionObject(m_collision_object);
  195. }
  196. }
  197. //-------------------------------------------------------------------------
  198. //Getter functons
  199. //--
  200. mat4 EasyPhysic::GetTransform()
  201. {
  202. m_local_to_world = lol::mat4(1.0f);
  203. if (m_rigid_body && m_motion_state)
  204. {
  205. btTransform CurTransform;
  206. m_motion_state->getWorldTransform(CurTransform);
  207. CurTransform.getOpenGLMatrix(&m_local_to_world[0][0]);
  208. }
  209. else if (m_collision_object)
  210. m_collision_object->getWorldTransform().getOpenGLMatrix(&m_local_to_world[0][0]);
  211. return m_local_to_world;
  212. }
  213. //Set Local Inertia
  214. void EasyPhysic::SetLocalInertia(float mass)
  215. {
  216. if (mass != .0f)
  217. m_collision_shape->calculateLocalInertia(mass, m_local_inertia);
  218. else
  219. m_local_inertia = btVector3(.0f, .0f, .0f);
  220. }
  221. #endif // HAVE_PHYS_USE_BULLET
  222. } /* namespace phys */
  223. } /* namespace lol */