public override bool solvePositionConstraints(SolverData data)
        {
            if (m_frequencyHz > 0.0d)
            {
                return(true);
            }
            Rot  qA = pool.popRot();
            Rot  qB = pool.popRot();
            Vec2 rA = pool.popVec2();
            Vec2 rB = pool.popVec2();
            Vec2 u  = pool.popVec2();

            Vec2   cA = data.positions[m_indexA].c;
            double aA = data.positions[m_indexA].a;
            Vec2   cB = data.positions[m_indexB].c;
            double aB = data.positions[m_indexB].a;

            qA.set(aA);
            qB.set(aB);

            Rot.mulToOutUnsafe(qA, u.set(m_localAnchorA).subLocal(m_localCenterA), rA);
            Rot.mulToOutUnsafe(qB, u.set(m_localAnchorB).subLocal(m_localCenterB), rB);
            u.set(cB).addLocal(rB).subLocal(cA).subLocal(rA);


            double length = u.normalize();
            double C      = length - m_length;

            C = MathUtils.clamp(C, -Settings.maxLinearCorrection, Settings.maxLinearCorrection);

            double impulse = -m_mass * C;
            double Px      = impulse * u.x;
            double Py      = impulse * u.y;

            cA.x -= m_invMassA * Px;
            cA.y -= m_invMassA * Py;
            aA   -= m_invIA * (rA.x * Py - rA.y * Px);
            cB.x += m_invMassB * Px;
            cB.y += m_invMassB * Py;
            aB   += m_invIB * (rB.x * Py - rB.y * Px);

//    data.positions[m_indexA].c.set(cA);
            data.positions[m_indexA].a = aA;
//    data.positions[m_indexB].c.set(cB);
            data.positions[m_indexB].a = aB;

            pool.pushVec2(3);
            pool.pushRot(2);

            return(MathUtils.abs(C) < Settings.linearSlop);
        }
Example #2
0
        public override bool solvePositionConstraints(SolverData data)
        {
            Vec2   cA = data.positions[m_indexA].c;
            double aA = data.positions[m_indexA].a;
            Vec2   cB = data.positions[m_indexB].c;
            double aB = data.positions[m_indexB].a;

            Rot  qA   = pool.popRot();
            Rot  qB   = pool.popRot();
            Vec2 u    = pool.popVec2();
            Vec2 rA   = pool.popVec2();
            Vec2 rB   = pool.popVec2();
            Vec2 temp = pool.popVec2();

            qA.set(aA);
            qB.set(aB);

            // Compute the effective masses.
            Rot.mulToOutUnsafe(qA, temp.set(m_localAnchorA).subLocal(m_localCenterA), rA);
            Rot.mulToOutUnsafe(qB, temp.set(m_localAnchorB).subLocal(m_localCenterB), rB);
            u.set(cB).addLocal(rB).subLocal(cA).subLocal(rA);

            double length = u.normalize();
            double C      = length - m_maxLength;

            C = MathUtils.clamp(C, 0.0d, Settings.maxLinearCorrection);

            double impulse = -m_mass * C;
            double Px      = impulse * u.x;
            double Py      = impulse * u.y;

            cA.x -= m_invMassA * Px;
            cA.y -= m_invMassA * Py;
            aA   -= m_invIA * (rA.x * Py - rA.y * Px);
            cB.x += m_invMassB * Px;
            cB.y += m_invMassB * Py;
            aB   += m_invIB * (rB.x * Py - rB.y * Px);

            pool.pushRot(2);
            pool.pushVec2(4);

            // data.positions[m_indexA].c = cA;
            data.positions[m_indexA].a = aA;
            // data.positions[m_indexB].c = cB;
            data.positions[m_indexB].a = aB;

            return(length - m_maxLength < Settings.linearSlop);
        }
Example #3
0
        /** Set this to equal another transform. */

        public Transform set(Transform xf)
        {
            p.set(xf.p);
            q.set(xf.q);
            return(this);
        }
