Example #1
0
        /// <summary>
        /// Contacts are persistant and will keep being persistant unless they are
        /// flagged for filtering.
        /// This methods flags all contacts associated with the body for filtering.
        /// </summary>
        internal void Refilter()
        {
            // Flag associated contacts for filtering.
            ContactEdge edge = Body.ContactList;

            while (edge != null)
            {
                Contact   contact  = edge.Contact;
                FSFixture fixtureA = contact.FixtureA;
                FSFixture fixtureB = contact.FixtureB;
                if (fixtureA == this || fixtureB == this)
                {
                    contact.FlagForFiltering();
                }
                edge = edge.Next;
            }

            var world = Body.World;

            if (world == null)
            {
                return;
            }

            // Touch each proxy so that new pairs may be created
            IBroadPhase broadPhase = world.ContactManager.BroadPhase;

            for (int i = 0; i < ProxyCount; ++i)
            {
                broadPhase.TouchProxy(Proxies[i].ProxyId);
            }
        }
Example #2
0
        private void Decompose()
        {
            //Unsubsribe from the PostSolve delegate
            _world.ContactManager.PostSolve -= PostSolve;

            for (int i = 0; i < Parts.Count; i++)
            {
                FSFixture fixture = Parts[i];

                Shape shape = fixture.Shape.Clone();

                object userdata = fixture.UserData;
                MainBody.DestroyFixture(fixture);

                FSBody body = BodyFactory.CreateBody(_world);
                body.BodyType = BodyType.Dynamic;
                body.Position = MainBody.Position;
                body.Rotation = MainBody.Rotation;
                body.UserData = MainBody.UserData;

                body.CreateFixture(shape, userdata);

                body.AngularVelocity = _angularVelocitiesCache[i];
                body.LinearVelocity  = _velocitiesCache[i];
            }

            _world.RemoveBody(MainBody);
            _world.RemoveBreakableBody(this);
        }
Example #3
0
        internal void Destroy(Contact contact)
        {
            FSFixture fixtureA = contact.FixtureA;
            FSFixture fixtureB = contact.FixtureB;
            FSBody    bodyA    = fixtureA.Body;
            FSBody    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;
            }

#if USE_ACTIVE_CONTACT_SET
            if (ActiveContacts.Contains(contact))
            {
                ActiveContacts.Remove(contact);
            }
#endif
            contact.Destroy();
        }
Example #4
0
        /// <summary>
        /// Restores collisions between this fixture and the provided fixture.
        /// </summary>
        /// <param name="fixture">The fixture.</param>
        public void RestoreCollisionWith(FSFixture fixture)
        {
            if (_collisionIgnores == null)
            {
                return;
            }

            if (_collisionIgnores.ContainsKey(fixture.FixtureId))
            {
                _collisionIgnores[fixture.FixtureId] = false;
                Refilter();
            }
        }
Example #5
0
        public void RestoreCollisionWith(FSBody other)
        {
            for (int i = 0; i < FixtureList.Count; i++)
            {
                FSFixture f = FixtureList[i];
                for (int j = 0; j < other.FixtureList.Count; j++)
                {
                    FSFixture f2 = other.FixtureList[j];

                    f.RestoreCollisionWith(f2);
                }
            }
        }
Example #6
0
 internal bool CompareTo(FSFixture fixture)
 {
     return(
         CollidesWith == fixture.CollidesWith &&
         CollisionCategories == fixture.CollisionCategories &&
         CollisionGroup == fixture.CollisionGroup &&
         Friction == fixture.Friction &&
         IsSensor == fixture.IsSensor &&
         Restitution == fixture.Restitution &&
         Shape.CompareTo(fixture.Shape) &&
         UserData == fixture.UserData &&
         UserBits == fixture.UserBits
         );
 }
Example #7
0
        /// <summary>
        /// Determines whether collisions are ignored between this fixture and the provided fixture.
        /// </summary>
        /// <param name="fixture">The fixture.</param>
        /// <returns>
        ///     <c>true</c> if the fixture is ignored; otherwise, <c>false</c>.
        /// </returns>
        public bool IsFixtureIgnored(FSFixture fixture)
        {
            if (_collisionIgnores == null)
            {
                return(false);
            }

            if (_collisionIgnores.ContainsKey(fixture.FixtureId))
            {
                return(_collisionIgnores[fixture.FixtureId]);
            }

            return(false);
        }
