Warning, file /education/gcompris/external/qml-box2d/Box2D/Dynamics/b2ContactManager.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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 #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         // Is this contact flagged for filtering?
0119         if (c->m_flags & b2Contact::e_filterFlag)
0120         {
0121             // Should these bodies collide?
0122             if (bodyB->ShouldCollide(bodyA) == false)
0123             {
0124                 b2Contact* cNuke = c;
0125                 c = cNuke->GetNext();
0126                 Destroy(cNuke);
0127                 continue;
0128             }
0129 
0130             // Check user filtering.
0131             if (m_contactFilter && m_contactFilter->ShouldCollide(fixtureA, fixtureB) == false)
0132             {
0133                 b2Contact* cNuke = c;
0134                 c = cNuke->GetNext();
0135                 Destroy(cNuke);
0136                 continue;
0137             }
0138 
0139             // Clear the filtering flag.
0140             c->m_flags &= ~b2Contact::e_filterFlag;
0141         }
0142 
0143         bool activeA = bodyA->IsAwake() && bodyA->m_type != b2_staticBody;
0144         bool activeB = bodyB->IsAwake() && bodyB->m_type != b2_staticBody;
0145 
0146         // At least one body must be awake and it must be dynamic or kinematic.
0147         if (activeA == false && activeB == false)
0148         {
0149             c = c->GetNext();
0150             continue;
0151         }
0152 
0153         int32 proxyIdA = fixtureA->m_proxies[indexA].proxyId;
0154         int32 proxyIdB = fixtureB->m_proxies[indexB].proxyId;
0155         bool overlap = m_broadPhase.TestOverlap(proxyIdA, proxyIdB);
0156 
0157         // Here we destroy contacts that cease to overlap in the broad-phase.
0158         if (overlap == false)
0159         {
0160             b2Contact* cNuke = c;
0161             c = cNuke->GetNext();
0162             Destroy(cNuke);
0163             continue;
0164         }
0165 
0166         // The contact persists.
0167         c->Update(m_contactListener);
0168         c = c->GetNext();
0169     }
0170 }
0171 
0172 void b2ContactManager::FindNewContacts()
0173 {
0174     m_broadPhase.UpdatePairs(this);
0175 }
0176 
0177 void b2ContactManager::AddPair(void* proxyUserDataA, void* proxyUserDataB)
0178 {
0179     b2FixtureProxy* proxyA = (b2FixtureProxy*)proxyUserDataA;
0180     b2FixtureProxy* proxyB = (b2FixtureProxy*)proxyUserDataB;
0181 
0182     b2Fixture* fixtureA = proxyA->fixture;
0183     b2Fixture* fixtureB = proxyB->fixture;
0184 
0185     int32 indexA = proxyA->childIndex;
0186     int32 indexB = proxyB->childIndex;
0187 
0188     b2Body* bodyA = fixtureA->GetBody();
0189     b2Body* bodyB = fixtureB->GetBody();
0190 
0191     // Are the fixtures on the same body?
0192     if (bodyA == bodyB)
0193     {
0194         return;
0195     }
0196 
0197     // TODO_ERIN use a hash table to remove a potential bottleneck when both
0198     // bodies have a lot of contacts.
0199     // Does a contact already exist?
0200     b2ContactEdge* edge = bodyB->GetContactList();
0201     while (edge)
0202     {
0203         if (edge->other == bodyA)
0204         {
0205             b2Fixture* fA = edge->contact->GetFixtureA();
0206             b2Fixture* fB = edge->contact->GetFixtureB();
0207             int32 iA = edge->contact->GetChildIndexA();
0208             int32 iB = edge->contact->GetChildIndexB();
0209 
0210             if (fA == fixtureA && fB == fixtureB && iA == indexA && iB == indexB)
0211             {
0212                 // A contact already exists.
0213                 return;
0214             }
0215 
0216             if (fA == fixtureB && fB == fixtureA && iA == indexB && iB == indexA)
0217             {
0218                 // A contact already exists.
0219                 return;
0220             }
0221         }
0222 
0223         edge = edge->next;
0224     }
0225 
0226     // Does a joint override collision? Is at least one body dynamic?
0227     if (bodyB->ShouldCollide(bodyA) == false)
0228     {
0229         return;
0230     }
0231 
0232     // Check user filtering.
0233     if (m_contactFilter && m_contactFilter->ShouldCollide(fixtureA, fixtureB) == false)
0234     {
0235         return;
0236     }
0237 
0238     // Call the factory.
0239     b2Contact* c = b2Contact::Create(fixtureA, indexA, fixtureB, indexB, m_allocator);
0240     if (c == NULL)
0241     {
0242         return;
0243     }
0244 
0245     // Contact creation may swap fixtures.
0246     fixtureA = c->GetFixtureA();
0247     fixtureB = c->GetFixtureB();
0248     indexA = c->GetChildIndexA();
0249     indexB = c->GetChildIndexB();
0250     bodyA = fixtureA->GetBody();
0251     bodyB = fixtureB->GetBody();
0252 
0253     // Insert into the world.
0254     c->m_prev = NULL;
0255     c->m_next = m_contactList;
0256     if (m_contactList != NULL)
0257     {
0258         m_contactList->m_prev = c;
0259     }
0260     m_contactList = c;
0261 
0262     // Connect to island graph.
0263 
0264     // Connect to body A
0265     c->m_nodeA.contact = c;
0266     c->m_nodeA.other = bodyB;
0267 
0268     c->m_nodeA.prev = NULL;
0269     c->m_nodeA.next = bodyA->m_contactList;
0270     if (bodyA->m_contactList != NULL)
0271     {
0272         bodyA->m_contactList->prev = &c->m_nodeA;
0273     }
0274     bodyA->m_contactList = &c->m_nodeA;
0275 
0276     // Connect to body B
0277     c->m_nodeB.contact = c;
0278     c->m_nodeB.other = bodyA;
0279 
0280     c->m_nodeB.prev = NULL;
0281     c->m_nodeB.next = bodyB->m_contactList;
0282     if (bodyB->m_contactList != NULL)
0283     {
0284         bodyB->m_contactList->prev = &c->m_nodeB;
0285     }
0286     bodyB->m_contactList = &c->m_nodeB;
0287 
0288     // Wake up the bodies
0289     if (fixtureA->IsSensor() == false && fixtureB->IsSensor() == false)
0290     {
0291         bodyA->SetAwake(true);
0292         bodyB->SetAwake(true);
0293     }
0294 
0295     ++m_contactCount;
0296 }