Example #4
0
        /**
         * @see org.jbox2d.dynamics.joints.Joint#initVelocityConstraints(org.jbox2d.dynamics.TimeStep)
         */

        public override void initVelocityConstraints(SolverData data)
        {
            m_indexA = m_bodyA.m_islandIndex;
            m_indexB = m_bodyB.m_islandIndex;
            m_localCenterA.set(m_bodyA.m_sweep.localCenter);
            m_localCenterB.set(m_bodyB.m_sweep.localCenter);
            m_invMassA = m_bodyA.m_invMass;
            m_invMassB = m_bodyB.m_invMass;
            m_invIA    = m_bodyA.m_invI;
            m_invIB    = m_bodyB.m_invI;

            double aA = data.positions[m_indexA].a;
            Vec2   vA = data.velocities[m_indexA].v;
            double wA = data.velocities[m_indexA].w;

            double aB = data.positions[m_indexB].a;
            Vec2   vB = data.velocities[m_indexB].v;
            double wB = data.velocities[m_indexB].w;


            Vec2 temp = pool.popVec2();
            Rot  qA   = pool.popRot();
            Rot  qB   = pool.popRot();

            qA.set(aA);
            qB.set(aB);

            // Compute the effective mass matrix.
            Rot.mulToOutUnsafe(qA, temp.set(m_localAnchorA).subLocal(m_localCenterA), m_rA);
            Rot.mulToOutUnsafe(qB, temp.set(m_localAnchorB).subLocal(m_localCenterB), m_rB);

            // J = [-I -r1_skew I r2_skew]
            // [ 0 -1 0 1]
            // r_skew = [-ry; rx]

            // Matlab
            // K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x, -r1y*iA-r2y*iB]
            // [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB, r1x*iA+r2x*iB]
            // [ -r1y*iA-r2y*iB, r1x*iA+r2x*iB, iA+iB]

            double mA = m_invMassA, mB = m_invMassB;
            double iA = m_invIA, iB = m_invIB;

            Mat22 K = pool.popMat22();

            K.ex.x = mA + mB + iA * m_rA.y * m_rA.y + iB * m_rB.y * m_rB.y;
            K.ex.y = -iA * m_rA.x * m_rA.y - iB * m_rB.x * m_rB.y;
            K.ey.x = K.ex.y;
            K.ey.y = mA + mB + iA * m_rA.x * m_rA.x + iB * m_rB.x * m_rB.x;

            K.invertToOut(m_linearMass);

            m_angularMass = iA + iB;
            if (m_angularMass > 0.0d)
            {
                m_angularMass = 1.0d / m_angularMass;
            }

            if (data.step.warmStarting)
            {
                // Scale impulses to support a variable time step.
                m_linearImpulse.mulLocal(data.step.dtRatio);
                m_angularImpulse *= data.step.dtRatio;

                Vec2 P = pool.popVec2();
                P.set(m_linearImpulse);

                temp.set(P).mulLocal(mA);
                vA.subLocal(temp);
                wA -= iA * (Vec2.cross(m_rA, P) + m_angularImpulse);

                temp.set(P).mulLocal(mB);
                vB.addLocal(temp);
                wB += iB * (Vec2.cross(m_rB, P) + m_angularImpulse);

                pool.pushVec2(1);
            }
            else
            {
                m_linearImpulse.setZero();
                m_angularImpulse = 0.0d;
            }
//    data.velocities[m_indexA].v.set(vA);
            if (data.velocities[m_indexA].w != wA)
            {
            }
            data.velocities[m_indexA].w = wA;
//    data.velocities[m_indexB].v.set(vB);
            data.velocities[m_indexB].w = wB;

            pool.pushRot(2);
            pool.pushVec2(1);
            pool.pushMat22(1);
        }
        public override bool solvePositionConstraints(SolverData data)
        {
            Rot    qA = pool.popRot();
            Rot    qB = pool.popRot();
            Vec2   cA = data.positions[m_indexA].c;
            double aA = data.positions[m_indexA].a;
            Vec2   cB = data.positions[m_indexB].c;
            double aB = data.positions[m_indexB].a;

            qA.set(aA);
            qB.set(aB);

            double angularError  = 0.0d;
            double positionError = 0.0d;

            bool fixedRotation = (m_invIA + m_invIB == 0.0d);

            // Solve angular limit constraint.
            if (m_enableLimit && m_limitState != LimitState.INACTIVE && fixedRotation == false)
            {
                double angle        = aB - aA - m_referenceAngle;
                double limitImpulse = 0.0d;

                if (m_limitState == LimitState.EQUAL)
                {
                    // Prevent large angular corrections
                    double C =
                        MathUtils.clamp(angle - m_lowerAngle, -Settings.maxAngularCorrection,
                                        Settings.maxAngularCorrection);
                    limitImpulse = -m_motorMass * C;
                    angularError = MathUtils.abs(C);
                }
                else if (m_limitState == LimitState.AT_LOWER)
                {
                    double C = angle - m_lowerAngle;
                    angularError = -C;

                    // Prevent large angular corrections and allow some slop.
                    C            = MathUtils.clamp(C + Settings.angularSlop, -Settings.maxAngularCorrection, 0.0d);
                    limitImpulse = -m_motorMass * C;
                }
                else if (m_limitState == LimitState.AT_UPPER)
                {
                    double C = angle - m_upperAngle;
                    angularError = C;

                    // Prevent large angular corrections and allow some slop.
                    C            = MathUtils.clamp(C - Settings.angularSlop, 0.0d, Settings.maxAngularCorrection);
                    limitImpulse = -m_motorMass * C;
                }

                aA -= m_invIA * limitImpulse;
                aB += m_invIB * limitImpulse;
            }
            // Solve point-to-point constraint.
            {
                qA.set(aA);
                qB.set(aB);

                Vec2 rA      = pool.popVec2();
                Vec2 rB      = pool.popVec2();
                Vec2 C       = pool.popVec2();
                Vec2 impulse = pool.popVec2();

                Rot.mulToOutUnsafe(qA, C.set(m_localAnchorA).subLocal(m_localCenterA), rA);
                Rot.mulToOutUnsafe(qB, C.set(m_localAnchorB).subLocal(m_localCenterB), rB);
                C.set(cB).addLocal(rB).subLocal(cA).subLocal(rA);
                positionError = C.length();

                double mA = m_invMassA, mB = m_invMassB;
                double iA = m_invIA, iB = m_invIB;

                Mat22 K = pool.popMat22();
                K.ex.x = mA + mB + iA * rA.y * rA.y + iB * rB.y * rB.y;
                K.ex.y = -iA * rA.x * rA.y - iB * rB.x * rB.y;
                K.ey.x = K.ex.y;
                K.ey.y = mA + mB + iA * rA.x * rA.x + iB * rB.x * rB.x;
                K.solveToOut(C, impulse);
                impulse.negateLocal();

                cA.x -= mA * impulse.x;
                cA.y -= mA * impulse.y;
                aA   -= iA * Vec2.cross(rA, impulse);

                cB.x += mB * impulse.x;
                cB.y += mB * impulse.y;
                aB   += iB * Vec2.cross(rB, impulse);

                pool.pushVec2(4);
                pool.pushMat22(1);
            }
            // data.positions[m_indexA].c.set(cA);
            data.positions[m_indexA].a = aA;
            // data.positions[m_indexB].c.set(cB);
            data.positions[m_indexB].a = aB;

            pool.pushRot(2);

            return(positionError <= Settings.linearSlop && angularError <= Settings.angularSlop);
        }
        public override void initVelocityConstraints(SolverData data)
        {
            m_indexA = m_bodyA.m_islandIndex;
            m_indexB = m_bodyB.m_islandIndex;
            m_localCenterA.set(m_bodyA.m_sweep.localCenter);
            m_localCenterB.set(m_bodyB.m_sweep.localCenter);
            m_invMassA = m_bodyA.m_invMass;
            m_invMassB = m_bodyB.m_invMass;
            m_invIA    = m_bodyA.m_invI;
            m_invIB    = m_bodyB.m_invI;

            // Vec2 cA = data.positions[m_indexA].c;
            double aA = data.positions[m_indexA].a;
            Vec2   vA = data.velocities[m_indexA].v;
            double wA = data.velocities[m_indexA].w;

            // Vec2 cB = data.positions[m_indexB].c;
            double aB   = data.positions[m_indexB].a;
            Vec2   vB   = data.velocities[m_indexB].v;
            double wB   = data.velocities[m_indexB].w;
            Rot    qA   = pool.popRot();
            Rot    qB   = pool.popRot();
            Vec2   temp = pool.popVec2();

            qA.set(aA);
            qB.set(aB);

            // Compute the effective masses.
            Rot.mulToOutUnsafe(qA, temp.set(m_localAnchorA).subLocal(m_localCenterA), m_rA);
            Rot.mulToOutUnsafe(qB, temp.set(m_localAnchorB).subLocal(m_localCenterB), m_rB);

            // J = [-I -r1_skew I r2_skew]
            // [ 0 -1 0 1]
            // r_skew = [-ry; rx]

            // Matlab
            // K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x, -r1y*iA-r2y*iB]
            // [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB, r1x*iA+r2x*iB]
            // [ -r1y*iA-r2y*iB, r1x*iA+r2x*iB, iA+iB]

            double mA = m_invMassA, mB = m_invMassB;
            double iA = m_invIA, iB = m_invIB;

            bool fixedRotation = (iA + iB == 0.0d);

            m_mass.ex.x = mA + mB + m_rA.y * m_rA.y * iA + m_rB.y * m_rB.y * iB;
            m_mass.ey.x = -m_rA.y * m_rA.x * iA - m_rB.y * m_rB.x * iB;
            m_mass.ez.x = -m_rA.y * iA - m_rB.y * iB;
            m_mass.ex.y = m_mass.ey.x;
            m_mass.ey.y = mA + mB + m_rA.x * m_rA.x * iA + m_rB.x * m_rB.x * iB;
            m_mass.ez.y = m_rA.x * iA + m_rB.x * iB;
            m_mass.ex.z = m_mass.ez.x;
            m_mass.ey.z = m_mass.ez.y;
            m_mass.ez.z = iA + iB;

            m_motorMass = iA + iB;
            if (m_motorMass > 0.0d)
            {
                m_motorMass = 1.0d / m_motorMass;
            }

            if (m_enableMotor == false || fixedRotation)
            {
                m_motorImpulse = 0.0d;
            }

            if (m_enableLimit && fixedRotation == false)
            {
                double jointAngle = aB - aA - m_referenceAngle;
                if (MathUtils.abs(m_upperAngle - m_lowerAngle) < 2.0d * Settings.angularSlop)
                {
                    m_limitState = LimitState.EQUAL;
                }
                else if (jointAngle <= m_lowerAngle)
                {
                    if (m_limitState != LimitState.AT_LOWER)
                    {
                        m_impulse.z = 0.0d;
                    }
                    m_limitState = LimitState.AT_LOWER;
                }
                else if (jointAngle >= m_upperAngle)
                {
                    if (m_limitState != LimitState.AT_UPPER)
                    {
                        m_impulse.z = 0.0d;
                    }
                    m_limitState = LimitState.AT_UPPER;
                }
                else
                {
                    m_limitState = LimitState.INACTIVE;
                    m_impulse.z  = 0.0d;
                }
            }
            else
            {
                m_limitState = LimitState.INACTIVE;
            }

            if (data.step.warmStarting)
            {
                Vec2 P = pool.popVec2();
                // Scale impulses to support a variable time step.
                m_impulse.x    *= data.step.dtRatio;
                m_impulse.y    *= data.step.dtRatio;
                m_motorImpulse *= data.step.dtRatio;

                P.x = m_impulse.x;
                P.y = m_impulse.y;

                vA.x -= mA * P.x;
                vA.y -= mA * P.y;
                wA   -= iA * (Vec2.cross(m_rA, P) + m_motorImpulse + m_impulse.z);

                vB.x += mB * P.x;
                vB.y += mB * P.y;
                wB   += iB * (Vec2.cross(m_rB, P) + m_motorImpulse + m_impulse.z);
                pool.pushVec2(1);
            }
            else
            {
                m_impulse.setZero();
                m_motorImpulse = 0.0d;
            }
            // data.velocities[m_indexA].v.set(vA);
            data.velocities[m_indexA].w = wA;
            // data.velocities[m_indexB].v.set(vB);
            data.velocities[m_indexB].w = wB;

            pool.pushVec2(1);
            pool.pushRot(2);
        }