Example #8
0
        public FSBreakableBody(IEnumerable <Vertices> vertices, FSWorld world, float density, object userData)
        {
            _world = world;
            _world.ContactManager.PostSolve += PostSolve;
            MainBody          = new FSBody(_world);
            MainBody.BodyType = BodyType.Dynamic;

            foreach (Vertices part in vertices)
            {
                PolygonShape polygonShape = new PolygonShape(part, density);
                FSFixture    fixture      = MainBody.CreateFixture(polygonShape, userData);
                Parts.Add(fixture);
            }
        }
Example #9
0
        private static bool ShouldCollide(FSFixture fixtureA, FSFixture fixtureB)
        {
            if (FSSettings.UseFPECollisionCategories)
            {
                if ((fixtureA.CollisionGroup == fixtureB.CollisionGroup) &&
                    fixtureA.CollisionGroup != 0 && fixtureB.CollisionGroup != 0)
                {
                    return(false);
                }

                if (((fixtureA.CollisionCategories & fixtureB.CollidesWith) ==
                     Category.None) &
                    ((fixtureB.CollisionCategories & fixtureA.CollidesWith) ==
                     Category.None))
                {
                    return(false);
                }

                if (fixtureA.IsFixtureIgnored(fixtureB) ||
                    fixtureB.IsFixtureIgnored(fixtureA))
                {
                    return(false);
                }

                return(true);
            }

            if (fixtureA.CollisionGroup == fixtureB.CollisionGroup &&
                fixtureA.CollisionGroup != 0)
            {
                return(fixtureA.CollisionGroup > 0);
            }

            bool collide = (fixtureA.CollidesWith & fixtureB.CollisionCategories) != 0 &&
                           (fixtureA.CollisionCategories & fixtureB.CollidesWith) != 0;

            if (collide)
            {
                if (fixtureA.IsFixtureIgnored(fixtureB) ||
                    fixtureB.IsFixtureIgnored(fixtureA))
                {
                    return(false);
                }
            }

            return(collide);
        }
Example #10
0
        /// <summary>
        /// Ignores collisions between this fixture and the provided fixture.
        /// </summary>
        /// <param name="fixture">The fixture.</param>
        public void IgnoreCollisionWith(FSFixture fixture)
        {
            if (_collisionIgnores == null)
            {
                _collisionIgnores = new Dictionary <int, bool>();
            }

            if (_collisionIgnores.ContainsKey(fixture.FixtureId))
            {
                _collisionIgnores[fixture.FixtureId] = true;
            }
            else
            {
                _collisionIgnores.Add(fixture.FixtureId, true);
            }

            Refilter();
        }
Example #11
0
        /// <summary>
        /// Destroy a fixture. This removes the fixture from the broad-phase and
        /// destroys all contacts associated with this fixture. This will
        /// automatically adjust the mass of the body if the body is dynamic and the
        /// fixture has positive density.
        /// All fixtures attached to a body are implicitly destroyed when the body is destroyed.
        /// Warning: This function is locked during callbacks.
        /// </summary>
        /// <param name="fixture">The fixture to be removed.</param>
        public void DestroyFixture(FSFixture fixture)
        {
            Debug.Assert(fixture.Body == this);

            // Remove the fixture from this body's singly linked list.
            Debug.Assert(FixtureList.Count > 0);

            // You tried to remove a fixture that not present in the fixturelist.
            Debug.Assert(FixtureList.Contains(fixture));

            // Destroy any contacts associated with the fixture.
            ContactEdge edge = ContactList;

            while (edge != null)
            {
                Contact c = edge.Contact;
                edge = edge.Next;

                FSFixture fixtureA = c.FixtureA;
                FSFixture fixtureB = c.FixtureB;

                if (fixture == fixtureA || fixture == fixtureB)
                {
                    // This destroys the contact and removes it from
                    // this body's contact list.
                    World.ContactManager.Destroy(c);
                }
            }

            if ((Flags & BodyFlags.Enabled) == BodyFlags.Enabled)
            {
                IBroadPhase broadPhase = World.ContactManager.BroadPhase;
                fixture.DestroyProxies(broadPhase);
            }

            FixtureList.Remove(fixture);
            fixture.Destroy();
            fixture.Body = null;

            ResetMassData();
        }
