// Broad-phase callback. private void AddPair(ref FixtureProxy proxyA, ref FixtureProxy proxyB) { Fixture fixtureA = proxyA.Fixture; Fixture fixtureB = proxyB.Fixture; int indexA = proxyA.ChildIndex; int indexB = proxyB.ChildIndex; Body bodyA = fixtureA.Body; Body bodyB = fixtureB.Body; // Are the fixtures on the same body? if (bodyA == bodyB) { return; } // Does a contact already exist? ContactEdge edge = bodyB.ContactList; while (edge != null) { if (edge.Other == bodyA) { Fixture fA = edge.Contact.FixtureA; Fixture fB = edge.Contact.FixtureB; int iA = edge.Contact.ChildIndexA; int iB = edge.Contact.ChildIndexB; 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 default filter if (ShouldCollide(fixtureA, fixtureB) == false) { return; } // Check user filtering. if (OnContactFilter != null && OnContactFilter(fixtureA, fixtureB) == false) { return; } // FPE feature: BeforeCollision delegate if (fixtureA.BeforeCollision != null && fixtureA.BeforeCollision(fixtureA, fixtureB) == false) { return; } if (fixtureB.BeforeCollision != null && fixtureB.BeforeCollision(fixtureB, fixtureA) == false) { return; } // Call the factory. Contact c = Contact.Create(fixtureA, indexA, fixtureB, indexB); if (c == null) { return; } // Contact creation may swap fixtures. fixtureA = c.FixtureA; fixtureB = c.FixtureB; bodyA = fixtureA.Body; bodyB = fixtureB.Body; // Insert into the world. ContactList.Add(c); #if USE_ACTIVE_CONTACT_SET ActiveContacts.Add(c); #endif // 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; // Wake up the bodies if (fixtureA.IsSensor == false && fixtureB.IsSensor == false) { bodyA.IsAwake = true; bodyB.IsAwake = true; } }
// Broad-phase callback. private void AddPair(ref FixtureProxy proxyA, ref FixtureProxy proxyB) { Fixture fixtureA = proxyA.Fixture; Fixture fixtureB = proxyB.Fixture; int indexA = proxyA.ChildIndex; int indexB = proxyB.ChildIndex; Body bodyA = fixtureA.Body; Body bodyB = fixtureB.Body; // Are the fixtures on the same body? if (bodyA == bodyB) { return; } // Does a contact already exist? ContactEdge edge = bodyB.ContactList; while (edge != null) { if (edge.Other == bodyA) { Fixture fA = edge.Contact.FixtureA; Fixture fB = edge.Contact.FixtureB; int iA = edge.Contact.ChildIndexA; int iB = edge.Contact.ChildIndexB; 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(fixtureA, fixtureB) == false) { return; } // Call the factory. Contact c = Contact.Create(fixtureA, indexA, fixtureB, indexB); // Contact creation may swap fixtures. fixtureA = c.FixtureA; fixtureB = c.FixtureB; indexA = c.ChildIndexA; indexB = c.ChildIndexB; bodyA = fixtureA.Body; bodyB = fixtureB.Body; // 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. #if USE_ACTIVE_CONTACT_SET ActiveList.AddRange(ActiveContacts); foreach (var c in ActiveList) { #else for (int i = 0; i < ContactList.Count; i++) { Contact c = ContactList[i]; #endif Fixture fixtureA = c.FixtureA; Fixture fixtureB = c.FixtureB; int indexA = c.ChildIndexA; int indexB = c.ChildIndexB; Body bodyA = fixtureA.Body; Body bodyB = fixtureB.Body; // Do no try to collide disabled bodies if (!bodyA.Enabled || !bodyB.Enabled) { continue; } // Is this contact flagged for filtering? if (c.filterFlag) { // Should these bodies collide? if (bodyB.ShouldCollide(bodyA) == false) { Contact cNuke = c; Destroy(cNuke); continue; } // Check default filtering if (ShouldCollide(fixtureA, fixtureB) == false) { Contact cNuke = c; Destroy(cNuke); continue; } // Check user filtering. if (OnContactFilter != null && OnContactFilter(fixtureA, fixtureB) == false) { Contact cNuke = c; Destroy(cNuke); continue; } // Clear the filtering flag. c.filterFlag = false; } bool activeA = bodyA.IsAwake && bodyA.BodyType != BodyType.Static; bool activeB = bodyB.IsAwake && bodyB.BodyType != BodyType.Static; // At least one body must be awake and it must be dynamic or kinematic. if (activeA == false && activeB == false) { #if USE_ACTIVE_CONTACT_SET ActiveContacts.Remove(c); #endif continue; } 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; Destroy(cNuke); continue; } // The contact persists. c.Update(this); } #if USE_ACTIVE_CONTACT_SET ActiveList.Clear(); #endif }
internal void Collide() { // Update awake contacts. var elements = ContactList.Elements; for (int i = 0, count = ContactList.count; i < count; i++) { Contact c = elements[i]; Fixture fixtureA = c.FixtureA; Fixture fixtureB = c.FixtureB; int indexA = c.ChildIndexA; int indexB = c.ChildIndexB; Body bodyA = fixtureA.Body; Body bodyB = fixtureB.Body; if (bodyA.Awake == false && bodyB.Awake == false) { continue; } // Is this contact flagged for filtering? if ((c.Flags & ContactFlags.Filter) == ContactFlags.Filter) { // Should these bodies collide? if (bodyB.ShouldCollide(bodyA) == false) { Destroy(c, i); count--; continue; } // Check default filtering if (ShouldCollide(fixtureA, fixtureB) == false) { Destroy(c, i); count--; continue; } // Check user filtering. if (ContactFilter != null && ContactFilter(fixtureA, fixtureB) == false) { Destroy(c, i); count--; 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) { Destroy(c, i); count--; continue; } // The contact persists. c.Update(this); } }
internal void Collide() { // Update awake contacts. Contact c = ContactList; while (c != null) { Fixture fixtureA = c.FixtureA; Fixture fixtureB = c.FixtureB; int indexA = c.ChildIndexA; int indexB = c.ChildIndexB; Body bodyA = fixtureA.Body; Body bodyB = fixtureB.Body; if (bodyA.Awake == false && bodyB.Awake == false) { c = c.Next; 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.Next; Destroy(cNuke); continue; } // Check user filtering. if (ContactFilter != null && ContactFilter(fixtureA, fixtureB) == false) { Contact cNuke = c; c = cNuke.Next; 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.Next; Destroy(cNuke); continue; } // The contact persists. c.Update(this); c = c.Next; } }
internal void Collide() { // Update awake contacts. #if USE_ACTIVE_CONTACT_SET ActiveList.AddRange(ActiveContacts); foreach (var c in ActiveList) { #else for (int i = 0; i < ContactList.Count; i++) { Contact c = ContactList[i]; #endif Fixture fixtureA = c.FixtureA; Fixture fixtureB = c.FixtureB; int indexA = c.ChildIndexA; int indexB = c.ChildIndexB; Body bodyA = fixtureA.Body; Body bodyB = fixtureB.Body; if (bodyA.Awake == false && bodyB.Awake == false) { #if USE_ACTIVE_CONTACT_SET ActiveContacts.Remove(c); #endif 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; Destroy(cNuke); continue; } // Check default filtering if (ShouldCollide(fixtureA, fixtureB) == false) { Contact cNuke = c; Destroy(cNuke); continue; } // Check user filtering. if (ContactFilter != null && ContactFilter(fixtureA, fixtureB) == false) { Contact cNuke = c; 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; Destroy(cNuke); continue; } // The contact persists. c.Update(this); } #if USE_ACTIVE_CONTACT_SET ActiveList.Clear(); #endif }
internal void CollideMultiCore() { int lockOrder = 0; // Update awake contacts. #if USE_ACTIVE_CONTACT_SET ActiveList.AddRange(ActiveContacts); foreach (var tmpc in ActiveList) { Contact c = tmpc; #else for (Contact c = ContactList.Next; c != ContactList;) { #endif Fixture fixtureA = c.FixtureA; Fixture fixtureB = c.FixtureB; int indexA = c.ChildIndexA; int indexB = c.ChildIndexB; Body bodyA = fixtureA.Body; Body bodyB = fixtureB.Body; //Do no try to collide disabled bodies if (!bodyA.Enabled || !bodyB.Enabled) { c = c.Next; continue; } // Is this contact flagged for filtering? if (c.FilterFlag) { // Should these bodies collide? if (bodyB.ShouldCollide(bodyA) == false) { Contact cNuke = c; c = c.Next; Destroy(cNuke); continue; } // Check default filtering if (ShouldCollide(fixtureA, fixtureB) == false) { Contact cNuke = c; c = c.Next; Destroy(cNuke); continue; } // Check user filtering. var contactFilterHandler = ContactFilter; if (contactFilterHandler != null) { if (contactFilterHandler(fixtureA, fixtureB) == false) { Contact cNuke = c; c = c.Next; Destroy(cNuke); continue; } } // Clear the filtering flag. c.FilterFlag = false; } bool activeA = bodyA.Awake && bodyA.BodyType != BodyType.Static; bool activeB = bodyB.Awake && bodyB.BodyType != BodyType.Static; // At least one body must be awake and it must be dynamic or kinematic. if (activeA == false && activeB == false) { #if USE_ACTIVE_CONTACT_SET ActiveContacts.Remove(c); #endif c = c.Next; continue; } 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 = c.Next; Destroy(cNuke); continue; } // The contact persists. updateList.Add(c); // Assign a unique id for lock order bodyA._lockOrder = lockOrder++; bodyB._lockOrder = lockOrder++; c = c.Next; } #if USE_ACTIVE_CONTACT_SET ActiveList.Clear(); #endif // TODO: Jää joskus tänne jumiin. // update contacts System.Threading.Tasks.Parallel.ForEach <Contact>(updateList, (c) => { // find lower order item Fixture fixtureA = c.FixtureA; Fixture fixtureB = c.FixtureB; // find lower order item Body orderedBodyA = fixtureA.Body; Body orderedBodyB = fixtureB.Body; int idA = orderedBodyA._lockOrder; int idB = orderedBodyB._lockOrder; if (idA == idB) { throw new System.Exception(); } if (idA > idB) { orderedBodyA = fixtureB.Body; orderedBodyB = fixtureA.Body; } // obtain lock for (; ;) { if (System.Threading.Interlocked.CompareExchange(ref orderedBodyA._lock, 1, 0) == 0) { if (System.Threading.Interlocked.CompareExchange(ref orderedBodyB._lock, 1, 0) == 0) { break; } System.Threading.Interlocked.Exchange(ref orderedBodyA._lock, 0); } #if NET40 || NET45 || NETSTANDARD2_0 System.Threading.Thread.Sleep(0); #endif } c.Update(this); System.Threading.Interlocked.Exchange(ref orderedBodyB._lock, 0); System.Threading.Interlocked.Exchange(ref orderedBodyA._lock, 0); }); updateList.Clear(); }
internal void Collide() { #if NET40 || NET45 || NETSTANDARD2_0 || PORTABLE40 || PORTABLE45 || W10 || W8_1 || WP8_1 if (this.ContactCount > CollideMultithreadThreshold && ThreadsToUse > 1) { CollideMultiCore(); return; } #endif // Update awake contacts. #if USE_ACTIVE_CONTACT_SET ActiveList.AddRange(ActiveContacts); foreach (var tmpc in ActiveList) { Contact c = tmpc; #else for (Contact c = ContactList.Next; c != ContactList;) { #endif Fixture fixtureA = c.FixtureA; Fixture fixtureB = c.FixtureB; int indexA = c.ChildIndexA; int indexB = c.ChildIndexB; Body bodyA = fixtureA.Body; Body bodyB = fixtureB.Body; //Do no try to collide disabled bodies if (!bodyA.Enabled || !bodyB.Enabled) { c = c.Next; continue; } // Is this contact flagged for filtering? if (c.FilterFlag) { // Should these bodies collide? if (bodyB.ShouldCollide(bodyA) == false) { Contact cNuke = c; c = c.Next; Destroy(cNuke); continue; } // Check default filtering if (ShouldCollide(fixtureA, fixtureB) == false) { Contact cNuke = c; c = c.Next; Destroy(cNuke); continue; } // Check user filtering. var contactFilterHandler = ContactFilter; if (contactFilterHandler != null) { if (contactFilterHandler(fixtureA, fixtureB) == false) { Contact cNuke = c; c = c.Next; Destroy(cNuke); continue; } } // Clear the filtering flag. c.FilterFlag = false; } bool activeA = bodyA.Awake && bodyA.BodyType != BodyType.Static; bool activeB = bodyB.Awake && bodyB.BodyType != BodyType.Static; // At least one body must be awake and it must be dynamic or kinematic. if (activeA == false && activeB == false) { #if USE_ACTIVE_CONTACT_SET ActiveContacts.Remove(c); #endif c = c.Next; continue; } 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 = c.Next; Destroy(cNuke); continue; } // The contact persists. c.Update(this); c = c.Next; } #if USE_ACTIVE_CONTACT_SET ActiveList.Clear(); #endif } /// <summary> /// A temporary list of contacts to be updated during Collide(). /// </summary> List <Contact> updateList = new List <Contact>();
// Broad-phase callback. private void AddPair(int proxyIdA, int proxyIdB) { FixtureProxy proxyA = BroadPhase.GetProxy(proxyIdA); FixtureProxy proxyB = BroadPhase.GetProxy(proxyIdB); Fixture fixtureA = proxyA.Fixture; Fixture fixtureB = proxyB.Fixture; int indexA = proxyA.ChildIndex; int indexB = proxyB.ChildIndex; Body bodyA = fixtureA.Body; Body bodyB = fixtureB.Body; // Are the fixtures on the same body? if (bodyA == bodyB) { return; } // Does a contact already exist? for (ContactEdge ceB = bodyB.ContactList; ceB != null; ceB = ceB.Next) { if (ceB.Other == bodyA) { Fixture fA = ceB.Contact.FixtureA; Fixture fB = ceB.Contact.FixtureB; int iA = ceB.Contact.ChildIndexA; int iB = ceB.Contact.ChildIndexB; 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; } } } // Does a joint override collision? Is at least one body dynamic? if (bodyB.ShouldCollide(bodyA) == false) { return; } //Check default filter if (ShouldCollide(fixtureA, fixtureB) == false) { return; } // Check user filtering. var contactFilterHandler = ContactFilter; if (contactFilterHandler != null) { if (contactFilterHandler(fixtureA, fixtureB) == false) { return; } } //FPE feature: BeforeCollision delegate var beforeCollisionHandlerA = fixtureA.BeforeCollision; if (beforeCollisionHandlerA != null) { if (beforeCollisionHandlerA(fixtureA, fixtureB) == false) { return; } } var beforeCollisionHandlerB = fixtureB.BeforeCollision; if (beforeCollisionHandlerB != null) { if (beforeCollisionHandlerB(fixtureB, fixtureA) == false) { return; } } // Call the factory. Contact c = Contact.Create(this, fixtureA, indexA, fixtureB, indexB); if (c == null) { return; } // Contact creation may swap fixtures. fixtureA = c.FixtureA; fixtureB = c.FixtureB; bodyA = fixtureA.Body; bodyB = fixtureB.Body; // Insert into the world. c.Prev = ContactList; c.Next = c.Prev.Next; c.Prev.Next = c; c.Next.Prev = c; ContactCount++; #if USE_ACTIVE_CONTACT_SET ActiveContacts.Add(c); #endif // 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; // Wake up the bodies if (fixtureA.IsSensor == false && fixtureB.IsSensor == false) { bodyA.Awake = true; bodyB.Awake = true; } }
internal void Collide() { // Update awake contacts. for (int i = 0; i < ContactList.Count; i++) { Contact c = ContactList[i]; Fixture fixtureA = c.FixtureA; Fixture fixtureB = c.FixtureB; int indexA = c.ChildIndexA; int indexB = c.ChildIndexB; Body bodyA = fixtureA.Body; Body bodyB = fixtureB.Body; if (bodyA.Awake == false && bodyB.Awake == false) { // If one or both of the fixtures are sensors, it is OK that they are not awake. if (!fixtureA.IsSensor && !fixtureB.IsSensor) { 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; Destroy(cNuke); continue; } // Check default filtering if (ShouldCollide(fixtureA, fixtureB) == false) { Contact cNuke = c; Destroy(cNuke); continue; } // Check user filtering. if (ContactFilter != null && ContactFilter(fixtureA, fixtureB) == false) { Contact cNuke = c; 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; Destroy(cNuke); continue; } // The contact persists. c.Update(this); } }