예제 #1
0
        public override void InitVelocityConstraints(b2TimeStep step)
        {
            b2Body b = m_bodyB;

            float mass = b.GetMass();

            // Frequency
            float omega = 2.0f * Mathf.PI * m_frequencyHz;

            // Damping co-efficient
            float d = 2.0f * mass * m_dampingRatio * omega;

            // Spring stiffness
            float k = mass * omega * omega;

            // magic formulas
            // gamma has units of inverse mass
            // beta hs units of inverse time
            //b2Settings.b2Assert(d + step.dt * k > Number.MIN_VALUE)
            m_gamma = step.dt * (d + step.dt * k);
            m_gamma = m_gamma != 0.0f ? 1.0f / m_gamma:0.0f;
            m_beta  = step.dt * k * m_gamma;

            b2Mat22 tMat;

            // Compute the effective mass matrix.
            //b2Vec2 r = b2Mul(b->m_xf.R, m_localAnchor - b->GetLocalCenter());
            tMat = b.m_xf.R;
            float rX = m_localAnchor.x - b.m_sweep.localCenter.x;
            float rY = m_localAnchor.y - b.m_sweep.localCenter.y;
            float tX = (tMat.col1.x * rX + tMat.col2.x * rY);

            rY = (tMat.col1.y * rX + tMat.col2.y * rY);
            rX = tX;

            // K    = [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew(r1) - skew(r2) * invI2 * skew(r2)]
            //      = [1/m1+1/m2     0    ] + invI1 * [r1.y*r1.y -r1.x*r1.y] + invI2 * [r1.y*r1.y -r1.x*r1.y]
            //        [    0     1/m1+1/m2]           [-r1.x*r1.y r1.x*r1.x]           [-r1.x*r1.y r1.x*r1.x]
            float invMass = b.m_invMass;
            float invI    = b.m_invI;

            //b2Mat22 K1;
            K1.col1.x = invMass;    K1.col2.x = 0.0f;
            K1.col1.y = 0.0f;               K1.col2.y = invMass;

            //b2Mat22 K2;
            K2.col1.x = invI * rY * rY;    K2.col2.x = -invI * rX * rY;
            K2.col1.y = -invI * rX * rY;    K2.col2.y = invI * rX * rX;

            //b2Mat22 K = K1 + K2;
            K.SetM(K1);
            K.AddM(K2);
            K.col1.x += m_gamma;
            K.col2.y += m_gamma;

            //m_ptpMass = K.GetInverse();
            K.GetInverse(m_mass);

            //m_C = b.m_position + r - m_target;
            m_C.x = b.m_sweep.c.x + rX - m_target.x;
            m_C.y = b.m_sweep.c.y + rY - m_target.y;

            // Cheat with some damping
            b.m_angularVelocity *= 0.98f;

            // Warm starting.
            m_impulse.x *= step.dtRatio;
            m_impulse.y *= step.dtRatio;
            //b.m_linearVelocity += invMass * m_impulse;
            b.m_linearVelocity.x += invMass * m_impulse.x;
            b.m_linearVelocity.y += invMass * m_impulse.y;
            //b.m_angularVelocity += invI * b2Cross(r, m_impulse);
            b.m_angularVelocity += invI * (rX * m_impulse.y - rY * m_impulse.x);
        }