Example #12
0
        public FSFixture Clone(FSBody body)
        {
            FSFixture fixture = new FSFixture();

            fixture.Body = body;

            if (FSSettings.ConserveMemory)
            {
                fixture.Shape = Shape;
            }
            else
            {
                fixture.Shape = Shape.Clone();
            }

            fixture.UserData             = UserData;
            fixture.UserBits             = UserBits;
            fixture.Restitution          = Restitution;
            fixture.Friction             = Friction;
            fixture.IsSensor             = IsSensor;
            fixture._collisionGroup      = CollisionGroup;
            fixture._collisionCategories = CollisionCategories;
            fixture._collidesWith        = CollidesWith;

            if (_collisionIgnores != null)
            {
                fixture._collisionIgnores = new Dictionary <int, bool>();

                foreach (KeyValuePair <int, bool> pair in _collisionIgnores)
                {
                    fixture._collisionIgnores.Add(pair.Key, pair.Value);
                }
            }

            fixture.RegisterFixture();
            return(fixture);
        }
Example #13
0
        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
                FSFixture fixtureA = c.FixtureA;
                FSFixture fixtureB = c.FixtureB;
                int       indexA   = c.ChildIndexA;
                int       indexB   = c.ChildIndexB;
                FSBody    bodyA    = fixtureA.Body;
                FSBody    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
        }
 private bool OnCollisionEvent(FSFixture fixtureA, FSFixture fixtureB, Contact contact)
 {
     if(!lastContacts.Contains(contact))
         lastContacts.Add(contact);
     return true;
 }
Example #15
0
		public FSFixture Clone(FSBody body) {
			FSFixture fixture = new FSFixture();
			fixture.Body = body;

			if (FSSettings.ConserveMemory)
				fixture.Shape = Shape;
			else
				fixture.Shape = Shape.Clone();

			fixture.UserData = UserData;
			fixture.UserBits = UserBits;
			fixture.Restitution = Restitution;
			fixture.Friction = Friction;
			fixture.IsSensor = IsSensor;
			fixture._collisionGroup = CollisionGroup;
			fixture._collisionCategories = CollisionCategories;
			fixture._collidesWith = CollidesWith;

			if (_collisionIgnores != null) {
				fixture._collisionIgnores = new Dictionary<int, bool>();

				foreach (KeyValuePair<int, bool> pair in _collisionIgnores)
					fixture._collisionIgnores.Add(pair.Key, pair.Value);
			}

			fixture.RegisterFixture();
			return fixture;
		}
Example #16
0
		/// <summary>
		/// Determines whether collisions are ignored between this fixture and the provided fixture.
		/// </summary>
		/// <param name="fixture">The fixture.</param>
		/// <returns>
		/// 	<c>true</c> if the fixture is ignored; otherwise, <c>false</c>.
		/// </returns>
		public bool IsFixtureIgnored(FSFixture fixture) {
			if (_collisionIgnores == null) return false;

			if (_collisionIgnores.ContainsKey(fixture.FixtureId))
				return _collisionIgnores[fixture.FixtureId];

			return false;
		}
Example #17
0
		/// <summary>
		/// Restores collisions between this fixture and the provided fixture.
		/// </summary>
		/// <param name="fixture">The fixture.</param>
		public void RestoreCollisionWith(FSFixture fixture) {
			if (_collisionIgnores == null)
				return;

			if (_collisionIgnores.ContainsKey(fixture.FixtureId)) {
				_collisionIgnores[fixture.FixtureId] = false;
				Refilter();
			}
		}
