public b2ContactEdge GetContactList() { global::System.IntPtr cPtr = Box2DPINVOKE.b2Body_GetContactList__SWIG_0(swigCPtr); b2ContactEdge ret = (cPtr == global::System.IntPtr.Zero) ? null : new b2ContactEdge(cPtr, false); return(ret); }
/** * Set if this fixture is a sensor. */ public void SetSensor(bool sensor) { if (m_isSensor == sensor) { return; } m_isSensor = sensor; if (m_body == null) { return; } b2ContactEdge edge = m_body.GetContactList(); while (edge != null) { b2Contact contact = edge.contact; b2Fixture fixtureA = contact.GetFixtureA(); b2Fixture fixtureB = contact.GetFixtureB(); if (fixtureA == this || fixtureB == this) { contact.SetSensor(fixtureA.IsSensor() || fixtureB.IsSensor()); } edge = edge.next; } }
/// Set the type of this body. This may alter the mass and velocity. public void SetType(BodyType type) { Debug.Assert(m_world.IsLocked() == false); if (m_world.IsLocked() == true) { return; } if (m_type == type) { return; } m_type = type; ResetMassData(); if (m_type == BodyType.b2_staticBody) { m_linearVelocity.SetZero(); m_angularVelocity = 0.0f; m_sweep.a0 = m_sweep.a; m_sweep.c0 = m_sweep.c; SynchronizeFixtures(); } SetAwake(true); m_force.SetZero(); m_torque = 0.0f; // Delete the attached contacts. b2ContactEdge ce = m_contactList; while (ce != null) { b2ContactEdge ce0 = ce; ce = ce.next; m_world.m_contactManager.Destroy(ce0.contact); } m_contactList = null; // Touch the proxies so that new contacts will be created (when appropriate) b2BroadPhase broadPhase = m_world.m_contactManager.m_broadPhase; for (b2Fixture f = m_fixtureList; f != null; f = f.m_next) { int proxyCount = f.m_proxyCount; for (int i = 0; i < proxyCount; ++i) { broadPhase.TouchProxy(f.m_proxies[i].proxyId); } } }
/// Set the active state of the body. An inactive body is not /// simulated and cannot be collided with or woken up. /// If you pass a flag of true, all fixtures will be added to the /// broad-phase. /// If you pass a flag of false, all fixtures will be removed from /// the broad-phase and all contacts will be destroyed. /// Fixtures and joints are otherwise unaffected. You may continue /// to create/destroy fixtures and joints on inactive bodies. /// Fixtures on an inactive body are implicitly inactive and will /// not participate in collisions, ray-casts, or queries. /// Joints connected to an inactive body are implicitly inactive. /// An inactive body is still owned by a b2World object and remains /// in the body list. public void SetActive(bool flag) { Debug.Assert(m_world.IsLocked() == false); if (flag == IsActive()) { return; } if (flag) { m_flags |= BodyFlags.e_activeFlag; // Create all proxies. b2BroadPhase broadPhase = m_world.m_contactManager.m_broadPhase; for (b2Fixture f = m_fixtureList; f != null; f = f.m_next) { f.CreateProxies(broadPhase, m_xf); } // Contacts are created the next time step. } else { m_flags &= ~BodyFlags.e_activeFlag; // Destroy all proxies. b2BroadPhase broadPhase = m_world.m_contactManager.m_broadPhase; for (b2Fixture f = m_fixtureList; f != null; f = f.m_next) { f.DestroyProxies(broadPhase); } // Destroy the attached contacts. b2ContactEdge ce = m_contactList; while (ce != null) { b2ContactEdge ce0 = ce; ce = ce.next; m_world.m_contactManager.Destroy(ce0.contact); } m_contactList = null; } }
public virtual void SetActive(bool flag) { if (flag == IsActive()) { return; } if (flag) { m_flags |= b2BodyFlags.e_activeFlag; // Create all proxies. b2BroadPhase broadPhase = m_world.ContactManager.BroadPhase; for (b2Fixture f = m_fixtureList; f != null; f = f.Next) { f.CreateProxies(broadPhase, m_xf); } // Contacts are created the next time step. } else { m_flags &= ~b2BodyFlags.e_activeFlag; // Destroy all proxies. b2BroadPhase broadPhase = m_world.ContactManager.BroadPhase; for (b2Fixture f = m_fixtureList; f != null; f = f.Next) { f.DestroyProxies(broadPhase); } // Destroy the attached contacts. b2ContactEdge ce = m_contactList; while (ce != null) { b2ContactEdge ce0 = ce; ce = ce.Next; m_world.ContactManager.Destroy(ce0.Contact); } m_contactList = null; } }
public virtual void Refilter() { if (m_body == null) { return; } // Flag associated contacts for filtering. b2ContactEdge edge = m_body.ContactList; while (edge != null) { b2Contact contact = edge.Contact; b2Fixture fixtureA = contact.GetFixtureA(); b2Fixture fixtureB = contact.GetFixtureB(); if (fixtureA == this || fixtureB == this) { contact.FlagForFiltering(); } edge = edge.Next; } b2World world = m_body.World; if (world == null) { return; } // Touch each proxy so that new pairs may be created b2BroadPhase broadPhase = world.ContactManager.BroadPhase; for (int i = 0; i < m_proxyCount; ++i) { broadPhase.TouchProxy(m_proxies[i].proxyId); } }
/** * Set the contact filtering data. This will not update contacts until the next time * step when either parent body is active and awake. */ public void SetFilterData(b2FilterData filter) { m_filter = filter.Copy(); if (m_body != null) { return; } b2ContactEdge edge = m_body.GetContactList(); while (edge != null) { b2Contact contact = edge.contact; b2Fixture fixtureA = contact.GetFixtureA(); b2Fixture fixtureB = contact.GetFixtureB(); if (fixtureA == this || fixtureB == this) { contact.FlagForFiltering(); } edge = edge.next; } }
public b2Body(b2BodyDef bd, b2World world) { m_flags = 0; if (bd.bullet) { m_flags |= b2BodyFlags.e_bulletFlag; } if (bd.fixedRotation) { m_flags |= b2BodyFlags.e_fixedRotationFlag; } if (bd.allowSleep) { m_flags |= b2BodyFlags.e_autoSleepFlag; } if (bd.awake) { m_flags |= b2BodyFlags.e_awakeFlag; } if (bd.active) { m_flags |= b2BodyFlags.e_activeFlag; } m_world = world; m_xf.p = bd.position; m_xf.q.Set(bd.angle); m_sweep.localCenter.SetZero(); m_sweep.c0 = m_xf.p; m_sweep.c = m_xf.p; m_sweep.a0 = bd.angle; m_sweep.a = bd.angle; m_sweep.alpha0 = 0.0f; m_jointList = null; m_contactList = null; m_prev = null; m_next = null; m_linearVelocity = bd.linearVelocity; m_angularVelocity = bd.angularVelocity; m_linearDamping = bd.linearDamping; m_angularDamping = bd.angularDamping; m_gravityScale = bd.gravityScale; m_force.SetZero(); m_torque = 0.0f; m_sleepTime = 0.0f; m_type = bd.type; if (m_type == b2BodyType.b2_dynamicBody) { m_mass = 1.0f; m_invMass = 1.0f; } else { m_mass = 0.0f; m_invMass = 0.0f; } m_I = 0.0f; m_invI = 0.0f; m_userData = bd.userData; m_fixtureList = null; m_fixtureCount = 0; }
public virtual void DestroyFixture(b2Fixture fixture) { Debug.Assert(m_world.IsLocked == false); if (m_world.IsLocked) { return; } Debug.Assert(fixture.Body == this); // Remove the fixture from this body's singly linked list. Debug.Assert(m_fixtureCount > 0); b2Fixture node = m_fixtureList; bool found = false; while (node != null) { if (node == fixture) { node = fixture.Next; found = true; break; } node = node.Next; } // You tried to remove a shape that is not attached to this body. Debug.Assert(found); // Destroy any contacts associated with the fixture. b2ContactEdge edge = m_contactList; while (edge != null) { b2Contact c = edge.Contact; edge = edge.Next; b2Fixture fixtureA = c.FixtureA; b2Fixture fixtureB = c.FixtureB; if (fixture == fixtureA || fixture == fixtureB) { // This destroys the contact and removes it from // this body's contact list. m_world.ContactManager.Destroy(c); } } if (m_flags.HasFlag(b2BodyFlags.e_activeFlag)) { b2BroadPhase broadPhase = m_world.ContactManager.BroadPhase; fixture.DestroyProxies(broadPhase); } fixture.Body = null; fixture.Next = null; --m_fixtureCount; // Reset the mass data. ResetMassData(); }
public b2Body(b2BodyDef bd, b2World world) { m_flags = 0; if (bd.bullet) { m_flags |= b2BodyFlags.e_bulletFlag; } if (bd.fixedRotation) { m_flags |= b2BodyFlags.e_fixedRotationFlag; } if (bd.allowSleep) { m_flags |= b2BodyFlags.e_autoSleepFlag; } if (bd.awake) { m_flags |= b2BodyFlags.e_awakeFlag; } if (bd.active) { m_flags |= b2BodyFlags.e_activeFlag; } m_world = world; m_xf.p = bd.position; m_xf.q.Set(bd.angle); Sweep.localCenter.SetZero(); Sweep.c0 = m_xf.p; Sweep.c = m_xf.p; Sweep.a0 = bd.angle; Sweep.a = bd.angle; Sweep.alpha0 = 0.0f; m_jointList = null; m_contactList = null; Prev = null; Next = null; m_linearVelocity = bd.linearVelocity; m_angularVelocity = bd.angularVelocity; m_linearDamping = bd.linearDamping; m_angularDamping = bd.angularDamping; m_gravityScale = bd.gravityScale; m_force.SetZero(); m_torque = 0.0f; m_sleepTime = 0.0f; m_type = bd.type; if (m_type == b2BodyType.b2_dynamicBody) { m_mass = 1.0f; m_invMass = 1.0f; } else { m_mass = 0.0f; m_invMass = 0.0f; } m_I = 0.0f; m_invI = 0.0f; m_userData = bd.userData; m_fixtureList = null; m_fixtureCount = 0; }
// Find TOI contacts and solve them. public void SolveTOI(b2TimeStep step) { b2Island island = new b2Island(2 * b2Settings.b2_maxTOIContacts, b2Settings.b2_maxTOIContacts, 0, m_contactManager.ContactListener); if (m_stepComplete) { for (b2Body b = m_bodyList; b; b = b.Next) { b.BodyFlags &= ~b2Body.e_islandFlag; b.m_sweep.alpha0 = 0.0f; } for (b2Contact c = m_contactManager.ContactList; c; c = c.Next) { // Invalidate TOI c.ContactFlags &= ~(b2ContactType.e_toiFlag | b2ContactType.e_islandFlag); c.m_toiCount = 0; c.m_toi = 1.0f; } } // Find TOI events and solve them. for (; ;) { // Find the first TOI. b2Contact minContact = null; float minAlpha = 1.0f; for (b2Contact c = m_contactManager.ContactList; c != null; c = c.Next) { // Is this contact disabled? if (c.IsEnabled() == false) { continue; } // Prevent excessive sub-stepping. if (c.m_toiCount > b2Settings.b2_maxSubSteps) { continue; } float alpha = 1.0f; if (c.ContactFlags.HasFlag(b2ContactFlags.e_toiFlag)) { // This contact has a valid cached TOI. alpha = c.m_toi; } else { b2Fixture fA = c.GetFixtureA(); b2Fixture fB = c.GetFixtureB(); // Is there a sensor? if (fA.IsSensor || fB.IsSensor) { continue; } b2Body bA = fA.Body; b2Body bB = fB.Body; b2BodyType typeA = bA.BodyType; b2BodyType typeB = bB.BodyType; bool activeA = bA.IsAwake() && typeA != b2BodyType.b2_staticBody; bool activeB = bB.IsAwake() && typeB != b2BodyType.b2_staticBody; // Is at least one body active (awake and dynamic or kinematic)? if (activeA == false && activeB == false) { continue; } bool collideA = bA.IsBullet() || typeA != b2BodyType.b2_dynamicBody; bool collideB = bB.IsBullet() || typeB != b2BodyType.b2_dynamicBody; // Are these two non-bullet dynamic bodies? if (collideA == false && collideB == false) { continue; } // Compute the TOI for this contact. // Put the sweeps onto the same time interval. float alpha0 = bA.Sweep.alpha0; if (bA.Sweep.alpha0 < bB.Sweep.alpha0) { alpha0 = bB.Sweep.alpha0; bA.Sweep.Advance(alpha0); } else if (bB.Sweep.alpha0 < bA.Sweep.alpha0) { alpha0 = bA.Sweep.alpha0; bB.Sweep.Advance(alpha0); } int indexA = c.GetChildIndexA(); int indexB = c.GetChildIndexB(); // Compute the time of impact in interval [0, minTOI] b2TOIInput input = new b2TOIInput(); input.proxyA.Set(fA.Shape, indexA); input.proxyB.Set(fB.Shape, indexB); input.sweepA = bA.Sweep; input.sweepB = bB.Sweep; input.tMax = 1.0f; b2TOIOutput output = b2TimeOfImpact(input); // Beta is the fraction of the remaining portion of the . float beta = output.t; if (output.state == b2TOIOutputType.e_touching) { alpha = b2Math.b2Min(alpha0 + (1.0f - alpha0) * beta, 1.0f); } else { alpha = 1.0f; } c.m_toi = alpha; c.ContactFlags |= b2ContactFlags.e_toiFlag; } if (alpha < minAlpha) { // This is the minimum TOI found so far. minContact = c; minAlpha = alpha; } } if (minContact == null || 1.0f - 10.0f * b2Settings.b2_epsilon < minAlpha) { // No more TOI events. Done! m_stepComplete = true; break; } { // Advance the bodies to the TOI. b2Fixture fA = minContact.GetFixtureA(); b2Fixture fB = minContact.GetFixtureB(); b2Body bA = fA.Body; b2Body bB = fB.Body; b2Sweep backup1 = bA.Sweep; b2Sweep backup2 = bB.Sweep; bA.Advance(minAlpha); bB.Advance(minAlpha); // The TOI contact likely has some new contact points. minContact.Update(m_contactManager.ContactListener); minContact.ContactFlags &= ~b2ContactFlags.e_toiFlag; ++minContact.m_toiCount; // Is the contact solid? if (minContact.IsEnabled() == false || minContact.IsTouching() == false) { // Restore the sweeps. minContact.SetEnabled(false); bA.Sweep = backup1; bB.Sweep = backup2; bA.SynchronizeTransform(); bB.SynchronizeTransform(); continue; } bA.SetAwake(true); bB.SetAwake(true); // Build the island island.Clear(); island.Add(bA); island.Add(bB); island.Add(minContact); bA.BodyFlags |= b2BodyFlags.e_islandFlag; bB.BodyFlags |= b2BodyFlags.e_islandFlag; minContact.ContentType |= b2ContactFlags.e_islandFlag; // Get contacts on bodyA and bodyB. b2Body[] bodies = new b2Body[] { bA, bB }; for (int i = 0; i < 2; ++i) { b2Body body = bodies[i]; if (body.BodyType == b2BodyType.b2_dynamicBody) { for (b2ContactEdge ce = body.ContactList; ce != null; ce = ce.next) { if (island.BodyCount == island.BodyCapacity) { break; } if (island.ContactCount == island.ContactCapacity) { break; } b2Contact contact = ce.contact; // Has this contact already been added to the island? if (contact.ContactType & b2ContactType.e_islandFlag) { continue; } // Only add static, kinematic, or bullet bodies. b2Body other = ce.other; if (other.BodyType == b2BodyType.b2_dynamicBody && body.IsBullet() == false && other.IsBullet() == false) { continue; } // Skip sensors. bool sensorA = contact.m_fixtureA.m_isSensor; bool sensorB = contact.m_fixtureB.m_isSensor; if (sensorA || sensorB) { continue; } // Tentatively advance the body to the TOI. b2Sweep backup = other.Sweep; if (other.BodyFlags.HasFlag(b2BodyFlags.e_islandFlag)) { other.Advance(minAlpha); } // Update the contact points contact.Update(m_contactManager.ContactListener); // Was the contact disabled by the user? if (contact.IsEnabled() == false) { other.Sweep = backup; other.SynchronizeTransform(); continue; } // Are there contact points? if (contact.IsTouching() == false) { other.Sweep = backup; other.SynchronizeTransform(); continue; } // Add the contact to the island contact.ContactFlags |= b2ContactFlags.e_islandFlag; island.Add(contact); // Has the other body already been added to the island? if (other.BodyFlags.HasFlag(b2BodyFlags.e_islandFlag)) { continue; } // Add the other body to the island. other.BodyFlags |= b2BodyFlags.e_islandFlag; if (other.BodyType != b2BodyType.b2_staticBody) { other.SetAwake(true); } island.Add(other); } } } b2TimeStep subStep; subStep.dt = (1.0f - minAlpha) * step.dt; subStep.inv_dt = 1.0f / subStep.dt; subStep.dtRatio = 1.0f; subStep.positionIterations = 20; subStep.velocityIterations = step.velocityIterations; subStep.warmStarting = false; island.SolveTOI(subStep, bA.m_islandIndex, bB.m_islandIndex); // Reset island flags and synchronize broad-phase proxies. for (int i = 0; i < island.m_bodyCount; ++i) { b2Body body = island.m_bodies[i]; body.BodyFlags &= ~b2BodyFlags.e_islandFlag; if (body.BodyType != b2BodyType.b2_dynamicBody) { continue; } body.SynchronizeFixtures(); // Invalidate all contact TOIs on this displaced body. for (b2ContactEdge ce = body.ContactList; ce != null; ce = ce.next) { ce.Contact.ContactFlags &= ~(b2ContactFlags.e_toiFlag | b2ContactFlags.e_islandFlag); } } // Commit fixture proxy movements to the broad-phase so that new contacts are created. // Also, some contacts can be destroyed. m_contactManager.FindNewContacts(); if (m_subStepping) { m_stepComplete = false; break; } } } }
// Find islands, integrate and solveraints, solve positionraints public void Solve(b2TimeStep step) { m_profile.solveInit = 0.0f; m_profile.solveVelocity = 0.0f; m_profile.solvePosition = 0.0f; // Size the island for the worst case. b2Island island = new b2Island(m_bodyCount, m_contactManager.ContactCount, m_jointCount, m_contactManager.ContactListener); // Clear all the island flags. for (b2Body b = m_bodyList; b != null; b = b.Next) { b.BodyFlags &= ~b2BodyFlags.e_islandFlag; } for (b2Contact c = m_contactManager.ContactList; c != null; c = c.Next) { c.ContactFlags &= ~b2ContactFlags.e_islandFlag; } for (b2Joint j = m_jointList; j; j = j.Next) { j.m_islandFlag = false; } // Build and simulate all awake islands. int stackSize = m_bodyCount; b2Body[] stack = new b2Body[stackSize]; for (b2Body seed = m_bodyList; seed != null; seed = seed.Next) { if (seed.BodyFlags & b2BodyFlags.e_islandFlag) { continue; } if (seed.IsAwake() == false || seed.IsActive() == false) { continue; } // The seed can be dynamic or kinematic. if (seed.BodyType == b2BodyType.b2_staticBody) { continue; } // Reset island and stack. island.Clear(); int stackCount = 0; stack[stackCount++] = seed; seed.BodyFlags |= b2BodyFlags.e_islandFlag; // Perform a depth first search (DFS) on theraint graph. while (stackCount > 0) { // Grab the next body off the stack and add it to the island. b2Body b = stack[--stackCount]; 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.BodyType == b2BodyType.b2_staticBody) { continue; } // Search all contacts connected to this body. for (b2ContactEdge ce = b.ContactList; ce != null; ce = ce.next) { b2Contact contact = ce.contact; // Has this contact already been added to an island? if (contact.ContactFlags & b2ContactFlags.e_islandFlag) { continue; } // Is this contact solid and touching? if (contact.IsEnabled() == false || contact.IsTouching() == false) { continue; } // Skip sensors. bool sensorA = contact.m_fixtureA.m_isSensor; bool sensorB = contact.m_fixtureB.m_isSensor; if (sensorA || sensorB) { continue; } island.Add(contact); contact.ContactFlags |= b2ContactType.e_islandFlag; b2Body other = ce.other; // Was the other body already added to this island? if ((other.BodyFlags & b2BodyFlags.e_islandFlag) > 0) { continue; } stack[stackCount++] = other; other.BodyFlags |= b2BodyFlags.e_islandFlag; } // Search all joints connect to this body. for (b2JointEdge je = b.JointList; je; je = je.next) { if (je.joint.IslandFlag == true) { continue; } b2Body other = je.other; // Don't simulate joints connected to inactive bodies. if (other.IsActive() == false) { continue; } island.Add(je.joint); je.joint.m_islandFlag = true; if ((other.BodyFlags & b2BodyFlags.e_islandFlag) > 0) { continue; } stack[stackCount++] = other; other.BodyFlags |= b2BodyFlags.e_islandFlag; } } b2Profile profile = island.Solve(step, m_gravity, m_allowSleep); m_profile.solveInit += profile.solveInit; m_profile.solveVelocity += profile.solveVelocity; m_profile.solvePosition += profile.solvePosition; // Post solve cleanup. for (int i = 0; i < island.m_bodyCount; ++i) { // Allow static bodies to participate in other islands. b2Body b = island.m_bodies[i]; if (b.BodyType == b2BodyType.b2_staticBody) { b.BodyFlags &= ~b2BodyFlags.e_islandFlag; } } } { b2Timer timer; // Synchronize fixtures, check for out of range bodies. for (b2Body b = m_bodyList; b != null; b = b.Next) { // If a body was not in an island then it did not move. if ((b.BodyFlags & b2BodyType.e_islandFlag) == 0) { continue; } if (b.GetBodyType() == b2BodyType.b2_staticBody) { continue; } // Update fixtures (for broad-phase). b.SynchronizeFixtures(); } // Look for new contacts. m_contactManager.FindNewContacts(); m_profile.broadphase = timer.GetMilliseconds(); } }
public void DestroyJoint(b2Joint j) { if (IsLocked()) { return; } bool collideConnected = j.m_collideConnected; // Remove from the doubly linked list. if (j.Prev) { j.Prev.Next = j.Next; } if (j.Next) { j.Next.Prev = j.Prev; } if (j == m_jointList) { m_jointList = j.Next; } // Disconnect from island graph. b2Body bodyA = j.m_bodyA; b2Body bodyB = j.m_bodyB; // Wake up connected bodies. bodyA.SetAwake(true); bodyB.SetAwake(true); // Remove from body 1. if (j.m_edgeA.prev) { j.m_edgeA.prev.next = j.m_edgeA.next; } if (j.m_edgeA.next) { j.m_edgeA.next.prev = j.m_edgeA.prev; } if (j.m_edgeA == bodyA.JointList) { bodyA.JointList = j.m_edgeA.next; } j.m_edgeA.prev = null; j.m_edgeA.next = null; // Remove from body 2 if (j.m_edgeB.prev) { j.m_edgeB.prev.next = j.m_edgeB.next; } if (j.m_edgeB.next) { j.m_edgeB.next.prev = j.m_edgeB.prev; } if (j.m_edgeB == bodyB.JointList) { bodyB.JointList = j.m_edgeB.next; } j.m_edgeB.prev = null; j.m_edgeB.next = null; b2Joint.Destroy(j); --m_jointCount; // If the joint prevents collisions, then flag any contacts for filtering. if (collideConnected == false) { b2ContactEdge edge = bodyB.ContactList; while (edge != null) { if (edge.other == bodyA) { // Flag the contact for filtering at the next time step (where either // body is awake). edge.contact.FlagForFiltering(); } edge = edge.next; } } }
public b2Joint CreateJoint(b2JointDef def) { if (IsLocked()) { return(null); } b2Joint j = b2Joint.Create(def); // Connect to the world list. j.Prev = null; j.Next = m_jointList; if (m_jointList) { m_jointList.Prev = j; } m_jointList = j; ++m_jointCount; // Connect to the bodies' doubly linked lists. j.m_edgeA.joint = j; j.m_edgeA.other = j.m_bodyB; j.m_edgeA.prev = null; j.m_edgeA.next = j.m_bodyA.JointList; if (j.m_bodyA.JointList) { j.m_bodyA.JointList.prev = &j.m_edgeA; } j.m_bodyA.JointList = &j.m_edgeA; j.m_edgeB.joint = j; j.m_edgeB.other = j.m_bodyA; j.m_edgeB.prev = null; j.m_edgeB.next = j.m_bodyB.JointList; if (j.m_bodyB.JointList) { j.m_bodyB.JointList.prev = &j.m_edgeB; } j.m_bodyB.JointList = &j.m_edgeB; b2Body bodyA = def.bodyA; b2Body bodyB = def.bodyB; // If the joint prevents collisions, then flag any contacts for filtering. if (def.collideConnected == false) { b2ContactEdge edge = bodyB.ContactList; while (edge != null) { if (edge.other == bodyA) { // Flag the contact for filtering at the next time step (where either // body is awake). edge.contact.FlagForFiltering(); } edge = edge.next; } } // Note: creating a joint doesn't wake the bodies. return(j); }
public void DestroyBody(b2Body b) { if (IsLocked()) { return; } // Delete the attached joints. b2JointEdge je = b.JointList; while (je) { b2JointEdge je0 = je; je = je.next; if (m_destructionListener != null) { m_destructionListener.SayGoodbye(je0.joint); } DestroyJoint(je0.joint); b.JointList = je; } b.JointList = null; // Delete the attached contacts. b2ContactEdge ce = b.ContactList; while (ce) { b2ContactEdge ce0 = ce; ce = ce.next; m_contactManager.Destroy(ce0.contact); } b.ContactList = null; // Delete the attached fixtures. This destroys broad-phase proxies. b2Fixture f = b.FixtureList; while (f != null) { b2Fixture f0 = f; f = f.Next; if (m_destructionListener != null) { m_destructionListener.SayGoodbye(f0); } f0.DestroyProxies(m_contactManager.BroadPhase); b.FixtureList = f; b.FixtureCount -= 1; } b.FixtureList = null; b.FixtureCount = 0; // Remove world body list. if (b.Prev != null) { b.Prev.Next = b.Next; } if (b.Next != null) { b.Next.Prev = b.Prev; } if (b == m_bodyList) { m_bodyList = b.Next; } --m_bodyCount; }
public virtual void SetActive(bool flag) { if (flag == IsActive()) { return; } if (flag) { m_flags |= b2BodyFlags.e_activeFlag; // Create all proxies. b2BroadPhase broadPhase = m_world.ContactManager.BroadPhase; for (b2Fixture f = m_fixtureList; f != null; f = f.Next) { f.CreateProxies(broadPhase, m_xf); } // Contacts are created the next time step. } else { m_flags &= ~b2BodyFlags.e_activeFlag; // Destroy all proxies. b2BroadPhase broadPhase = m_world.ContactManager.BroadPhase; for (b2Fixture f = m_fixtureList; f != null; f = f.Next) { f.DestroyProxies(broadPhase); } // Destroy the attached contacts. b2ContactEdge ce = m_contactList; while (ce != null) { b2ContactEdge ce0 = ce; ce = ce.Next; m_world.ContactManager.Destroy(ce0.contact); } m_contactList = null; } }
public b2Body(b2BodyDef bd, b2World world) { BodyFlags = 0; if (bd.bullet) { BodyFlags |= b2BodyFlags.e_bulletFlag; } if (bd.fixedRotation) { BodyFlags |= b2BodyFlags.e_fixedRotationFlag; } if (bd.allowSleep) { BodyFlags |= b2BodyFlags.e_autoSleepFlag; } if (bd.awake) { BodyFlags |= b2BodyFlags.e_awakeFlag; } if (bd.active) { BodyFlags |= b2BodyFlags.e_activeFlag; } World = world; Transform.p = bd.position; Transform.q.Set(bd.angle); Sweep.localCenter.SetZero(); Sweep.c0 = Transform.p; Sweep.c = Transform.p; Sweep.a0 = bd.angle; Sweep.a = bd.angle; Sweep.alpha0 = 0.0f; JointList = null; ContactList = null; Prev = null; Next = null; m_linearVelocity = bd.linearVelocity; m_angularVelocity = bd.angularVelocity; LinearDamping = bd.linearDamping; AngularDamping = bd.angularDamping; GravityScale = bd.gravityScale; Force.SetZero(); Torque = 0.0f; SleepTime = 0.0f; BodyType = bd.type; if (BodyType == b2BodyType.b2_dynamicBody) { Mass = 1.0f; InvertedMass = 1.0f; } else { Mass = 0.0f; InvertedMass = 0.0f; } m_I = 0.0f; InvertedI = 0.0f; UserData = bd.userData; FixtureList = null; FixtureCount = 0; }
public void AddPair(object proxyUserDataA, object proxyUserDataB) { b2FixtureProxy proxyA = (b2FixtureProxy)proxyUserDataA; b2FixtureProxy proxyB = (b2FixtureProxy)proxyUserDataB; b2Fixture fixtureA = proxyA.fixture; b2Fixture fixtureB = proxyB.fixture; int indexA = proxyA.childIndex; int indexB = proxyB.childIndex; b2Body bodyA = fixtureA.GetBody(); b2Body bodyB = fixtureB.GetBody(); // Are the fixtures on the same body? if (bodyA == bodyB) { return; } // TODO_ERIN use a hash table to remove a potential bottleneck when both // bodies have a lot of contacts. // Does a contact already exist? b2ContactEdge edge = bodyB.GetContactList(); while (edge) { if (edge.other == bodyA) { b2Fixture fA = edge.contact.GetFixtureA(); b2Fixture fB = edge.contact.GetFixtureB(); int iA = edge.contact.GetChildIndexA(); int iB = edge.contact.GetChildIndexB(); 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 (m_contactFilter && m_contactFilter.ShouldCollide(fixtureA, fixtureB) == false) { return; } // Call the factory. b2Contact c = b2Contact.Create(fixtureA, indexA, fixtureB, indexB, m_allocator); if (c == null) { return; } // Contact creation may swap fixtures. fixtureA = c.GetFixtureA(); fixtureB = c.GetFixtureB(); indexA = c.GetChildIndexA(); indexB = c.GetChildIndexB(); bodyA = fixtureA.GetBody(); bodyB = fixtureB.GetBody(); // Insert into the world. c.m_prev = null; c.m_next = m_contactList; if (m_contactList != null) { m_contactList.m_prev = c; } m_contactList = c; // Connect to island graph. // Connect to body A c.m_nodeA.contact = c; c.m_nodeA.other = bodyB; c.m_nodeA.prev = null; c.m_nodeA.next = bodyA.m_contactList; if (bodyA.m_contactList != null) { bodyA.m_contactList.prev = &c.m_nodeA; } bodyA.m_contactList = &c.m_nodeA; // Connect to body B c.m_nodeB.contact = c; c.m_nodeB.other = bodyA; c.m_nodeB.prev = null; c.m_nodeB.next = bodyB.m_contactList; if (bodyB.m_contactList != null) { bodyB.m_contactList.prev = &c.m_nodeB; } bodyB.m_contactList = &c.m_nodeB; // Wake up the bodies bodyA.SetAwake(true); bodyB.SetAwake(true); ++m_contactCount; }
public void AddPair(ref b2FixtureProxy proxyA, ref b2FixtureProxy proxyB) { b2Fixture fixtureA = proxyA.fixture; b2Fixture fixtureB = proxyB.fixture; int indexA = proxyA.childIndex; int indexB = proxyB.childIndex; b2Body bodyA = fixtureA.Body; b2Body bodyB = fixtureB.Body; // Are the fixtures on the same body? if (bodyA == bodyB) { return; } // TODO_ERIN use a hash table to remove a potential bottleneck when both // bodies have a lot of contacts. // Does a contact already exist? b2ContactEdge edge = bodyB.ContactList; while (edge != null) { if (edge.Other == bodyA) { b2Fixture fA = edge.Contact.FixtureA; b2Fixture fB = edge.Contact.FixtureB; int iA = edge.Contact.m_indexA; int iB = edge.Contact.m_indexB; 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)) { return; } // Check user filtering. if (m_contactFilter != null && !m_contactFilter.ShouldCollide(fixtureA, fixtureB)) { return; } // Call the factory. b2Contact c = b2Contact.Create(fixtureA, indexA, fixtureB, indexB); if (c == null) { return; } // Contact creation may swap fixtures. //fixtureA = c.FixtureA; //fixtureB = c.FixtureB; //indexA = c.m_indexA; //indexB = c.m_indexB; bodyA = c.FixtureA.Body; bodyB = c.FixtureB.Body; // Insert into the world. c.Prev = null; c.Next = m_contactList; if (m_contactList != null) { m_contactList.Prev = c; } m_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; // Wake up the bodies bodyA.SetAwake(true); bodyB.SetAwake(true); ++m_contactCount; }
// This is a callback from the broadphase when two AABB proxies begin // to overlap. We create a b2Contact to manage the narrow phase. public void AddPair(object proxyUserDataA, object proxyUserDataB) { b2Fixture fixtureA = proxyUserDataA as b2Fixture; b2Fixture fixtureB = proxyUserDataB as b2Fixture; b2Body bodyA = fixtureA.GetBody(); b2Body bodyB = fixtureB.GetBody(); // Are the fixtures on the same body? if (bodyA == bodyB) { return; } // Does a contact already exist? b2ContactEdge edge = bodyB.GetContactList(); while (edge != null) { if (edge.other == bodyA) { b2Fixture fA = edge.contact.GetFixtureA(); b2Fixture fB = edge.contact.GetFixtureB(); if (fA == fixtureA && fB == fixtureB) { return; } if (fA == fixtureB && fB == fixtureA) { 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 (m_contactFilter.ShouldCollide(fixtureA, fixtureB) == false) { return; } // Call the factory. b2Contact c = m_contactFactory.Create(fixtureA, fixtureB); // Contact creation may swap shapes. fixtureA = c.GetFixtureA(); fixtureB = c.GetFixtureB(); bodyA = fixtureA.m_body; bodyB = fixtureB.m_body; // Insert into the world. c.m_prev = null; c.m_next = m_world.m_contactList; if (m_world.m_contactList != null) { m_world.m_contactList.m_prev = c; } m_world.m_contactList = c; // Connect to island graph. // Connect to body A c.m_nodeA.contact = c; c.m_nodeA.other = bodyB; c.m_nodeA.prev = null; c.m_nodeA.next = bodyA.m_contactList; if (bodyA.m_contactList != null) { bodyA.m_contactList.prev = c.m_nodeA; } bodyA.m_contactList = c.m_nodeA; // Connect to body 2 c.m_nodeB.contact = c; c.m_nodeB.other = bodyA; c.m_nodeB.prev = null; c.m_nodeB.next = bodyB.m_contactList; if (bodyB.m_contactList != null) { bodyB.m_contactList.prev = c.m_nodeB; } bodyB.m_contactList = c.m_nodeB; ++m_world.m_contactCount; return; }
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(b2ContactEdge obj) { return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr); }