예제 #2
0
        public override bool SolvePositionConstraints(float baumgarte)
        {
            // TODO_ERIN block solve with limit

            float oldLimitImpulse;
            float C;

            b2Mat22 tMat;

            b2Body bA = m_bodyA;
            b2Body bB = m_bodyB;

            float angularError  = 0.0f;
            float positionError = 0.0f;

            float tX;

            float impulseX;
            float impulseY;

            // Solve angular limit constraint.
            if (m_enableLimit && m_limitState != e_inactiveLimit)
            {
                float angle        = bB.m_sweep.a - bA.m_sweep.a - m_referenceAngle;
                float limitImpulse = 0.0f;

                if (m_limitState == e_equalLimits)
                {
                    // Prevent large angular corrections
                    C            = b2Math.Clamp(angle - m_lowerAngle, -b2Settings.b2_maxAngularCorrection, b2Settings.b2_maxAngularCorrection);
                    limitImpulse = -m_motorMass * C;
                    angularError = b2Math.Abs(C);
                }
                else if (m_limitState == e_atLowerLimit)
                {
                    C            = angle - m_lowerAngle;
                    angularError = -C;

                    // Prevent large angular corrections and allow some slop.
                    C            = b2Math.Clamp(C + b2Settings.b2_angularSlop, -b2Settings.b2_maxAngularCorrection, 0.0f);
                    limitImpulse = -m_motorMass * C;
                }
                else if (m_limitState == e_atUpperLimit)
                {
                    C            = angle - m_upperAngle;
                    angularError = C;

                    // Prevent large angular corrections and allow some slop.
                    C            = b2Math.Clamp(C - b2Settings.b2_angularSlop, 0.0f, b2Settings.b2_maxAngularCorrection);
                    limitImpulse = -m_motorMass * C;
                }

                bA.m_sweep.a -= bA.m_invI * limitImpulse;
                bB.m_sweep.a += bB.m_invI * limitImpulse;

                bA.SynchronizeTransform();
                bB.SynchronizeTransform();
            }

            // Solve point-to-point constraint
            {
                //b2Vec2 r1 = b2Mul(bA->m_xf.R, m_localAnchor1 - bA->GetLocalCenter());
                tMat = bA.m_xf.R;
                float r1X = m_localAnchor1.x - bA.m_sweep.localCenter.x;
                float r1Y = m_localAnchor1.y - bA.m_sweep.localCenter.y;
                tX  = (tMat.col1.x * r1X + tMat.col2.x * r1Y);
                r1Y = (tMat.col1.y * r1X + tMat.col2.y * r1Y);
                r1X = tX;
                //b2Vec2 r2 = b2Mul(bB->m_xf.R, m_localAnchor2 - bB->GetLocalCenter());
                tMat = bB.m_xf.R;
                float r2X = m_localAnchor2.x - bB.m_sweep.localCenter.x;
                float r2Y = m_localAnchor2.y - bB.m_sweep.localCenter.y;
                tX  = (tMat.col1.x * r2X + tMat.col2.x * r2Y);
                r2Y = (tMat.col1.y * r2X + tMat.col2.y * r2Y);
                r2X = tX;

                //b2Vec2 C = bB->m_sweep.c + r2 - bA->m_sweep.c - r1;
                float CX             = bB.m_sweep.c.x + r2X - bA.m_sweep.c.x - r1X;
                float CY             = bB.m_sweep.c.y + r2Y - bA.m_sweep.c.y - r1Y;
                float CLengthSquared = CX * CX + CY * CY;
                float CLength        = Mathf.Sqrt(CLengthSquared);
                positionError = CLength;

                float invMass1 = bA.m_invMass;
                float invMass2 = bB.m_invMass;
                float invI1    = bA.m_invI;
                float invI2    = bB.m_invI;

                //Handle large detachment.
                const float k_allowedStretch = 10.0f * b2Settings.b2_linearSlop;
                if (CLengthSquared > k_allowedStretch * k_allowedStretch)
                {
                    // Use a particle solution (no rotation)
                    //b2Vec2 u = C; u.Normalize();
                    float uX = CX / CLength;
                    float uY = CY / CLength;
                    float k  = invMass1 + invMass2;
                    //b2Settings.b2Assert(k>Number.MIN_VALUE)
                    float m = 1.0f / k;
                    impulseX = m * (-CX);
                    impulseY = m * (-CY);
                    const float k_beta = 0.5f;
                    bA.m_sweep.c.x -= k_beta * invMass1 * impulseX;
                    bA.m_sweep.c.y -= k_beta * invMass1 * impulseY;
                    bB.m_sweep.c.x += k_beta * invMass2 * impulseX;
                    bB.m_sweep.c.y += k_beta * invMass2 * impulseY;

                    //C = bB->m_sweep.c + r2 - bA->m_sweep.c - r1;
                    CX = bB.m_sweep.c.x + r2X - bA.m_sweep.c.x - r1X;
                    CY = bB.m_sweep.c.y + r2Y - bA.m_sweep.c.y - r1Y;
                }

                //b2Mat22 K1;
                K1.col1.x = invMass1 + invMass2;        K1.col2.x = 0.0f;
                K1.col1.y = 0.0f;                                       K1.col2.y = invMass1 + invMass2;

                //b2Mat22 K2;
                K2.col1.x = invI1 * r1Y * r1Y; K2.col2.x = -invI1 * r1X * r1Y;
                K2.col1.y = -invI1 * r1X * r1Y; K2.col2.y = invI1 * r1X * r1X;

                //b2Mat22 K3;
                K3.col1.x = invI2 * r2Y * r2Y;         K3.col2.x = -invI2 * r2X * r2Y;
                K3.col1.y = -invI2 * r2X * r2Y;         K3.col2.y = invI2 * r2X * r2X;

                //b2Mat22 K = K1 + K2 + K3;
                K.SetM(K1);
                K.AddM(K2);
                K.AddM(K3);
                //b2Vec2 impulse = K.Solve(-C);
                K.Solve(tImpulse, -CX, -CY);
                impulseX = tImpulse.x;
                impulseY = tImpulse.y;

                //bA.m_sweep.c -= bA.m_invMass * impulse;
                bA.m_sweep.c.x -= bA.m_invMass * impulseX;
                bA.m_sweep.c.y -= bA.m_invMass * impulseY;
                //bA.m_sweep.a -= bA.m_invI * b2Cross(r1, impulse);
                bA.m_sweep.a -= bA.m_invI * (r1X * impulseY - r1Y * impulseX);

                //bB.m_sweep.c += bB.m_invMass * impulse;
                bB.m_sweep.c.x += bB.m_invMass * impulseX;
                bB.m_sweep.c.y += bB.m_invMass * impulseY;
                //bB.m_sweep.a += bB.m_invI * b2Cross(r2, impulse);
                bB.m_sweep.a += bB.m_invI * (r2X * impulseY - r2Y * impulseX);

                bA.SynchronizeTransform();
                bB.SynchronizeTransform();
            }

            return(positionError <= b2Settings.b2_linearSlop && angularError <= b2Settings.b2_angularSlop);
        }