Example #18
0
        //Cutting a shape into two is based on the work of Daid and his prototype BoxCutter: http://www.box2d.org/forum/viewtopic.php?f=3&t=1473
        /// <summary>
        /// Split a fixture into 2 vertice collections using the given entry and exit-point.
        /// </summary>
        /// <param name="fixture">The Fixture to split</param>
        /// <param name="entryPoint">The entry point - The start point</param>
        /// <param name="exitPoint">The exit point - The end point</param>
        /// <param name="splitSize">The size of the split. Think of this as the laser-width</param>
        /// <param name="first">The first collection of vertexes</param>
        /// <param name="second">The second collection of vertexes</param>
        public static void SplitShape(FSFixture fixture, FVector2 entryPoint, FVector2 exitPoint, float splitSize,
                                      out Vertices first, out Vertices second)
        {
            FVector2 localEntryPoint = fixture.Body.GetLocalPoint(ref entryPoint);
            FVector2 localExitPoint = fixture.Body.GetLocalPoint(ref exitPoint);

            PolygonShape shape = fixture.Shape as PolygonShape;

            if (shape == null)
            {
                first = new Vertices();
                second = new Vertices();
                return;
            }

            Vertices vertices = new Vertices(shape.Vertices);
            Vertices[] newPolygon = new Vertices[2];

            for (int i = 0; i < newPolygon.Length; i++)
            {
                newPolygon[i] = new Vertices(vertices.Count);
            }

            int[] cutAdded = { -1, -1 };
            int last = -1;
            for (int i = 0; i < vertices.Count; i++)
            {
                int n;
                //Find out if this vertex is on the old or new shape.
                if (FVector2.Dot(MathUtils.Cross(localExitPoint - localEntryPoint, 1), vertices[i] - localEntryPoint) > FSSettings.Epsilon)
                    n = 0;
                else
                    n = 1;

                if (last != n)
                {
                    //If we switch from one shape to the other add the cut vertices.
                    if (last == 0)
                    {
                        Debug.Assert(cutAdded[0] == -1);
                        cutAdded[0] = newPolygon[last].Count;
                        newPolygon[last].Add(localExitPoint);
                        newPolygon[last].Add(localEntryPoint);
                    }
                    if (last == 1)
                    {
                        Debug.Assert(cutAdded[last] == -1);
                        cutAdded[last] = newPolygon[last].Count;
                        newPolygon[last].Add(localEntryPoint);
                        newPolygon[last].Add(localExitPoint);
                    }
                }

                newPolygon[n].Add(vertices[i]);
                last = n;
            }

            //Add the cut in case it has not been added yet.
            if (cutAdded[0] == -1)
            {
                cutAdded[0] = newPolygon[0].Count;
                newPolygon[0].Add(localExitPoint);
                newPolygon[0].Add(localEntryPoint);
            }
            if (cutAdded[1] == -1)
            {
                cutAdded[1] = newPolygon[1].Count;
                newPolygon[1].Add(localEntryPoint);
                newPolygon[1].Add(localExitPoint);
            }

            for (int n = 0; n < 2; n++)
            {
                FVector2 offset;
                if (cutAdded[n] > 0)
                {
                    offset = (newPolygon[n][cutAdded[n] - 1] - newPolygon[n][cutAdded[n]]);
                }
                else
                {
                    offset = (newPolygon[n][newPolygon[n].Count - 1] - newPolygon[n][0]);
                }
                offset.Normalize();

                newPolygon[n][cutAdded[n]] += splitSize * offset;

                if (cutAdded[n] < newPolygon[n].Count - 2)
                {
                    offset = (newPolygon[n][cutAdded[n] + 2] - newPolygon[n][cutAdded[n] + 1]);
                }
                else
                {
                    offset = (newPolygon[n][0] - newPolygon[n][newPolygon[n].Count - 1]);
                }
                offset.Normalize();

                newPolygon[n][cutAdded[n] + 1] += splitSize * offset;
            }

            first = newPolygon[0];
            second = newPolygon[1];
        }
Example #19
0
        /// <summary>
        /// Destroy a fixture. This removes the fixture from the broad-phase and
        /// destroys all contacts associated with this fixture. This will
        /// automatically adjust the mass of the body if the body is dynamic and the
        /// fixture has positive density.
        /// All fixtures attached to a body are implicitly destroyed when the body is destroyed.
        /// Warning: This function is locked during callbacks.
        /// </summary>
        /// <param name="fixture">The fixture to be removed.</param>
        public void DestroyFixture(FSFixture fixture)
        {
            Debug.Assert(fixture.Body == this);

            // Remove the fixture from this body's singly linked list.
            Debug.Assert(FixtureList.Count > 0);

            // You tried to remove a fixture that not present in the fixturelist.
            Debug.Assert(FixtureList.Contains(fixture));

            // Destroy any contacts associated with the fixture.
            ContactEdge edge = ContactList;
            while (edge != null)
            {
                Contact c = edge.Contact;
                edge = edge.Next;

                FSFixture fixtureA = c.FixtureA;
                FSFixture fixtureB = c.FixtureB;

                if (fixture == fixtureA || fixture == fixtureB)
                {
                    // This destroys the contact and removes it from
                    // this body's contact list.
                    World.ContactManager.Destroy(c);
                }
            }

            if ((Flags & BodyFlags.Enabled) == BodyFlags.Enabled)
            {
                IBroadPhase broadPhase = World.ContactManager.BroadPhase;
                fixture.DestroyProxies(broadPhase);
            }

            FixtureList.Remove(fixture);
            fixture.Destroy();
            fixture.Body = null;

            ResetMassData();
        }
