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