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 19#ifndef B2_CONTACT_H 20#define B2_CONTACT_H 21 22#include <Box2D/Common/b2Math.h> 23#include <Box2D/Collision/b2Collision.h> 24#include <Box2D/Collision/Shapes/b2Shape.h> 25#include <Box2D/Dynamics/b2Fixture.h> 26 27class b2Body; 28class b2Contact; 29class b2Fixture; 30class b2World; 31class b2BlockAllocator; 32class b2StackAllocator; 33class b2ContactListener; 34 35/// Friction mixing law. The idea is to allow either fixture to drive the restitution to zero. 36/// For example, anything slides on ice. 37inline float32 b2MixFriction(float32 friction1, float32 friction2) 38{ 39 return b2Sqrt(friction1 * friction2); 40} 41 42/// Restitution mixing law. The idea is allow for anything to bounce off an inelastic surface. 43/// For example, a superball bounces on anything. 44inline float32 b2MixRestitution(float32 restitution1, float32 restitution2) 45{ 46 return restitution1 > restitution2 ? restitution1 : restitution2; 47} 48 49typedef b2Contact* b2ContactCreateFcn( b2Fixture* fixtureA, int32 indexA, 50 b2Fixture* fixtureB, int32 indexB, 51 b2BlockAllocator* allocator); 52typedef void b2ContactDestroyFcn(b2Contact* contact, b2BlockAllocator* allocator); 53 54struct b2ContactRegister 55{ 56 b2ContactCreateFcn* createFcn; 57 b2ContactDestroyFcn* destroyFcn; 58 bool primary; 59}; 60 61/// A contact edge is used to connect bodies and contacts together 62/// in a contact graph where each body is a node and each contact 63/// is an edge. A contact edge belongs to a doubly linked list 64/// maintained in each attached body. Each contact has two contact 65/// nodes, one for each attached body. 66struct b2ContactEdge 67{ 68 b2Body* other; ///< provides quick access to the other body attached. 69 b2Contact* contact; ///< the contact 70 b2ContactEdge* prev; ///< the previous contact edge in the body's contact list 71 b2ContactEdge* next; ///< the next contact edge in the body's contact list 72}; 73 74/// The class manages contact between two shapes. A contact exists for each overlapping 75/// AABB in the broad-phase (except if filtered). Therefore a contact object may exist 76/// that has no contact points. 77class b2Contact 78{ 79public: 80 81 /// Get the contact manifold. Do not modify the manifold unless you understand the 82 /// internals of Box2D. 83 b2Manifold* GetManifold(); 84 const b2Manifold* GetManifold() const; 85 86 /// Get the world manifold. 87 void GetWorldManifold(b2WorldManifold* worldManifold) const; 88 89 /// Is this contact touching? 90 bool IsTouching() const; 91 92 /// Enable/disable this contact. This can be used inside the pre-solve 93 /// contact listener. The contact is only disabled for the current 94 /// time step (or sub-step in continuous collisions). 95 void SetEnabled(bool flag); 96 97 /// Has this contact been disabled? 98 bool IsEnabled() const; 99 100 /// Get the next contact in the world's contact list. 101 b2Contact* GetNext(); 102 const b2Contact* GetNext() const; 103 104 /// Get fixture A in this contact. 105 b2Fixture* GetFixtureA(); 106 const b2Fixture* GetFixtureA() const; 107 108 /// Get the child primitive index for fixture A. 109 int32 GetChildIndexA() const; 110 111 /// Get fixture B in this contact. 112 b2Fixture* GetFixtureB(); 113 const b2Fixture* GetFixtureB() const; 114 115 /// Get the child primitive index for fixture B. 116 int32 GetChildIndexB() const; 117 118 /// Override the default friction mixture. You can call this in b2ContactListener::PreSolve. 119 /// This value persists until set or reset. 120 void SetFriction(float32 friction); 121 122 /// Get the friction. 123 float32 GetFriction() const; 124 125 /// Reset the friction mixture to the default value. 126 void ResetFriction(); 127 128 /// Override the default restitution mixture. You can call this in b2ContactListener::PreSolve. 129 /// The value persists until you set or reset. 130 void SetRestitution(float32 restitution); 131 132 /// Get the restitution. 133 float32 GetRestitution() const; 134 135 /// Reset the restitution to the default value. 136 void ResetRestitution(); 137 138 /// Set the desired tangent speed for a conveyor belt behavior. In meters per second. 139 void SetTangentSpeed(float32 speed); 140 141 /// Get the desired tangent speed. In meters per second. 142 float32 GetTangentSpeed() const; 143 144 /// Evaluate this contact with your own manifold and transforms. 145 virtual void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) = 0; 146 147protected: 148 friend class b2ContactManager; 149 friend class b2World; 150 friend class b2ContactSolver; 151 friend class b2Body; 152 friend class b2Fixture; 153 154 // Flags stored in m_flags 155 enum 156 { 157 // Used when crawling contact graph when forming islands. 158 e_islandFlag = 0x0001, 159 160 // Set when the shapes are touching. 161 e_touchingFlag = 0x0002, 162 163 // This contact can be disabled (by user) 164 e_enabledFlag = 0x0004, 165 166 // This contact needs filtering because a fixture filter was changed. 167 e_filterFlag = 0x0008, 168 169 // This bullet contact had a TOI event 170 e_bulletHitFlag = 0x0010, 171 172 // This contact has a valid TOI in m_toi 173 e_toiFlag = 0x0020 174 }; 175 176 /// Flag this contact for filtering. Filtering will occur the next time step. 177 void FlagForFiltering(); 178 179 static void AddType(b2ContactCreateFcn* createFcn, b2ContactDestroyFcn* destroyFcn, 180 b2Shape::Type typeA, b2Shape::Type typeB); 181 static void InitializeRegisters(); 182 static b2Contact* Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator); 183 static void Destroy(b2Contact* contact, b2Shape::Type typeA, b2Shape::Type typeB, b2BlockAllocator* allocator); 184 static void Destroy(b2Contact* contact, b2BlockAllocator* allocator); 185 186 b2Contact() : m_fixtureA(NULL), m_fixtureB(NULL) {} 187 b2Contact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB); 188 virtual ~b2Contact() {} 189 190 void Update(b2ContactListener* listener); 191 192 static b2ContactRegister s_registers[b2Shape::e_typeCount][b2Shape::e_typeCount]; 193 static bool s_initialized; 194 195 uint32 m_flags; 196 197 // World pool and list pointers. 198 b2Contact* m_prev; 199 b2Contact* m_next; 200 201 // Nodes for connecting bodies. 202 b2ContactEdge m_nodeA; 203 b2ContactEdge m_nodeB; 204 205 b2Fixture* m_fixtureA; 206 b2Fixture* m_fixtureB; 207 208 int32 m_indexA; 209 int32 m_indexB; 210 211 b2Manifold m_manifold; 212 213 int32 m_toiCount; 214 float32 m_toi; 215 216 float32 m_friction; 217 float32 m_restitution; 218 219 float32 m_tangentSpeed; 220}; 221 222inline b2Manifold* b2Contact::GetManifold() 223{ 224 return &m_manifold; 225} 226 227inline const b2Manifold* b2Contact::GetManifold() const 228{ 229 return &m_manifold; 230} 231 232inline void b2Contact::GetWorldManifold(b2WorldManifold* worldManifold) const 233{ 234 const b2Body* bodyA = m_fixtureA->GetBody(); 235 const b2Body* bodyB = m_fixtureB->GetBody(); 236 const b2Shape* shapeA = m_fixtureA->GetShape(); 237 const b2Shape* shapeB = m_fixtureB->GetShape(); 238 239 worldManifold->Initialize(&m_manifold, bodyA->GetTransform(), shapeA->m_radius, bodyB->GetTransform(), shapeB->m_radius); 240} 241 242inline void b2Contact::SetEnabled(bool flag) 243{ 244 if (flag) 245 { 246 m_flags |= e_enabledFlag; 247 } 248 else 249 { 250 m_flags &= ~e_enabledFlag; 251 } 252} 253 254inline bool b2Contact::IsEnabled() const 255{ 256 return (m_flags & e_enabledFlag) == e_enabledFlag; 257} 258 259inline bool b2Contact::IsTouching() const 260{ 261 return (m_flags & e_touchingFlag) == e_touchingFlag; 262} 263 264inline b2Contact* b2Contact::GetNext() 265{ 266 return m_next; 267} 268 269inline const b2Contact* b2Contact::GetNext() const 270{ 271 return m_next; 272} 273 274inline b2Fixture* b2Contact::GetFixtureA() 275{ 276 return m_fixtureA; 277} 278 279inline const b2Fixture* b2Contact::GetFixtureA() const 280{ 281 return m_fixtureA; 282} 283 284inline b2Fixture* b2Contact::GetFixtureB() 285{ 286 return m_fixtureB; 287} 288 289inline int32 b2Contact::GetChildIndexA() const 290{ 291 return m_indexA; 292} 293 294inline const b2Fixture* b2Contact::GetFixtureB() const 295{ 296 return m_fixtureB; 297} 298 299inline int32 b2Contact::GetChildIndexB() const 300{ 301 return m_indexB; 302} 303 304inline void b2Contact::FlagForFiltering() 305{ 306 m_flags |= e_filterFlag; 307} 308 309inline void b2Contact::SetFriction(float32 friction) 310{ 311 m_friction = friction; 312} 313 314inline float32 b2Contact::GetFriction() const 315{ 316 return m_friction; 317} 318 319inline void b2Contact::ResetFriction() 320{ 321 m_friction = b2MixFriction(m_fixtureA->m_friction, m_fixtureB->m_friction); 322} 323 324inline void b2Contact::SetRestitution(float32 restitution) 325{ 326 m_restitution = restitution; 327} 328 329inline float32 b2Contact::GetRestitution() const 330{ 331 return m_restitution; 332} 333 334inline void b2Contact::ResetRestitution() 335{ 336 m_restitution = b2MixRestitution(m_fixtureA->m_restitution, m_fixtureB->m_restitution); 337} 338 339inline void b2Contact::SetTangentSpeed(float32 speed) 340{ 341 m_tangentSpeed = speed; 342} 343 344inline float32 b2Contact::GetTangentSpeed() const 345{ 346 return m_tangentSpeed; 347} 348 349#endif 350