/// <summary> /// Update the contact manifold and touching status. /// Note: do not assume the fixture AABBs are overlapping or are valid. /// </summary> /// <param name="contactManager">The contact manager.</param> internal void Update(ContactManager contactManager) { Body bodyA = FixtureA.Body; Body bodyB = FixtureB.Body; if (FixtureA == null || FixtureB == null) return; Manifold oldManifold = Manifold; // Re-enable this contact. Enabled = true; bool touching; bool wasTouching = IsTouching; bool sensor = FixtureA.IsSensor || FixtureB.IsSensor; // Is this contact a sensor? if (sensor) { Shape shapeA = FixtureA.Shape; Shape shapeB = FixtureB.Shape; touching = Collision.Collision.TestOverlap(shapeA, ChildIndexA, shapeB, ChildIndexB, ref bodyA._xf, ref bodyB._xf); // Sensors don't generate manifolds. Manifold.PointCount = 0; } else { Evaluate(ref Manifold, ref bodyA._xf, ref bodyB._xf); touching = Manifold.PointCount > 0; // Match old contact ids to new contact ids and copy the // stored impulses to warm start the solver. for (int i = 0; i < Manifold.PointCount; ++i) { ManifoldPoint mp2 = Manifold.Points[i]; mp2.NormalImpulse = 0.0f; mp2.TangentImpulse = 0.0f; ContactID id2 = mp2.Id; for (int j = 0; j < oldManifold.PointCount; ++j) { ManifoldPoint mp1 = oldManifold.Points[j]; if (mp1.Id.Key == id2.Key) { mp2.NormalImpulse = mp1.NormalImpulse; mp2.TangentImpulse = mp1.TangentImpulse; break; } } Manifold.Points[i] = mp2; } if (touching != wasTouching) { bodyA.Awake = true; bodyB.Awake = true; } } IsTouching = touching; if (wasTouching == false) { if (touching) { if (Settings.AllCollisionCallbacksAgree) { bool enabledA = true, enabledB = true; // Report the collision to both participants. Track which ones returned true so we can // later call OnSeparation if the contact is disabled for a different reason. if (FixtureA.OnCollision != null) foreach (OnCollisionEventHandler handler in FixtureA.OnCollision.GetInvocationList()) enabledA = handler(FixtureA, FixtureB, this) && enabledA; // Reverse the order of the reported fixtures. The first fixture is always the one that the // user subscribed to. if (FixtureB.OnCollision != null) foreach (OnCollisionEventHandler handler in FixtureB.OnCollision.GetInvocationList()) enabledB = handler(FixtureB, FixtureA, this) && enabledB; Enabled = enabledA && enabledB; // BeginContact can also return false and disable the contact if (enabledA && enabledB && contactManager.BeginContact != null) Enabled = contactManager.BeginContact(this); } else { //Report the collision to both participants: if (FixtureA.OnCollision != null) foreach (OnCollisionEventHandler handler in FixtureA.OnCollision.GetInvocationList()) Enabled = handler(FixtureA, FixtureB, this); //Reverse the order of the reported fixtures. The first fixture is always the one that the //user subscribed to. if (FixtureB.OnCollision != null) foreach (OnCollisionEventHandler handler in FixtureB.OnCollision.GetInvocationList()) Enabled = handler(FixtureB, FixtureA, this); //BeginContact can also return false and disable the contact if (contactManager.BeginContact != null) Enabled = contactManager.BeginContact(this); } // If the user disabled the contact (needed to exclude it in TOI solver) at any point by // any of the callbacks, we need to mark it as not touching and call any separation // callbacks for fixtures that didn't explicitly disable the collision. if (!Enabled) IsTouching = false; } } else { if (touching == false) { //Report the separation to both participants: if (FixtureA != null && FixtureA.OnSeparation != null) FixtureA.OnSeparation(FixtureA, FixtureB); //Reverse the order of the reported fixtures. The first fixture is always the one that the //user subscribed to. if (FixtureB != null && FixtureB.OnSeparation != null) FixtureB.OnSeparation(FixtureB, FixtureA); if (contactManager.EndContact != null) contactManager.EndContact(this); } } if (sensor) return; if (contactManager.PreSolve != null) contactManager.PreSolve(this, ref oldManifold); }
/// <summary> /// Update the contact manifold and touching status. /// Note: do not assume the fixture AABBs are overlapping or are valid. /// </summary> /// <param name="contactManager">The contact manager.</param> internal void Update(ContactManager contactManager) { Manifold oldManifold = Manifold; // Re-enable this contact. Flags |= ContactFlags.Enabled; bool touching; bool wasTouching = (Flags & ContactFlags.Touching) == ContactFlags.Touching; bool sensorA = FixtureA.IsSensor; bool sensorB = FixtureB.IsSensor; bool sensor = sensorA || sensorB; Body bodyA = FixtureA.Body; Body bodyB = FixtureB.Body; Transform xfA; bodyA.GetTransform(out xfA); Transform xfB; bodyB.GetTransform(out xfB); // Is this contact a sensor? if (sensor) { Shape shapeA = FixtureA.Shape; Shape shapeB = FixtureB.Shape; touching = AABB.TestOverlap(shapeA, ChildIndexA, shapeB, ChildIndexB, ref xfA, ref xfB); // Sensors don't generate manifolds. Manifold.PointCount = 0; } else { Evaluate(ref Manifold, ref xfA, ref xfB); touching = Manifold.PointCount > 0; // Match old contact ids to new contact ids and copy the // stored impulses to warm start the solver. for (int i = 0; i < Manifold.PointCount; ++i) { ManifoldPoint mp2 = Manifold.Points[i]; mp2.NormalImpulse = 0.0f; mp2.TangentImpulse = 0.0f; ContactID id2 = mp2.Id; bool found = false; for (int j = 0; j < oldManifold.PointCount; ++j) { ManifoldPoint mp1 = oldManifold.Points[j]; if (mp1.Id.Key == id2.Key) { mp2.NormalImpulse = mp1.NormalImpulse; mp2.TangentImpulse = mp1.TangentImpulse; found = true; break; } } if (found == false) { mp2.NormalImpulse = 0.0f; mp2.TangentImpulse = 0.0f; } Manifold.Points[i] = mp2; } if (touching != wasTouching) { bodyA.Awake = true; bodyB.Awake = true; } } if (touching) { Flags |= ContactFlags.Touching; } else { Flags &= ~ContactFlags.Touching; } if (wasTouching == false && touching) { // Report the collision to both participants: if (FixtureA.OnCollision != null) Enabled = FixtureA.OnCollision(FixtureA, FixtureB, this); // Reverse the order of the reported fixtures. The first fixture is always the one that the // user subscribed to. if (FixtureB.OnCollision != null) Enabled = FixtureB.OnCollision(FixtureB, FixtureA, this); // if the user disabled the contact (needed to exclude it in TOI solver), we also need to mark // it as not touching. if (Enabled == false) Flags &= ~ContactFlags.Touching; if (contactManager.BeginContact != null) contactManager.BeginContact(this); } if (wasTouching && touching == false) { // Report the separation to both participants: if (FixtureA.OnSeparation != null) FixtureA.OnSeparation(FixtureA, FixtureB); // Reverse the order of the reported fixtures. The first fixture is always the one that the // user subscribed to. if (FixtureB.OnSeparation != null) FixtureB.OnSeparation(FixtureB, FixtureA); if (contactManager.EndContact != null) contactManager.EndContact(this); } if (sensor == false) { if (contactManager.PreSolve != null) contactManager.PreSolve(this, ref oldManifold); } }
/// <summary> /// Update the contact manifold and touching status. /// Note: do not assume the fixture AABBs are overlapping or are valid. /// </summary> /// <param name="contactManager">The contact manager.</param> internal void Update(ContactManager contactManager) { Body bodyA = FixtureA.Body; Body bodyB = FixtureB.Body; if (FixtureA == null || FixtureB == null) { return; } Manifold oldManifold = Manifold; // Re-enable this contact. Enabled = true; bool touching; bool wasTouching = IsTouching; bool sensor = FixtureA.IsSensor || FixtureB.IsSensor; // Is this contact a sensor? if (sensor) { Shape shapeA = FixtureA.Shape; Shape shapeB = FixtureB.Shape; touching = Collision.Collision.TestOverlap(shapeA, ChildIndexA, shapeB, ChildIndexB, ref bodyA._xf, ref bodyB._xf); // Sensors don't generate manifolds. Manifold.PointCount = 0; } else { Evaluate(ref Manifold, ref bodyA._xf, ref bodyB._xf); touching = Manifold.PointCount > 0; // Match old contact ids to new contact ids and copy the // stored impulses to warm start the solver. for (int i = 0; i < Manifold.PointCount; ++i) { ManifoldPoint mp2 = Manifold.Points[i]; mp2.NormalImpulse = 0.0f; mp2.TangentImpulse = 0.0f; ContactID id2 = mp2.Id; for (int j = 0; j < oldManifold.PointCount; ++j) { ManifoldPoint mp1 = oldManifold.Points[j]; if (mp1.Id.Key == id2.Key) { mp2.NormalImpulse = mp1.NormalImpulse; mp2.TangentImpulse = mp1.TangentImpulse; break; } } Manifold.Points[i] = mp2; } if (touching != wasTouching) { bodyA.Awake = true; bodyB.Awake = true; } } IsTouching = touching; if (wasTouching == false) { if (touching) { if (Settings.AllCollisionCallbacksAgree) { bool enabledA = true, enabledB = true; // Report the collision to both participants. Track which ones returned true so we can // later call OnSeparation if the contact is disabled for a different reason. if (FixtureA.OnCollision != null) { foreach (OnCollisionEventHandler handler in FixtureA.OnCollision.GetInvocationList()) { enabledA = handler(FixtureA, FixtureB, this) && enabledA; } } // Reverse the order of the reported fixtures. The first fixture is always the one that the // user subscribed to. if (FixtureB.OnCollision != null) { foreach (OnCollisionEventHandler handler in FixtureB.OnCollision.GetInvocationList()) { enabledB = handler(FixtureB, FixtureA, this) && enabledB; } } Enabled = enabledA && enabledB; // BeginContact can also return false and disable the contact if (enabledA && enabledB && contactManager.BeginContact != null) { Enabled = contactManager.BeginContact(this); } } else { //Report the collision to both participants: if (FixtureA.OnCollision != null) { foreach (OnCollisionEventHandler handler in FixtureA.OnCollision.GetInvocationList()) { Enabled = handler(FixtureA, FixtureB, this); } } //Reverse the order of the reported fixtures. The first fixture is always the one that the //user subscribed to. if (FixtureB.OnCollision != null) { foreach (OnCollisionEventHandler handler in FixtureB.OnCollision.GetInvocationList()) { Enabled = handler(FixtureB, FixtureA, this); } } //BeginContact can also return false and disable the contact if (contactManager.BeginContact != null) { Enabled = contactManager.BeginContact(this); } } // If the user disabled the contact (needed to exclude it in TOI solver) at any point by // any of the callbacks, we need to mark it as not touching and call any separation // callbacks for fixtures that didn't explicitly disable the collision. if (!Enabled) { IsTouching = false; } } } else { if (touching == false) { //Report the separation to both participants: if (FixtureA != null && FixtureA.OnSeparation != null) { FixtureA.OnSeparation(FixtureA, FixtureB); } //Reverse the order of the reported fixtures. The first fixture is always the one that the //user subscribed to. if (FixtureB != null && FixtureB.OnSeparation != null) { FixtureB.OnSeparation(FixtureB, FixtureA); } if (contactManager.EndContact != null) { contactManager.EndContact(this); } } } if (sensor) { return; } if (contactManager.PreSolve != null) { contactManager.PreSolve(this, ref oldManifold); } }
/// <summary> /// Update the contact manifold and touching status. /// Note: do not assume the fixture AABBs are overlapping or are valid. /// </summary> /// <param name="contactManager">The contact manager.</param> internal void Update(ContactManager contactManager) { Manifold oldManifold = Manifold; // Re-enable this contact. Flags |= ContactFlags.Enabled; bool touching; bool wasTouching = (Flags & ContactFlags.Touching) == ContactFlags.Touching; bool sensor = FixtureA.IsSensor || FixtureB.IsSensor; Body bodyA = FixtureA.Body; Body bodyB = FixtureB.Body; // Is this contact a sensor? if (sensor) { Shape shapeA = FixtureA.Shape; Shape shapeB = FixtureB.Shape; //touching = AABB.TestOverlap(shapeA, ChildIndexA, shapeB, ChildIndexB, ref bodyA.Xf, ref bodyB.Xf); //HACK: Super hack sensor overlap, triggers if AABBs overlap AABB AABBA, AABBB; shapeA.ComputeAABB(out AABBA, ref bodyA.Xf, 0); shapeB.ComputeAABB(out AABBB, ref bodyB.Xf, 0); touching = AABB.TestOverlap(ref AABBA, ref AABBB); // Sensors don't generate manifolds. Manifold.PointCount = 0; } else { Evaluate(ref Manifold, ref bodyA.Xf, ref bodyB.Xf); touching = Manifold.PointCount > 0; // Match old contact ids to new contact ids and copy the // stored impulses to warm start the solver. for (int i = 0; i < Manifold.PointCount; ++i) { ManifoldPoint mp2 = Manifold.Points[i]; mp2.NormalImpulse = 0.0f; mp2.TangentImpulse = 0.0f; ContactID id2 = mp2.Id; for (int j = 0; j < oldManifold.PointCount; ++j) { ManifoldPoint mp1 = oldManifold.Points[j]; if (mp1.Id.Key == id2.Key) { mp2.NormalImpulse = mp1.NormalImpulse; mp2.TangentImpulse = mp1.TangentImpulse; break; } } Manifold.Points[i] = mp2; } if (touching != wasTouching) { bodyA.Awake = true; bodyB.Awake = true; } } if (touching) { Flags |= ContactFlags.Touching; } else { Flags &= ~ContactFlags.Touching; } if (wasTouching == false) { if (touching) { #if true bool enabledA, enabledB; // Report the collision to both participants. Track which ones returned true so we can // later call OnSeparation if the contact is disabled for a different reason. if (FixtureA.OnCollision != null) enabledA = FixtureA.OnCollision(FixtureA, FixtureB, this); else enabledA = true; // Reverse the order of the reported fixtures. The first fixture is always the one that the // user subscribed to. if (FixtureB.OnCollision != null) enabledB = FixtureB.OnCollision(FixtureB, FixtureA, this); else enabledB = true; Enabled = enabledA && enabledB; // BeginContact can also return false and disable the contact if (enabledA && enabledB && contactManager.BeginContact != null) { Enabled = contactManager.BeginContact(this); } // If the user disabled the contact (needed to exclude it in TOI solver) at any point by // any of the callbacks, we need to mark it as not touching and call any separation // callbacks for fixtures that didn't explicitly disable the collision. if(!Enabled) { Flags &= ~ContactFlags.Touching; if (enabledA && FixtureA.OnSeparation != null) { FixtureA.OnSeparation(FixtureA, FixtureB); } if (enabledB && FixtureB.OnSeparation != null) { FixtureB.OnSeparation(FixtureB, FixtureA); } } #else //Report the collision to both participants: if (FixtureA.OnCollision != null) Enabled = FixtureA.OnCollision(FixtureA, FixtureB, this); //Reverse the order of the reported fixtures. The first fixture is always the one that the //user subscribed to. if (FixtureB.OnCollision != null) Enabled = FixtureB.OnCollision(FixtureB, FixtureA, this); //BeginContact can also return false and disable the contact if (contactManager.BeginContact != null) Enabled = contactManager.BeginContact(this); //if the user disabled the contact (needed to exclude it in TOI solver), we also need to mark //it as not touching. if (Enabled == false) Flags &= ~ContactFlags.Touching; #endif } } else { if (touching == false) { //Report the separation to both participants: if (FixtureA != null && FixtureA.OnSeparation != null) FixtureA.OnSeparation(FixtureA, FixtureB); //Reverse the order of the reported fixtures. The first fixture is always the one that the //user subscribed to. if (FixtureB != null && FixtureB.OnSeparation != null) FixtureB.OnSeparation(FixtureB, FixtureA); if (contactManager.EndContact != null) contactManager.EndContact(this); } } if (sensor) return; if (contactManager.PreSolve != null) contactManager.PreSolve(this, ref oldManifold); }
/// <summary> /// Update the contact manifold and touching status. /// Note: do not assume the fixture AABBs are overlapping or are valid. /// </summary> /// <param name="contactManager">The contact manager.</param> internal void Update(ContactManager contactManager) { Manifold oldManifold = Manifold; // Re-enable this contact. Flags |= ContactFlags.Enabled; bool touching; bool wasTouching = (Flags & ContactFlags.Touching) == ContactFlags.Touching; bool sensor = FixtureA.IsSensor || FixtureB.IsSensor; Body bodyA = FixtureA.Body; Body bodyB = FixtureB.Body; // Is this contact a sensor? if (sensor) { Shape shapeA = FixtureA.Shape; Shape shapeB = FixtureB.Shape; touching = AABB.TestOverlap(shapeA, ChildIndexA, shapeB, ChildIndexB, ref bodyA.Xf, ref bodyB.Xf); // Sensors don't generate manifolds. Manifold.PointCount = 0; } else { Evaluate(ref Manifold, ref bodyA.Xf, ref bodyB.Xf); touching = Manifold.PointCount > 0; // Match old contact ids to new contact ids and copy the // stored impulses to warm start the solver. for (int i = 0; i < Manifold.PointCount; ++i) { ManifoldPoint mp2 = Manifold.Points[i]; mp2.NormalImpulse = 0.0f; mp2.TangentImpulse = 0.0f; ContactID id2 = mp2.Id; bool found = false; for (int j = 0; j < oldManifold.PointCount; ++j) { ManifoldPoint mp1 = oldManifold.Points[j]; if (mp1.Id.Key == id2.Key) { mp2.NormalImpulse = mp1.NormalImpulse; mp2.TangentImpulse = mp1.TangentImpulse; found = true; break; } } if (found == false) { mp2.NormalImpulse = 0.0f; mp2.TangentImpulse = 0.0f; } Manifold.Points[i] = mp2; } if (touching != wasTouching) { bodyA.Awake = true; bodyB.Awake = true; } } if (touching) { Flags |= ContactFlags.Touching; } else { Flags &= ~ContactFlags.Touching; } if (wasTouching == false && touching) { //Report the collision to both participants: if (FixtureA.OnCollision != null) { Enabled = FixtureA.OnCollision(FixtureA, FixtureB, this); } //Reverse the order of the reported fixtures. The first fixture is always the one that the //user subscribed to. if (FixtureB.OnCollision != null) { Enabled = FixtureB.OnCollision(FixtureB, FixtureA, this); } //BeginContact can also return false and disable the contact if (contactManager.BeginContact != null) { Enabled = contactManager.BeginContact(this); } //if the user disabled the contact (needed to exclude it in TOI solver), we also need to mark //it as not touching. if (Enabled == false) { Flags &= ~ContactFlags.Touching; } } if (wasTouching && touching == false) { //Report the separation to both participants: if (FixtureA != null && FixtureA.OnSeparation != null) { FixtureA.OnSeparation(FixtureA, FixtureB); } //Reverse the order of the reported fixtures. The first fixture is always the one that the //user subscribed to. if (FixtureB != null && FixtureB.OnSeparation != null) { FixtureB.OnSeparation(FixtureB, FixtureA); } if (contactManager.EndContact != null) { contactManager.EndContact(this); } } if (sensor) { return; } if (contactManager.PreSolve != null) { contactManager.PreSolve(this, ref oldManifold); } }