Ejemplo n.º 1
0
        public void solve(Profile profile, TimeStep step, Vec2 gravity, bool allowSleep)
        {
            // System.ref.println("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];
                Sweep bm_sweep = b.m_sweep;
                Vec2 c = bm_sweep.c;
                float a = bm_sweep.a;
                Vec2 v = b.m_linearVelocity;
                float w = b.m_angularVelocity;

                // Store positions for continuous collision.
                bm_sweep.c0.set(bm_sweep.c);
                bm_sweep.a0 = bm_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
                    // Pade approximation:
                    // v2 = v1 * 1 / (1 + c * dt)
                    v.x *= 1.0f/(1.0f + h*b.m_linearDamping);
                    v.y *= 1.0f/(1.0f + h*b.m_linearDamping);
                    w *= 1.0f/(1.0f + h*b.m_angularDamping);
                }

                m_positions[i].c.x = c.x;
                m_positions[i].c.y = c.y;
                m_positions[i].a = a;
                m_velocities[i].v.x = v.x;
                m_velocities[i].v.y = v.y;
                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);
            // System.ref.println("island init vel");
            contactSolver.initializeVelocityConstraints();

            if (step.warmStarting)
            {
                // System.ref.println("island warm start");
                contactSolver.warmStart();
            }

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

            profile.solveInit.accum(timer.getMilliseconds());

            // Solve velocity constraints
            timer.reset();
            // System.ref.println("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.accum(timer.getMilliseconds());

            // 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
                float translationx = v.x*h;
                float translationy = v.y*h;

                if (translationx*translationx + translationy*translationy > Settings.maxTranslationSquared)
                {
                    float ratio = Settings.maxTranslation
                                  /MathUtils.sqrt(translationx*translationx + translationy*translationy);
                    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.x = m_positions[i].c.x;
                body.m_sweep.c.y = m_positions[i].c.y;
                body.m_sweep.a = m_positions[i].a;
                body.m_linearVelocity.x = m_velocities[i].v.x;
                body.m_linearVelocity.y = m_velocities[i].v.y;
                body.m_angularVelocity = m_velocities[i].w;
                body.synchronizeTransform();
            }

            profile.solvePosition.accum(timer.getMilliseconds());

            report(contactSolver.m_velocityConstraints);

            if (allowSleep)
            {
                float minSleepTime = float.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.getType() == BodyType.STATIC)
                    {
                        continue;
                    }

                    if ((b.m_flags & BodyFlags.AutoSleep) == 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.setAwake(false);
                    }
                }
            }
        }
Ejemplo n.º 2
0
        public World(Vec2 gravity, IWorldPool pool, BroadPhase broadPhase)
        {
            this.pool = pool;
            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(gravity);

            m_flags = CLEAR_FORCES;

            m_inv_dt0 = 0f;

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

            m_particleSystem = new ParticleSystem(this);

            for (int i = 0; i < contactStacks.Length; i++)
            {
                contactStacks[i] = new ContactRegister[Enum.GetValues(typeof (ShapeType)).Length];
            }

            initializeRegisters();
        }