private void PostSolve(Contact contact, ContactConstraint impulse) { if (!Broken) { if (Parts.Contains(contact.FixtureA) || Parts.Contains(contact.FixtureB)) { float maxImpulse = 0.0f; int count = contact.Manifold.PointCount; for (int i = 0; i < count; ++i) { maxImpulse = Math.Max(maxImpulse, impulse.Points[i].NormalImpulse); } if (maxImpulse > Strength) { // Flag the body for breaking. _break = true; } } } }
public void Add(Contact contact) { if (ContactCount < _contactCapacity) ; _contacts[ContactCount++] = contact; }
internal static Contact Create(Fixture fixtureA, int indexA, Fixture fixtureB, int indexB) { ShapeType type1 = fixtureA.ShapeType; ShapeType type2 = fixtureB.ShapeType; Debug.Assert(ShapeType.Unknown < type1 && type1 < ShapeType.TypeCount); Debug.Assert(ShapeType.Unknown < type2 && type2 < ShapeType.TypeCount); Contact c; Queue<Contact> pool = fixtureA.Body.World.ContactPool; if (pool.Count > 0) { c = pool.Dequeue(); if ((type1 >= type2 || (type1 == ShapeType.Edge && type2 == ShapeType.Polygon)) && !(type2 == ShapeType.Edge && type1 == ShapeType.Polygon)) { c.Reset(fixtureA, indexA, fixtureB, indexB); } else { c.Reset(fixtureB, indexB, fixtureA, indexA); } } else { // Edge+Polygon is non-symetrical due to the way Erin handles collision type registration. if ((type1 >= type2 || (type1 == ShapeType.Edge && type2 == ShapeType.Polygon)) && !(type2 == ShapeType.Edge && type1 == ShapeType.Polygon)) { c = new Contact(fixtureA, indexA, fixtureB, indexB); } else { c = new Contact(fixtureB, indexB, fixtureA, indexA); } } c._type = _registers[(int)type1, (int)type2]; return c; }
public void Reset(Contact[] contacts, int contactCount, float impulseRatio, bool warmstarting) { _contacts = contacts; _constraintCount = contactCount; // grow the array if (Constraints == null || Constraints.Length < _constraintCount) { Constraints = new ContactConstraint[_constraintCount * 2]; for (int i = 0; i < Constraints.Length; i++) { Constraints[i] = new ContactConstraint(); } } // Initialize position independent portions of the constraints. for (int i = 0; i < _constraintCount; ++i) { Contact contact = contacts[i]; Fixture fixtureA = contact.FixtureA; Fixture fixtureB = contact.FixtureB; Shape shapeA = fixtureA.Shape; Shape shapeB = fixtureB.Shape; float radiusA = shapeA.Radius; float radiusB = shapeB.Radius; PhysicsBody bodyA = fixtureA.Body; PhysicsBody bodyB = fixtureB.Body; Manifold manifold = contact.Manifold; Debug.Assert(manifold.PointCount > 0); ContactConstraint cc = Constraints[i]; cc.Friction = Settings.MixFriction(fixtureA.Friction, fixtureB.Friction); cc.Restitution = Settings.MixRestitution(fixtureA.Restitution, fixtureB.Restitution); cc.BodyA = bodyA; cc.BodyB = bodyB; cc.Manifold = manifold; cc.Normal = Vector2.Zero; cc.PointCount = manifold.PointCount; cc.LocalNormal = manifold.LocalNormal; cc.LocalPoint = manifold.LocalPoint; cc.RadiusA = radiusA; cc.RadiusB = radiusB; cc.Type = manifold.Type; for (int j = 0; j < cc.PointCount; ++j) { ManifoldPoint cp = manifold.Points[j]; ContactConstraintPoint ccp = cc.Points[j]; if (warmstarting) { ccp.NormalImpulse = impulseRatio * cp.NormalImpulse; ccp.TangentImpulse = impulseRatio * cp.TangentImpulse; } else { ccp.NormalImpulse = 0.0f; ccp.TangentImpulse = 0.0f; } ccp.LocalPoint = cp.LocalPoint; ccp.rA = Vector2.Zero; ccp.rB = Vector2.Zero; ccp.NormalMass = 0.0f; ccp.TangentMass = 0.0f; ccp.VelocityBias = 0.0f; } cc.K.SetZero(); cc.NormalMass.SetZero(); } }
internal void Destroy(Contact contact) { Fixture fixtureA = contact.FixtureA; Fixture fixtureB = contact.FixtureB; PhysicsBody bodyA = fixtureA.Body; PhysicsBody bodyB = fixtureB.Body; if (EndContact != null && contact.IsTouching()) { EndContact(contact); } // Remove from the world. ContactList.Remove(contact); // Remove from body 1 if (contact.NodeA.Prev != null) { contact.NodeA.Prev.Next = contact.NodeA.Next; } if (contact.NodeA.Next != null) { contact.NodeA.Next.Prev = contact.NodeA.Prev; } if (contact.NodeA == bodyA.ContactList) { bodyA.ContactList = contact.NodeA.Next; } // Remove from body 2 if (contact.NodeB.Prev != null) { contact.NodeB.Prev.Next = contact.NodeB.Next; } if (contact.NodeB.Next != null) { contact.NodeB.Next.Prev = contact.NodeB.Prev; } if (contact.NodeB == bodyB.ContactList) { bodyB.ContactList = contact.NodeB.Next; } contact.Destroy(); }