File indexing completed on 2025-02-16 03:29:35
0001 /* 0002 * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 0003 * 0004 * This software is provided 'as-is', without any express or implied 0005 * warranty. In no event will the authors be held liable for any damages 0006 * arising from the use of this software. 0007 * Permission is granted to anyone to use this software for any purpose, 0008 * including commercial applications, and to alter it and redistribute it 0009 * freely, subject to the following restrictions: 0010 * 1. The origin of this software must not be misrepresented; you must not 0011 * claim that you wrote the original software. If you use this software 0012 * in a product, an acknowledgment in the product documentation would be 0013 * appreciated but is not required. 0014 * 2. Altered source versions must be plainly marked as such, and must not be 0015 * misrepresented as being the original software. 0016 * 3. This notice may not be removed or altered from any source distribution. 0017 */ 0018 0019 #ifndef B2_CONTACT_H 0020 #define B2_CONTACT_H 0021 0022 #include <Box2D/Common/b2Math.h> 0023 #include <Box2D/Collision/b2Collision.h> 0024 #include <Box2D/Collision/Shapes/b2Shape.h> 0025 #include <Box2D/Dynamics/b2Fixture.h> 0026 0027 class b2Body; 0028 class b2Contact; 0029 class b2Fixture; 0030 class b2World; 0031 class b2BlockAllocator; 0032 class b2StackAllocator; 0033 class b2ContactListener; 0034 0035 /// Friction mixing law. The idea is to allow either fixture to drive the restitution to zero. 0036 /// For example, anything slides on ice. 0037 inline float32 b2MixFriction(float32 friction1, float32 friction2) 0038 { 0039 return b2Sqrt(friction1 * friction2); 0040 } 0041 0042 /// Restitution mixing law. The idea is allow for anything to bounce off an inelastic surface. 0043 /// For example, a superball bounces on anything. 0044 inline float32 b2MixRestitution(float32 restitution1, float32 restitution2) 0045 { 0046 return restitution1 > restitution2 ? restitution1 : restitution2; 0047 } 0048 0049 typedef b2Contact* b2ContactCreateFcn( b2Fixture* fixtureA, int32 indexA, 0050 b2Fixture* fixtureB, int32 indexB, 0051 b2BlockAllocator* allocator); 0052 typedef void b2ContactDestroyFcn(b2Contact* contact, b2BlockAllocator* allocator); 0053 0054 struct b2ContactRegister 0055 { 0056 b2ContactCreateFcn* createFcn; 0057 b2ContactDestroyFcn* destroyFcn; 0058 bool primary; 0059 }; 0060 0061 /// A contact edge is used to connect bodies and contacts together 0062 /// in a contact graph where each body is a node and each contact 0063 /// is an edge. A contact edge belongs to a doubly linked list 0064 /// maintained in each attached body. Each contact has two contact 0065 /// nodes, one for each attached body. 0066 struct b2ContactEdge 0067 { 0068 b2Body* other; ///< provides quick access to the other body attached. 0069 b2Contact* contact; ///< the contact 0070 b2ContactEdge* prev; ///< the previous contact edge in the body's contact list 0071 b2ContactEdge* next; ///< the next contact edge in the body's contact list 0072 }; 0073 0074 /// The class manages contact between two shapes. A contact exists for each overlapping 0075 /// AABB in the broad-phase (except if filtered). Therefore a contact object may exist 0076 /// that has no contact points. 0077 class b2Contact 0078 { 0079 public: 0080 0081 /// Get the contact manifold. Do not modify the manifold unless you understand the 0082 /// internals of Box2D. 0083 b2Manifold* GetManifold(); 0084 const b2Manifold* GetManifold() const; 0085 0086 /// Get the world manifold. 0087 void GetWorldManifold(b2WorldManifold* worldManifold) const; 0088 0089 /// Is this contact touching? 0090 bool IsTouching() const; 0091 0092 /// Enable/disable this contact. This can be used inside the pre-solve 0093 /// contact listener. The contact is only disabled for the current 0094 /// time step (or sub-step in continuous collisions). 0095 void SetEnabled(bool flag); 0096 0097 /// Has this contact been disabled? 0098 bool IsEnabled() const; 0099 0100 /// Get the next contact in the world's contact list. 0101 b2Contact* GetNext(); 0102 const b2Contact* GetNext() const; 0103 0104 /// Get fixture A in this contact. 0105 b2Fixture* GetFixtureA(); 0106 const b2Fixture* GetFixtureA() const; 0107 0108 /// Get the child primitive index for fixture A. 0109 int32 GetChildIndexA() const; 0110 0111 /// Get fixture B in this contact. 0112 b2Fixture* GetFixtureB(); 0113 const b2Fixture* GetFixtureB() const; 0114 0115 /// Get the child primitive index for fixture B. 0116 int32 GetChildIndexB() const; 0117 0118 /// Override the default friction mixture. You can call this in b2ContactListener::PreSolve. 0119 /// This value persists until set or reset. 0120 void SetFriction(float32 friction); 0121 0122 /// Get the friction. 0123 float32 GetFriction() const; 0124 0125 /// Reset the friction mixture to the default value. 0126 void ResetFriction(); 0127 0128 /// Override the default restitution mixture. You can call this in b2ContactListener::PreSolve. 0129 /// The value persists until you set or reset. 0130 void SetRestitution(float32 restitution); 0131 0132 /// Get the restitution. 0133 float32 GetRestitution() const; 0134 0135 /// Reset the restitution to the default value. 0136 void ResetRestitution(); 0137 0138 /// Set the desired tangent speed for a conveyor belt behavior. In meters per second. 0139 void SetTangentSpeed(float32 speed); 0140 0141 /// Get the desired tangent speed. In meters per second. 0142 float32 GetTangentSpeed() const; 0143 0144 /// Evaluate this contact with your own manifold and transforms. 0145 virtual void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) = 0; 0146 0147 protected: 0148 friend class b2ContactManager; 0149 friend class b2World; 0150 friend class b2ContactSolver; 0151 friend class b2Body; 0152 friend class b2Fixture; 0153 0154 // Flags stored in m_flags 0155 enum 0156 { 0157 // Used when crawling contact graph when forming islands. 0158 e_islandFlag = 0x0001, 0159 0160 // Set when the shapes are touching. 0161 e_touchingFlag = 0x0002, 0162 0163 // This contact can be disabled (by user) 0164 e_enabledFlag = 0x0004, 0165 0166 // This contact needs filtering because a fixture filter was changed. 0167 e_filterFlag = 0x0008, 0168 0169 // This bullet contact had a TOI event 0170 e_bulletHitFlag = 0x0010, 0171 0172 // This contact has a valid TOI in m_toi 0173 e_toiFlag = 0x0020 0174 }; 0175 0176 /// Flag this contact for filtering. Filtering will occur the next time step. 0177 void FlagForFiltering(); 0178 0179 static void AddType(b2ContactCreateFcn* createFcn, b2ContactDestroyFcn* destroyFcn, 0180 b2Shape::Type typeA, b2Shape::Type typeB); 0181 static void InitializeRegisters(); 0182 static b2Contact* Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator); 0183 static void Destroy(b2Contact* contact, b2Shape::Type typeA, b2Shape::Type typeB, b2BlockAllocator* allocator); 0184 static void Destroy(b2Contact* contact, b2BlockAllocator* allocator); 0185 0186 b2Contact() : m_fixtureA(NULL), m_fixtureB(NULL) {} 0187 b2Contact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB); 0188 virtual ~b2Contact() {} 0189 0190 void Update(b2ContactListener* listener); 0191 0192 static b2ContactRegister s_registers[b2Shape::e_typeCount][b2Shape::e_typeCount]; 0193 static bool s_initialized; 0194 0195 uint32 m_flags; 0196 0197 // World pool and list pointers. 0198 b2Contact* m_prev; 0199 b2Contact* m_next; 0200 0201 // Nodes for connecting bodies. 0202 b2ContactEdge m_nodeA; 0203 b2ContactEdge m_nodeB; 0204 0205 b2Fixture* m_fixtureA; 0206 b2Fixture* m_fixtureB; 0207 0208 int32 m_indexA; 0209 int32 m_indexB; 0210 0211 b2Manifold m_manifold; 0212 0213 int32 m_toiCount; 0214 float32 m_toi; 0215 0216 float32 m_friction; 0217 float32 m_restitution; 0218 0219 float32 m_tangentSpeed; 0220 }; 0221 0222 inline b2Manifold* b2Contact::GetManifold() 0223 { 0224 return &m_manifold; 0225 } 0226 0227 inline const b2Manifold* b2Contact::GetManifold() const 0228 { 0229 return &m_manifold; 0230 } 0231 0232 inline void b2Contact::GetWorldManifold(b2WorldManifold* worldManifold) const 0233 { 0234 const b2Body* bodyA = m_fixtureA->GetBody(); 0235 const b2Body* bodyB = m_fixtureB->GetBody(); 0236 const b2Shape* shapeA = m_fixtureA->GetShape(); 0237 const b2Shape* shapeB = m_fixtureB->GetShape(); 0238 0239 worldManifold->Initialize(&m_manifold, bodyA->GetTransform(), shapeA->m_radius, bodyB->GetTransform(), shapeB->m_radius); 0240 } 0241 0242 inline void b2Contact::SetEnabled(bool flag) 0243 { 0244 if (flag) 0245 { 0246 m_flags |= e_enabledFlag; 0247 } 0248 else 0249 { 0250 m_flags &= ~e_enabledFlag; 0251 } 0252 } 0253 0254 inline bool b2Contact::IsEnabled() const 0255 { 0256 return (m_flags & e_enabledFlag) == e_enabledFlag; 0257 } 0258 0259 inline bool b2Contact::IsTouching() const 0260 { 0261 return (m_flags & e_touchingFlag) == e_touchingFlag; 0262 } 0263 0264 inline b2Contact* b2Contact::GetNext() 0265 { 0266 return m_next; 0267 } 0268 0269 inline const b2Contact* b2Contact::GetNext() const 0270 { 0271 return m_next; 0272 } 0273 0274 inline b2Fixture* b2Contact::GetFixtureA() 0275 { 0276 return m_fixtureA; 0277 } 0278 0279 inline const b2Fixture* b2Contact::GetFixtureA() const 0280 { 0281 return m_fixtureA; 0282 } 0283 0284 inline b2Fixture* b2Contact::GetFixtureB() 0285 { 0286 return m_fixtureB; 0287 } 0288 0289 inline int32 b2Contact::GetChildIndexA() const 0290 { 0291 return m_indexA; 0292 } 0293 0294 inline const b2Fixture* b2Contact::GetFixtureB() const 0295 { 0296 return m_fixtureB; 0297 } 0298 0299 inline int32 b2Contact::GetChildIndexB() const 0300 { 0301 return m_indexB; 0302 } 0303 0304 inline void b2Contact::FlagForFiltering() 0305 { 0306 m_flags |= e_filterFlag; 0307 } 0308 0309 inline void b2Contact::SetFriction(float32 friction) 0310 { 0311 m_friction = friction; 0312 } 0313 0314 inline float32 b2Contact::GetFriction() const 0315 { 0316 return m_friction; 0317 } 0318 0319 inline void b2Contact::ResetFriction() 0320 { 0321 m_friction = b2MixFriction(m_fixtureA->m_friction, m_fixtureB->m_friction); 0322 } 0323 0324 inline void b2Contact::SetRestitution(float32 restitution) 0325 { 0326 m_restitution = restitution; 0327 } 0328 0329 inline float32 b2Contact::GetRestitution() const 0330 { 0331 return m_restitution; 0332 } 0333 0334 inline void b2Contact::ResetRestitution() 0335 { 0336 m_restitution = b2MixRestitution(m_fixtureA->m_restitution, m_fixtureB->m_restitution); 0337 } 0338 0339 inline void b2Contact::SetTangentSpeed(float32 speed) 0340 { 0341 m_tangentSpeed = speed; 0342 } 0343 0344 inline float32 b2Contact::GetTangentSpeed() const 0345 { 0346 return m_tangentSpeed; 0347 } 0348 0349 #endif