Exemplo n.º 1
0
        /// <summary>
        ///     Describes whether this instance solve position constraints
        /// </summary>
        /// <param name="baumgarte">The baumgarte</param>
        /// <returns>The bool</returns>
        internal override bool SolvePositionConstraints(float baumgarte)
        {
            Body body1 = Body1;
            Body body2 = Body2;

            Vec2 groundAnchor1 = Ground.GetXForm().Position + GroundAnchor1;
            Vec2 groundAnchor2 = Ground.GetXForm().Position + GroundAnchor2;

            float linearError = 0.0f;

            if (State == LimitState.AtUpperLimit)
            {
                Vec2 mulR1 = Box2DXMath.Mul(body1.GetXForm().R, LocalAnchor1 - body1.GetLocalCenter());
                Vec2 mulR2 = Box2DXMath.Mul(body2.GetXForm().R, LocalAnchor2 - body2.GetLocalCenter());

                Vec2 body1SweepC = body1.Sweep.C + mulR1;
                Vec2 body2SweepC = body2.Sweep.C + mulR2;

                // Get the pulley axes.
                U1 = body1SweepC - groundAnchor1;
                U2 = body2SweepC - groundAnchor2;

                float length1 = U1.Length();
                float length2 = U2.Length();

                if (length1 > Settings.LinearSlop)
                {
                    U1 *= 1.0f / length1;
                }
                else
                {
                    U1.SetZero();
                }

                if (length2 > Settings.LinearSlop)
                {
                    U2 *= 1.0f / length2;
                }
                else
                {
                    U2.SetZero();
                }

                float c = Constant - length1 - Ratio * length2;
                linearError = Box2DXMath.Max(linearError, -c);

                c = Box2DXMath.Clamp(c + Settings.LinearSlop, -Settings.MaxLinearCorrection, 0.0f);
                float impulse = -PulleyMass * c;

                Vec2 p1 = -impulse * U1;
                Vec2 p2 = -Ratio * impulse * U2;

                body1.Sweep.C += body1.InvMass * p1;
                body1.Sweep.A += body1.InvI * Vec2.Cross(mulR1, p1);
                body2.Sweep.C += body2.InvMass * p2;
                body2.Sweep.A += body2.InvI * Vec2.Cross(mulR2, p2);

                body1.SynchronizeTransform();
                body2.SynchronizeTransform();
            }

            if (LimitState1 == LimitState.AtUpperLimit)
            {
                Vec2 mulR1       = Box2DXMath.Mul(body1.GetXForm().R, LocalAnchor1 - body1.GetLocalCenter());
                Vec2 body1SweepC = body1.Sweep.C + mulR1;

                U1 = body1SweepC - groundAnchor1;
                float length1 = U1.Length();

                if (length1 > Settings.LinearSlop)
                {
                    U1 *= 1.0f / length1;
                }
                else
                {
                    U1.SetZero();
                }

                float c = MaxLength1 - length1;
                linearError = Box2DXMath.Max(linearError, -c);
                c           = Box2DXMath.Clamp(c + Settings.LinearSlop, -Settings.MaxLinearCorrection, 0.0f);
                float impulse = -LimitMass1 * c;

                Vec2 p1 = -impulse * U1;
                body1.Sweep.C += body1.InvMass * p1;
                body1.Sweep.A += body1.InvI * Vec2.Cross(mulR1, p1);

                body1.SynchronizeTransform();
            }

            if (LimitState2 == LimitState.AtUpperLimit)
            {
                Vec2 mulR2       = Box2DXMath.Mul(body2.GetXForm().R, LocalAnchor2 - body2.GetLocalCenter());
                Vec2 body2SweepC = body2.Sweep.C + mulR2;

                U2 = body2SweepC - groundAnchor2;
                float length2 = U2.Length();

                if (length2 > Settings.LinearSlop)
                {
                    U2 *= 1.0f / length2;
                }
                else
                {
                    U2.SetZero();
                }

                float c = MaxLength2 - length2;
                linearError = Box2DXMath.Max(linearError, -c);
                c           = Box2DXMath.Clamp(c + Settings.LinearSlop, -Settings.MaxLinearCorrection, 0.0f);
                float impulse = -LimitMass2 * c;

                Vec2 p2 = -impulse * U2;
                body2.Sweep.C += body2.InvMass * p2;
                body2.Sweep.A += body2.InvI * Vec2.Cross(mulR2, p2);

                body2.SynchronizeTransform();
            }

            return(linearError < Settings.LinearSlop);
        }
