The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

332 lines
9.1KB

  1. /*
  2. * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. * Permission is granted to anyone to use this software for any purpose,
  8. * including commercial applications, and to alter it and redistribute it
  9. * freely, subject to the following restrictions:
  10. * 1. The origin of this software must not be misrepresented; you must not
  11. * claim that you wrote the original software. If you use this software
  12. * in a product, an acknowledgment in the product documentation would be
  13. * appreciated but is not required.
  14. * 2. Altered source versions must be plainly marked as such, and must not be
  15. * misrepresented as being the original software.
  16. * 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #ifndef B2_CONTACT_H
  19. #define B2_CONTACT_H
  20. #include "../../Common/b2Math.h"
  21. #include "../../Collision/b2Collision.h"
  22. #include "../../Collision/Shapes/b2Shape.h"
  23. #include "../b2Fixture.h"
  24. class b2Body;
  25. class b2Contact;
  26. class b2Fixture;
  27. class b2World;
  28. class b2BlockAllocator;
  29. class b2StackAllocator;
  30. class b2ContactListener;
  31. /// Friction mixing law. The idea is to allow either fixture to drive the restitution to zero.
  32. /// For example, anything slides on ice.
  33. inline float32 b2MixFriction(float32 friction1, float32 friction2)
  34. {
  35. return std::sqrt(friction1 * friction2);
  36. }
  37. /// Restitution mixing law. The idea is allow for anything to bounce off an inelastic surface.
  38. /// For example, a superball bounces on anything.
  39. inline float32 b2MixRestitution(float32 restitution1, float32 restitution2)
  40. {
  41. return restitution1 > restitution2 ? restitution1 : restitution2;
  42. }
  43. typedef b2Contact* b2ContactCreateFcn( b2Fixture* fixtureA, juce::int32 indexA,
  44. b2Fixture* fixtureB, juce::int32 indexB,
  45. b2BlockAllocator* allocator);
  46. typedef void b2ContactDestroyFcn(b2Contact* contact, b2BlockAllocator* allocator);
  47. struct b2ContactRegister
  48. {
  49. b2ContactCreateFcn* createFcn;
  50. b2ContactDestroyFcn* destroyFcn;
  51. bool primary;
  52. };
  53. /// A contact edge is used to connect bodies and contacts together
  54. /// in a contact graph where each body is a node and each contact
  55. /// is an edge. A contact edge belongs to a doubly linked list
  56. /// maintained in each attached body. Each contact has two contact
  57. /// nodes, one for each attached body.
  58. struct b2ContactEdge
  59. {
  60. b2Body* other; ///< provides quick access to the other body attached.
  61. b2Contact* contact; ///< the contact
  62. b2ContactEdge* prev; ///< the previous contact edge in the body's contact list
  63. b2ContactEdge* next; ///< the next contact edge in the body's contact list
  64. };
  65. /// The class manages contact between two shapes. A contact exists for each overlapping
  66. /// AABB in the broad-phase (except if filtered). Therefore a contact object may exist
  67. /// that has no contact points.
  68. class b2Contact
  69. {
  70. public:
  71. /// Get the contact manifold. Do not modify the manifold unless you understand the
  72. /// internals of Box2D.
  73. b2Manifold* GetManifold();
  74. const b2Manifold* GetManifold() const;
  75. /// Get the world manifold.
  76. void GetWorldManifold(b2WorldManifold* worldManifold) const;
  77. /// Is this contact touching?
  78. bool IsTouching() const;
  79. /// Enable/disable this contact. This can be used inside the pre-solve
  80. /// contact listener. The contact is only disabled for the current
  81. /// time step (or sub-step in continuous collisions).
  82. void SetEnabled(bool flag);
  83. /// Has this contact been disabled?
  84. bool IsEnabled() const;
  85. /// Get the next contact in the world's contact list.
  86. b2Contact* GetNext();
  87. const b2Contact* GetNext() const;
  88. /// Get fixture A in this contact.
  89. b2Fixture* GetFixtureA();
  90. const b2Fixture* GetFixtureA() const;
  91. /// Get the child primitive index for fixture A.
  92. juce::int32 GetChildIndexA() const;
  93. /// Get fixture B in this contact.
  94. b2Fixture* GetFixtureB();
  95. const b2Fixture* GetFixtureB() const;
  96. /// Get the child primitive index for fixture B.
  97. juce::int32 GetChildIndexB() const;
  98. /// Override the default friction mixture. You can call this in b2ContactListener::PreSolve.
  99. /// This value persists until set or reset.
  100. void SetFriction(float32 friction);
  101. /// Get the friction.
  102. float32 GetFriction() const;
  103. /// Reset the friction mixture to the default value.
  104. void ResetFriction();
  105. /// Override the default restitution mixture. You can call this in b2ContactListener::PreSolve.
  106. /// The value persists until you set or reset.
  107. void SetRestitution(float32 restitution);
  108. /// Get the restitution.
  109. float32 GetRestitution() const;
  110. /// Reset the restitution to the default value.
  111. void ResetRestitution();
  112. /// Evaluate this contact with your own manifold and transforms.
  113. virtual void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) = 0;
  114. protected:
  115. friend class b2ContactManager;
  116. friend class b2World;
  117. friend class b2ContactSolver;
  118. friend class b2Body;
  119. friend class b2Fixture;
  120. // Flags stored in m_flags
  121. enum
  122. {
  123. // Used when crawling contact graph when forming islands.
  124. e_islandFlag = 0x0001,
  125. // Set when the shapes are touching.
  126. e_touchingFlag = 0x0002,
  127. // This contact can be disabled (by user)
  128. e_enabledFlag = 0x0004,
  129. // This contact needs filtering because a fixture filter was changed.
  130. e_filterFlag = 0x0008,
  131. // This bullet contact had a TOI event
  132. e_bulletHitFlag = 0x0010,
  133. // This contact has a valid TOI in m_toi
  134. e_toiFlag = 0x0020
  135. };
  136. /// Flag this contact for filtering. Filtering will occur the next time step.
  137. void FlagForFiltering();
  138. static void AddType(b2ContactCreateFcn* createFcn, b2ContactDestroyFcn* destroyFcn,
  139. b2Shape::Type typeA, b2Shape::Type typeB);
  140. static void InitializeRegisters();
  141. static b2Contact* Create(b2Fixture* fixtureA, juce::int32 indexA, b2Fixture* fixtureB, juce::int32 indexB, b2BlockAllocator* allocator);
  142. static void Destroy(b2Contact* contact, b2Shape::Type typeA, b2Shape::Type typeB, b2BlockAllocator* allocator);
  143. static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);
  144. b2Contact() : m_fixtureA(NULL), m_fixtureB(NULL) {}
  145. b2Contact(b2Fixture* fixtureA, juce::int32 indexA, b2Fixture* fixtureB, juce::int32 indexB);
  146. virtual ~b2Contact() {}
  147. void Update(b2ContactListener* listener);
  148. static b2ContactRegister s_registers[b2Shape::e_typeCount][b2Shape::e_typeCount];
  149. static bool s_initialized;
  150. juce::uint32 m_flags;
  151. // World pool and list pointers.
  152. b2Contact* m_prev;
  153. b2Contact* m_next;
  154. // Nodes for connecting bodies.
  155. b2ContactEdge m_nodeA;
  156. b2ContactEdge m_nodeB;
  157. b2Fixture* m_fixtureA;
  158. b2Fixture* m_fixtureB;
  159. juce::int32 m_indexA;
  160. juce::int32 m_indexB;
  161. b2Manifold m_manifold;
  162. juce::int32 m_toiCount;
  163. float32 m_toi;
  164. float32 m_friction;
  165. float32 m_restitution;
  166. };
  167. inline b2Manifold* b2Contact::GetManifold()
  168. {
  169. return &m_manifold;
  170. }
  171. inline const b2Manifold* b2Contact::GetManifold() const
  172. {
  173. return &m_manifold;
  174. }
  175. inline void b2Contact::GetWorldManifold(b2WorldManifold* worldManifold) const
  176. {
  177. const b2Body* bodyA = m_fixtureA->GetBody();
  178. const b2Body* bodyB = m_fixtureB->GetBody();
  179. const b2Shape* shapeA = m_fixtureA->GetShape();
  180. const b2Shape* shapeB = m_fixtureB->GetShape();
  181. worldManifold->Initialize(&m_manifold, bodyA->GetTransform(), shapeA->m_radius, bodyB->GetTransform(), shapeB->m_radius);
  182. }
  183. inline void b2Contact::SetEnabled(bool flag)
  184. {
  185. if (flag)
  186. {
  187. m_flags |= e_enabledFlag;
  188. }
  189. else
  190. {
  191. m_flags &= ~((unsigned int) e_enabledFlag);
  192. }
  193. }
  194. inline bool b2Contact::IsEnabled() const
  195. {
  196. return (m_flags & e_enabledFlag) == e_enabledFlag;
  197. }
  198. inline bool b2Contact::IsTouching() const
  199. {
  200. return (m_flags & e_touchingFlag) == e_touchingFlag;
  201. }
  202. inline b2Contact* b2Contact::GetNext()
  203. {
  204. return m_next;
  205. }
  206. inline const b2Contact* b2Contact::GetNext() const
  207. {
  208. return m_next;
  209. }
  210. inline b2Fixture* b2Contact::GetFixtureA()
  211. {
  212. return m_fixtureA;
  213. }
  214. inline const b2Fixture* b2Contact::GetFixtureA() const
  215. {
  216. return m_fixtureA;
  217. }
  218. inline b2Fixture* b2Contact::GetFixtureB()
  219. {
  220. return m_fixtureB;
  221. }
  222. inline juce::int32 b2Contact::GetChildIndexA() const
  223. {
  224. return m_indexA;
  225. }
  226. inline const b2Fixture* b2Contact::GetFixtureB() const
  227. {
  228. return m_fixtureB;
  229. }
  230. inline juce::int32 b2Contact::GetChildIndexB() const
  231. {
  232. return m_indexB;
  233. }
  234. inline void b2Contact::FlagForFiltering()
  235. {
  236. m_flags |= e_filterFlag;
  237. }
  238. inline void b2Contact::SetFriction(float32 friction)
  239. {
  240. m_friction = friction;
  241. }
  242. inline float32 b2Contact::GetFriction() const
  243. {
  244. return m_friction;
  245. }
  246. inline void b2Contact::ResetFriction()
  247. {
  248. m_friction = b2MixFriction(m_fixtureA->m_friction, m_fixtureB->m_friction);
  249. }
  250. inline void b2Contact::SetRestitution(float32 restitution)
  251. {
  252. m_restitution = restitution;
  253. }
  254. inline float32 b2Contact::GetRestitution() const
  255. {
  256. return m_restitution;
  257. }
  258. inline void b2Contact::ResetRestitution()
  259. {
  260. m_restitution = b2MixRestitution(m_fixtureA->m_restitution, m_fixtureB->m_restitution);
  261. }
  262. #endif