b2_contact.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. // MIT License
  2. // Copyright (c) 2019 Erin Catto
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. // The above copyright notice and this permission notice shall be included in all
  10. // copies or substantial portions of the Software.
  11. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  17. // SOFTWARE.
  18. #ifndef B2_CONTACT_H
  19. #define B2_CONTACT_H
  20. #include "b2_api.h"
  21. #include "b2_collision.h"
  22. #include "b2_fixture.h"
  23. #include "b2_math.h"
  24. #include "b2_shape.h"
  25. class b2Body;
  26. class b2Contact;
  27. class b2Fixture;
  28. class b2World;
  29. class b2BlockAllocator;
  30. class b2StackAllocator;
  31. class b2ContactListener;
  32. /// Friction mixing law. The idea is to allow either fixture to drive the friction to zero.
  33. /// For example, anything slides on ice.
  34. inline float b2MixFriction(float friction1, float friction2)
  35. {
  36. return b2Sqrt(friction1 * friction2);
  37. }
  38. /// Restitution mixing law. The idea is allow for anything to bounce off an inelastic surface.
  39. /// For example, a superball bounces on anything.
  40. inline float b2MixRestitution(float restitution1, float restitution2)
  41. {
  42. return restitution1 > restitution2 ? restitution1 : restitution2;
  43. }
  44. /// Restitution mixing law. This picks the lowest value.
  45. inline float b2MixRestitutionThreshold(float threshold1, float threshold2)
  46. {
  47. return threshold1 < threshold2 ? threshold1 : threshold2;
  48. }
  49. typedef b2Contact* b2ContactCreateFcn( b2Fixture* fixtureA, int32 indexA,
  50. b2Fixture* fixtureB, int32 indexB,
  51. b2BlockAllocator* allocator);
  52. typedef void b2ContactDestroyFcn(b2Contact* contact, b2BlockAllocator* allocator);
  53. struct B2_API b2ContactRegister
  54. {
  55. b2ContactCreateFcn* createFcn;
  56. b2ContactDestroyFcn* destroyFcn;
  57. bool primary;
  58. };
  59. /// A contact edge is used to connect bodies and contacts together
  60. /// in a contact graph where each body is a node and each contact
  61. /// is an edge. A contact edge belongs to a doubly linked list
  62. /// maintained in each attached body. Each contact has two contact
  63. /// nodes, one for each attached body.
  64. struct B2_API b2ContactEdge
  65. {
  66. b2Body* other; ///< provides quick access to the other body attached.
  67. b2Contact* contact; ///< the contact
  68. b2ContactEdge* prev; ///< the previous contact edge in the body's contact list
  69. b2ContactEdge* next; ///< the next contact edge in the body's contact list
  70. };
  71. /// The class manages contact between two shapes. A contact exists for each overlapping
  72. /// AABB in the broad-phase (except if filtered). Therefore a contact object may exist
  73. /// that has no contact points.
  74. class B2_API b2Contact
  75. {
  76. public:
  77. /// Get the contact manifold. Do not modify the manifold unless you understand the
  78. /// internals of Box2D.
  79. b2Manifold* GetManifold();
  80. const b2Manifold* GetManifold() const;
  81. /// Get the world manifold.
  82. void GetWorldManifold(b2WorldManifold* worldManifold) const;
  83. /// Is this contact touching?
  84. bool IsTouching() const;
  85. /// Enable/disable this contact. This can be used inside the pre-solve
  86. /// contact listener. The contact is only disabled for the current
  87. /// time step (or sub-step in continuous collisions).
  88. void SetEnabled(bool flag);
  89. /// Has this contact been disabled?
  90. bool IsEnabled() const;
  91. /// Get the next contact in the world's contact list.
  92. b2Contact* GetNext();
  93. const b2Contact* GetNext() const;
  94. /// Get fixture A in this contact.
  95. b2Fixture* GetFixtureA();
  96. const b2Fixture* GetFixtureA() const;
  97. /// Get the child primitive index for fixture A.
  98. int32 GetChildIndexA() const;
  99. /// Get fixture B in this contact.
  100. b2Fixture* GetFixtureB();
  101. const b2Fixture* GetFixtureB() const;
  102. /// Get the child primitive index for fixture B.
  103. int32 GetChildIndexB() const;
  104. /// Override the default friction mixture. You can call this in b2ContactListener::PreSolve.
  105. /// This value persists until set or reset.
  106. void SetFriction(float friction);
  107. /// Get the friction.
  108. float GetFriction() const;
  109. /// Reset the friction mixture to the default value.
  110. void ResetFriction();
  111. /// Override the default restitution mixture. You can call this in b2ContactListener::PreSolve.
  112. /// The value persists until you set or reset.
  113. void SetRestitution(float restitution);
  114. /// Get the restitution.
  115. float GetRestitution() const;
  116. /// Reset the restitution to the default value.
  117. void ResetRestitution();
  118. /// Override the default restitution velocity threshold mixture. You can call this in b2ContactListener::PreSolve.
  119. /// The value persists until you set or reset.
  120. void SetRestitutionThreshold(float threshold);
  121. /// Get the restitution threshold.
  122. float GetRestitutionThreshold() const;
  123. /// Reset the restitution threshold to the default value.
  124. void ResetRestitutionThreshold();
  125. /// Set the desired tangent speed for a conveyor belt behavior. In meters per second.
  126. void SetTangentSpeed(float speed);
  127. /// Get the desired tangent speed. In meters per second.
  128. float GetTangentSpeed() const;
  129. /// Evaluate this contact with your own manifold and transforms.
  130. virtual void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) = 0;
  131. protected:
  132. friend class b2ContactManager;
  133. friend class b2World;
  134. friend class b2ContactSolver;
  135. friend class b2Body;
  136. friend class b2Fixture;
  137. // Flags stored in m_flags
  138. enum
  139. {
  140. // Used when crawling contact graph when forming islands.
  141. e_islandFlag = 0x0001,
  142. // Set when the shapes are touching.
  143. e_touchingFlag = 0x0002,
  144. // This contact can be disabled (by user)
  145. e_enabledFlag = 0x0004,
  146. // This contact needs filtering because a fixture filter was changed.
  147. e_filterFlag = 0x0008,
  148. // This bullet contact had a TOI event
  149. e_bulletHitFlag = 0x0010,
  150. // This contact has a valid TOI in m_toi
  151. e_toiFlag = 0x0020
  152. };
  153. /// Flag this contact for filtering. Filtering will occur the next time step.
  154. void FlagForFiltering();
  155. static void AddType(b2ContactCreateFcn* createFcn, b2ContactDestroyFcn* destroyFcn,
  156. b2Shape::Type typeA, b2Shape::Type typeB);
  157. static void InitializeRegisters();
  158. static b2Contact* Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator);
  159. static void Destroy(b2Contact* contact, b2Shape::Type typeA, b2Shape::Type typeB, b2BlockAllocator* allocator);
  160. static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);
  161. b2Contact() : m_fixtureA(nullptr), m_fixtureB(nullptr) {}
  162. b2Contact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB);
  163. virtual ~b2Contact() {}
  164. void Update(b2ContactListener* listener);
  165. static b2ContactRegister s_registers[b2Shape::e_typeCount][b2Shape::e_typeCount];
  166. static bool s_initialized;
  167. uint32 m_flags;
  168. // World pool and list pointers.
  169. b2Contact* m_prev;
  170. b2Contact* m_next;
  171. // Nodes for connecting bodies.
  172. b2ContactEdge m_nodeA;
  173. b2ContactEdge m_nodeB;
  174. b2Fixture* m_fixtureA;
  175. b2Fixture* m_fixtureB;
  176. int32 m_indexA;
  177. int32 m_indexB;
  178. b2Manifold m_manifold;
  179. int32 m_toiCount;
  180. float m_toi;
  181. float m_friction;
  182. float m_restitution;
  183. float m_restitutionThreshold;
  184. float m_tangentSpeed;
  185. };
  186. inline b2Manifold* b2Contact::GetManifold()
  187. {
  188. return &m_manifold;
  189. }
  190. inline const b2Manifold* b2Contact::GetManifold() const
  191. {
  192. return &m_manifold;
  193. }
  194. inline void b2Contact::GetWorldManifold(b2WorldManifold* worldManifold) const
  195. {
  196. const b2Body* bodyA = m_fixtureA->GetBody();
  197. const b2Body* bodyB = m_fixtureB->GetBody();
  198. const b2Shape* shapeA = m_fixtureA->GetShape();
  199. const b2Shape* shapeB = m_fixtureB->GetShape();
  200. worldManifold->Initialize(&m_manifold, bodyA->GetTransform(), shapeA->m_radius, bodyB->GetTransform(), shapeB->m_radius);
  201. }
  202. inline void b2Contact::SetEnabled(bool flag)
  203. {
  204. if (flag)
  205. {
  206. m_flags |= e_enabledFlag;
  207. }
  208. else
  209. {
  210. m_flags &= ~e_enabledFlag;
  211. }
  212. }
  213. inline bool b2Contact::IsEnabled() const
  214. {
  215. return (m_flags & e_enabledFlag) == e_enabledFlag;
  216. }
  217. inline bool b2Contact::IsTouching() const
  218. {
  219. return (m_flags & e_touchingFlag) == e_touchingFlag;
  220. }
  221. inline b2Contact* b2Contact::GetNext()
  222. {
  223. return m_next;
  224. }
  225. inline const b2Contact* b2Contact::GetNext() const
  226. {
  227. return m_next;
  228. }
  229. inline b2Fixture* b2Contact::GetFixtureA()
  230. {
  231. return m_fixtureA;
  232. }
  233. inline const b2Fixture* b2Contact::GetFixtureA() const
  234. {
  235. return m_fixtureA;
  236. }
  237. inline b2Fixture* b2Contact::GetFixtureB()
  238. {
  239. return m_fixtureB;
  240. }
  241. inline int32 b2Contact::GetChildIndexA() const
  242. {
  243. return m_indexA;
  244. }
  245. inline const b2Fixture* b2Contact::GetFixtureB() const
  246. {
  247. return m_fixtureB;
  248. }
  249. inline int32 b2Contact::GetChildIndexB() const
  250. {
  251. return m_indexB;
  252. }
  253. inline void b2Contact::FlagForFiltering()
  254. {
  255. m_flags |= e_filterFlag;
  256. }
  257. inline void b2Contact::SetFriction(float friction)
  258. {
  259. m_friction = friction;
  260. }
  261. inline float b2Contact::GetFriction() const
  262. {
  263. return m_friction;
  264. }
  265. inline void b2Contact::ResetFriction()
  266. {
  267. m_friction = b2MixFriction(m_fixtureA->m_friction, m_fixtureB->m_friction);
  268. }
  269. inline void b2Contact::SetRestitution(float restitution)
  270. {
  271. m_restitution = restitution;
  272. }
  273. inline float b2Contact::GetRestitution() const
  274. {
  275. return m_restitution;
  276. }
  277. inline void b2Contact::ResetRestitution()
  278. {
  279. m_restitution = b2MixRestitution(m_fixtureA->m_restitution, m_fixtureB->m_restitution);
  280. }
  281. inline void b2Contact::SetRestitutionThreshold(float threshold)
  282. {
  283. m_restitutionThreshold = threshold;
  284. }
  285. inline float b2Contact::GetRestitutionThreshold() const
  286. {
  287. return m_restitutionThreshold;
  288. }
  289. inline void b2Contact::ResetRestitutionThreshold()
  290. {
  291. m_restitutionThreshold = b2MixRestitutionThreshold(m_fixtureA->m_restitutionThreshold, m_fixtureB->m_restitutionThreshold);
  292. }
  293. inline void b2Contact::SetTangentSpeed(float speed)
  294. {
  295. m_tangentSpeed = speed;
  296. }
  297. inline float b2Contact::GetTangentSpeed() const
  298. {
  299. return m_tangentSpeed;
  300. }
  301. #endif