File indexing completed on 2025-08-03 03:50:00

0001 /*
0002 * Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
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 #include <Box2D/Dynamics/b2ContactManager.h>
0020 #include <Box2D/Dynamics/b2Body.h>
0021 #include <Box2D/Dynamics/b2Fixture.h>
0022 #include <Box2D/Dynamics/b2WorldCallbacks.h>
0023 #include <Box2D/Dynamics/Contacts/b2Contact.h>
0024 
0025 b2ContactFilter b2_defaultFilter;
0026 b2ContactListener b2_defaultListener;
0027 
0028 b2ContactManager::b2ContactManager()
0029 {
0030     m_contactList = NULL;
0031     m_contactCount = 0;
0032     m_contactFilter = &b2_defaultFilter;
0033     m_contactListener = &b2_defaultListener;
0034     m_allocator = NULL;
0035 }
0036 
0037 void b2ContactManager::Destroy(b2Contact* c)
0038 {
0039     b2Fixture* fixtureA = c->GetFixtureA();
0040     b2Fixture* fixtureB = c->GetFixtureB();
0041     b2Body* bodyA = fixtureA->GetBody();
0042     b2Body* bodyB = fixtureB->GetBody();
0043 
0044     if (m_contactListener && c->IsTouching())
0045     {
0046         m_contactListener->EndContact(c);
0047     }
0048 
0049     // Remove from the world.
0050     if (c->m_prev)
0051     {
0052         c->m_prev->m_next = c->m_next;
0053     }
0054 
0055     if (c->m_next)
0056     {
0057         c->m_next->m_prev = c->m_prev;
0058     }
0059 
0060     if (c == m_contactList)
0061     {
0062         m_contactList = c->m_next;
0063     }
0064 
0065     // Remove from body 1
0066     if (c->m_nodeA.prev)
0067     {
0068         c->m_nodeA.prev->next = c->m_nodeA.next;
0069     }
0070 
0071     if (c->m_nodeA.next)
0072     {
0073         c->m_nodeA.next->prev = c->m_nodeA.prev;
0074     }
0075 
0076     if (&c->m_nodeA == bodyA->m_contactList)
0077     {
0078         bodyA->m_contactList = c->m_nodeA.next;
0079     }
0080 
0081     // Remove from body 2
0082     if (c->m_nodeB.prev)
0083     {
0084         c->m_nodeB.prev->next = c->m_nodeB.next;
0085     }
0086 
0087     if (c->m_nodeB.next)
0088     {
0089         c->m_nodeB.next->prev = c->m_nodeB.prev;
0090     }
0091 
0092     if (&c->m_nodeB == bodyB->m_contactList)
0093     {
0094         bodyB->m_contactList = c->m_nodeB.next;
0095     }
0096 
0097     // Call the factory.
0098     b2Contact::Destroy(c, m_allocator);
0099     --m_contactCount;
0100 }
0101 
0102 // This is the top level collision call for the time step. Here
0103 // all the narrow phase collision is processed for the world
0104 // contact list.
0105 void b2ContactManager::Collide()
0106 {
0107     // Update awake contacts.
0108     b2Contact* c = m_contactList;
0109     while (c)
0110     {
0111         b2Fixture* fixtureA = c->GetFixtureA();
0112         b2Fixture* fixtureB = c->GetFixtureB();
0113         int32 indexA = c->GetChildIndexA();
0114         int32 indexB = c->GetChildIndexB();
0115         b2Body* bodyA = fixtureA->GetBody();
0116         b2Body* bodyB = fixtureB->GetBody();
0117 
0118         if (bodyA->IsAwake() == false && bodyB->IsAwake() == false)
0119         {
0120             c = c->GetNext();
0121             continue;
0122         }
0123 
0124         // Is this contact flagged for filtering?
0125         if (c->m_flags & b2Contact::e_filterFlag)
0126         {
0127             // Should these bodies collide?
0128             if (bodyB->ShouldCollide(bodyA) == false)
0129             {
0130                 b2Contact* cNuke = c;
0131                 c = cNuke->GetNext();
0132                 Destroy(cNuke);
0133                 continue;
0134             }
0135 
0136             // Check user filtering.
0137             if (m_contactFilter && m_contactFilter->ShouldCollide(fixtureA, fixtureB) == false)
0138             {
0139                 b2Contact* cNuke = c;
0140                 c = cNuke->GetNext();
0141                 Destroy(cNuke);
0142                 continue;
0143             }
0144 
0145             // Clear the filtering flag.
0146             c->m_flags &= ~b2Contact::e_filterFlag;
0147         }
0148 
0149         int32 proxyIdA = fixtureA->m_proxies[indexA].proxyId;
0150         int32 proxyIdB = fixtureB->m_proxies[indexB].proxyId;
0151         bool overlap = m_broadPhase.TestOverlap(proxyIdA, proxyIdB);
0152 
0153         // Here we destroy contacts that cease to overlap in the broad-phase.
0154         if (overlap == false)
0155         {
0156             b2Contact* cNuke = c;
0157             c = cNuke->GetNext();
0158             Destroy(cNuke);
0159             continue;
0160         }
0161 
0162         // The contact persists.
0163         c->Update(m_contactListener);
0164         c = c->GetNext();
0165     }
0166 }
0167 
0168 void b2ContactManager::FindNewContacts()
0169 {
0170     m_broadPhase.UpdatePairs(this);
0171 }
0172 
0173 void b2ContactManager::AddPair(void* proxyUserDataA, void* proxyUserDataB)
0174 {
0175     b2FixtureProxy* proxyA = (b2FixtureProxy*)proxyUserDataA;
0176     b2FixtureProxy* proxyB = (b2FixtureProxy*)proxyUserDataB;
0177 
0178     b2Fixture* fixtureA = proxyA->fixture;
0179     b2Fixture* fixtureB = proxyB->fixture;
0180 
0181     int32 indexA = proxyA->childIndex;
0182     int32 indexB = proxyB->childIndex;
0183 
0184     b2Body* bodyA = fixtureA->GetBody();
0185     b2Body* bodyB = fixtureB->GetBody();
0186 
0187     // Are the fixtures on the same body?
0188     if (bodyA == bodyB)
0189     {
0190         return;
0191     }
0192 
0193     // Does a contact already exist?
0194     b2ContactEdge* edge = bodyB->GetContactList();
0195     while (edge)
0196     {
0197         if (edge->other == bodyA)
0198         {
0199             b2Fixture* fA = edge->contact->GetFixtureA();
0200             b2Fixture* fB = edge->contact->GetFixtureB();
0201             int32 iA = edge->contact->GetChildIndexA();
0202             int32 iB = edge->contact->GetChildIndexB();
0203 
0204             if (fA == fixtureA && fB == fixtureB && iA == indexA && iB == indexB)
0205             {
0206                 // A contact already exists.
0207                 return;
0208             }
0209 
0210             if (fA == fixtureB && fB == fixtureA && iA == indexB && iB == indexA)
0211             {
0212                 // A contact already exists.
0213                 return;
0214             }
0215         }
0216 
0217         edge = edge->next;
0218     }
0219 
0220     // Does a joint override collision? Is at least one body dynamic?
0221     if (bodyB->ShouldCollide(bodyA) == false)
0222     {
0223         return;
0224     }
0225 
0226     // Check user filtering.
0227     if (m_contactFilter && m_contactFilter->ShouldCollide(fixtureA, fixtureB) == false)
0228     {
0229         return;
0230     }
0231 
0232     // Call the factory.
0233     b2Contact* c = b2Contact::Create(fixtureA, indexA, fixtureB, indexB, m_allocator);
0234 
0235     // Contact creation may swap fixtures.
0236     fixtureA = c->GetFixtureA();
0237     fixtureB = c->GetFixtureB();
0238     indexA = c->GetChildIndexA();
0239     indexB = c->GetChildIndexB();
0240     bodyA = fixtureA->GetBody();
0241     bodyB = fixtureB->GetBody();
0242 
0243     // Insert into the world.
0244     c->m_prev = NULL;
0245     c->m_next = m_contactList;
0246     if (m_contactList != NULL)
0247     {
0248         m_contactList->m_prev = c;
0249     }
0250     m_contactList = c;
0251 
0252     // Connect to island graph.
0253 
0254     // Connect to body A
0255     c->m_nodeA.contact = c;
0256     c->m_nodeA.other = bodyB;
0257 
0258     c->m_nodeA.prev = NULL;
0259     c->m_nodeA.next = bodyA->m_contactList;
0260     if (bodyA->m_contactList != NULL)
0261     {
0262         bodyA->m_contactList->prev = &c->m_nodeA;
0263     }
0264     bodyA->m_contactList = &c->m_nodeA;
0265 
0266     // Connect to body B
0267     c->m_nodeB.contact = c;
0268     c->m_nodeB.other = bodyA;
0269 
0270     c->m_nodeB.prev = NULL;
0271     c->m_nodeB.next = bodyB->m_contactList;
0272     if (bodyB->m_contactList != NULL)
0273     {
0274         bodyB->m_contactList->prev = &c->m_nodeB;
0275     }
0276     bodyB->m_contactList = &c->m_nodeB;
0277 
0278     ++m_contactCount;
0279 }