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 (ContactFilter != null && ContactFilter(fixtureA, fixtureB) == false) { Contact cNuke = c; 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 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() { #if NET40 || NET45 || NETSTANDARD2_0 || PORTABLE40 || PORTABLE45 || W10 || W8_1 || WP8_1 if (this.ContactCount > CollideMultithreadThreshold && System.Environment.ProcessorCount > 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. if (ContactFilter != null && ContactFilter(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>();
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 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. if (ContactFilter != null && ContactFilter(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 // 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 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() { // 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 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); } }