public ContactManager() { m_contactList = new List <Contact>(); m_contactFilter = _defaultFilter; m_contactListener = _defaultListener; m_broadPhase = new BroadPhase(); }
// Broad-phase callback. internal void AddPair(FixtureProxy proxyA, FixtureProxy proxyB) { Fixture fixtureA = proxyA.fixture; Fixture fixtureB = proxyB.fixture; int indexA = proxyA.childIndex; int indexB = proxyB.childIndex; Body bodyA = fixtureA.GetBody(); Body bodyB = fixtureB.GetBody(); // Are the fixtures on the same body? if (bodyA == bodyB) { return; } // Does a contact already exist? ContactEdge edge = bodyB.GetContactList(); while (edge != null) { if (edge.Other == bodyA) { Fixture fA = edge.Contact.GetFixtureA(); Fixture fB = edge.Contact.GetFixtureB(); int iA = edge.Contact.GetChildIndexA(); int iB = edge.Contact.GetChildIndexB(); if (fA == fixtureA && fB == fixtureB && iA == indexA && iB == indexB) { // A contact already exists. return; } if (fA == fixtureB && fB == fixtureA && iA == indexB && iB == indexA) { // A contact already exists. return; } } edge = edge.Next; } // Does a joint override collision? Is at least one body dynamic? if (bodyB.ShouldCollide(bodyA) == false) { return; } // Check user filtering. if (ContactFilter != null && ContactFilter.ShouldCollide(fixtureA, fixtureB) == false) { return; } // Call the factory. Contact c = Contact.Create(fixtureA, indexA, fixtureB, indexB); // Contact creation may swap fixtures. fixtureA = c.GetFixtureA(); fixtureB = c.GetFixtureB(); indexA = c.GetChildIndexA(); indexB = c.GetChildIndexB(); bodyA = fixtureA.GetBody(); bodyB = fixtureB.GetBody(); // Insert into the world. c._prev = null; c._next = _contactList; if (_contactList != null) { _contactList._prev = c; } _contactList = c; // Connect to island graph. // Connect to body A c._nodeA.Contact = c; c._nodeA.Other = bodyB; c._nodeA.Prev = null; c._nodeA.Next = bodyA._contactList; if (bodyA._contactList != null) { bodyA._contactList.Prev = c._nodeA; } bodyA._contactList = c._nodeA; // Connect to body B c._nodeB.Contact = c; c._nodeB.Other = bodyA; c._nodeB.Prev = null; c._nodeB.Next = bodyB._contactList; if (bodyB._contactList != null) { bodyB._contactList.Prev = c._nodeB; } bodyB._contactList = c._nodeB; ++_contactCount; }
internal void Collide() { // Update awake contacts. Contact c = _contactList; while (c != null) { Fixture fixtureA = c.GetFixtureA(); Fixture fixtureB = c.GetFixtureB(); int indexA = c.GetChildIndexA(); int indexB = c.GetChildIndexB(); Body bodyA = fixtureA.GetBody(); Body bodyB = fixtureB.GetBody(); if (bodyA.IsAwake() == false && bodyB.IsAwake() == false) { c = c.GetNext(); continue; } // Is this contact flagged for filtering? if ((c._flags & ContactFlags.Filter) == ContactFlags.Filter) { // Should these bodies collide? if (bodyB.ShouldCollide(bodyA) == false) { Contact cNuke = c; c = cNuke.GetNext(); Destroy(cNuke); continue; } // Check user filtering. if (ContactFilter != null && ContactFilter.ShouldCollide(fixtureA, fixtureB) == false) { Contact cNuke = c; c = cNuke.GetNext(); Destroy(cNuke); continue; } // Clear the filtering flag. c._flags &= ~ContactFlags.Filter; } int proxyIdA = fixtureA._proxies[indexA].proxyId; int proxyIdB = fixtureB._proxies[indexB].proxyId; bool overlap = _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(ContactListener); c = c.GetNext(); } }
/// Register a contact filter to provide specific control over collision. /// Otherwise the default filter is used (_defaultFilter). The listener is /// owned by you and must remain in scope. public void SetContactFilter(ContactFilter filter){ m_contactManager.m_contactFilter = filter; }
public ContactManager() { m_contactList = new List<Contact>(); m_contactFilter = _defaultFilter; m_contactListener = _defaultListener; m_broadPhase = new BroadPhase(); }
/// Register a contact filter to provide specific control over collision. /// Otherwise the default filter is used (_defaultFilter). The listener is /// owned by you and must remain in scope. public void SetContactFilter(ContactFilter filter) { m_contactManager.m_contactFilter = filter; }