void Arbiter::AddContact(const Vector& p1, const Vector& p2, const Vector& normal) { Vector point = 0.5f * (p1 + p2); Contact* contact = NULL; ContactList::iterator it = contacts.begin(); ContactList::iterator endIt = contacts.end(); while (it != endIt) { if ( ((*it)->point - point).Len3Squared() < 1.0f ) { contact = *it; break; } it++; } if ( contact == NULL ) { contact = new Contact(b1, b2, p1, p2, normal); contacts.push_back(contact); } else { contact->point = point; contact->Update(p1, p2, normal); } }
// This is the top level collision call for the time step. Here // all the narrow phase collision is processed for the world // contact list. void ContactManager::Collide() { // Update awake contacts. Contact* c = m_contactList; while (c) { Fixture* fixtureA = c->GetFixtureA(); Fixture* fixtureB = c->GetFixtureB(); s32 indexA = c->GetChildIndexA(); s32 indexB = c->GetChildIndexB(); Body* bodyA = fixtureA->GetBody(); Body* bodyB = fixtureB->GetBody(); // Is this contact flagged for filtering? if (c->m_flags & Contact::filterFlag) { // Should these bodies collide? if (bodyB->ShouldCollide(bodyA) == false) { Contact* cNuke = c; c = cNuke->GetNext(); Destroy(cNuke); continue; } // Check user filtering. if (m_contactFilter && m_contactFilter->ShouldCollide(fixtureA, fixtureB) == false) { Contact* cNuke = c; c = cNuke->GetNext(); Destroy(cNuke); continue; } // Clear the filtering flag. c->m_flags &= ~Contact::filterFlag; } bool activeA = bodyA->IsAwake() && bodyA->m_type != staticBody; bool activeB = bodyB->IsAwake() && bodyB->m_type != staticBody; // At least one body must be awake and it must be dynamic or kinematic. if (activeA == false && activeB == false) { c = c->GetNext(); continue; } s32 proxyIdA = fixtureA->m_proxies[indexA].proxyId; s32 proxyIdB = fixtureB->m_proxies[indexB].proxyId; bool overlap = m_broadPhase.TestOverlap(proxyIdA, proxyIdB); // Here we destroy contacts that cease to overlap in the broad-phase. if (overlap == false) { Contact* cNuke = c; c = cNuke->GetNext(); Destroy(cNuke); continue; } // The contact persists. c->Update(m_contactListener); c = c->GetNext(); } }