public void Reset(int bodyCapacity, int contactCapacity, int jointCapacity, IContactListener listener) { _bodyCapacity = bodyCapacity; _contactCapacity = contactCapacity; _jointCapacity = jointCapacity; _bodyCount = 0; _jointCount = 0; _listener = listener; if (_bodies == null || _bodies.Length < bodyCapacity) { _bodies = new Body[bodyCapacity]; } if (_contacts == null || _contacts.Length < contactCapacity) { _contacts = new Contact[contactCapacity * 2]; } if (_joints == null || _joints.Length < jointCapacity) { _joints = new Joint[jointCapacity * 2]; } }
public void BeginContact(Contact contact) { GameObject A = (GameObject)contact.GetFixtureA().GetUserData(); GameObject B = (GameObject)contact.GetFixtureB().GetUserData(); Manifold manifold; Transform xfA; Transform xfB; float radiusA; float radiusB; contact.GetFixtureA().GetBody().GetTransform(out xfA); contact.GetFixtureB().GetBody().GetTransform(out xfB); radiusA = contact.GetFixtureA().GetShape()._radius; radiusB = contact.GetFixtureB().GetShape()._radius; contact.GetManifold(out manifold); WorldManifold worldManifold = new WorldManifold(ref manifold,ref xfA,radiusA,ref xfB,radiusB); Vector2 ptA = worldManifold._points[0]; Vector2 ptB = worldManifold._points[1]; //System.Console.Write(" point {0} {1}\n", ptA, ptB); ColHdr cHdr; cHdr.goID1 = A.getIndexNum(); cHdr.goID2 = B.getIndexNum(); cHdr.pos = ptA; InputHdr iHdr; iHdr.colInfo = cHdr; iHdr.input = InputType.Collision; iHdr.player = PlayerID.none; iHdr.networked = false; OutputQueue.pushHeader(iHdr); //if (A.CollideAvailable == true && B.CollideAvailable == true) //{ // if (A.type < B.type) // { // A.Accept(B, ptA); // } // else // { // B.Accept(A, ptA); // } //} //if (A.type == GameObjType.p1missiles || A.type == GameObjType.p2missiles) //{ // A.CollideAvailable = false; //} //if (B.type == GameObjType.p1missiles || B.type == GameObjType.p2missiles) //{ // B.CollideAvailable = false; //} }
internal ContactManager() { _addPair = AddPair; _contactList = null; _contactCount = 0; ContactFilter = new DefaultContactFilter(); ContactListener = new DefaultContactListener(); }
public void PostSolve(Contact contact, ref ContactImpulse impulse) { Body[] bodies = new Body[2]; bodies[0] = contact.GetFixtureA().GetBody(); bodies[1] = contact.GetFixtureB().GetBody(); mBodies.Add(bodies); if (mBodies.Count > 10000) { mBodies.Clear(); Console.WriteLine("Clear contacts."); } }
public void BeginContact(Contact contact) { Fixture fixtureA = contact.GetFixtureA(); Fixture fixtureB = contact.GetFixtureB(); var unitA = (Unit) fixtureA.GetBody().GetUserData(); var unitB = (Unit) fixtureB.GetBody().GetUserData(); bool shouldContact = GroupManager.Instance.ShouldContact(unitA.Group, unitB.Group); if (shouldContact) { if (fixtureA.IsSensor()) { var sensorData = (SensorInfo) fixtureA.GetUserData(); if (sensorData.Enable && !fixtureB.IsSensor()) { if (unitB is Character && sensorData.SensorName == Constants.SURFACE_SENSOR) { } sensorData.Add(unitB); } } if (fixtureB.IsSensor()) { var sensorData = (SensorInfo) fixtureB.GetUserData(); if (sensorData.Enable && !fixtureA.IsSensor()) { sensorData.Add(unitA); } } } else { if (fixtureA.IsSensor()) { var sensorData = (SensorInfo)fixtureA.GetUserData(); if (sensorData.SensorName == Constants.VISUAL_SENSOR && sensorData.Enable && !fixtureB.IsSensor() && unitB is Character) { sensorData.Add(unitB); } } if (fixtureB.IsSensor()) { var sensorData = (SensorInfo)fixtureB.GetUserData(); if (sensorData.SensorName == Constants.VISUAL_SENSOR && sensorData.Enable && !fixtureA.IsSensor() && unitA is Character) { sensorData.Add(unitA); } } } }
/// <summary> /// Update the gameworld /// </summary> /// <param name="gameTime">GameTime</param> public virtual void update(GameTime gameTime) { Vector2 t_CP = getCheckPoint(entityManager.player.my_Body.Position); if (t_CP.X > lastCP.X) { lastCP = t_CP; entityManager.player.copyInventory(); EntityManager.getEntityManager(game).pushAFloater("Checkpoint", Color.DarkBlue); } physicsWorld.Step((float)gameTime.ElapsedGameTime.TotalSeconds, 15, 6); Box2D.XNA.Contact contact = physicsWorld.GetContactList(); if (contact != null) { entityManager.processContacts(contact); } entityManager.updateAIs(entities.ToArray()); }
public void BeginContact(Contact contact) { object obj1 = contact.GetFixtureA().GetBody().GetUserData(); object obj2 = contact.GetFixtureB().GetBody().GetUserData(); if (obj1 == TYPE_WATER || obj2 == TYPE_WATER) { if (obj1 is Sprite) { ((Sprite)obj1).Drown = true; } else if (obj2 is Sprite) { ((Sprite)obj2).Drown = true; } } }
public void EndContact(Contact contact) { Fixture fixtureA = contact.GetFixtureA(); Fixture fixtureB = contact.GetFixtureB(); if (fixtureA.IsSensor()) { var sensorData = (SensorInfo) fixtureA.GetUserData(); var unitB = (Unit) fixtureB.GetBody().GetUserData(); if (sensorData.Enable) { sensorData.Remove(unitB); } } if (fixtureB.IsSensor()) { var sensorData = (SensorInfo) fixtureB.GetUserData(); var unitA = (Unit) fixtureA.GetBody().GetUserData(); if (sensorData.Enable) { sensorData.Remove(unitA); } } }
/// <summary> Call this to draw shapes and other debug draw data. /// </summary> public void DrawDebugData() { if (DebugDraw == null) { return; } DebugDrawFlags flags = DebugDraw.Flags; if ((flags & DebugDrawFlags.Shape) == DebugDrawFlags.Shape) { for (Body b = _bodyList; b != null; b = b.GetNext()) { Transform xf; b.GetTransform(out xf); for (Fixture f = b.GetFixtureList(); f != null; f = f.GetNext()) { if (b.IsActive() == false) { DrawShape(f, xf, new Color(0.5f, 0.5f, 0.3f)); } else if (b.GetType() == BodyType.Static) { DrawShape(f, xf, new Color(0.5f, 0.9f, 0.5f)); } else if (b.GetType() == BodyType.Kinematic) { DrawShape(f, xf, new Color(0.5f, 0.5f, 0.9f)); } else if (b.IsAwake() == false) { DrawShape(f, xf, new Color(0.6f, 0.6f, 0.6f)); } else { DrawShape(f, xf, new Color(0.9f, 0.7f, 0.7f)); } } } } if ((flags & DebugDrawFlags.Joint) == DebugDrawFlags.Joint) { for (Joint j = _jointList; j != null; j = j.GetNext()) { DrawJoint(j); } } if ((flags & DebugDrawFlags.Pair) == DebugDrawFlags.Pair) { Color color = new Color(0.3f, 0.9f, 0.9f); for (Contact c = _contactManager._contactList; c != null; c = c.GetNext()) { /* * Fixture fixtureA = c.GetFixtureA(); * Fixture fixtureB = c.GetFixtureB(); * * AABB aabbA; * AABB aabbB; * fixtureA.GetAABB(out aabbA); * fixtureB.GetAABB(out aabbB); * * Vector2 cA = aabbA.GetCenter(); * Vector2 cB = aabbB.GetCenter(); * * DebugDraw.DrawSegment(cA, cB, color); */ } } if ((flags & DebugDrawFlags.AABB) == DebugDrawFlags.AABB) { Color color = new Color(0.9f, 0.3f, 0.9f); BroadPhase bp = _contactManager._broadPhase; for (Body b = _bodyList; b != null; b = b.GetNext()) { if (b.IsActive() == false) { continue; } for (Fixture f = b.GetFixtureList(); f != null; f = f.GetNext()) { for (int i = 0; i < f._proxyCount; ++i) { FixtureProxy proxy = f._proxies[i]; AABB aabb; bp.GetFatAABB(proxy.proxyId, out aabb); FixedArray8 <Vector2> vs = new FixedArray8 <Vector2>(); vs[0] = new Vector2(aabb.lowerBound.X, aabb.lowerBound.Y); vs[1] = new Vector2(aabb.upperBound.X, aabb.lowerBound.Y); vs[2] = new Vector2(aabb.upperBound.X, aabb.upperBound.Y); vs[3] = new Vector2(aabb.lowerBound.X, aabb.upperBound.Y); DebugDraw.DrawPolygon(ref vs, 4, color); } } } } if ((flags & DebugDrawFlags.CenterOfMass) == DebugDrawFlags.CenterOfMass) { for (Body b = _bodyList; b != null; b = b.GetNext()) { Transform xf; b.GetTransform(out xf); xf.Position = b.GetWorldCenter(); DebugDraw.DrawTransform(ref xf); } } }
internal void Destroy(Contact c) { Fixture fixtureA = c.GetFixtureA(); Fixture fixtureB = c.GetFixtureB(); Body bodyA = fixtureA.GetBody(); Body bodyB = fixtureB.GetBody(); if (c.IsTouching()) { ContactListener.EndContact(c); } // Remove from the world. if (c._prev != null) { c._prev._next = c._next; } if (c._next != null) { c._next._prev = c._prev; } if (c == _contactList) { _contactList = c._next; } // Remove from body 1 if (c._nodeA.Prev != null) { c._nodeA.Prev.Next = c._nodeA.Next; } if (c._nodeA.Next != null) { c._nodeA.Next.Prev = c._nodeA.Prev; } if (c._nodeA == bodyA._contactList) { bodyA._contactList = c._nodeA.Next; } // Remove from body 2 if (c._nodeB.Prev != null) { c._nodeB.Prev.Next = c._nodeB.Next; } if (c._nodeB.Next != null) { c._nodeB.Next.Prev = c._nodeB.Prev; } if (c._nodeB == bodyB._contactList) { bodyB._contactList = c._nodeB.Next; } c.Destroy(); --_contactCount; }
// Sequentially solve TOIs for each body. We bring each // body to the time of contact and perform some position correction. // Time is not conserved. void SolveTOI() { // Prepare all contacts. for (Contact c = _contactManager._contactList; c != null; c = c._next) { // Enable the contact c._flags |= ContactFlags.Enabled; // Set the number of TOI events for this contact to zero. c._toiCount = 0; } // Initialize the TOI flag. for (Body body = _bodyList; body != null; body = body._next) { // Kinematic, and static bodies will not be affected by the TOI event. // If a body was not in an island then it did not move. if ((body._flags & BodyFlags.Island) == 0 || body.GetType() == BodyType.Kinematic || body.GetType() == BodyType.Static) { body._flags |= BodyFlags.Toi; } else { body._flags &= ~BodyFlags.Toi; } } // Collide non-bullets. for (Body body = _bodyList; body != null; body = body._next) { if ((body._flags & BodyFlags.Toi) != BodyFlags.None) { continue; } if (body.IsBullet == true) { continue; } SolveTOI(body); body._flags |= BodyFlags.Toi; } // Collide bullets. for (Body body = _bodyList; body != null; body = body._next) { if ((body._flags & BodyFlags.Toi) != BodyFlags.None) { continue; } if (body.IsBullet == false) { continue; } SolveTOI(body); body._flags |= BodyFlags.Toi; } }
/// <summary> /// This is one the methods of the IContactListener interface. /// No implementation. /// </summary> /// <param name="contact">Box2D Contact</param> /// <param name="impulse">Box2D ContactImpulse</param> public void PostSolve(Contact contact, ref ContactImpulse impulse) { }
/// <summary> /// A callback function for Box2D to inform that two shapes are beginning to contact with /// each other. Collects the information of the contacts and that information will be /// handled after the physics simulation iterations are completed. /// </summary> /// <param name="contact">Box2D Contact</param> public virtual void BeginContact(Contact contact) { if (!bike.OffTheBike) { UserData data = (UserData)contact.GetFixtureA().GetBody().GetUserData(); if (data != null) { if (data.Name == "finish") { if (Win != null) Win(this); } else if (data.Name == "nail") { if (TireFail != null) TireFail(this); } else if ( (data.Name == "head" && contact.GetFixtureB().GetBody().GetType() == BodyType.Static) || (data.Name == null && ((UserData)contact.GetFixtureB().GetBody().GetUserData()).Name == "head") ) { bikeShouldBeReleased = true; if (HeadFail != null) HeadFail(this); } } } }
void Solve(ref TimeStep step) { // Size the island for the worst case. _island.Reset(_bodyCount, _contactManager._contactCount, _jointCount, _contactManager.ContactListener); // Clear all the island flags. for (Body b = _bodyList; b != null; b = b._next) { b._flags &= ~BodyFlags.Island; } for (Contact c = _contactManager._contactList; c != null; c = c._next) { c._flags &= ~ContactFlags.Island; } for (Joint j = _jointList; j != null; j = j._next) { j._islandFlag = false; } // Build and simulate all awake islands. int stackSize = _bodyCount; if (stackSize > stack.Length) { stack = new Body[Math.Max(stack.Length * 2, stackSize)]; } for (Body seed = _bodyList; seed != null; seed = seed._next) { if ((seed._flags & (BodyFlags.Island)) != BodyFlags.None) { continue; } if (seed.IsAwake() == false || seed.IsActive() == false) { continue; } // The seed can be dynamic or kinematic. if (seed.GetType() == BodyType.Static) { continue; } // Reset island and stack. _island.Clear(); int stackCount = 0; stack[stackCount++] = seed; seed._flags |= BodyFlags.Island; // Perform a depth first search (DFS) on the raint graph. while (stackCount > 0) { // Grab the next body off the stack and add it to the island. Body b = stack[--stackCount]; Debug.Assert(b.IsActive() == true); _island.Add(b); // Make sure the body is awake. b.SetAwake(true); // To keep islands as small as possible, we don't // propagate islands across static bodies. if (b.GetType() == BodyType.Static) { continue; } // Search all contacts connected to this body. for (ContactEdge ce = b._contactList; ce != null; ce = ce.Next) { Contact contact = ce.Contact; // Has this contact already been added to an island? if ((contact._flags & ContactFlags.Island) != ContactFlags.None) { continue; } // Is this contact solid and touching? if (!ce.Contact.IsEnabled() || !ce.Contact.IsTouching()) { continue; } // Skip sensors. bool sensorA = contact._fixtureA._isSensor; bool sensorB = contact._fixtureB._isSensor; if (sensorA || sensorB) { continue; } _island.Add(contact); contact._flags |= ContactFlags.Island; Body other = ce.Other; // Was the other body already added to this island? if ((other._flags & BodyFlags.Island) != BodyFlags.None) { continue; } Debug.Assert(stackCount < stackSize); stack[stackCount++] = other; other._flags |= BodyFlags.Island; } // Search all joints connect to this body. for (JointEdge je = b._jointList; je != null; je = je.Next) { if (je.Joint._islandFlag == true) { continue; } Body other = je.Other; // Don't simulate joints connected to inactive bodies. if (other.IsActive() == false) { continue; } _island.Add(je.Joint); je.Joint._islandFlag = true; if ((other._flags & BodyFlags.Island) != BodyFlags.None) { continue; } Debug.Assert(stackCount < stackSize); stack[stackCount++] = other; other._flags |= BodyFlags.Island; } } _island.Solve(ref step, Gravity, _allowSleep); // Post solve cleanup. for (int i = 0; i < _island._bodyCount; ++i) { // Allow static bodies to participate in other islands. Body b = _island._bodies[i]; if (b.GetType() == BodyType.Static) { b._flags &= ~BodyFlags.Island; } } } // Synchronize fixtures, check for out of range bodies. for (Body b = _bodyList; b != null; b = b.GetNext()) { // If a body was not in an island then it did not move. if ((b._flags & BodyFlags.Island) != BodyFlags.Island) { continue; } if (b.GetType() == BodyType.Static) { continue; } // Update fixtures (for broad-phase). b.SynchronizeFixtures(); } // Look for new contacts. _contactManager.FindNewContacts(); }
public override void PostSolve(Contact contact, ref Box2D.XNA.ContactImpulse impulse) { float intensity = impulse.normalImpulses[0] / 2800F; //intensity = Math.Min(1F, intensity); if (intensity > 0.20F) { Camera.Shake(intensity); OnShake(contact, intensity); } base.PostSolve(contact, ref impulse); }
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; var 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 = Contact.s_registers[(int)type1, (int)type2]; return c; }
public override void BeginContact(Contact contact) { base.BeginContact(contact); }
public void Initialize(Contact[] contacts, int count, Body toiBody) { _count = count; _toiBody = toiBody; if (_constraints.Length < _count) _constraints = new TOIConstraint[Math.Max(_constraints.Length * 2, _count)]; for (int i = 0; i < _count; ++i) { Contact contact = contacts[i]; Fixture fixtureA = contact.GetFixtureA(); Fixture fixtureB = contact.GetFixtureB(); Shape shapeA = fixtureA.GetShape(); Shape shapeB = fixtureB.GetShape(); float radiusA = shapeA._radius; float radiusB = shapeB._radius; Body bodyA = fixtureA.GetBody(); Body bodyB = fixtureB.GetBody(); Manifold manifold; contact.GetManifold(out manifold); Debug.Assert(manifold._pointCount > 0); TOIConstraint constraint = _constraints[i]; constraint.bodyA = bodyA; constraint.bodyB = bodyB; constraint.localNormal = manifold._localNormal; constraint.localPoint = manifold._localPoint; constraint.type = manifold._type; constraint.pointCount = manifold._pointCount; constraint.radius = radiusA + radiusB; for (int j = 0; j < constraint.pointCount; ++j) { constraint.localPoints[j] = manifold._points[j].LocalPoint; } _constraints[i] = constraint; } }
public void PreSolve(Contact contact, ref Manifold oldManifold) { var unitA = (Unit) contact.GetFixtureA().GetBody().GetUserData(); var unitB = (Unit) contact.GetFixtureB().GetBody().GetUserData(); if (!(unitA.EnableCollision && unitB.EnableCollision && GroupManager.Instance.ShouldContact(unitA.Group, unitB.Group))) { contact.SetEnabled(false); } }
// Broad-phase callback. internal void AddPair(Fixture proxyUserDataA, Fixture proxyUserDataB) { Fixture fixtureA = proxyUserDataA; Fixture fixtureB = proxyUserDataB; 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(); if (fA == fixtureA && fB == fixtureB) { // A contact already exists. return; } if (fA == fixtureB && fB == fixtureA) { // 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.ShouldCollide(fixtureA, fixtureB) == false) { return; } // Call the factory. Contact c = Contact.Create(fixtureA, fixtureB); // Contact creation may swap fixtures. fixtureA = c.GetFixtureA(); fixtureB = c.GetFixtureB(); 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; }
public void BeginContact(Contact contact) { }
public void EndContact(Contact contact) { while (contact != null) { var lhsInfo = new ContactInfo(); var rhsInfo = new ContactInfo(); lhsInfo.contact = contact; rhsInfo.contact = contact; lhsInfo.fixtureType = FixtureType.A; rhsInfo.fixtureType = FixtureType.B; var lhsGo = contact.GetFixtureA().GetBody().GetUserData() as GameObject; var rhsGo = contact.GetFixtureB().GetBody().GetUserData() as GameObject; lhsInfo.other = rhsGo; rhsInfo.other = lhsGo; if (lhsGo != null) { lhsGo.EndContact(lhsInfo); } if (rhsGo != null) { rhsGo.EndContact(rhsInfo); } contact = contact.GetNext(); } }
// Advance a dynamic body to its first time of contact // and adjust the position to ensure clearance. void SolveTOI(Body body) { // Find the minimum contact. Contact toiContact = null; float toi = 1.0f; Body toiOther = null; bool found; int count; int iter = 0; bool bullet = body.IsBullet; // Iterate until all contacts agree on the minimum TOI. We have // to iterate because the TOI algorithm may skip some intermediate // collisions when objects rotate through each other. do { count = 0; found = false; for (ContactEdge ce = body._contactList; ce != null; ce = ce.Next) { if (ce.Contact == toiContact) { continue; } Body other = ce.Other; BodyType type = other.GetType(); // Only bullets perform TOI with dynamic bodies. if (bullet == true) { // Bullets only perform TOI with bodies that have their TOI resolved. if ((other._flags & BodyFlags.Toi) == 0) { continue; } // No repeated hits on non-static bodies if (type != BodyType.Static && (ce.Contact._flags & ContactFlags.BulletHit) != 0) { continue; } } else if (type == BodyType.Dynamic) { continue; } // Check for a disabled contact. Contact contact = ce.Contact; if (contact.IsEnabled() == false) { continue; } // Prevent infinite looping. if (contact._toiCount > 10) { continue; } Fixture fixtureA = contact._fixtureA; Fixture fixtureB = contact._fixtureB; int indexA = contact._indexA; int indexB = contact._indexB; // Cull sensors. if (fixtureA.IsSensor() || fixtureB.IsSensor()) { continue; } Body bodyA = fixtureA._body; Body bodyB = fixtureB._body; // Compute the time of impact in interval [0, minTOI] TOIInput input = new TOIInput(); input.proxyA.Set(fixtureA.GetShape(), indexA); input.proxyB.Set(fixtureB.GetShape(), indexB); input.sweepA = bodyA._sweep; input.sweepB = bodyB._sweep; input.tMax = toi; TOIOutput output; TimeOfImpact.CalculateTimeOfImpact(out output, ref input); if (output.State == TOIOutputState.Touching && output.t < toi) { toiContact = contact; toi = output.t; toiOther = other; found = true; } ++count; } ++iter; } while (found && count > 1 && iter < 50); if (toiContact == null) { body.Advance(1.0f); return; } Sweep backup = body._sweep; body.Advance(toi); toiContact.Update(_contactManager.ContactListener); if (toiContact.IsEnabled() == false) { // Contact disabled. Backup and recurse. body._sweep = backup; SolveTOI(body); } ++toiContact._toiCount; // Update all the valid contacts on this body and build a contact island. count = 0; for (ContactEdge ce = body._contactList; (ce != null) && (count < Settings.b2_maxTOIContacts); ce = ce.Next) { Body other = ce.Other; BodyType type = other.GetType(); // Only perform correction with static bodies, so the // body won't get pushed out of the world. if (type == BodyType.Dynamic) { continue; } // Check for a disabled contact. Contact contact = ce.Contact; if (contact.IsEnabled() == false) { continue; } Fixture fixtureA = contact._fixtureA; Fixture fixtureB = contact._fixtureB; // Cull sensors. if (fixtureA.IsSensor() || fixtureB.IsSensor()) { continue; } // The contact likely has some new contact points. The listener // gives the user a chance to disable the contact. if (contact != toiContact) { contact.Update(_contactManager.ContactListener); } // Did the user disable the contact? if (contact.IsEnabled() == false) { // Skip this contact. continue; } if (contact.IsTouching() == false) { continue; } _toiContacts[count] = contact; ++count; } // Reduce the TOI body's overlap with the contact island. _toiSolver.Initialize(_toiContacts, count, body); float k_toiBaumgarte = 0.75f; //bool solved = false; for (int i = 0; i < 20; ++i) { bool contactsOkay = _toiSolver.Solve(k_toiBaumgarte); if (contactsOkay) { //solved = true; break; } } if (toiOther.GetType() != BodyType.Static) { toiContact._flags |= ContactFlags.BulletHit; } }
public void Reset(Contact[] contacts, int contactCount, float impulseRatio) { _contacts = contacts; _constraintCount = contactCount; // grow the array if (_constraints == null || _constraints.Length < _constraintCount) { _constraints = new ContactConstraint[_constraintCount * 2]; } for (int i = 0; i < _constraintCount; ++i) { Contact contact = contacts[i]; Fixture fixtureA = contact._fixtureA; Fixture fixtureB = contact._fixtureB; Shape shapeA = fixtureA.GetShape(); Shape shapeB = fixtureB.GetShape(); float radiusA = shapeA._radius; float radiusB = shapeB._radius; Body bodyA = fixtureA.GetBody(); Body bodyB = fixtureB.GetBody(); Manifold manifold; contact.GetManifold(out manifold); float friction = Settings.b2MixFriction(fixtureA.GetFriction(), fixtureB.GetFriction()); float restitution = Settings.b2MixRestitution(fixtureA.GetRestitution(), fixtureB.GetRestitution()); Vector2 vA = bodyA._linearVelocity; Vector2 vB = bodyB._linearVelocity; float wA = bodyA._angularVelocity; float wB = bodyB._angularVelocity; Debug.Assert(manifold._pointCount > 0); WorldManifold worldManifold = new WorldManifold(ref manifold, ref bodyA._xf, radiusA, ref bodyB._xf, radiusB); ContactConstraint cc = _constraints[i]; cc.bodyA = bodyA; cc.bodyB = bodyB; cc.manifold = manifold; cc.normal = worldManifold._normal; cc.pointCount = manifold._pointCount; cc.friction = friction; cc.localNormal = manifold._localNormal; cc.localPoint = manifold._localPoint; cc.radius = radiusA + radiusB; cc.type = manifold._type; for (int j = 0; j < cc.pointCount; ++j) { ManifoldPoint cp = manifold._points[j]; ContactConstraintPoint ccp = cc.points[j]; ccp.normalImpulse = impulseRatio * cp.NormalImpulse; ccp.tangentImpulse = impulseRatio * cp.TangentImpulse; ccp.localPoint = cp.LocalPoint; ccp.rA = worldManifold._points[j] - bodyA._sweep.c; ccp.rB = worldManifold._points[j] - bodyB._sweep.c; #if MATH_OVERLOADS float rnA = MathUtils.Cross(ccp.rA, cc.normal); float rnB = MathUtils.Cross(ccp.rB, cc.normal); #else float rnA = ccp.rA.X * cc.normal.Y - ccp.rA.Y * cc.normal.X; float rnB = ccp.rB.X * cc.normal.Y - ccp.rB.Y * cc.normal.X; #endif rnA *= rnA; rnB *= rnB; float kNormal = bodyA._invMass + bodyB._invMass + bodyA._invI * rnA + bodyB._invI * rnB; Debug.Assert(kNormal > Settings.b2_epsilon); ccp.normalMass = 1.0f / kNormal; #if MATH_OVERLOADS Vector2 tangent = MathUtils.Cross(cc.normal, 1.0f); float rtA = MathUtils.Cross(ccp.rA, tangent); float rtB = MathUtils.Cross(ccp.rB, tangent); #else Vector2 tangent = new Vector2(cc.normal.Y, -cc.normal.X); float rtA = ccp.rA.X * tangent.Y - ccp.rA.Y * tangent.X; float rtB = ccp.rB.X * tangent.Y - ccp.rB.Y * tangent.X; #endif rtA *= rtA; rtB *= rtB; float kTangent = bodyA._invMass + bodyB._invMass + bodyA._invI * rtA + bodyB._invI * rtB; Debug.Assert(kTangent > Settings.b2_epsilon); ccp.tangentMass = 1.0f / kTangent; // Setup a velocity bias for restitution. ccp.velocityBias = 0.0f; float vRel = Vector2.Dot(cc.normal, vB + MathUtils.Cross(wB, ccp.rB) - vA - MathUtils.Cross(wA, ccp.rA)); if (vRel < -Settings.b2_velocityThreshold) { ccp.velocityBias = -restitution * vRel; } cc.points[j] = ccp; } // If we have two points, then prepare the block solver. if (cc.pointCount == 2) { ContactConstraintPoint ccp1 = cc.points[0]; ContactConstraintPoint ccp2 = cc.points[1]; float invMassA = bodyA._invMass; float invIA = bodyA._invI; float invMassB = bodyB._invMass; float invIB = bodyB._invI; float rn1A = MathUtils.Cross(ccp1.rA, cc.normal); float rn1B = MathUtils.Cross(ccp1.rB, cc.normal); float rn2A = MathUtils.Cross(ccp2.rA, cc.normal); float rn2B = MathUtils.Cross(ccp2.rB, cc.normal); float k11 = invMassA + invMassB + invIA * rn1A * rn1A + invIB * rn1B * rn1B; float k22 = invMassA + invMassB + invIA * rn2A * rn2A + invIB * rn2B * rn2B; float k12 = invMassA + invMassB + invIA * rn1A * rn2A + invIB * rn1B * rn2B; // Ensure a reasonable condition number. const float k_maxConditionNumber = 100.0f; if (k11 * k11 < k_maxConditionNumber * (k11 * k22 - k12 * k12)) { // K is safe to invert. cc.K = new Mat22(new Vector2(k11, k12), new Vector2(k12, k22)); cc.normalMass = cc.K.GetInverse(); } else { // The constraints are redundant, just use one. // TODO_ERIN use deepest? cc.pointCount = 1; } } _constraints[i] = cc; } }
internal static Contact Create(Fixture fixtureA, Fixture fixtureB) { 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; var pool = fixtureA._body._world._contactPool; if (pool.Count > 0) { c = pool.Dequeue(); if (type1 >= type2) { c.Reset(fixtureA, fixtureB); } else { c.Reset(fixtureB, fixtureA); } } else { if (type1 >= type2) { c = new Contact(fixtureA, fixtureB); } else { c = new Contact(fixtureB, fixtureA); } } c._type = Contact.s_registers[(int)type1, (int)type2]; return c; }
//public override void BeginContact(Contact contact) //{ // base.BeginContact(contact); // object objA = contact.GetFixtureA().GetBody().GetUserData(); // object objB = contact.GetFixtureB().GetBody().GetUserData(); // foreach (Type t in contactTypes.Keys) // { // if (objA.GetType() == t) // { // contactTypes[t](objA, objB); // break; // } // else if (objB.GetType() == t) // { // contactTypes[t](objB, objA); // break; // } // } //} public override void EndContact(Contact contact) { base.EndContact(contact); object objA = contact.GetFixtureA().GetBody().GetUserData(); object objB = contact.GetFixtureB().GetBody().GetUserData(); if (objA is Walker || objB is Walker) { walker.EndContact(); } }
internal void Reset(Fixture fA, Fixture fB) { _flags = ContactFlags.Enabled; _fixtureA = fA; _fixtureB = fB; _manifold._pointCount = 0; _prev = null; _next = null; _nodeA.Contact = null; _nodeA.Prev = null; _nodeA.Next = null; _nodeA.Other = null; _nodeB.Contact = null; _nodeB.Prev = null; _nodeB.Next = null; _nodeB.Other = null; _toiCount = 0; }
protected virtual void OnShake(Contact contact, float intensity) { if (!(contact.GetFixtureA().GetBody().GetUserData() is Walker) && !(contact.GetFixtureB().GetBody().GetUserData() is Walker)) { if (stage != null) { if (intensity < .5f) { Cue c = stage.audio.PlaySound(Sfx.woodHit); c.SetVariable("Volume", 1); } else { float vol = intensity / 4 + .75f; vol = vol > 1 ? 1f : vol < 0.75f ? 0.75f : vol; Cue c = stage.audio.PlaySound(Sfx.smash); c.SetVariable("Volume", vol); } } } }
public void Add(Contact contact) { Debug.Assert(_contactCount < _contactCapacity); _contacts[_contactCount++] = contact; }
public void EndContact(Contact contact) { }
public virtual void EndContact(Contact contact) { object objA = contact.GetFixtureA().GetBody().GetUserData(); object objB = contact.GetFixtureB().GetBody().GetUserData(); foreach (Type t in contactEndTypes.Keys) { if (objA.GetType() == t) { contactEndTypes[t](objA, objB, contact.GetFixtureA(), contact.GetFixtureB()); break; } else if (objB.GetType() == t) { contactEndTypes[t](objB, objA, contact.GetFixtureB(), contact.GetFixtureA()); break; } } }
/// <summary> /// This is one the methods of the IContactListener interface. /// No implementation. /// </summary> /// <param name="contact">Box2D Contact</param> public virtual void EndContact(Contact contact) { }
public virtual void PreSolve(Contact contact, ref Manifold oldManifold) { // call this in the base class if points are needed // PreSolveCalcPoints(contact, ref oldManifold); }
/// <summary> /// This is one the methods of the IContactListener interface. /// No implementation. /// </summary> /// <param name="contact">Box2D Contact</param> /// <param name="oldManifold">Box2D Manifold</param> public void PreSolve(Contact contact, ref Manifold oldManifold) { }
protected void PreSolveCalcPoints(Contact contact, ref Manifold oldManifold) { Manifold manifold; contact.GetManifold(out manifold); if (manifold._pointCount == 0) { return; } Fixture fixtureA = contact.GetFixtureA(); Fixture fixtureB = contact.GetFixtureB(); FixedArray2<PointState> state1, state2; Collision.GetPointStates(out state1, out state2, ref oldManifold, ref manifold); WorldManifold worldManifold; contact.GetWorldManifold(out worldManifold); for (int i = 0; i < manifold._pointCount && _pointCount < k_maxContactPoints; ++i) { if (fixtureA == null) { _points[i] = new ContactPoint(); } ContactPoint cp = _points[_pointCount]; cp.fixtureA = fixtureA; cp.fixtureB = fixtureB; cp.position = worldManifold._points[i]; cp.normal = worldManifold._normal; cp.state = state2[i]; _points[_pointCount] = cp; ++_pointCount; } }