Example #7
0
        public override bool solvePositionConstraints(SolverData data)
        {
            Vec2   cA = data.positions[m_indexA].c;
            double aA = data.positions[m_indexA].a;
            Vec2   cB = data.positions[m_indexB].c;
            double aB = data.positions[m_indexB].a;
            Vec2   cC = data.positions[m_indexC].c;
            double aC = data.positions[m_indexC].a;
            Vec2   cD = data.positions[m_indexD].c;
            double aD = data.positions[m_indexD].a;

            Rot qA = pool.popRot(), qB = pool.popRot(), qC = pool.popRot(), qD = pool.popRot();

            qA.set(aA);
            qB.set(aB);
            qC.set(aC);
            qD.set(aD);

            double linearError = 0.0d;

            double coordinateA, coordinateB;

            Vec2   temp = pool.popVec2();
            Vec2   JvAC = pool.popVec2();
            Vec2   JvBD = pool.popVec2();
            double JwA, JwB, JwC, JwD;
            double mass = 0.0d;

            if (m_typeA == JointType.REVOLUTE)
            {
                JvAC.setZero();
                JwA   = 1.0d;
                JwC   = 1.0d;
                mass += m_iA + m_iC;

                coordinateA = aA - aC - m_referenceAngleA;
            }
            else
            {
                Vec2 rC = pool.popVec2();
                Vec2 rA = pool.popVec2();
                Vec2 pC = pool.popVec2();
                Vec2 pA = pool.popVec2();
                Rot.mulToOutUnsafe(qC, m_localAxisC, JvAC);
                Rot.mulToOutUnsafe(qC, temp.set(m_localAnchorC).subLocal(m_lcC), rC);
                Rot.mulToOutUnsafe(qA, temp.set(m_localAnchorA).subLocal(m_lcA), rA);
                JwC   = Vec2.cross(rC, JvAC);
                JwA   = Vec2.cross(rA, JvAC);
                mass += m_mC + m_mA + m_iC * JwC * JwC + m_iA * JwA * JwA;

                pC.set(m_localAnchorC).subLocal(m_lcC);
                Rot.mulTransUnsafe(qC, temp.set(rA).addLocal(cA).subLocal(cC), pA);
                coordinateA = Vec2.dot(pA.subLocal(pC), m_localAxisC);
                pool.pushVec2(4);
            }

            if (m_typeB == JointType.REVOLUTE)
            {
                JvBD.setZero();
                JwB   = m_ratio;
                JwD   = m_ratio;
                mass += m_ratio * m_ratio * (m_iB + m_iD);

                coordinateB = aB - aD - m_referenceAngleB;
            }
            else
            {
                Vec2 u  = pool.popVec2();
                Vec2 rD = pool.popVec2();
                Vec2 rB = pool.popVec2();
                Vec2 pD = pool.popVec2();
                Vec2 pB = pool.popVec2();
                Rot.mulToOutUnsafe(qD, m_localAxisD, u);
                Rot.mulToOutUnsafe(qD, temp.set(m_localAnchorD).subLocal(m_lcD), rD);
                Rot.mulToOutUnsafe(qB, temp.set(m_localAnchorB).subLocal(m_lcB), rB);
                JvBD.set(u).mulLocal(m_ratio);
                JwD   = Vec2.cross(rD, u);
                JwB   = Vec2.cross(rB, u);
                mass += m_ratio * m_ratio * (m_mD + m_mB) + m_iD * JwD * JwD + m_iB * JwB * JwB;

                pD.set(m_localAnchorD).subLocal(m_lcD);
                Rot.mulTransUnsafe(qD, temp.set(rB).addLocal(cB).subLocal(cD), pB);
                coordinateB = Vec2.dot(pB.subLocal(pD), m_localAxisD);
                pool.pushVec2(5);
            }

            double C = (coordinateA + m_ratio * coordinateB) - m_constant;

            double impulse = 0.0d;

            if (mass > 0.0d)
            {
                impulse = -C / mass;
            }
            pool.pushVec2(3);
            pool.pushRot(4);

            cA.x += (m_mA * impulse) * JvAC.x;
            cA.y += (m_mA * impulse) * JvAC.y;
            aA   += m_iA * impulse * JwA;

            cB.x += (m_mB * impulse) * JvBD.x;
            cB.y += (m_mB * impulse) * JvBD.y;
            aB   += m_iB * impulse * JwB;

            cC.x -= (m_mC * impulse) * JvAC.x;
            cC.y -= (m_mC * impulse) * JvAC.y;
            aC   -= m_iC * impulse * JwC;

            cD.x -= (m_mD * impulse) * JvBD.x;
            cD.y -= (m_mD * impulse) * JvBD.y;
            aD   -= m_iD * impulse * JwD;

            // data.positions[m_indexA].c = cA;
            data.positions[m_indexA].a = aA;
            // data.positions[m_indexB].c = cB;
            data.positions[m_indexB].a = aB;
            // data.positions[m_indexC].c = cC;
            data.positions[m_indexC].a = aC;
            // data.positions[m_indexD].c = cD;
            data.positions[m_indexD].a = aD;

            // TODO_ERIN not implemented
            return(linearError < Settings.linearSlop);
        }
Example #8
0
        public override void initVelocityConstraints(SolverData data)
        {
            m_indexA = m_bodyA.m_islandIndex;
            m_indexB = m_bodyB.m_islandIndex;
            m_localCenterA.set(m_bodyA.m_sweep.localCenter);
            m_localCenterB.set(m_bodyB.m_sweep.localCenter);
            m_invMassA = m_bodyA.m_invMass;
            m_invMassB = m_bodyB.m_invMass;
            m_invIA    = m_bodyA.m_invI;
            m_invIB    = m_bodyB.m_invI;

            Vec2   cA = data.positions[m_indexA].c;
            double aA = data.positions[m_indexA].a;
            Vec2   vA = data.velocities[m_indexA].v;
            double wA = data.velocities[m_indexA].w;

            Vec2   cB = data.positions[m_indexB].c;
            double aB = data.positions[m_indexB].a;
            Vec2   vB = data.velocities[m_indexB].v;
            double wB = data.velocities[m_indexB].w;

            Rot  qA   = pool.popRot();
            Rot  qB   = pool.popRot();
            Vec2 temp = pool.popVec2();

            qA.set(aA);
            qB.set(aB);

            // Compute the effective masses.
            Rot.mulToOutUnsafe(qA, temp.set(m_localAnchorA).subLocal(m_localCenterA), m_rA);
            Rot.mulToOutUnsafe(qB, temp.set(m_localAnchorB).subLocal(m_localCenterB), m_rB);

            m_uA.set(cA).addLocal(m_rA).subLocal(m_groundAnchorA);
            m_uB.set(cB).addLocal(m_rB).subLocal(m_groundAnchorB);

            double lengthA = m_uA.length();
            double lengthB = m_uB.length();

            if (lengthA > 10d * Settings.linearSlop)
            {
                m_uA.mulLocal(1.0d / lengthA);
            }
            else
            {
                m_uA.setZero();
            }

            if (lengthB > 10d * Settings.linearSlop)
            {
                m_uB.mulLocal(1.0d / lengthB);
            }
            else
            {
                m_uB.setZero();
            }

            // Compute effective mass.
            double ruA = Vec2.cross(m_rA, m_uA);
            double ruB = Vec2.cross(m_rB, m_uB);

            double mA = m_invMassA + m_invIA * ruA * ruA;
            double mB = m_invMassB + m_invIB * ruB * ruB;

            m_mass = mA + m_ratio * m_ratio * mB;

            if (m_mass > 0.0d)
            {
                m_mass = 1.0d / m_mass;
            }

            if (data.step.warmStarting)
            {
                // Scale impulses to support variable time steps.
                m_impulse *= data.step.dtRatio;

                // Warm starting.
                Vec2 PA = pool.popVec2();
                Vec2 PB = pool.popVec2();

                PA.set(m_uA).mulLocal(-m_impulse);
                PB.set(m_uB).mulLocal(-m_ratio * m_impulse);

                vA.x += m_invMassA * PA.x;
                vA.y += m_invMassA * PA.y;
                wA   += m_invIA * Vec2.cross(m_rA, PA);
                vB.x += m_invMassB * PB.x;
                vB.y += m_invMassB * PB.y;
                wB   += m_invIB * Vec2.cross(m_rB, PB);

                pool.pushVec2(2);
            }
            else
            {
                m_impulse = 0.0d;
            }
//    data.velocities[m_indexA].v.set(vA);
            data.velocities[m_indexA].w = wA;
//    data.velocities[m_indexB].v.set(vB);
            data.velocities[m_indexB].w = wB;

            pool.pushVec2(1);
            pool.pushRot(2);
        }