Example #20
0
            private static bool ShouldCollide(FSFixture fixtureA, FSFixture fixtureB)
            {
            if (FSSettings.UseFPECollisionCategories)
            {
                if ((fixtureA.CollisionGroup == fixtureB.CollisionGroup) &&
                    fixtureA.CollisionGroup != 0 && fixtureB.CollisionGroup != 0)
                    return false;

                if (((fixtureA.CollisionCategories & fixtureB.CollidesWith) ==
                     Category.None) &
                    ((fixtureB.CollisionCategories & fixtureA.CollidesWith) ==
                     Category.None))
                    return false;

                if (fixtureA.IsFixtureIgnored(fixtureB) ||
                    fixtureB.IsFixtureIgnored(fixtureA))
                    return false;

                return true;
            }

            if (fixtureA.CollisionGroup == fixtureB.CollisionGroup &&
                fixtureA.CollisionGroup != 0)
            {
                return fixtureA.CollisionGroup > 0;
            }

            bool collide = (fixtureA.CollidesWith & fixtureB.CollisionCategories) != 0 &&
                           (fixtureA.CollisionCategories & fixtureB.CollidesWith) != 0;

            if (collide)
            {
                if (fixtureA.IsFixtureIgnored(fixtureB) ||
                    fixtureB.IsFixtureIgnored(fixtureA))
                {
                    return false;
                }
            }

            return collide;
            }
Example #21
0
        public FSFixture DeepClone()
        {
            FSFixture fix = Clone(Body.Clone());

            return(fix);
        }
Example #22
0
		internal bool CompareTo(FSFixture fixture) {
			return (
					   CollidesWith == fixture.CollidesWith &&
					   CollisionCategories == fixture.CollisionCategories &&
					   CollisionGroup == fixture.CollisionGroup &&
					   Friction == fixture.Friction &&
					   IsSensor == fixture.IsSensor &&
					   Restitution == fixture.Restitution &&
					   Shape.CompareTo(fixture.Shape) &&
					   UserData == fixture.UserData &&
					   UserBits == fixture.UserBits
					);
		}
Example #23
0
		/// <summary>
		/// Ignores collisions between this fixture and the provided fixture.
		/// </summary>
		/// <param name="fixture">The fixture.</param>
		public void IgnoreCollisionWith(FSFixture fixture) {
			if (_collisionIgnores == null)
				_collisionIgnores = new Dictionary<int, bool>();

			if (_collisionIgnores.ContainsKey(fixture.FixtureId))
				_collisionIgnores[fixture.FixtureId] = true;
			else
				_collisionIgnores.Add(fixture.FixtureId, true);

			Refilter();
		}
Example #24
0
        // Broad-phase callback.
        private void AddPair(ref FixtureProxy proxyA, ref FixtureProxy proxyB)
        {
            FSFixture fixtureA = proxyA.Fixture;
            FSFixture fixtureB = proxyB.Fixture;

            int indexA = proxyA.ChildIndex;
            int indexB = proxyB.ChildIndex;

            FSBody bodyA = fixtureA.Body;
            FSBody bodyB = fixtureB.Body;

            // Are the fixtures on the same body?
            if (bodyA == bodyB)
            {
                return;
            }

            // Does a contact already exist?
            ContactEdge edge = bodyB.ContactList;

            while (edge != null)
            {
                if (edge.Other == bodyA)
                {
                    FSFixture fA = edge.Contact.FixtureA;
                    FSFixture fB = edge.Contact.FixtureB;
                    int       iA = edge.Contact.ChildIndexA;
                    int       iB = edge.Contact.ChildIndexB;

                    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 default filter
            if (ShouldCollide(fixtureA, fixtureB) == false)
            {
                return;
            }

            // Check user filtering.
            if (ContactFilter != null && ContactFilter(fixtureA, fixtureB) == false)
            {
                return;
            }

            if (fixtureA.BeforeCollision != null && fixtureA.BeforeCollision(fixtureA, fixtureB) == false)
            {
                return;
            }

            if (fixtureB.BeforeCollision != null && fixtureB.BeforeCollision(fixtureB, fixtureA) == false)
            {
                return;
            }

            // Call the factory.
            Contact c = Contact.Create(fixtureA, indexA, fixtureB, indexB);

            // Contact creation may swap fixtures.
            fixtureA = c.FixtureA;
            fixtureB = c.FixtureB;
            bodyA    = fixtureA.Body;
            bodyB    = fixtureB.Body;

            // Insert into the world.
            ContactList.Add(c);

#if USE_ACTIVE_CONTACT_SET
            ActiveContacts.Add(c);
#endif
            // 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;
        }