b2ContactManager.cpp
Go to the documentation of this file.
00001 /*
00002 * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
00003 *
00004 * This software is provided 'as-is', without any express or implied
00005 * warranty.  In no event will the authors be held liable for any damages
00006 * arising from the use of this software.
00007 * Permission is granted to anyone to use this software for any purpose,
00008 * including commercial applications, and to alter it and redistribute it
00009 * freely, subject to the following restrictions:
00010 * 1. The origin of this software must not be misrepresented; you must not
00011 * claim that you wrote the original software. If you use this software
00012 * in a product, an acknowledgment in the product documentation would be
00013 * appreciated but is not required.
00014 * 2. Altered source versions must be plainly marked as such, and must not be
00015 * misrepresented as being the original software.
00016 * 3. This notice may not be removed or altered from any source distribution.
00017 */
00018 
00019 #include <Box2D/Dynamics/b2ContactManager.h>
00020 #include <Box2D/Dynamics/b2Body.h>
00021 #include <Box2D/Dynamics/b2Fixture.h>
00022 #include <Box2D/Dynamics/b2WorldCallbacks.h>
00023 #include <Box2D/Dynamics/Contacts/b2Contact.h>
00024 
00025 b2ContactFilter b2_defaultFilter;
00026 b2ContactListener b2_defaultListener;
00027 
00028 b2ContactManager::b2ContactManager()
00029 {
00030         m_contactList = NULL;
00031         m_contactCount = 0;
00032         m_contactFilter = &b2_defaultFilter;
00033         m_contactListener = &b2_defaultListener;
00034         m_allocator = NULL;
00035 }
00036 
00037 void b2ContactManager::Destroy(b2Contact* c)
00038 {
00039         b2Fixture* fixtureA = c->GetFixtureA();
00040         b2Fixture* fixtureB = c->GetFixtureB();
00041         b2Body* bodyA = fixtureA->GetBody();
00042         b2Body* bodyB = fixtureB->GetBody();
00043 
00044         if (m_contactListener && c->IsTouching())
00045         {
00046                 m_contactListener->EndContact(c);
00047         }
00048 
00049         // Remove from the world.
00050         if (c->m_prev)
00051         {
00052                 c->m_prev->m_next = c->m_next;
00053         }
00054 
00055         if (c->m_next)
00056         {
00057                 c->m_next->m_prev = c->m_prev;
00058         }
00059 
00060         if (c == m_contactList)
00061         {
00062                 m_contactList = c->m_next;
00063         }
00064 
00065         // Remove from body 1
00066         if (c->m_nodeA.prev)
00067         {
00068                 c->m_nodeA.prev->next = c->m_nodeA.next;
00069         }
00070 
00071         if (c->m_nodeA.next)
00072         {
00073                 c->m_nodeA.next->prev = c->m_nodeA.prev;
00074         }
00075 
00076         if (&c->m_nodeA == bodyA->m_contactList)
00077         {
00078                 bodyA->m_contactList = c->m_nodeA.next;
00079         }
00080 
00081         // Remove from body 2
00082         if (c->m_nodeB.prev)
00083         {
00084                 c->m_nodeB.prev->next = c->m_nodeB.next;
00085         }
00086 
00087         if (c->m_nodeB.next)
00088         {
00089                 c->m_nodeB.next->prev = c->m_nodeB.prev;
00090         }
00091 
00092         if (&c->m_nodeB == bodyB->m_contactList)
00093         {
00094                 bodyB->m_contactList = c->m_nodeB.next;
00095         }
00096 
00097         // Call the factory.
00098         b2Contact::Destroy(c, m_allocator);
00099         --m_contactCount;
00100 }
00101 
00102 // This is the top level collision call for the time step. Here
00103 // all the narrow phase collision is processed for the world
00104 // contact list.
00105 void b2ContactManager::Collide()
00106 {
00107         // Update awake contacts.
00108         b2Contact* c = m_contactList;
00109         while (c)
00110         {
00111                 b2Fixture* fixtureA = c->GetFixtureA();
00112                 b2Fixture* fixtureB = c->GetFixtureB();
00113                 int32 indexA = c->GetChildIndexA();
00114                 int32 indexB = c->GetChildIndexB();
00115                 b2Body* bodyA = fixtureA->GetBody();
00116                 b2Body* bodyB = fixtureB->GetBody();
00117                  
00118                 // Is this contact flagged for filtering?
00119                 if (c->m_flags & b2Contact::e_filterFlag)
00120                 {
00121                         // Should these bodies collide?
00122                         if (bodyB->ShouldCollide(bodyA) == false)
00123                         {
00124                                 b2Contact* cNuke = c;
00125                                 c = cNuke->GetNext();
00126                                 Destroy(cNuke);
00127                                 continue;
00128                         }
00129 
00130                         // Check user filtering.
00131                         if (m_contactFilter && m_contactFilter->ShouldCollide(fixtureA, fixtureB) == false)
00132                         {
00133                                 b2Contact* cNuke = c;
00134                                 c = cNuke->GetNext();
00135                                 Destroy(cNuke);
00136                                 continue;
00137                         }
00138 
00139                         // Clear the filtering flag.
00140                         c->m_flags &= ~b2Contact::e_filterFlag;
00141                 }
00142 
00143                 bool activeA = bodyA->IsAwake() && bodyA->m_type != b2_staticBody;
00144                 bool activeB = bodyB->IsAwake() && bodyB->m_type != b2_staticBody;
00145 
00146                 // At least one body must be awake and it must be dynamic or kinematic.
00147                 if (activeA == false && activeB == false)
00148                 {
00149                         c = c->GetNext();
00150                         continue;
00151                 }
00152 
00153                 int32 proxyIdA = fixtureA->m_proxies[indexA].proxyId;
00154                 int32 proxyIdB = fixtureB->m_proxies[indexB].proxyId;
00155                 bool overlap = m_broadPhase.TestOverlap(proxyIdA, proxyIdB);
00156 
00157                 // Here we destroy contacts that cease to overlap in the broad-phase.
00158                 if (overlap == false)
00159                 {
00160                         b2Contact* cNuke = c;
00161                         c = cNuke->GetNext();
00162                         Destroy(cNuke);
00163                         continue;
00164                 }
00165 
00166                 // The contact persists.
00167                 c->Update(m_contactListener);
00168                 c = c->GetNext();
00169         }
00170 }
00171 
00172 void b2ContactManager::FindNewContacts()
00173 {
00174         m_broadPhase.UpdatePairs(this);
00175 }
00176 
00177 void b2ContactManager::AddPair(void* proxyUserDataA, void* proxyUserDataB)
00178 {
00179         b2FixtureProxy* proxyA = (b2FixtureProxy*)proxyUserDataA;
00180         b2FixtureProxy* proxyB = (b2FixtureProxy*)proxyUserDataB;
00181 
00182         b2Fixture* fixtureA = proxyA->fixture;
00183         b2Fixture* fixtureB = proxyB->fixture;
00184 
00185         int32 indexA = proxyA->childIndex;
00186         int32 indexB = proxyB->childIndex;
00187 
00188         b2Body* bodyA = fixtureA->GetBody();
00189         b2Body* bodyB = fixtureB->GetBody();
00190 
00191         // Are the fixtures on the same body?
00192         if (bodyA == bodyB)
00193         {
00194                 return;
00195         }
00196 
00197         // TODO_ERIN use a hash table to remove a potential bottleneck when both
00198         // bodies have a lot of contacts.
00199         // Does a contact already exist?
00200         b2ContactEdge* edge = bodyB->GetContactList();
00201         while (edge)
00202         {
00203                 if (edge->other == bodyA)
00204                 {
00205                         b2Fixture* fA = edge->contact->GetFixtureA();
00206                         b2Fixture* fB = edge->contact->GetFixtureB();
00207                         int32 iA = edge->contact->GetChildIndexA();
00208                         int32 iB = edge->contact->GetChildIndexB();
00209 
00210                         if (fA == fixtureA && fB == fixtureB && iA == indexA && iB == indexB)
00211                         {
00212                                 // A contact already exists.
00213                                 return;
00214                         }
00215 
00216                         if (fA == fixtureB && fB == fixtureA && iA == indexB && iB == indexA)
00217                         {
00218                                 // A contact already exists.
00219                                 return;
00220                         }
00221                 }
00222 
00223                 edge = edge->next;
00224         }
00225 
00226         // Does a joint override collision? Is at least one body dynamic?
00227         if (bodyB->ShouldCollide(bodyA) == false)
00228         {
00229                 return;
00230         }
00231 
00232         // Check user filtering.
00233         if (m_contactFilter && m_contactFilter->ShouldCollide(fixtureA, fixtureB) == false)
00234         {
00235                 return;
00236         }
00237 
00238         // Call the factory.
00239         b2Contact* c = b2Contact::Create(fixtureA, indexA, fixtureB, indexB, m_allocator);
00240         if (c == NULL)
00241         {
00242                 return;
00243         }
00244 
00245         // Contact creation may swap fixtures.
00246         fixtureA = c->GetFixtureA();
00247         fixtureB = c->GetFixtureB();
00248         indexA = c->GetChildIndexA();
00249         indexB = c->GetChildIndexB();
00250         bodyA = fixtureA->GetBody();
00251         bodyB = fixtureB->GetBody();
00252 
00253         // Insert into the world.
00254         c->m_prev = NULL;
00255         c->m_next = m_contactList;
00256         if (m_contactList != NULL)
00257         {
00258                 m_contactList->m_prev = c;
00259         }
00260         m_contactList = c;
00261 
00262         // Connect to island graph.
00263 
00264         // Connect to body A
00265         c->m_nodeA.contact = c;
00266         c->m_nodeA.other = bodyB;
00267 
00268         c->m_nodeA.prev = NULL;
00269         c->m_nodeA.next = bodyA->m_contactList;
00270         if (bodyA->m_contactList != NULL)
00271         {
00272                 bodyA->m_contactList->prev = &c->m_nodeA;
00273         }
00274         bodyA->m_contactList = &c->m_nodeA;
00275 
00276         // Connect to body B
00277         c->m_nodeB.contact = c;
00278         c->m_nodeB.other = bodyA;
00279 
00280         c->m_nodeB.prev = NULL;
00281         c->m_nodeB.next = bodyB->m_contactList;
00282         if (bodyB->m_contactList != NULL)
00283         {
00284                 bodyB->m_contactList->prev = &c->m_nodeB;
00285         }
00286         bodyB->m_contactList = &c->m_nodeB;
00287 
00288         // Wake up the bodies
00289         if (fixtureA->IsSensor() == false && fixtureB->IsSensor() == false)
00290         {
00291                 bodyA->SetAwake(true);
00292                 bodyB->SetAwake(true);
00293         }
00294 
00295         ++m_contactCount;
00296 }


mvsim
Author(s):
autogenerated on Thu Sep 7 2017 09:27:47