Example #9
0
        // pooling


        public override void initVelocityConstraints(SolverData data)
        {
            m_indexA = m_bodyA.m_islandIndex;
            m_indexB = m_bodyB.m_islandIndex;
            m_localCenterA.set(m_bodyA.m_sweep.localCenter);
            m_localCenterB.set(m_bodyB.m_sweep.localCenter);
            m_invMassA = m_bodyA.m_invMass;
            m_invMassB = m_bodyB.m_invMass;
            m_invIA    = m_bodyA.m_invI;
            m_invIB    = m_bodyB.m_invI;

            double mA = m_invMassA, mB = m_invMassB;
            double iA = m_invIA, iB = m_invIB;

            Vec2   cA = data.positions[m_indexA].c;
            double aA = data.positions[m_indexA].a;
            Vec2   vA = data.velocities[m_indexA].v;
            double wA = data.velocities[m_indexA].w;

            Vec2   cB = data.positions[m_indexB].c;
            double aB = data.positions[m_indexB].a;
            Vec2   vB = data.velocities[m_indexB].v;
            double wB = data.velocities[m_indexB].w;

            Rot  qA   = pool.popRot();
            Rot  qB   = pool.popRot();
            Vec2 temp = pool.popVec2();

            qA.set(aA);
            qB.set(aB);

            // Compute the effective masses.
            Rot.mulToOutUnsafe(qA, temp.set(m_localAnchorA).subLocal(m_localCenterA), rA);
            Rot.mulToOutUnsafe(qB, temp.set(m_localAnchorB).subLocal(m_localCenterB), rB);
            d2.set(cB).addLocal(rB).subLocal(cA).subLocal(rA);

            // Point to line constraint
            {
                Rot.mulToOut(qA, m_localYAxisA, m_ay);
                m_sAy = Vec2.cross(temp.set(d2).addLocal(rA), m_ay);
                m_sBy = Vec2.cross(rB, m_ay);

                m_mass = mA + mB + iA * m_sAy * m_sAy + iB * m_sBy * m_sBy;

                if (m_mass > 0.0d)
                {
                    m_mass = 1.0d / m_mass;
                }
            }

            // Spring constraint
            m_springMass = 0.0d;
            m_bias       = 0.0d;
            m_gamma      = 0.0d;
            if (m_frequencyHz > 0.0d)
            {
                Rot.mulToOut(qA, m_localXAxisA, m_ax);
                m_sAx = Vec2.cross(temp.set(d2).addLocal(rA), m_ax);
                m_sBx = Vec2.cross(rB, m_ax);

                double invMass = mA + mB + iA * m_sAx * m_sAx + iB * m_sBx * m_sBx;

                if (invMass > 0.0d)
                {
                    m_springMass = 1.0d / invMass;

                    double C = Vec2.dot(d2, m_ax);

                    // Frequency
                    double omega = 2.0d * MathUtils.PI * m_frequencyHz;

                    // Damping coefficient
                    double d = 2.0d * m_springMass * m_dampingRatio * omega;

                    // Spring stiffness
                    double k = m_springMass * omega * omega;

                    // magic formulas
                    double h = data.step.dt;
                    m_gamma = h * (d + h * k);
                    if (m_gamma > 0.0d)
                    {
                        m_gamma = 1.0d / m_gamma;
                    }

                    m_bias = C * h * k * m_gamma;

                    m_springMass = invMass + m_gamma;
                    if (m_springMass > 0.0d)
                    {
                        m_springMass = 1.0d / m_springMass;
                    }
                }
            }
            else
            {
                m_springImpulse = 0.0d;
            }

            // Rotational motor
            if (m_enableMotor)
            {
                m_motorMass = iA + iB;
                if (m_motorMass > 0.0d)
                {
                    m_motorMass = 1.0d / m_motorMass;
                }
            }
            else
            {
                m_motorMass    = 0.0d;
                m_motorImpulse = 0.0d;
            }

            if (data.step.warmStarting)
            {
                Vec2 P = pool.popVec2();
                // Account for variable time step.
                m_impulse       *= data.step.dtRatio;
                m_springImpulse *= data.step.dtRatio;
                m_motorImpulse  *= data.step.dtRatio;

                P.x = m_impulse * m_ay.x + m_springImpulse * m_ax.x;
                P.y = m_impulse * m_ay.y + m_springImpulse * m_ax.y;
                double LA = m_impulse * m_sAy + m_springImpulse * m_sAx + m_motorImpulse;
                double LB = m_impulse * m_sBy + m_springImpulse * m_sBx + m_motorImpulse;

                vA.x -= m_invMassA * P.x;
                vA.y -= m_invMassA * P.y;
                wA   -= m_invIA * LA;

                vB.x += m_invMassB * P.x;
                vB.y += m_invMassB * P.y;
                wB   += m_invIB * LB;
                pool.pushVec2(1);
            }
            else
            {
                m_impulse       = 0.0d;
                m_springImpulse = 0.0d;
                m_motorImpulse  = 0.0d;
            }
            pool.pushRot(2);
            pool.pushVec2(1);

            // data.velocities[m_indexA].v = vA;
            data.velocities[m_indexA].w = wA;
            // data.velocities[m_indexB].v = vB;
            data.velocities[m_indexB].w = wB;
        }
Example #10
0
        public override bool solvePositionConstraints(SolverData data)
        {
            Vec2   cA = data.positions[m_indexA].c;
            double aA = data.positions[m_indexA].a;
            Vec2   cB = data.positions[m_indexB].c;
            double aB = data.positions[m_indexB].a;

            Rot  qA   = pool.popRot();
            Rot  qB   = pool.popRot();
            Vec2 temp = pool.popVec2();

            qA.set(aA);
            qB.set(aB);

            Rot.mulToOut(qA, temp.set(m_localAnchorA).subLocal(m_localCenterA), rA);
            Rot.mulToOut(qB, temp.set(m_localAnchorB).subLocal(m_localCenterB), rB);
            d2.set(cB).subLocal(cA).addLocal(rB).subLocal(rA);

            Vec2 ay = pool.popVec2();

            Rot.mulToOut(qA, m_localYAxisA, ay);

            double sAy = Vec2.cross(temp.set(d2).addLocal(rA), ay);
            double sBy = Vec2.cross(rB, ay);

            double C = Vec2.dot(d2, ay);

            double k = m_invMassA + m_invMassB + m_invIA * m_sAy * m_sAy + m_invIB * m_sBy * m_sBy;

            double impulse;

            if (k != 0.0d)
            {
                impulse = -C / k;
            }
            else
            {
                impulse = 0.0d;
            }

            Vec2 P = pool.popVec2();

            P.x = impulse * ay.x;
            P.y = impulse * ay.y;
            double LA = impulse * sAy;
            double LB = impulse * sBy;

            cA.x -= m_invMassA * P.x;
            cA.y -= m_invMassA * P.y;
            aA   -= m_invIA * LA;
            cB.x += m_invMassB * P.x;
            cB.y += m_invMassB * P.y;
            aB   += m_invIB * LB;

            pool.pushVec2(3);
            pool.pushRot(2);
            // data.positions[m_indexA].c = cA;
            data.positions[m_indexA].a = aA;
            // data.positions[m_indexB].c = cB;
            data.positions[m_indexB].a = aB;

            return(MathUtils.abs(C) <= Settings.linearSlop);
        }
Example #11
0
        public override void initVelocityConstraints(SolverData data)
        {
            m_indexB = m_bodyB.m_islandIndex;
            m_localCenterB.set(m_bodyB.m_sweep.localCenter);
            m_invMassB = m_bodyB.m_invMass;
            m_invIB    = m_bodyB.m_invI;

            Vec2   cB = data.positions[m_indexB].c;
            double aB = data.positions[m_indexB].a;
            Vec2   vB = data.velocities[m_indexB].v;
            double wB = data.velocities[m_indexB].w;

            Rot qB = pool.popRot();

            qB.set(aB);

            double mass = m_bodyB.getMass();

            // Frequency
            double omega = 2.0d * MathUtils.PI * m_frequencyHz;

            // Damping coefficient
            double d = 2.0d * mass * m_dampingRatio * omega;

            // Spring stiffness
            double k = mass * (omega * omega);

            // magic formulas
            // gamma has units of inverse mass.
            // beta has units of inverse time.
            double h = data.step.dt;

            m_gamma = h * (d + h * k);
            if (m_gamma != 0.0d)
            {
                m_gamma = 1.0d / m_gamma;
            }
            m_beta = h * k * m_gamma;

            Vec2 temp = pool.popVec2();

            // Compute the effective mass matrix.
            Rot.mulToOutUnsafe(qB, temp.set(m_localAnchorB).subLocal(m_localCenterB), m_rB);

            // 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]
            Mat22 K = pool.popMat22();

            K.ex.x = m_invMassB + m_invIB * m_rB.y * m_rB.y + m_gamma;
            K.ex.y = -m_invIB * m_rB.x * m_rB.y;
            K.ey.x = K.ex.y;
            K.ey.y = m_invMassB + m_invIB * m_rB.x * m_rB.x + m_gamma;

            K.invertToOut(m_mass);

            m_C.set(cB).addLocal(m_rB).subLocal(m_targetA);
            m_C.mulLocal(m_beta);

            // Cheat with some damping
            wB *= 0.98d;

            if (data.step.warmStarting)
            {
                m_impulse.mulLocal(data.step.dtRatio);
                vB.x += m_invMassB * m_impulse.x;
                vB.y += m_invMassB * m_impulse.y;
                wB   += m_invIB * Vec2.cross(m_rB, m_impulse);
            }
            else
            {
                m_impulse.setZero();
            }

//    data.velocities[m_indexB].v.set(vB);
            data.velocities[m_indexB].w = wB;

            pool.pushVec2(1);
            pool.pushMat22(1);
            pool.pushRot(1);
        }
