Exemple #1
0
        /// <summary>
        /// Construct a world object.
        /// </summary>
        /// <param name="gravity">the world gravity vector.</param>
        /// <param name="doSleep">improve performance by not simulating inactive bodies.</param>
        public World(Vec2 gravity, IWorldPool argPool)
        {
            contactStacks = new ContactRegister[ShapeTypesCount][];
            for (int i = 0; i < ShapeTypesCount; i++)
            {
                contactStacks[i] = new ContactRegister[ShapeTypesCount];
            }

            pool = argPool;
            m_destructionListener = null;
            m_debugDraw = null;

            m_bodyList = null;
            m_jointList = null;

            m_bodyCount = 0;
            m_jointCount = 0;

            m_warmStarting = true;
            m_continuousPhysics = true;
            m_subStepping = false;
            m_stepComplete = true;

            m_allowSleep = true;
            m_gravity.set_Renamed(gravity);

            m_flags = CLEAR_FORCES;

            m_inv_dt0 = 0f;

            m_contactManager = new ContactManager(this);
            m_profile = new Profile();

            initializeRegisters();
        }
Exemple #2
0
        public void Solve(Profile profile, TimeStep step, Vec2 gravity, bool allowSleep)
        {
            // Console.WriteLine("Solving Island");

            float h = step.Dt;

            // Integrate velocities and apply damping. Initialize the body state.
            for (int i = 0; i < BodyCount; ++i)
            {
                Body b = Bodies[i];
                Vec2 c = b.Sweep.C;
                float a = b.Sweep.A;
                Vec2 v = b.LinearVelocity;
                float w = b.AngularVelocity;

                // Store positions for continuous collision.
                b.Sweep.C0.Set(b.Sweep.C);
                b.Sweep.A0 = b.Sweep.A;

                if (b.Type == BodyType.Dynamic)
                {
                    // Integrate velocities.
                    // v += h * (b.m_gravityScale * gravity + b.m_invMass * b.m_force);
                    v.X += h * (b.GravityScale * gravity.X + b.InvMass * b.Force.X);
                    v.Y += h * (b.GravityScale * gravity.Y + b.InvMass * b.Force.Y);
                    w += h * b.InvI * b.Torque;

                    // Apply damping.
                    // ODE: dv/dt + c * v = 0
                    // Solution: v(t) = v0 * exp(-c * t)
                    // Time step: v(t + dt) = v0 * exp(-c * (t + dt)) = v0 * exp(-c * t) * exp(-c * dt) = v *
                    // exp(-c * dt)
                    // v2 = exp(-c * dt) * v1
                    // Taylor expansion:
                    // v2 = (1.0f - c * dt) * v1
                    v.MulLocal(MathUtils.Clamp(1.0f - h * b.LinearDamping, 0.0f, 1.0f));
                    w *= MathUtils.Clamp(1.0f - h * b.AngularDamping, 0.0f, 1.0f);
                }
                //Debug.Assert (v.x == 0);

                Positions[i].C.Set(c);
                Positions[i].A = a;
                Velocities[i].V.Set(v);
                Velocities[i].W = w;
            }

            timer.Reset();

            // Solver data
            solverData.Step = step;
            solverData.Positions = Positions;
            solverData.Velocities = Velocities;

            // Initialize velocity constraints.
            solverDef.Step = step;
            solverDef.Contacts = Contacts;
            solverDef.Count = ContactCount;
            solverDef.Positions = Positions;
            solverDef.Velocities = Velocities;

            contactSolver.Init(solverDef);
            //Console.WriteLine("island init vel");
            contactSolver.InitializeVelocityConstraints();

            if (step.WarmStarting)
            {
                //Console.WriteLine("island warm start");
                contactSolver.WarmStart();
            }

            for (int i = 0; i < JointCount; ++i)
            {
                Joints[i].InitVelocityConstraints(solverData);
            }

            profile.SolveInit = timer.Milliseconds;

            // Solve velocity constraints
            timer.Reset();
            //Console.WriteLine("island solving velocities");
            for (int i = 0; i < step.VelocityIterations; ++i)
            {
                for (int j = 0; j < JointCount; ++j)
                {
                    Joints[j].SolveVelocityConstraints(solverData);
                }

                contactSolver.SolveVelocityConstraints();
            }

            // Store impulses for warm starting
            contactSolver.StoreImpulses();
            profile.SolveVelocity = timer.Milliseconds;

            // Integrate positions
            for (int i = 0; i < BodyCount; ++i)
            {
                Vec2 c = Positions[i].C;
                float a = Positions[i].A;
                Vec2 v = Velocities[i].V;
                float w = Velocities[i].W;

                // Check for large velocities
                translation.X = v.X * h;
                translation.Y = v.Y * h;

                if (Vec2.Dot(translation, translation) > Settings.MAX_TRANSLATION_SQUARED)
                {
                    float ratio = Settings.MAX_TRANSLATION / translation.Length();
                    v.X *= ratio;
                    v.Y *= ratio;
                }

                float rotation = h * w;
                if (rotation * rotation > Settings.MaxRotationSquared)
                {
                    float ratio = Settings.MAX_ROTATION / MathUtils.Abs(rotation);
                    w *= ratio;
                }

                // Integrate
                c.X += h * v.X;
                c.Y += h * v.Y;
                a += h * w;

                Positions[i].A = a;
                Velocities[i].W = w;
            }

            // Solve position constraints
            timer.Reset();
            bool positionSolved = false;
            for (int i = 0; i < step.PositionIterations; ++i)
            {
                bool contactsOkay = contactSolver.SolvePositionConstraints();

                bool jointsOkay = true;
                for (int j = 0; j < JointCount; ++j)
                {
                    bool jointOkay = Joints[j].SolvePositionConstraints(solverData);
                    jointsOkay = jointsOkay && jointOkay;
                }

                if (contactsOkay && jointsOkay)
                {
                    // Exit early if the position errors are small.
                    positionSolved = true;
                    break;
                }
            }

            // Copy state buffers back to the bodies
            for (int i = 0; i < BodyCount; ++i)
            {
                Body body = Bodies[i];
                body.Sweep.C.Set(Positions[i].C);
                body.Sweep.A = Positions[i].A;
                body.LinearVelocity.Set(Velocities[i].V);
                body.AngularVelocity = Velocities[i].W;
                body.SynchronizeTransform();
            }

            profile.SolvePosition = timer.Milliseconds;

            Report(contactSolver.VelocityConstraints);

            if (allowSleep)
            {
                float minSleepTime = Single.MaxValue;

                const float linTolSqr = Settings.LINEAR_SLEEP_TOLERANCE * Settings.LINEAR_SLEEP_TOLERANCE;
                float angTolSqr = Settings.ANGULAR_SLEEP_TOLERANCE * Settings.ANGULAR_SLEEP_TOLERANCE;

                for (int i = 0; i < BodyCount; ++i)
                {
                    Body b = Bodies[i];
                    if (b.Type == BodyType.Static)
                    {
                        continue;
                    }

                    if ((b.Flags & Body.TypeFlags.AutoSleep) == 0 || b.AngularVelocity * b.AngularVelocity > angTolSqr || Vec2.Dot(b.LinearVelocity, b.LinearVelocity) > linTolSqr)
                    {
                        b.SleepTime = 0.0f;
                        minSleepTime = 0.0f;
                    }
                    else
                    {
                        b.SleepTime += h;
                        minSleepTime = MathUtils.Min(minSleepTime, b.SleepTime);
                    }
                }

                if (minSleepTime >= Settings.TIME_TO_SLEEP && positionSolved)
                {
                    for (int i = 0; i < BodyCount; ++i)
                    {
                        Body b = Bodies[i];
                        b.Awake = false;
                    }
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Construct a world object.
        /// </summary>
        /// <param name="gravity">the world gravity vector.</param>
        /// <param name="argPool"> </param>
        public World(Vec2 gravity, IWorldPool argPool)
        {
            contactStacks = new ContactRegister[ShapeTypesCount][];
            for (int i = 0; i < ShapeTypesCount; i++)
            {
                contactStacks[i] = new ContactRegister[ShapeTypesCount];
            }

            Pool = argPool;
            DestructionListener = null;
            DebugDraw = null;

            BodyList = null;
            JointList = null;

            BodyCount = 0;
            JointCount = 0;

            WarmStarting = true;
            ContinuousPhysics = true;
            m_subStepping = false;
            m_stepComplete = true;

            SleepingAllowed = true;
            m_gravity.Set(gravity);

            Flags = CLEAR_FORCES;

            invDt0 = 0f;

            ContactManager = new ContactManager(this);
            Profile = new Profile();

            InitializeRegisters();
        }
Exemple #4
0
        public virtual void solve(Profile profile, TimeStep step, Vec2 gravity, bool allowSleep)
        {
            // Console.WriteLine("Solving Island");

            float h = step.dt;

            // Integrate velocities and apply damping. Initialize the body state.
            for (int i = 0; i < m_bodyCount; ++i)
            {
                Body b = m_bodies[i];
                Vec2 c = b.m_sweep.c;
                float a = b.m_sweep.a;
                Vec2 v = b.m_linearVelocity;
                float w = b.m_angularVelocity;

                // Store positions for continuous collision.
                b.m_sweep.c0.set_Renamed(b.m_sweep.c);
                b.m_sweep.a0 = b.m_sweep.a;

                if (b.m_type == BodyType.DYNAMIC)
                {
                    // Integrate velocities.
                    // v += h * (b.m_gravityScale * gravity + b.m_invMass * b.m_force);
                    v.x += h * (b.m_gravityScale * gravity.x + b.m_invMass * b.m_force.x);
                    v.y += h * (b.m_gravityScale * gravity.y + b.m_invMass * b.m_force.y);
                    w += h * b.m_invI * b.m_torque;

                    // Apply damping.
                    // ODE: dv/dt + c * v = 0
                    // Solution: v(t) = v0 * exp(-c * t)
                    // Time step: v(t + dt) = v0 * exp(-c * (t + dt)) = v0 * exp(-c * t) * exp(-c * dt) = v *
                    // exp(-c * dt)
                    // v2 = exp(-c * dt) * v1
                    // Taylor expansion:
                    // v2 = (1.0f - c * dt) * v1
                    v.mulLocal(MathUtils.clamp(1.0f - h * b.m_linearDamping, 0.0f, 1.0f));
                    w *= MathUtils.clamp(1.0f - h * b.m_angularDamping, 0.0f, 1.0f);
                }
                //Debug.Assert (v.x == 0);

                m_positions[i].c.set_Renamed(c);
                m_positions[i].a = a;
                m_velocities[i].v.set_Renamed(v);
                m_velocities[i].w = w;
            }

            timer.reset();

            // Solver data
            solverData.step = step;
            solverData.positions = m_positions;
            solverData.velocities = m_velocities;

            // Initialize velocity constraints.
            solverDef.step = step;
            solverDef.contacts = m_contacts;
            solverDef.count = m_contactCount;
            solverDef.positions = m_positions;
            solverDef.velocities = m_velocities;

            contactSolver.init(solverDef);
            //Console.WriteLine("island init vel");
            contactSolver.initializeVelocityConstraints();

            if (step.warmStarting)
            {
                //Console.WriteLine("island warm start");
                contactSolver.warmStart();
            }

            for (int i = 0; i < m_jointCount; ++i)
            {
                m_joints[i].initVelocityConstraints(solverData);
            }

            profile.solveInit = timer.Milliseconds;

            // Solve velocity constraints
            timer.reset();
            //Console.WriteLine("island solving velocities");
            for (int i = 0; i < step.velocityIterations; ++i)
            {
                for (int j = 0; j < m_jointCount; ++j)
                {
                    m_joints[j].solveVelocityConstraints(solverData);
                }

                contactSolver.solveVelocityConstraints();
            }

            // Store impulses for warm starting
            contactSolver.storeImpulses();
            profile.solveVelocity = timer.Milliseconds;

            // Integrate positions
            for (int i = 0; i < m_bodyCount; ++i)
            {
                Vec2 c = m_positions[i].c;
                float a = m_positions[i].a;
                Vec2 v = m_velocities[i].v;
                float w = m_velocities[i].w;

                // Check for large velocities
                translation.x = v.x * h;
                translation.y = v.y * h;

                if (Vec2.dot(translation, translation) > Settings.maxTranslationSquared)
                {
                    float ratio = Settings.maxTranslation / translation.length();
                    v.x *= ratio;
                    v.y *= ratio;
                }

                float rotation = h * w;
                if (rotation * rotation > Settings.maxRotationSquared)
                {
                    float ratio = Settings.maxRotation / MathUtils.abs(rotation);
                    w *= ratio;
                }

                // Integrate
                c.x += h * v.x;
                c.y += h * v.y;
                a += h * w;

                m_positions[i].a = a;
                m_velocities[i].w = w;
            }

            // Solve position constraints
            timer.reset();
            bool positionSolved = false;
            for (int i = 0; i < step.positionIterations; ++i)
            {
                bool contactsOkay = contactSolver.solvePositionConstraints();

                bool jointsOkay = true;
                for (int j = 0; j < m_jointCount; ++j)
                {
                    bool jointOkay = m_joints[j].solvePositionConstraints(solverData);
                    jointsOkay = jointsOkay && jointOkay;
                }

                if (contactsOkay && jointsOkay)
                {
                    // Exit early if the position errors are small.
                    positionSolved = true;
                    break;
                }
            }

            // Copy state buffers back to the bodies
            for (int i = 0; i < m_bodyCount; ++i)
            {
                Body body = m_bodies[i];
                body.m_sweep.c.set_Renamed(m_positions[i].c);
                body.m_sweep.a = m_positions[i].a;
                body.m_linearVelocity.set_Renamed(m_velocities[i].v);
                body.m_angularVelocity = m_velocities[i].w;
                body.synchronizeTransform();
            }

            profile.solvePosition = timer.Milliseconds;

            report(contactSolver.m_velocityConstraints);

            if (allowSleep)
            {
                float minSleepTime = Single.MaxValue;

                float linTolSqr = Settings.linearSleepTolerance * Settings.linearSleepTolerance;
                float angTolSqr = Settings.angularSleepTolerance * Settings.angularSleepTolerance;

                for (int i = 0; i < m_bodyCount; ++i)
                {
                    Body b = m_bodies[i];
                    if (b.Type == BodyType.STATIC)
                    {
                        continue;
                    }

                    if ((b.m_flags & Body.e_autoSleepFlag) == 0 || b.m_angularVelocity * b.m_angularVelocity > angTolSqr || Vec2.dot(b.m_linearVelocity, b.m_linearVelocity) > linTolSqr)
                    {
                        b.m_sleepTime = 0.0f;
                        minSleepTime = 0.0f;
                    }
                    else
                    {
                        b.m_sleepTime += h;
                        minSleepTime = MathUtils.min(minSleepTime, b.m_sleepTime);
                    }
                }

                if (minSleepTime >= Settings.timeToSleep && positionSolved)
                {
                    for (int i = 0; i < m_bodyCount; ++i)
                    {
                        Body b = m_bodies[i];
                        b.Awake = false;
                    }
                }
            }
        }