Exemple #1
0
        // Removes this box from the body and broadphase. Forces the body
        // to recompute its mass if the body is dynamic. Frees the memory
        // pointed to by the box pointer.
        public void RemoveBox(Box box)
        {
            Assert(box != null);
            Assert(box.body == this);

            bool found = Boxes.Remove(box);

            // This shape was not connected to this body.
            Assert(found);

            // Remove all contacts associated with this shape
            foreach (var edge in ContactList)
            {
                ContactConstraint contact = edge.constraint;

                Box A = contact.A;
                Box B = contact.B;

                if (box == A || box == B)
                {
                    Scene.ContactManager.RemoveContact(contact);
                }
            }

            Scene.ContactManager.Broadphase.RemoveBox(box);

            CalculateMassData();

            // Scene.Heap.Free((void)box);
        }
        // Add a new contact constraint for a pair of objects
        // unless the contact constraint already exists
        public void AddContact(Box A, Box B)
        {
            Body bodyA = A.body;
            Body bodyB = B.body;

            if (!bodyA.CanCollide(bodyB))
            {
                return;
            }

            // Search for existing matching contact
            // Return if found duplicate to avoid duplicate constraints
            // Mark pre-existing duplicates as active
            foreach (var edge in A.body.ContactList)
            {
                if (edge.other == bodyB)
                {
                    Box shapeA = edge.constraint.A;
                    Box shapeB = edge.constraint.B;

                    // @TODO: Verify this against Box2D; not sure if this is all we need here
                    if ((A == shapeA) && (B == shapeB))
                    {
                        return;
                    }
                }
            }

            // Create new contact
            ContactConstraint contact = new ContactConstraint()
            {
                A           = A,
                B           = B,
                bodyA       = A.body,
                bodyB       = B.body,
                Flags       = 0,
                friction    = MixFriction(A, B),
                restitution = MixRestitution(A, B),
            };

            contact.manifold.SetPair(A, B);

            ContactList.Add(contact);

            // Connect A
            contact.edgeA.constraint = contact;
            contact.edgeA.other      = bodyB;
            bodyA.ContactList.Add(contact.edgeA);

            // Connect B
            contact.edgeB.constraint = contact;
            contact.edgeB.other      = bodyA;
            bodyB.ContactList.Add(contact.edgeB);

            bodyA.SetToAwake();
            bodyB.SetToAwake();
        }
Exemple #3
0
        public void ShutDown()
        {
            for (int i = 0; i < Contacts.Count; ++i)
            {
                ContactConstraintState c  = Contacts[i];
                ContactConstraint      cc = Island.Contacts[i];

                for (int j = 0; j < c.contactCount; ++j)
                {
                    Contact      oc = cc.manifold.contacts[j];
                    ContactState cs = c.contacts[j];
                    oc.normalImpulse    = cs.normalImpulse;
                    oc.tangentImpulse   = cs.tangentImpulse;
                    oc.bitangentImpulse = cs.bitangentImpulse;
                }
            }
        }
        // Remove a specific contact
        public void RemoveContact(ContactConstraint contact)
        {
            Body A = contact.bodyA;
            Body B = contact.bodyB;

            // Remove from A

            A.ContactList.Remove(contact.edgeA);

            // Remove from B
            B.ContactList.Remove(contact.edgeB);


            A.SetToAwake();
            B.SetToAwake();

            // Remove contact from the manager
            ContactList.Remove(contact);
        }
Exemple #5
0
        public void Initialize()
        {
            for (int i = 0; i < Contacts.Count; ++i)
            {
                ContactConstraint cc = Contacts[i];

                ContactConstraintState c = ContactStates[i];

                c.centerA          = cc.bodyA.WorldCenter;
                c.centerB          = cc.bodyB.WorldCenter;
                c.iA               = cc.bodyA.InvInertiaWorld;
                c.iB               = cc.bodyB.InvInertiaWorld;
                c.mA               = cc.bodyA.InvMass;
                c.mB               = cc.bodyB.InvMass;
                c.restitution      = cc.restitution;
                c.friction         = cc.friction;
                c.indexA           = cc.bodyA.IslandIndex;
                c.indexB           = cc.bodyB.IslandIndex;
                c.normal           = cc.manifold.normal;
                c.tangentVectors   = cc.manifold.tangentVectors;
                c.bitangentVectors = cc.manifold.bitangentVectors;
                c.contactCount     = cc.manifold.contactCount;

                for (int j = 0; j < c.contactCount; ++j)
                {
                    ContactState s  = c.contacts[j] = ContactState.Allocate();
                    Contact      cp = cc.manifold.contacts[j];
                    s.ra               = cp.position - c.centerA;
                    s.rb               = cp.position - c.centerB;
                    s.penetration      = cp.penetration;
                    s.normalImpulse    = cp.normalImpulse;
                    s.tangentImpulse   = cp.tangentImpulse;
                    s.bitangentImpulse = cp.bitangentImpulse;
                }
            }
        }