Example #12
0
        public override bool solvePositionConstraints(SolverData data)
        {
            Vec2   cA   = data.positions[m_indexA].c;
            double aA   = data.positions[m_indexA].a;
            Vec2   cB   = data.positions[m_indexB].c;
            double aB   = data.positions[m_indexB].a;
            Rot    qA   = pool.popRot();
            Rot    qB   = pool.popRot();
            Vec2   temp = pool.popVec2();
            Vec2   rA   = pool.popVec2();
            Vec2   rB   = pool.popVec2();

            qA.set(aA);
            qB.set(aB);

            double mA = m_invMassA, mB = m_invMassB;
            double iA = m_invIA, iB = m_invIB;

            Rot.mulToOutUnsafe(qA, temp.set(m_localAnchorA).subLocal(m_localCenterA), rA);
            Rot.mulToOutUnsafe(qB, temp.set(m_localAnchorB).subLocal(m_localCenterB), rB);
            double positionError, angularError;

            Mat33 K  = pool.popMat33();
            Vec2  C1 = pool.popVec2();
            Vec2  P  = pool.popVec2();

            K.ex.x = mA + mB + rA.y * rA.y * iA + rB.y * rB.y * iB;
            K.ey.x = -rA.y * rA.x * iA - rB.y * rB.x * iB;
            K.ez.x = -rA.y * iA - rB.y * iB;
            K.ex.y = K.ey.x;
            K.ey.y = mA + mB + rA.x * rA.x * iA + rB.x * rB.x * iB;
            K.ez.y = rA.x * iA + rB.x * iB;
            K.ex.z = K.ez.x;
            K.ey.z = K.ez.y;
            K.ez.z = iA + iB;
            if (m_frequencyHz > 0.0d)
            {
                C1.set(cB).addLocal(rB).subLocal(cA).subLocal(rA);

                positionError = C1.length();
                angularError  = 0.0d;

                K.solve22ToOut(C1, P);
                P.negateLocal();

                cA.x -= mA * P.x;
                cA.y -= mA * P.y;
                aA   -= iA * Vec2.cross(rA, P);

                cB.x += mB * P.x;
                cB.y += mB * P.y;
                aB   += iB * Vec2.cross(rB, P);
            }
            else
            {
                C1.set(cB).addLocal(rB).subLocal(cA).subLocal(rA);
                double C2 = aB - aA - m_referenceAngle;

                positionError = C1.length();
                angularError  = MathUtils.abs(C2);

                Vec3 C       = pool.popVec3();
                Vec3 impulse = pool.popVec3();
                C.set(C1.x, C1.y, C2);

                K.solve33ToOut(C, impulse);
                impulse.negateLocal();
                P.set(impulse.x, impulse.y);

                cA.x -= mA * P.x;
                cA.y -= mA * P.y;
                aA   -= iA * (Vec2.cross(rA, P) + impulse.z);

                cB.x += mB * P.x;
                cB.y += mB * P.y;
                aB   += iB * (Vec2.cross(rB, P) + impulse.z);
                pool.pushVec3(2);
            }

//    data.positions[m_indexA].c.set(cA);
            data.positions[m_indexA].a = aA;
//    data.positions[m_indexB].c.set(cB);
            data.positions[m_indexB].a = aB;

            pool.pushVec2(5);
            pool.pushRot(2);
            pool.pushMat33(1);

            return(positionError <= Settings.linearSlop && angularError <= Settings.angularSlop);
        }
Example #13
0
        public override void initVelocityConstraints(SolverData data)
        {
            m_indexA = m_bodyA.m_islandIndex;
            m_indexB = m_bodyB.m_islandIndex;
            m_localCenterA.set(m_bodyA.m_sweep.localCenter);
            m_localCenterB.set(m_bodyB.m_sweep.localCenter);
            m_invMassA = m_bodyA.m_invMass;
            m_invMassB = m_bodyB.m_invMass;
            m_invIA    = m_bodyA.m_invI;
            m_invIB    = m_bodyB.m_invI;

            // Vec2 cA = data.positions[m_indexA].c;
            double aA = data.positions[m_indexA].a;
            Vec2   vA = data.velocities[m_indexA].v;
            double wA = data.velocities[m_indexA].w;

            // Vec2 cB = data.positions[m_indexB].c;
            double aB = data.positions[m_indexB].a;
            Vec2   vB = data.velocities[m_indexB].v;
            double wB = data.velocities[m_indexB].w;

            Rot  qA   = pool.popRot();
            Rot  qB   = pool.popRot();
            Vec2 temp = pool.popVec2();

            qA.set(aA);
            qB.set(aB);

            // Compute the effective masses.
            Rot.mulToOutUnsafe(qA, temp.set(m_localAnchorA).subLocal(m_localCenterA), m_rA);
            Rot.mulToOutUnsafe(qB, temp.set(m_localAnchorB).subLocal(m_localCenterB), m_rB);

            // J = [-I -r1_skew I r2_skew]
            // [ 0 -1 0 1]
            // r_skew = [-ry; rx]

            // Matlab
            // K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x, -r1y*iA-r2y*iB]
            // [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB, r1x*iA+r2x*iB]
            // [ -r1y*iA-r2y*iB, r1x*iA+r2x*iB, iA+iB]

            double mA = m_invMassA, mB = m_invMassB;
            double iA = m_invIA, iB = m_invIB;

            Mat33 K = pool.popMat33();

            K.ex.x = mA + mB + m_rA.y * m_rA.y * iA + m_rB.y * m_rB.y * iB;
            K.ey.x = -m_rA.y * m_rA.x * iA - m_rB.y * m_rB.x * iB;
            K.ez.x = -m_rA.y * iA - m_rB.y * iB;
            K.ex.y = K.ey.x;
            K.ey.y = mA + mB + m_rA.x * m_rA.x * iA + m_rB.x * m_rB.x * iB;
            K.ez.y = m_rA.x * iA + m_rB.x * iB;
            K.ex.z = K.ez.x;
            K.ey.z = K.ez.y;
            K.ez.z = iA + iB;

            if (m_frequencyHz > 0.0d)
            {
                K.getInverse22(m_mass);

                double invM = iA + iB;
                double m    = invM > 0.0d ? 1.0d / invM : 0.0d;

                double C = aB - aA - m_referenceAngle;

                // Frequency
                double omega = 2.0d * MathUtils.PI * m_frequencyHz;

                // Damping coefficient
                double d = 2.0d * m * m_dampingRatio * omega;

                // Spring stiffness
                double k = m * omega * omega;

                // magic formulas
                double h = data.step.dt;
                m_gamma = h * (d + h * k);
                m_gamma = m_gamma != 0.0d ? 1.0d / m_gamma : 0.0d;
                m_bias  = C * h * k * m_gamma;

                invM       += m_gamma;
                m_mass.ez.z = invM != 0.0d ? 1.0d / invM : 0.0d;
            }
            else
            {
                K.getSymInverse33(m_mass);
                m_gamma = 0.0d;
                m_bias  = 0.0d;
            }

            if (data.step.warmStarting)
            {
                Vec2 P = pool.popVec2();
                // Scale impulses to support a variable time step.
                m_impulse.mulLocal(data.step.dtRatio);

                P.set(m_impulse.x, m_impulse.y);

                vA.x -= mA * P.x;
                vA.y -= mA * P.y;
                wA   -= iA * (Vec2.cross(m_rA, P) + m_impulse.z);

                vB.x += mB * P.x;
                vB.y += mB * P.y;
                wB   += iB * (Vec2.cross(m_rB, P) + m_impulse.z);
                pool.pushVec2(1);
            }
            else
            {
                m_impulse.setZero();
            }

//    data.velocities[m_indexA].v.set(vA);
            data.velocities[m_indexA].w = wA;
//    data.velocities[m_indexB].v.set(vB);
            data.velocities[m_indexB].w = wB;

            pool.pushVec2(1);
            pool.pushRot(2);
            pool.pushMat33(1);
        }