Exemplo n.º 2
0
        /// <summary>
        ///     Inits the velocity constraints using the specified step
        /// </summary>
        /// <param name="step">The step</param>
        internal override void InitVelocityConstraints(TimeStep step)
        {
            Body body1 = Body1;
            Body body2 = Body2;

            Vec2 mulR1 = Box2DXMath.Mul(body1.GetXForm().R, LocalAnchor1 - body1.GetLocalCenter());
            Vec2 mulR2 = Box2DXMath.Mul(body2.GetXForm().R, LocalAnchor2 - body2.GetLocalCenter());

            Vec2 body1SweepC = body1.Sweep.C + mulR1;
            Vec2 body2SweepC = body2.Sweep.C + mulR2;

            Vec2 groundAnchor1 = Ground.GetXForm().Position + GroundAnchor1;
            Vec2 groundAnchor2 = Ground.GetXForm().Position + GroundAnchor2;

            // Get the pulley axes.
            U1 = body1SweepC - groundAnchor1;
            U2 = body2SweepC - groundAnchor2;

            float length1 = U1.Length();
            float length2 = U2.Length();

            if (length1 > Settings.LinearSlop)
            {
                U1 *= 1.0f / length1;
            }
            else
            {
                U1.SetZero();
            }

            if (length2 > Settings.LinearSlop)
            {
                U2 *= 1.0f / length2;
            }
            else
            {
                U2.SetZero();
            }

            float c = Constant - length1 - Ratio * length2;

            if (c > 0.0f)
            {
                State   = LimitState.InactiveLimit;
                Impulse = 0.0f;
            }
            else
            {
                State = LimitState.AtUpperLimit;
            }

            if (length1 < MaxLength1)
            {
                LimitState1   = LimitState.InactiveLimit;
                LimitImpulse1 = 0.0f;
            }
            else
            {
                LimitState1 = LimitState.AtUpperLimit;
            }

            if (length2 < MaxLength2)
            {
                LimitState2   = LimitState.InactiveLimit;
                LimitImpulse2 = 0.0f;
            }
            else
            {
                LimitState2 = LimitState.AtUpperLimit;
            }

            // Compute effective mass.
            float cr1U1 = Vec2.Cross(mulR1, U1);
            float cr2U2 = Vec2.Cross(mulR2, U2);

            LimitMass1 = body1.InvMass + body1.InvI * cr1U1 * cr1U1;
            LimitMass2 = body2.InvMass + body2.InvI * cr2U2 * cr2U2;
            PulleyMass = LimitMass1 + Ratio * Ratio * LimitMass2;
            Box2DxDebug.Assert(LimitMass1 > Settings.FltEpsilon);
            Box2DxDebug.Assert(LimitMass2 > Settings.FltEpsilon);
            Box2DxDebug.Assert(PulleyMass > Settings.FltEpsilon);
            LimitMass1 = 1.0f / LimitMass1;
            LimitMass2 = 1.0f / LimitMass2;
            PulleyMass = 1.0f / PulleyMass;

            if (step.WarmStarting)
            {
                // Scale impulses to support variable time steps.
                Impulse       *= step.DtRatio;
                LimitImpulse1 *= step.DtRatio;
                LimitImpulse2 *= step.DtRatio;

                // Warm starting.
                Vec2 p1 = -(Impulse + LimitImpulse1) * U1;
                Vec2 p2 = (-Ratio * Impulse - LimitImpulse2) * U2;
                body1.LinearVelocity  += body1.InvMass * p1;
                body1.AngularVelocity += body1.InvI * Vec2.Cross(mulR1, p1);
                body2.LinearVelocity  += body2.InvMass * p2;
                body2.AngularVelocity += body2.InvI * Vec2.Cross(mulR2, p2);
            }
            else
            {
                Impulse       = 0.0f;
                LimitImpulse1 = 0.0f;
                LimitImpulse2 = 0.0f;
            }
        }