Exemple #6
0
        // Run the simulation forward in time by dt (fixed timestep). Variable
        // timestep is not supported.
        public void Step(double Dt)
        {
            if (NewBox)
            {
                ContactManager.Broadphase.UpdatePairs();
                NewBox = false;
            }

            ContactManager.TestCollisions();

            foreach (var body in Bodies)
            {
                body.Flags &= ~BodyFlags.eIsland;
            }

            Island.AllowSleep     = AllowSleep;
            Island.EnableFriction = EnableFriction;
            Island.Dt             = Dt;
            Island.Gravity        = Gravity;
            Island.Iterations     = Iterations;

            // Build each active Island and then solve each built Island
//            int stackSize = Bodies.Count;
            foreach (var seed in Bodies)
            {
                // Seed cannot be apart of an Island already
                if ((seed.Flags & BodyFlags.eIsland) > 0)
                {
                    continue;
                }

                // Seed must be awake
                if ((seed.Flags & BodyFlags.eAwake) == 0)
                {
                    continue;
                }

                // Seed cannot be a static body in order to keep islands
                // as small as possible
                if ((seed.Flags & BodyFlags.eStatic) > 0)
                {
                    continue;
                }

                int stackCount = 0;
                stack[stackCount++] = seed;
                Island.Clear();


                // Mark seed as apart of Island
                seed.Flags |= BodyFlags.eIsland;

                // Perform DFS on constraint graph
                while (stackCount > 0)
                {
                    // Decrement stack to implement iterative backtracking
                    Body body = stack[--stackCount];
                    Island.Add(body);

                    // Awaken all bodies connected to the Island
                    body.SetToAwake();

                    // Do not search across static bodies to keep Island
                    // formations as small as possible, however the static
                    // body itself should be apart of the Island in order
                    // to properly represent a full contact
                    if ((body.Flags & BodyFlags.eStatic) > 0)
                    {
                        continue;
                    }

                    // Search all contacts connected to this body
                    foreach (var edge in body.ContactList)
                    {
                        ContactConstraint contact = edge.constraint;

                        // Skip contacts that have been added to an Island already
                        if ((contact.Flags & ContactFlags.eIsland) > 0)
                        {
                            continue;
                        }

                        // Can safely skip this contact if it didn't actually collide with anything
                        if ((contact.Flags & ContactFlags.eColliding) == 0)
                        {
                            continue;
                        }

                        // Skip sensors
                        if (contact.A.sensor || contact.B.sensor)
                        {
                            continue;
                        }

                        // Mark Island flag and add to Island
                        contact.Flags |= ContactFlags.eIsland;
                        Island.Add(contact);

                        // Attempt to add the other body in the contact to the Island
                        // to simulate contact awakening propogation
                        Body other = edge.other;
                        if ((other.Flags & BodyFlags.eIsland) > 0)
                        {
                            continue;
                        }

                        Assert(stackCount < 256);

                        stack[stackCount++] = other;
                        other.Flags        |= BodyFlags.eIsland;
                    }
                }

                Assert(Island.Bodies.Count != 0);

                Island.Initialize();
                Island.Solve();

                // Reset all static Island flags
                // This allows static bodies to participate in other Island formations
                foreach (var body in Island.Bodies)
                {
                    if ((body.Flags & BodyFlags.eStatic) > 0)
                    {
                        body.Flags &= ~BodyFlags.eIsland;
                    }
                }
            }

            // Update the broadphase AABBs
            foreach (var body in Bodies)
            {
                if ((body.Flags & BodyFlags.eStatic) > 0)
                {
                    continue;
                }

                body.SynchronizeProxies();
            }

            // Look for new contacts
            ContactManager.FindNewContacts();

            // Clear all forces
            foreach (var body in Bodies)
            {
                Vec3.Identity(ref body.Force);
                Vec3.Identity(ref body.Torque);
            }
        }
Exemple #7
0
 public abstract void EndContact(ContactConstraint contact);
Exemple #8
0
 public abstract void BeginContact(ContactConstraint contact);
Exemple #9
0
 public void Add(ContactConstraint contact)
 {
     Contacts.Add(contact);
     ContactStates.Add(ContactConstraintState.Allocate());
 }