Example #14
0
        public override void initVelocityConstraints(SolverData data)
        {
            m_indexA = m_bodyA.m_islandIndex;
            m_indexB = m_bodyB.m_islandIndex;
            m_localCenterA.set(m_bodyA.m_sweep.localCenter);
            m_localCenterB.set(m_bodyB.m_sweep.localCenter);
            m_invMassA = m_bodyA.m_invMass;
            m_invMassB = m_bodyB.m_invMass;
            m_invIA    = m_bodyA.m_invI;
            m_invIB    = m_bodyB.m_invI;

            Vec2   cA = data.positions[m_indexA].c;
            double aA = data.positions[m_indexA].a;
            Vec2   vA = data.velocities[m_indexA].v;
            double wA = data.velocities[m_indexA].w;

            Vec2   cB = data.positions[m_indexB].c;
            double aB = data.positions[m_indexB].a;
            Vec2   vB = data.velocities[m_indexB].v;
            double wB = data.velocities[m_indexB].w;

            Rot  qA   = pool.popRot();
            Rot  qB   = pool.popRot();
            Vec2 d    = pool.popVec2();
            Vec2 temp = pool.popVec2();
            Vec2 rA   = pool.popVec2();
            Vec2 rB   = pool.popVec2();

            qA.set(aA);
            qB.set(aB);

            // Compute the effective masses.
            Rot.mulToOutUnsafe(qA, d.set(m_localAnchorA).subLocal(m_localCenterA), rA);
            Rot.mulToOutUnsafe(qB, d.set(m_localAnchorB).subLocal(m_localCenterB), rB);
            d.set(cB).subLocal(cA).addLocal(rB).subLocal(rA);

            double mA = m_invMassA, mB = m_invMassB;
            double iA = m_invIA, iB = m_invIB;

            // Compute motor Jacobian and effective mass.
            {
                Rot.mulToOutUnsafe(qA, m_localXAxisA, m_axis);
                temp.set(d).addLocal(rA);
                m_a1 = Vec2.cross(temp, m_axis);
                m_a2 = Vec2.cross(rB, m_axis);

                m_motorMass = mA + mB + iA * m_a1 * m_a1 + iB * m_a2 * m_a2;
                if (m_motorMass > 0.0d)
                {
                    m_motorMass = 1.0d / m_motorMass;
                }
            }

            // Prismatic constraint.
            {
                Rot.mulToOutUnsafe(qA, m_localYAxisA, m_perp);

                temp.set(d).addLocal(rA);
                m_s1 = Vec2.cross(temp, m_perp);
                m_s2 = Vec2.cross(rB, m_perp);

                double k11 = mA + mB + iA * m_s1 * m_s1 + iB * m_s2 * m_s2;
                double k12 = iA * m_s1 + iB * m_s2;
                double k13 = iA * m_s1 * m_a1 + iB * m_s2 * m_a2;
                double k22 = iA + iB;
                if (k22 == 0.0d)
                {
                    // For bodies with fixed rotation.
                    k22 = 1.0d;
                }
                double k23 = iA * m_a1 + iB * m_a2;
                double k33 = mA + mB + iA * m_a1 * m_a1 + iB * m_a2 * m_a2;

                m_K.ex.set(k11, k12, k13);
                m_K.ey.set(k12, k22, k23);
                m_K.ez.set(k13, k23, k33);
            }

            // Compute motor and limit terms.
            if (m_enableLimit)
            {
                double jointTranslation = Vec2.dot(m_axis, d);
                if (MathUtils.abs(m_upperTranslation - m_lowerTranslation) < 2.0d * Settings.linearSlop)
                {
                    m_limitState = LimitState.EQUAL;
                }
                else if (jointTranslation <= m_lowerTranslation)
                {
                    if (m_limitState != LimitState.AT_LOWER)
                    {
                        m_limitState = LimitState.AT_LOWER;
                        m_impulse.z  = 0.0d;
                    }
                }
                else if (jointTranslation >= m_upperTranslation)
                {
                    if (m_limitState != LimitState.AT_UPPER)
                    {
                        m_limitState = LimitState.AT_UPPER;
                        m_impulse.z  = 0.0d;
                    }
                }
                else
                {
                    m_limitState = LimitState.INACTIVE;
                    m_impulse.z  = 0.0d;
                }
            }
            else
            {
                m_limitState = LimitState.INACTIVE;
                m_impulse.z  = 0.0d;
            }

            if (m_enableMotor == false)
            {
                m_motorImpulse = 0.0d;
            }

            if (data.step.warmStarting)
            {
                // Account for variable time step.
                m_impulse.mulLocal(data.step.dtRatio);
                m_motorImpulse *= data.step.dtRatio;

                Vec2 P = pool.popVec2();
                temp.set(m_axis).mulLocal(m_motorImpulse + m_impulse.z);
                P.set(m_perp).mulLocal(m_impulse.x).addLocal(temp);

                double LA = m_impulse.x * m_s1 + m_impulse.y + (m_motorImpulse + m_impulse.z) * m_a1;
                double LB = m_impulse.x * m_s2 + m_impulse.y + (m_motorImpulse + m_impulse.z) * m_a2;

                vA.x -= mA * P.x;
                vA.y -= mA * P.y;
                wA   -= iA * LA;

                vB.x += mB * P.x;
                vB.y += mB * P.y;
                wB   += iB * LB;

                pool.pushVec2(1);
            }
            else
            {
                m_impulse.setZero();
                m_motorImpulse = 0.0d;
            }

            // data.velocities[m_indexA].v.set(vA);
            data.velocities[m_indexA].w = wA;
            // data.velocities[m_indexB].v.set(vB);
            data.velocities[m_indexB].w = wB;

            pool.pushRot(2);
            pool.pushVec2(4);
        }
Example #15
0
        public override void initVelocityConstraints(SolverData data)
        {
            m_indexA = m_bodyA.m_islandIndex;
            m_indexB = m_bodyB.m_islandIndex;
            m_localCenterA.set(m_bodyA.m_sweep.localCenter);
            m_localCenterB.set(m_bodyB.m_sweep.localCenter);
            m_invMassA = m_bodyA.m_invMass;
            m_invMassB = m_bodyB.m_invMass;
            m_invIA    = m_bodyA.m_invI;
            m_invIB    = m_bodyB.m_invI;

            Vec2   cA = data.positions[m_indexA].c;
            double aA = data.positions[m_indexA].a;
            Vec2   vA = data.velocities[m_indexA].v;
            double wA = data.velocities[m_indexA].w;

            Vec2   cB = data.positions[m_indexB].c;
            double aB = data.positions[m_indexB].a;
            Vec2   vB = data.velocities[m_indexB].v;
            double wB = data.velocities[m_indexB].w;

            Rot  qA   = pool.popRot();
            Rot  qB   = pool.popRot();
            Vec2 temp = pool.popVec2();

            qA.set(aA);
            qB.set(aB);

            // Compute the effective masses.
            Rot.mulToOutUnsafe(qA, temp.set(m_localAnchorA).subLocal(m_localCenterA), m_rA);
            Rot.mulToOutUnsafe(qB, temp.set(m_localAnchorB).subLocal(m_localCenterB), m_rB);

            m_u.set(cB).addLocal(m_rB).subLocal(cA).subLocal(m_rA);

            m_length = m_u.length();

            double C = m_length - m_maxLength;

            if (C > 0.0d)
            {
                m_state = LimitState.AT_UPPER;
            }
            else
            {
                m_state = LimitState.INACTIVE;
            }

            if (m_length > Settings.linearSlop)
            {
                m_u.mulLocal(1.0d / m_length);
            }
            else
            {
                m_u.setZero();
                m_mass    = 0.0d;
                m_impulse = 0.0d;
                return;
            }

            // Compute effective mass.
            double crA     = Vec2.cross(m_rA, m_u);
            double crB     = Vec2.cross(m_rB, m_u);
            double invMass = m_invMassA + m_invIA * crA * crA + m_invMassB + m_invIB * crB * crB;

            m_mass = invMass != 0.0d ? 1.0d / invMass : 0.0d;

            if (data.step.warmStarting)
            {
                // Scale the impulse to support a variable time step.
                m_impulse *= data.step.dtRatio;

                double Px = m_impulse * m_u.x;
                double Py = m_impulse * m_u.y;
                vA.x -= m_invMassA * Px;
                vA.y -= m_invMassA * Py;
                wA   -= m_invIA * (m_rA.x * Py - m_rA.y * Px);

                vB.x += m_invMassB * Px;
                vB.y += m_invMassB * Py;
                wB   += m_invIB * (m_rB.x * Py - m_rB.y * Px);
            }
            else
            {
                m_impulse = 0.0d;
            }

            pool.pushRot(2);
            pool.pushVec2(1);

            // data.velocities[m_indexA].v = vA;
            data.velocities[m_indexA].w = wA;
            // data.velocities[m_indexB].v = vB;
            data.velocities[m_indexB].w = wB;
        }
