| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386 |
- // MIT License
- // Copyright (c) 2019 Erin Catto
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- // The above copyright notice and this permission notice shall be included in all
- // copies or substantial portions of the Software.
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- // SOFTWARE.
- #ifndef B2_CONTACT_H
- #define B2_CONTACT_H
- #include "b2_api.h"
- #include "b2_collision.h"
- #include "b2_fixture.h"
- #include "b2_math.h"
- #include "b2_shape.h"
- class b2Body;
- class b2Contact;
- class b2Fixture;
- class b2World;
- class b2BlockAllocator;
- class b2StackAllocator;
- class b2ContactListener;
- /// Friction mixing law. The idea is to allow either fixture to drive the friction to zero.
- /// For example, anything slides on ice.
- inline float b2MixFriction(float friction1, float friction2)
- {
- return b2Sqrt(friction1 * friction2);
- }
- /// Restitution mixing law. The idea is allow for anything to bounce off an inelastic surface.
- /// For example, a superball bounces on anything.
- inline float b2MixRestitution(float restitution1, float restitution2)
- {
- return restitution1 > restitution2 ? restitution1 : restitution2;
- }
- /// Restitution mixing law. This picks the lowest value.
- inline float b2MixRestitutionThreshold(float threshold1, float threshold2)
- {
- return threshold1 < threshold2 ? threshold1 : threshold2;
- }
- typedef b2Contact* b2ContactCreateFcn( b2Fixture* fixtureA, int32 indexA,
- b2Fixture* fixtureB, int32 indexB,
- b2BlockAllocator* allocator);
- typedef void b2ContactDestroyFcn(b2Contact* contact, b2BlockAllocator* allocator);
- struct B2_API b2ContactRegister
- {
- b2ContactCreateFcn* createFcn;
- b2ContactDestroyFcn* destroyFcn;
- bool primary;
- };
- /// A contact edge is used to connect bodies and contacts together
- /// in a contact graph where each body is a node and each contact
- /// is an edge. A contact edge belongs to a doubly linked list
- /// maintained in each attached body. Each contact has two contact
- /// nodes, one for each attached body.
- struct B2_API b2ContactEdge
- {
- b2Body* other; ///< provides quick access to the other body attached.
- b2Contact* contact; ///< the contact
- b2ContactEdge* prev; ///< the previous contact edge in the body's contact list
- b2ContactEdge* next; ///< the next contact edge in the body's contact list
- };
- /// The class manages contact between two shapes. A contact exists for each overlapping
- /// AABB in the broad-phase (except if filtered). Therefore a contact object may exist
- /// that has no contact points.
- class B2_API b2Contact
- {
- public:
- /// Get the contact manifold. Do not modify the manifold unless you understand the
- /// internals of Box2D.
- b2Manifold* GetManifold();
- const b2Manifold* GetManifold() const;
- /// Get the world manifold.
- void GetWorldManifold(b2WorldManifold* worldManifold) const;
- /// Is this contact touching?
- bool IsTouching() const;
- /// Enable/disable this contact. This can be used inside the pre-solve
- /// contact listener. The contact is only disabled for the current
- /// time step (or sub-step in continuous collisions).
- void SetEnabled(bool flag);
- /// Has this contact been disabled?
- bool IsEnabled() const;
- /// Get the next contact in the world's contact list.
- b2Contact* GetNext();
- const b2Contact* GetNext() const;
- /// Get fixture A in this contact.
- b2Fixture* GetFixtureA();
- const b2Fixture* GetFixtureA() const;
- /// Get the child primitive index for fixture A.
- int32 GetChildIndexA() const;
- /// Get fixture B in this contact.
- b2Fixture* GetFixtureB();
- const b2Fixture* GetFixtureB() const;
- /// Get the child primitive index for fixture B.
- int32 GetChildIndexB() const;
- /// Override the default friction mixture. You can call this in b2ContactListener::PreSolve.
- /// This value persists until set or reset.
- void SetFriction(float friction);
- /// Get the friction.
- float GetFriction() const;
- /// Reset the friction mixture to the default value.
- void ResetFriction();
- /// Override the default restitution mixture. You can call this in b2ContactListener::PreSolve.
- /// The value persists until you set or reset.
- void SetRestitution(float restitution);
- /// Get the restitution.
- float GetRestitution() const;
- /// Reset the restitution to the default value.
- void ResetRestitution();
- /// Override the default restitution velocity threshold mixture. You can call this in b2ContactListener::PreSolve.
- /// The value persists until you set or reset.
- void SetRestitutionThreshold(float threshold);
- /// Get the restitution threshold.
- float GetRestitutionThreshold() const;
- /// Reset the restitution threshold to the default value.
- void ResetRestitutionThreshold();
- /// Set the desired tangent speed for a conveyor belt behavior. In meters per second.
- void SetTangentSpeed(float speed);
- /// Get the desired tangent speed. In meters per second.
- float GetTangentSpeed() const;
- /// Evaluate this contact with your own manifold and transforms.
- virtual void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) = 0;
- protected:
- friend class b2ContactManager;
- friend class b2World;
- friend class b2ContactSolver;
- friend class b2Body;
- friend class b2Fixture;
- // Flags stored in m_flags
- enum
- {
- // Used when crawling contact graph when forming islands.
- e_islandFlag = 0x0001,
- // Set when the shapes are touching.
- e_touchingFlag = 0x0002,
- // This contact can be disabled (by user)
- e_enabledFlag = 0x0004,
- // This contact needs filtering because a fixture filter was changed.
- e_filterFlag = 0x0008,
- // This bullet contact had a TOI event
- e_bulletHitFlag = 0x0010,
- // This contact has a valid TOI in m_toi
- e_toiFlag = 0x0020
- };
- /// Flag this contact for filtering. Filtering will occur the next time step.
- void FlagForFiltering();
- static void AddType(b2ContactCreateFcn* createFcn, b2ContactDestroyFcn* destroyFcn,
- b2Shape::Type typeA, b2Shape::Type typeB);
- static void InitializeRegisters();
- static b2Contact* Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator);
- static void Destroy(b2Contact* contact, b2Shape::Type typeA, b2Shape::Type typeB, b2BlockAllocator* allocator);
- static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);
- b2Contact() : m_fixtureA(nullptr), m_fixtureB(nullptr) {}
- b2Contact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB);
- virtual ~b2Contact() {}
- void Update(b2ContactListener* listener);
- static b2ContactRegister s_registers[b2Shape::e_typeCount][b2Shape::e_typeCount];
- static bool s_initialized;
- uint32 m_flags;
- // World pool and list pointers.
- b2Contact* m_prev;
- b2Contact* m_next;
- // Nodes for connecting bodies.
- b2ContactEdge m_nodeA;
- b2ContactEdge m_nodeB;
- b2Fixture* m_fixtureA;
- b2Fixture* m_fixtureB;
- int32 m_indexA;
- int32 m_indexB;
- b2Manifold m_manifold;
- int32 m_toiCount;
- float m_toi;
- float m_friction;
- float m_restitution;
- float m_restitutionThreshold;
- float m_tangentSpeed;
- };
- inline b2Manifold* b2Contact::GetManifold()
- {
- return &m_manifold;
- }
- inline const b2Manifold* b2Contact::GetManifold() const
- {
- return &m_manifold;
- }
- inline void b2Contact::GetWorldManifold(b2WorldManifold* worldManifold) const
- {
- const b2Body* bodyA = m_fixtureA->GetBody();
- const b2Body* bodyB = m_fixtureB->GetBody();
- const b2Shape* shapeA = m_fixtureA->GetShape();
- const b2Shape* shapeB = m_fixtureB->GetShape();
- worldManifold->Initialize(&m_manifold, bodyA->GetTransform(), shapeA->m_radius, bodyB->GetTransform(), shapeB->m_radius);
- }
- inline void b2Contact::SetEnabled(bool flag)
- {
- if (flag)
- {
- m_flags |= e_enabledFlag;
- }
- else
- {
- m_flags &= ~e_enabledFlag;
- }
- }
- inline bool b2Contact::IsEnabled() const
- {
- return (m_flags & e_enabledFlag) == e_enabledFlag;
- }
- inline bool b2Contact::IsTouching() const
- {
- return (m_flags & e_touchingFlag) == e_touchingFlag;
- }
- inline b2Contact* b2Contact::GetNext()
- {
- return m_next;
- }
- inline const b2Contact* b2Contact::GetNext() const
- {
- return m_next;
- }
- inline b2Fixture* b2Contact::GetFixtureA()
- {
- return m_fixtureA;
- }
- inline const b2Fixture* b2Contact::GetFixtureA() const
- {
- return m_fixtureA;
- }
- inline b2Fixture* b2Contact::GetFixtureB()
- {
- return m_fixtureB;
- }
- inline int32 b2Contact::GetChildIndexA() const
- {
- return m_indexA;
- }
- inline const b2Fixture* b2Contact::GetFixtureB() const
- {
- return m_fixtureB;
- }
- inline int32 b2Contact::GetChildIndexB() const
- {
- return m_indexB;
- }
- inline void b2Contact::FlagForFiltering()
- {
- m_flags |= e_filterFlag;
- }
- inline void b2Contact::SetFriction(float friction)
- {
- m_friction = friction;
- }
- inline float b2Contact::GetFriction() const
- {
- return m_friction;
- }
- inline void b2Contact::ResetFriction()
- {
- m_friction = b2MixFriction(m_fixtureA->m_friction, m_fixtureB->m_friction);
- }
- inline void b2Contact::SetRestitution(float restitution)
- {
- m_restitution = restitution;
- }
- inline float b2Contact::GetRestitution() const
- {
- return m_restitution;
- }
- inline void b2Contact::ResetRestitution()
- {
- m_restitution = b2MixRestitution(m_fixtureA->m_restitution, m_fixtureB->m_restitution);
- }
- inline void b2Contact::SetRestitutionThreshold(float threshold)
- {
- m_restitutionThreshold = threshold;
- }
- inline float b2Contact::GetRestitutionThreshold() const
- {
- return m_restitutionThreshold;
- }
- inline void b2Contact::ResetRestitutionThreshold()
- {
- m_restitutionThreshold = b2MixRestitutionThreshold(m_fixtureA->m_restitutionThreshold, m_fixtureB->m_restitutionThreshold);
- }
- inline void b2Contact::SetTangentSpeed(float speed)
- {
- m_tangentSpeed = speed;
- }
- inline float b2Contact::GetTangentSpeed() const
- {
- return m_tangentSpeed;
- }
- #endif
|