Esempio n. 1
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);
            }
        }