Example #16
0
        public override bool solvePositionConstraints(SolverData data)
        {
            Rot  qA   = pool.popRot();
            Rot  qB   = pool.popRot();
            Vec2 rA   = pool.popVec2();
            Vec2 rB   = pool.popVec2();
            Vec2 d    = pool.popVec2();
            Vec2 axis = pool.popVec2();
            Vec2 perp = pool.popVec2();
            Vec2 temp = pool.popVec2();
            Vec2 C1   = pool.popVec2();

            Vec3 impulse = pool.popVec3();

            Vec2   cA = data.positions[m_indexA].c;
            double aA = data.positions[m_indexA].a;
            Vec2   cB = data.positions[m_indexB].c;
            double aB = data.positions[m_indexB].a;

            qA.set(aA);
            qB.set(aB);

            double mA = m_invMassA, mB = m_invMassB;
            double iA = m_invIA, iB = m_invIB;

            // Compute fresh Jacobians
            Rot.mulToOutUnsafe(qA, temp.set(m_localAnchorA).subLocal(m_localCenterA), rA);
            Rot.mulToOutUnsafe(qB, temp.set(m_localAnchorB).subLocal(m_localCenterB), rB);
            d.set(cB).addLocal(rB).subLocal(cA).subLocal(rA);

            Rot.mulToOutUnsafe(qA, m_localXAxisA, axis);
            double a1 = Vec2.cross(temp.set(d).addLocal(rA), axis);
            double a2 = Vec2.cross(rB, axis);

            Rot.mulToOutUnsafe(qA, m_localYAxisA, perp);

            double s1 = Vec2.cross(temp.set(d).addLocal(rA), perp);
            double s2 = Vec2.cross(rB, perp);

            C1.x = Vec2.dot(perp, d);
            C1.y = aB - aA - m_referenceAngle;

            double linearError  = MathUtils.abs(C1.x);
            double angularError = MathUtils.abs(C1.y);

            bool   active = false;
            double C2     = 0.0d;

            if (m_enableLimit)
            {
                double translation = Vec2.dot(axis, d);
                if (MathUtils.abs(m_upperTranslation - m_lowerTranslation) < 2.0d * Settings.linearSlop)
                {
                    // Prevent large angular corrections
                    C2 =
                        MathUtils.clamp(translation, -Settings.maxLinearCorrection,
                                        Settings.maxLinearCorrection);
                    linearError = MathUtils.max(linearError, MathUtils.abs(translation));
                    active      = true;
                }
                else if (translation <= m_lowerTranslation)
                {
                    // Prevent large linear corrections and allow some slop.
                    C2 =
                        MathUtils.clamp(translation - m_lowerTranslation + Settings.linearSlop,
                                        -Settings.maxLinearCorrection, 0.0d);
                    linearError = MathUtils.max(linearError, m_lowerTranslation - translation);
                    active      = true;
                }
                else if (translation >= m_upperTranslation)
                {
                    // Prevent large linear corrections and allow some slop.
                    C2 =
                        MathUtils.clamp(translation - m_upperTranslation - Settings.linearSlop, 0.0d,
                                        Settings.maxLinearCorrection);
                    linearError = MathUtils.max(linearError, translation - m_upperTranslation);
                    active      = true;
                }
            }

            if (active)
            {
                double k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2;
                double k12 = iA * s1 + iB * s2;
                double k13 = iA * s1 * a1 + iB * s2 * a2;
                double k22 = iA + iB;
                if (k22 == 0.0d)
                {
                    // For fixed rotation
                    k22 = 1.0d;
                }
                double k23 = iA * a1 + iB * a2;
                double k33 = mA + mB + iA * a1 * a1 + iB * a2 * a2;

                Mat33 K = pool.popMat33();
                K.ex.set(k11, k12, k13);
                K.ey.set(k12, k22, k23);
                K.ez.set(k13, k23, k33);

                Vec3 C = pool.popVec3();
                C.x = C1.x;
                C.y = C1.y;
                C.z = C2;

                K.solve33ToOut(C.negateLocal(), impulse);
                pool.pushVec3(1);
                pool.pushMat33(1);
            }
            else
            {
                double k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2;
                double k12 = iA * s1 + iB * s2;
                double k22 = iA + iB;
                if (k22 == 0.0d)
                {
                    k22 = 1.0d;
                }

                Mat22 K = pool.popMat22();
                K.ex.set(k11, k12);
                K.ey.set(k12, k22);

                // temp is impulse1
                K.solveToOut(C1.negateLocal(), temp);
                C1.negateLocal();

                impulse.x = temp.x;
                impulse.y = temp.y;
                impulse.z = 0.0d;

                pool.pushMat22(1);
            }

            double Px = impulse.x * perp.x + impulse.z * axis.x;
            double Py = impulse.x * perp.y + impulse.z * axis.y;
            double LA = impulse.x * s1 + impulse.y + impulse.z * a1;
            double LB = impulse.x * s2 + impulse.y + impulse.z * a2;

            cA.x -= mA * Px;
            cA.y -= mA * Py;
            aA   -= iA * LA;
            cB.x += mB * Px;
            cB.y += mB * Py;
            aB   += iB * LB;

            // data.positions[m_indexA].c.set(cA);
            data.positions[m_indexA].a = aA;
            // data.positions[m_indexB].c.set(cB);
            data.positions[m_indexB].a = aB;

            pool.pushVec2(7);
            pool.pushVec3(1);
            pool.pushRot(2);

            return(linearError <= Settings.linearSlop && angularError <= Settings.angularSlop);
        }
        public override void initVelocityConstraints(SolverData data)
        {
            m_indexA = m_bodyA.m_islandIndex;
            m_indexB = m_bodyB.m_islandIndex;
            m_localCenterA.set(m_bodyA.m_sweep.localCenter);
            m_localCenterB.set(m_bodyB.m_sweep.localCenter);
            m_invMassA = m_bodyA.m_invMass;
            m_invMassB = m_bodyB.m_invMass;
            m_invIA    = m_bodyA.m_invI;
            m_invIB    = m_bodyB.m_invI;

            Vec2   cA = data.positions[m_indexA].c;
            double aA = data.positions[m_indexA].a;
            Vec2   vA = data.velocities[m_indexA].v;
            double wA = data.velocities[m_indexA].w;

            Vec2   cB = data.positions[m_indexB].c;
            double aB = data.positions[m_indexB].a;
            Vec2   vB = data.velocities[m_indexB].v;
            double wB = data.velocities[m_indexB].w;

            Rot qA = pool.popRot();
            Rot qB = pool.popRot();

            qA.set(aA);
            qB.set(aB);

            // use m_u as temporary variable
            Rot.mulToOutUnsafe(qA, m_u.set(m_localAnchorA).subLocal(m_localCenterA), m_rA);
            Rot.mulToOutUnsafe(qB, m_u.set(m_localAnchorB).subLocal(m_localCenterB), m_rB);
            m_u.set(cB).addLocal(m_rB).subLocal(cA).subLocal(m_rA);

            pool.pushRot(2);

            // Handle singularity.
            double length = m_u.length();

            if (length > Settings.linearSlop)
            {
                m_u.x *= 1.0d / length;
                m_u.y *= 1.0d / length;
            }
            else
            {
                m_u.set(0.0d, 0.0d);
            }


            double crAu    = Vec2.cross(m_rA, m_u);
            double crBu    = Vec2.cross(m_rB, m_u);
            double invMass = m_invMassA + m_invIA * crAu * crAu + m_invMassB + m_invIB * crBu * crBu;

            // Compute the effective mass matrix.
            m_mass = invMass != 0.0d ? 1.0d / invMass : 0.0d;

            if (m_frequencyHz > 0.0d)
            {
                double C = length - m_length;

                // Frequency
                double omega = 2.0d * MathUtils.PI * m_frequencyHz;

                // Damping coefficient
                double d = 2.0d * m_mass * m_dampingRatio * omega;

                // Spring stiffness
                double k = m_mass * omega * omega;

                // magic formulas
                double h = data.step.dt;
                m_gamma = h * (d + h * k);
                m_gamma = m_gamma != 0.0d ? 1.0d / m_gamma : 0.0d;
                m_bias  = C * h * k * m_gamma;

                invMass += m_gamma;
                m_mass   = invMass != 0.0d ? 1.0d / invMass : 0.0d;
            }
            else
            {
                m_gamma = 0.0d;
                m_bias  = 0.0d;
            }
            if (data.step.warmStarting)
            {
                // Scale the impulse to support a variable time step.
                m_impulse *= data.step.dtRatio;

                Vec2 P = pool.popVec2();
                P.set(m_u).mulLocal(m_impulse);

                vA.x -= m_invMassA * P.x;
                vA.y -= m_invMassA * P.y;
                wA   -= m_invIA * Vec2.cross(m_rA, P);

                vB.x += m_invMassB * P.x;
                vB.y += m_invMassB * P.y;
                wB   += m_invIB * Vec2.cross(m_rB, P);

                pool.pushVec2(1);
            }
            else
            {
                m_impulse = 0.0d;
            }
//    data.velocities[m_indexA].v.set(vA);
            data.velocities[m_indexA].w = wA;
//    data.velocities[m_indexB].v.set(vB);
            data.velocities[m_indexB].w = wB;
        }
Example #18
0
        public override bool solvePositionConstraints(SolverData data)
        {
            Rot  qA   = pool.popRot();
            Rot  qB   = pool.popRot();
            Vec2 rA   = pool.popVec2();
            Vec2 rB   = pool.popVec2();
            Vec2 uA   = pool.popVec2();
            Vec2 uB   = pool.popVec2();
            Vec2 temp = pool.popVec2();
            Vec2 PA   = pool.popVec2();
            Vec2 PB   = pool.popVec2();

            Vec2   cA = data.positions[m_indexA].c;
            double aA = data.positions[m_indexA].a;
            Vec2   cB = data.positions[m_indexB].c;
            double aB = data.positions[m_indexB].a;

            qA.set(aA);
            qB.set(aB);

            Rot.mulToOutUnsafe(qA, temp.set(m_localAnchorA).subLocal(m_localCenterA), rA);
            Rot.mulToOutUnsafe(qB, temp.set(m_localAnchorB).subLocal(m_localCenterB), rB);

            uA.set(cA).addLocal(rA).subLocal(m_groundAnchorA);
            uB.set(cB).addLocal(rB).subLocal(m_groundAnchorB);

            double lengthA = uA.length();
            double lengthB = uB.length();

            if (lengthA > 10.0d * Settings.linearSlop)
            {
                uA.mulLocal(1.0d / lengthA);
            }
            else
            {
                uA.setZero();
            }

            if (lengthB > 10.0d * Settings.linearSlop)
            {
                uB.mulLocal(1.0d / lengthB);
            }
            else
            {
                uB.setZero();
            }

            // Compute effective mass.
            double ruA = Vec2.cross(rA, uA);
            double ruB = Vec2.cross(rB, uB);

            double mA = m_invMassA + m_invIA * ruA * ruA;
            double mB = m_invMassB + m_invIB * ruB * ruB;

            double mass = mA + m_ratio * m_ratio * mB;

            if (mass > 0.0d)
            {
                mass = 1.0d / mass;
            }

            double C           = m_constant - lengthA - m_ratio * lengthB;
            double linearError = MathUtils.abs(C);

            double impulse = -mass * C;

            PA.set(uA).mulLocal(-impulse);
            PB.set(uB).mulLocal(-m_ratio * impulse);

            cA.x += m_invMassA * PA.x;
            cA.y += m_invMassA * PA.y;
            aA   += m_invIA * Vec2.cross(rA, PA);
            cB.x += m_invMassB * PB.x;
            cB.y += m_invMassB * PB.y;
            aB   += m_invIB * Vec2.cross(rB, PB);

//    data.positions[m_indexA].c.set(cA);
            data.positions[m_indexA].a = aA;
//    data.positions[m_indexB].c.set(cB);
            data.positions[m_indexB].a = aB;

            pool.pushRot(2);
            pool.pushVec2(7);

            return(linearError < Settings.linearSlop);
        }
Example #19
0
        public override void initVelocityConstraints(SolverData data)
        {
            m_indexA = m_bodyA.m_islandIndex;
            m_indexB = m_bodyB.m_islandIndex;
            m_indexC = m_bodyC.m_islandIndex;
            m_indexD = m_bodyD.m_islandIndex;
            m_lcA.set(m_bodyA.m_sweep.localCenter);
            m_lcB.set(m_bodyB.m_sweep.localCenter);
            m_lcC.set(m_bodyC.m_sweep.localCenter);
            m_lcD.set(m_bodyD.m_sweep.localCenter);
            m_mA = m_bodyA.m_invMass;
            m_mB = m_bodyB.m_invMass;
            m_mC = m_bodyC.m_invMass;
            m_mD = m_bodyD.m_invMass;
            m_iA = m_bodyA.m_invI;
            m_iB = m_bodyB.m_invI;
            m_iC = m_bodyC.m_invI;
            m_iD = m_bodyD.m_invI;

            // Vec2 cA = data.positions[m_indexA].c;
            double aA = data.positions[m_indexA].a;
            Vec2   vA = data.velocities[m_indexA].v;
            double wA = data.velocities[m_indexA].w;

            // Vec2 cB = data.positions[m_indexB].c;
            double aB = data.positions[m_indexB].a;
            Vec2   vB = data.velocities[m_indexB].v;
            double wB = data.velocities[m_indexB].w;

            // Vec2 cC = data.positions[m_indexC].c;
            double aC = data.positions[m_indexC].a;
            Vec2   vC = data.velocities[m_indexC].v;
            double wC = data.velocities[m_indexC].w;

            // Vec2 cD = data.positions[m_indexD].c;
            double aD = data.positions[m_indexD].a;
            Vec2   vD = data.velocities[m_indexD].v;
            double wD = data.velocities[m_indexD].w;

            Rot qA = pool.popRot(), qB = pool.popRot(), qC = pool.popRot(), qD = pool.popRot();

            qA.set(aA);
            qB.set(aB);
            qC.set(aC);
            qD.set(aD);

            m_mass = 0.0d;

            Vec2 temp = pool.popVec2();

            if (m_typeA == JointType.REVOLUTE)
            {
                m_JvAC.setZero();
                m_JwA   = 1.0d;
                m_JwC   = 1.0d;
                m_mass += m_iA + m_iC;
            }
            else
            {
                Vec2 rC = pool.popVec2();
                Vec2 rA = pool.popVec2();
                Rot.mulToOutUnsafe(qC, m_localAxisC, m_JvAC);
                Rot.mulToOutUnsafe(qC, temp.set(m_localAnchorC).subLocal(m_lcC), rC);
                Rot.mulToOutUnsafe(qA, temp.set(m_localAnchorA).subLocal(m_lcA), rA);
                m_JwC   = Vec2.cross(rC, m_JvAC);
                m_JwA   = Vec2.cross(rA, m_JvAC);
                m_mass += m_mC + m_mA + m_iC * m_JwC * m_JwC + m_iA * m_JwA * m_JwA;
                pool.pushVec2(2);
            }

            if (m_typeB == JointType.REVOLUTE)
            {
                m_JvBD.setZero();
                m_JwB   = m_ratio;
                m_JwD   = m_ratio;
                m_mass += m_ratio * m_ratio * (m_iB + m_iD);
            }
            else
            {
                Vec2 u  = pool.popVec2();
                Vec2 rD = pool.popVec2();
                Vec2 rB = pool.popVec2();
                Rot.mulToOutUnsafe(qD, m_localAxisD, u);
                Rot.mulToOutUnsafe(qD, temp.set(m_localAnchorD).subLocal(m_lcD), rD);
                Rot.mulToOutUnsafe(qB, temp.set(m_localAnchorB).subLocal(m_lcB), rB);
                m_JvBD.set(u).mulLocal(m_ratio);
                m_JwD   = m_ratio * Vec2.cross(rD, u);
                m_JwB   = m_ratio * Vec2.cross(rB, u);
                m_mass += m_ratio * m_ratio * (m_mD + m_mB) + m_iD * m_JwD * m_JwD + m_iB * m_JwB * m_JwB;
                pool.pushVec2(3);
            }

            // Compute effective mass.
            m_mass = m_mass > 0.0d ? 1.0d / m_mass : 0.0d;

            if (data.step.warmStarting)
            {
                vA.x += (m_mA * m_impulse) * m_JvAC.x;
                vA.y += (m_mA * m_impulse) * m_JvAC.y;
                wA   += m_iA * m_impulse * m_JwA;

                vB.x += (m_mB * m_impulse) * m_JvBD.x;
                vB.y += (m_mB * m_impulse) * m_JvBD.y;
                wB   += m_iB * m_impulse * m_JwB;

                vC.x -= (m_mC * m_impulse) * m_JvAC.x;
                vC.y -= (m_mC * m_impulse) * m_JvAC.y;
                wC   -= m_iC * m_impulse * m_JwC;

                vD.x -= (m_mD * m_impulse) * m_JvBD.x;
                vD.y -= (m_mD * m_impulse) * m_JvBD.y;
                wD   -= m_iD * m_impulse * m_JwD;
            }
            else
            {
                m_impulse = 0.0d;
            }
            pool.pushVec2(1);
            pool.pushRot(4);

            // data.velocities[m_indexA].v = vA;
            data.velocities[m_indexA].w = wA;
            // data.velocities[m_indexB].v = vB;
            data.velocities[m_indexB].w = wB;
            // data.velocities[m_indexC].v = vC;
            data.velocities[m_indexC].w = wC;
            // data.velocities[m_indexD].v = vD;
            data.velocities[m_indexD].w = wD;
        }