예제 #1
0
        internal override void InitVelocityConstraints(ref SolverData data)
        {
            _jointError = BodyA.Sweep.A - TargetAngle;

            _bias = -BiasFactor * data.step.inv_dt * _jointError;

            _massFactor = (1 - Softness) / (BodyA.InvI);
        }
예제 #2
0
        internal override void SolveVelocityConstraints(ref SolverData data)
        {
			//GABS: NOT A BOTTLENECK
			
            float p = (_bias - BodyB.AngularVelocity + BodyA.AngularVelocity) * _massFactor;
            BodyA.AngularVelocity -= BodyA.InvI * Math.Sign(p) * Math.Min(Math.Abs(p), MaxImpulse);
            BodyB.AngularVelocity += BodyB.InvI * Math.Sign(p) * Math.Min(Math.Abs(p), MaxImpulse);
        }
예제 #3
0
        internal override void InitVelocityConstraints(ref SolverData data)
        {
            Body b1 = BodyA;
            Body b2 = BodyB;

            Transform xf1, xf2;

            b1.GetTransform(out xf1);
            b2.GetTransform(out xf2);

            // Compute the effective mass matrix.
            FVector2 r1 = MathUtils.Mul(ref xf1.q, LocalAnchorA - b1.LocalCenter);
            FVector2 r2 = MathUtils.Mul(ref xf2.q, LocalAnchorB - b2.LocalCenter);

            _u = b2.Sweep.C + r2 - b1.Sweep.C - r1;

            // Handle singularity.
            float length = _u.Length();

            if (length < MaxLength && length > MinLength)
            {
                return;
            }

            if (length > Settings.LinearSlop)
            {
                _u *= 1.0f / length;
            }
            else
            {
                _u = FVector2.Zero;
            }

            float cr1u    = MathUtils.Cross(r1, _u);
            float cr2u    = MathUtils.Cross(r2, _u);
            float invMass = b1.InvMass + b1.InvI * cr1u * cr1u + b2.InvMass + b2.InvI * cr2u * cr2u;

            Debug.Assert(invMass > Settings.Epsilon);
            _mass = invMass != 0.0f ? 1.0f / invMass : 0.0f;

            if (Frequency > 0.0f)
            {
                float C = length - MaxLength;

                // Frequency
                float omega = 2.0f * Settings.Pi * Frequency;

                // Damping coefficient
                float d = 2.0f * _mass * DampingRatio * omega;

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

                // magic formulas
                _gamma = data.step.dt * (d + data.step.dt * k);
                _gamma = _gamma != 0.0f ? 1.0f / _gamma : 0.0f;
                _bias  = C * data.step.dt * k * _gamma;

                _mass = invMass + _gamma;
                _mass = _mass != 0.0f ? 1.0f / _mass : 0.0f;
            }

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

                FVector2 P = _impulse * _u;
                b1.LinearVelocityInternal  -= b1.InvMass * P;
                b1.AngularVelocityInternal -= b1.InvI * MathUtils.Cross(r1, P);
                b2.LinearVelocityInternal  += b2.InvMass * P;
                b2.AngularVelocityInternal += b2.InvI * MathUtils.Cross(r2, P);
            }
            else
            {
                _impulse = 0.0f;
            }
        }
예제 #4
0
        public override void solveVelocityConstraints(SolverData data)
        {
            Vec2 vA = data.velocities[m_indexA].v;
            float wA = data.velocities[m_indexA].w;
            Vec2 vB = data.velocities[m_indexB].v;
            float wB = data.velocities[m_indexB].w;

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

            Vec2 temp = pool.popVec2();

            // Solve linear motor constraint.
            if (m_enableMotor && m_limitState != LimitState.EQUAL)
            {
                temp.set_Renamed(vB).subLocal(vA);
                float Cdot = Vec2.dot(m_axis, temp) + m_a2 * wB - m_a1 * wA;
                float impulse = m_motorMass * (m_motorSpeed - Cdot);
                float oldImpulse = m_motorImpulse;
                float maxImpulse = data.step.dt * m_maxMotorForce;
                m_motorImpulse = MathUtils.clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse);
                impulse = m_motorImpulse - oldImpulse;

                Vec2 P = pool.popVec2();
                P.set_Renamed(m_axis).mulLocal(impulse);
                float LA = impulse * m_a1;
                float LB = impulse * 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);
            }

            Vec2 Cdot1 = pool.popVec2();
            temp.set_Renamed(vB).subLocal(vA);
            Cdot1.x = Vec2.dot(m_perp, temp) + m_s2 * wB - m_s1 * wA;
            Cdot1.y = wB - wA;
            // System.out.println(Cdot1);

            if (m_enableLimit && m_limitState != LimitState.INACTIVE)
            {
                // Solve prismatic and limit constraint in block form.
                float Cdot2;
                temp.set_Renamed(vB).subLocal(vA);
                Cdot2 = Vec2.dot(m_axis, temp) + m_a2 * wB - m_a1 * wA;

                Vec3 Cdot = pool.popVec3();
                Cdot.set_Renamed(Cdot1.x, Cdot1.y, Cdot2);
                Cdot.negateLocal();

                Vec3 f1 = pool.popVec3();
                Vec3 df = pool.popVec3();

                f1.set_Renamed(m_impulse);
                m_K.solve33ToOut(Cdot.negateLocal(), df);
                //Cdot.negateLocal(); not used anymore
                m_impulse.addLocal(df);

                if (m_limitState == LimitState.AT_LOWER)
                {
                    m_impulse.z = MathUtils.max(m_impulse.z, 0.0f);
                }
                else if (m_limitState == LimitState.AT_UPPER)
                {
                    m_impulse.z = MathUtils.min(m_impulse.z, 0.0f);
                }

                // f2(1:2) = invK(1:2,1:2) * (-Cdot(1:2) - K(1:2,3) * (f2(3) - f1(3))) +
                // f1(1:2)
                Vec2 b = pool.popVec2();
                Vec2 f2r = pool.popVec2();

                temp.set_Renamed(m_K.ez.x, m_K.ez.y).mulLocal(m_impulse.z - f1.z);
                b.set_Renamed(Cdot1).negateLocal().subLocal(temp);

                temp.set_Renamed(f1.x, f1.y);
                m_K.solve22ToOut(b, f2r);
                f2r.addLocal(temp);
                m_impulse.x = f2r.x;
                m_impulse.y = f2r.y;

                df.set_Renamed(m_impulse).subLocal(f1);

                Vec2 P = pool.popVec2();
                temp.set_Renamed(m_axis).mulLocal(df.z);
                P.set_Renamed(m_perp).mulLocal(df.x).addLocal(temp);

                float LA = df.x * m_s1 + df.y + df.z * m_a1;
                float LB = df.x * m_s2 + df.y + df.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(3);
                pool.pushVec3(3);
            }
            else
            {
                // Limit is inactive, just solve the prismatic constraint in block form.
                Vec2 df = pool.popVec2();
                m_K.solve22ToOut(Cdot1.negateLocal(), df);
                Cdot1.negateLocal();

                m_impulse.x += df.x;
                m_impulse.y += df.y;

                Vec2 P = pool.popVec2();
                P.set_Renamed(m_perp).mulLocal(df.x);
                float LA = df.x * m_s1 + df.y;
                float LB = df.x * m_s2 + df.y;

                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;

                Vec2 Cdot10 = pool.popVec2();
                Cdot10.set_Renamed(Cdot1);

                Cdot1.x = Vec2.dot(m_perp, temp.set_Renamed(vB).subLocal(vA)) + m_s2 * wB - m_s1 * wA;
                Cdot1.y = wB - wA;

                if (MathUtils.abs(Cdot1.x) > 0.01f || MathUtils.abs(Cdot1.y) > 0.01f)
                {
                    // djm note: what's happening here?
                    Mat33.mul22ToOutUnsafe(m_K, df, temp);
                    Cdot1.x += 0.0f;
                }

                pool.pushVec2(3);
            }

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

            pool.pushVec2(2);
        }
예제 #5
0
        internal override void InitVelocityConstraints(ref SolverData data)
        {
            _indexA       = BodyA.IslandIndex;
            _indexB       = BodyB.IslandIndex;
            _localCenterA = BodyA._sweep.LocalCenter;
            _localCenterB = BodyB._sweep.LocalCenter;
            _invMassA     = BodyA._invMass;
            _invMassB     = BodyB._invMass;
            _invIA        = BodyA._invI;
            _invIB        = BodyB._invI;

            float mA = _invMassA, mB = _invMassB;
            float iA = _invIA, iB = _invIB;

            Vector2 cA = data.Positions[_indexA].C;
            float   aA = data.Positions[_indexA].A;
            Vector2 vA = data.Velocities[_indexA].V;
            float   wA = data.Velocities[_indexA].W;

            Vector2 cB = data.Positions[_indexB].C;
            float   aB = data.Positions[_indexB].A;
            Vector2 vB = data.Velocities[_indexB].V;
            float   wB = data.Velocities[_indexB].W;

            Rot qA = new Rot(aA), qB = new Rot(aB);

            // Compute the effective masses.
            Vector2 rA = MathUtils.Mul(qA, LocalAnchorA - _localCenterA);
            Vector2 rB = MathUtils.Mul(qB, LocalAnchorB - _localCenterB);
            Vector2 d1 = cB + rB - cA - rA;

            // Point to line constraint
            {
                _ay  = MathUtils.Mul(qA, _localYAxis);
                _sAy = MathUtils.Cross(d1 + rA, _ay);
                _sBy = MathUtils.Cross(rB, _ay);

                _mass = mA + mB + iA * _sAy * _sAy + iB * _sBy * _sBy;

                if (_mass > 0.0f)
                {
                    _mass = 1.0f / _mass;
                }
            }

            // Spring constraint
            _springMass = 0.0f;
            _bias       = 0.0f;
            _gamma      = 0.0f;
            if (Frequency > 0.0f)
            {
                _ax  = MathUtils.Mul(qA, LocalXAxis);
                _sAx = MathUtils.Cross(d1 + rA, _ax);
                _sBx = MathUtils.Cross(rB, _ax);

                float invMass = mA + mB + iA * _sAx * _sAx + iB * _sBx * _sBx;

                if (invMass > 0.0f)
                {
                    _springMass = 1.0f / invMass;

                    float C = Vector2.Dot(d1, _ax);

                    // Frequency
                    float omega = 2.0f * Settings.Pi * Frequency;

                    // Damping coefficient
                    float d = 2.0f * _springMass * DampingRatio * omega;

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

                    // magic formulas
                    float h = data.Step.dt;
                    _gamma = h * (d + h * k);
                    if (_gamma > 0.0f)
                    {
                        _gamma = 1.0f / _gamma;
                    }

                    _bias = C * h * k * _gamma;

                    _springMass = invMass + _gamma;
                    if (_springMass > 0.0f)
                    {
                        _springMass = 1.0f / _springMass;
                    }
                }
            }
            else
            {
                _springImpulse = 0.0f;
            }

            // Rotational motor
            if (_enableMotor)
            {
                _motorMass = iA + iB;
                if (_motorMass > 0.0f)
                {
                    _motorMass = 1.0f / _motorMass;
                }
            }
            else
            {
                _motorMass    = 0.0f;
                _motorImpulse = 0.0f;
            }

#pragma warning disable 162
            // ReSharper disable once ConditionIsAlwaysTrueOrFalse
            if (Settings.EnableWarmstarting)
            {
                // Account for variable time step.
                _impulse       *= data.Step.dtRatio;
                _springImpulse *= data.Step.dtRatio;
                _motorImpulse  *= data.Step.dtRatio;

                Vector2 P  = _impulse * _ay + _springImpulse * _ax;
                float   LA = _impulse * _sAy + _springImpulse * _sAx + _motorImpulse;
                float   LB = _impulse * _sBy + _springImpulse * _sBx + _motorImpulse;

                vA -= _invMassA * P;
                wA -= _invIA * LA;

                vB += _invMassB * P;
                wB += _invIB * LB;
            }
            else
            {
                _impulse       = 0.0f;
                _springImpulse = 0.0f;
                _motorImpulse  = 0.0f;
            }
#pragma warning restore 162

            data.Velocities[_indexA].V = vA;
            data.Velocities[_indexA].W = wA;
            data.Velocities[_indexB].V = vB;
            data.Velocities[_indexB].W = wB;
        }
예제 #6
0
        internal override void InitVelocityConstraints(ref SolverData data)
        {
            _indexA = BodyA.IslandIndex;
            _indexB = BodyB.IslandIndex;
            _localCenterA = BodyA.Sweep.LocalCenter;
            _localCenterB = BodyB.Sweep.LocalCenter;
            _invMassA = BodyA.InvMass;
            _invMassB = BodyB.InvMass;
            _invIA = BodyA.InvI;
            _invIB = BodyB.InvI;

            Vector2 cA = data.positions[_indexA].c;
            float aA = data.positions[_indexA].a;
            Vector2 vA = data.velocities[_indexA].v;
            float wA = data.velocities[_indexA].w;

            Vector2 cB = data.positions[_indexB].c;
            float aB = data.positions[_indexB].a;
            Vector2 vB = data.velocities[_indexB].v;
            float wB = data.velocities[_indexB].w;

            Rot qA = new Rot(aA), qB = new Rot(aB);

            _rA = MathUtils.Mul(qA, LocalAnchorA - _localCenterA);
            _rB = MathUtils.Mul(qB, LocalAnchorB - _localCenterB);
            _u = cB + _rB - cA - _rA;

            _length = _u.Length();

            float C = _length - MaxLength;
            if (C > 0.0f)
            {
                _state = LimitState.AtUpper;
            }
            else
            {
                _state = LimitState.Inactive;
            }

            if (_length > Settings.LinearSlop)
            {
                _u *= 1.0f / _length;
            }
            else
            {
                _u = Vector2.Zero;
                _mass = 0.0f;
                _impulse = 0.0f;
                return;
            }

            // Compute effective mass.
            float crA = MathUtils.Cross(_rA, _u);
            float crB = MathUtils.Cross(_rB, _u);
            float invMass = _invMassA + _invIA * crA * crA + _invMassB + _invIB * crB * crB;

            _mass = invMass != 0.0f ? 1.0f / invMass : 0.0f;

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

                Vector2 P = _impulse * _u;
                vA -= _invMassA * P;
                wA -= _invIA * MathUtils.Cross(_rA, P);
                vB += _invMassB * P;
                wB += _invIB * MathUtils.Cross(_rB, P);
            }
            else
            {
                _impulse = 0.0f;
            }

            data.velocities[_indexA].v = vA;
            data.velocities[_indexA].w = wA;
            data.velocities[_indexB].v = vB;
            data.velocities[_indexB].w = wB;
        }
예제 #7
0
        internal override bool SolvePositionConstraints(ref SolverData data)
        {
            if (Frequency > 0.0f)
            {
                // There is no position correction for soft distance constraints.
                return true;
            }

            Body b1 = BodyA;
            Body b2 = BodyB;

            Transform xf1, xf2;
            b1.GetTransform(out xf1);
            b2.GetTransform(out xf2);

            Vector2 r1 = MathUtils.Mul(ref xf1.q, LocalAnchorA - b1.LocalCenter);
            Vector2 r2 = MathUtils.Mul(ref xf2.q, LocalAnchorB - b2.LocalCenter);

            Vector2 d = b2.Sweep.C + r2 - b1.Sweep.C - r1;

            float length = d.Length();

            if (length < MaxLength && length > MinLength)
            {
                return true;
            }

            if (length == 0.0f)
                return true;

            d /= length;
            float C = length - MaxLength;
            C = MathUtils.Clamp(C, -Settings.MaxLinearCorrection, Settings.MaxLinearCorrection);

            float impulse = -_mass * C;
            _u = d;
            Vector2 P = impulse * _u;

            b1.Sweep.C -= b1.InvMass * P;
            b1.Sweep.A -= b1.InvI * MathUtils.Cross(r1, P);
            b2.Sweep.C += b2.InvMass * P;
            b2.Sweep.A += b2.InvI * MathUtils.Cross(r2, P);

            b1.SynchronizeTransform();
            b2.SynchronizeTransform();

            return Math.Abs(C) < Settings.LinearSlop;
        }
예제 #8
0
        public override bool solvePositionConstraints(SolverData data)
        {
            Vec2 cA = data.positions[m_indexA].c;
            float aA = data.positions[m_indexA].a;
            Vec2 cB = data.positions[m_indexB].c;
            float aB = data.positions[m_indexB].a;

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

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

            Vec2 ay = pool.popVec2();
            Rot.mulToOut(qA, m_localYAxisA, ref ay);

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

            float C = Vec2.dot(d, ay);

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

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

            Vec2 P = pool.popVec2();
            P.x = impulse*ay.x;
            P.y = impulse*ay.y;
            float LA = impulse*sAy;
            float 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;
        }
예제 #9
0
        internal override void SolveVelocityConstraints(ref SolverData data)
        {
            Vector2 vA = data.velocities[_indexA].v;
            float wA = data.velocities[_indexA].w;
            Vector2 vB = data.velocities[_indexB].v;
            float wB = data.velocities[_indexB].w;
            Vector2 vC = data.velocities[_indexC].v;
            float wC = data.velocities[_indexC].w;
            Vector2 vD = data.velocities[_indexD].v;
            float wD = data.velocities[_indexD].w;

            float Cdot = Vector2.Dot(_JvAC, vA - vC) + Vector2.Dot(_JvBD, vB - vD);
            Cdot += (_JwA * wA - _JwC * wC) + (_JwB * wB - _JwD * wD);

            float impulse = -_mass * Cdot;
            _impulse += impulse;

            vA += (_mA * impulse) * _JvAC;
            wA += _iA * impulse * _JwA;
            vB += (_mB * impulse) * _JvBD;
            wB += _iB * impulse * _JwB;
            vC -= (_mC * impulse) * _JvAC;
            wC -= _iC * impulse * _JwC;
            vD -= (_mD * impulse) * _JvBD;
            wD -= _iD * impulse * _JwD;

            data.velocities[_indexA].v = vA;
            data.velocities[_indexA].w = wA;
            data.velocities[_indexB].v = vB;
            data.velocities[_indexB].w = wB;
            data.velocities[_indexC].v = vC;
            data.velocities[_indexC].w = wC;
            data.velocities[_indexD].v = vD;
            data.velocities[_indexD].w = wD;
        }
예제 #10
0
        internal override void InitVelocityConstraints(ref SolverData data)
        {
            _indexA       = BodyA.IslandIndex;
            _indexB       = BodyB.IslandIndex;
            _localCenterA = BodyA._sweep.LocalCenter;
            _localCenterB = BodyB._sweep.LocalCenter;
            _invMassA     = BodyA._invMass;
            _invMassB     = BodyB._invMass;
            _invIA        = BodyA._invI;
            _invIB        = BodyB._invI;

            Vector2 cA = data.positions[_indexA].c;
            float   aA = data.positions[_indexA].a;
            Vector2 vA = data.velocities[_indexA].v;
            float   wA = data.velocities[_indexA].w;

            Vector2 cB = data.positions[_indexB].c;
            float   aB = data.positions[_indexB].a;
            Vector2 vB = data.velocities[_indexB].v;
            float   wB = data.velocities[_indexB].w;

            Complex qA = Complex.FromAngle(aA);
            Complex qB = Complex.FromAngle(aB);

            _rA = Complex.Multiply(LocalAnchorA - _localCenterA, ref qA);
            _rB = Complex.Multiply(LocalAnchorB - _localCenterB, ref qB);

            // Get the pulley axes.
            _uA = cA + _rA - WorldAnchorA;
            _uB = cB + _rB - WorldAnchorB;

            float lengthA = _uA.Length();
            float lengthB = _uB.Length();

            if (lengthA > 10.0f * Settings.LinearSlop)
            {
                _uA *= 1.0f / lengthA;
            }
            else
            {
                _uA = Vector2.Zero;
            }

            if (lengthB > 10.0f * Settings.LinearSlop)
            {
                _uB *= 1.0f / lengthB;
            }
            else
            {
                _uB = Vector2.Zero;
            }

            // Compute effective mass.
            float ruA = MathUtils.Cross(ref _rA, ref _uA);
            float ruB = MathUtils.Cross(ref _rB, ref _uB);

            float mA = _invMassA + _invIA * ruA * ruA;
            float mB = _invMassB + _invIB * ruB * ruB;

            _mass = mA + Ratio * Ratio * mB;

            if (_mass > 0.0f)
            {
                _mass = 1.0f / _mass;
            }

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

                // Warm starting.
                Vector2 PA = -(_impulse) * _uA;
                Vector2 PB = (-Ratio * _impulse) * _uB;

                vA += _invMassA * PA;
                wA += _invIA * MathUtils.Cross(ref _rA, ref PA);
                vB += _invMassB * PB;
                wB += _invIB * MathUtils.Cross(ref _rB, ref PB);
            }
            else
            {
                _impulse = 0.0f;
            }

            data.velocities[_indexA].v = vA;
            data.velocities[_indexA].w = wA;
            data.velocities[_indexB].v = vB;
            data.velocities[_indexB].w = wB;
        }
예제 #11
0
        internal override bool SolvePositionConstraints(ref SolverData data)
        {
            Vector2 cA = data.positions[_indexA].c;
            float   aA = data.positions[_indexA].a;
            Vector2 cB = data.positions[_indexB].c;
            float   aB = data.positions[_indexB].a;

            Complex qA = Complex.FromAngle(aA);
            Complex qB = Complex.FromAngle(aB);

            Vector2 rA = Complex.Multiply(LocalAnchorA - _localCenterA, ref qA);
            Vector2 rB = Complex.Multiply(LocalAnchorB - _localCenterB, ref qB);

            // Get the pulley axes.
            Vector2 uA = cA + rA - WorldAnchorA;
            Vector2 uB = cB + rB - WorldAnchorB;

            float lengthA = uA.Length();
            float lengthB = uB.Length();

            if (lengthA > 10.0f * Settings.LinearSlop)
            {
                uA *= 1.0f / lengthA;
            }
            else
            {
                uA = Vector2.Zero;
            }

            if (lengthB > 10.0f * Settings.LinearSlop)
            {
                uB *= 1.0f / lengthB;
            }
            else
            {
                uB = Vector2.Zero;
            }

            // Compute effective mass.
            float ruA = MathUtils.Cross(ref rA, ref uA);
            float ruB = MathUtils.Cross(ref rB, ref uB);

            float mA = _invMassA + _invIA * ruA * ruA;
            float mB = _invMassB + _invIB * ruB * ruB;

            float mass = mA + Ratio * Ratio * mB;

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

            float C           = Constant - lengthA - Ratio * lengthB;
            float linearError = Math.Abs(C);

            float impulse = -mass * C;

            Vector2 PA = -impulse * uA;
            Vector2 PB = -Ratio * impulse * uB;

            cA += _invMassA * PA;
            aA += _invIA * MathUtils.Cross(ref rA, ref PA);
            cB += _invMassB * PB;
            aB += _invIB * MathUtils.Cross(ref rB, ref PB);

            data.positions[_indexA].c = cA;
            data.positions[_indexA].a = aA;
            data.positions[_indexB].c = cB;
            data.positions[_indexB].a = aB;

            return(linearError < Settings.LinearSlop);
        }
예제 #12
0
        internal override void InitVelocityConstraints(ref SolverData data)
        {
            _indexA       = BodyA.IslandIndex;
            _indexB       = BodyB.IslandIndex;
            _localCenterA = BodyA._sweep.LocalCenter;
            _localCenterB = BodyB._sweep.LocalCenter;
            _invMassA     = BodyA._invMass;
            _invMassB     = BodyB._invMass;
            _invIA        = BodyA._invI;
            _invIB        = BodyB._invI;

            float mA = _invMassA, mB = _invMassB;
            float iA = _invIA, iB = _invIB;

            Vector2 cA = data.positions[_indexA].c;
            float   aA = data.positions[_indexA].a;
            Vector2 vA = data.velocities[_indexA].v;
            float   wA = data.velocities[_indexA].w;

            Vector2 cB = data.positions[_indexB].c;
            float   aB = data.positions[_indexB].a;
            Vector2 vB = data.velocities[_indexB].v;
            float   wB = data.velocities[_indexB].w;

            Complex qA = Complex.FromAngle(aA);
            Complex qB = Complex.FromAngle(aB);

            // Compute the effective masses.
            Vector2 rA = Complex.Multiply(LocalAnchorA - _localCenterA, ref qA);
            Vector2 rB = Complex.Multiply(LocalAnchorB - _localCenterB, ref qB);
            Vector2 d1 = cB + rB - cA - rA;

            // Point to line constraint
            {
                _ay  = Complex.Multiply(ref _localYAxis, ref qA);
                _sAy = MathUtils.Cross(d1 + rA, _ay);
                _sBy = MathUtils.Cross(ref rB, ref _ay);

                _mass = mA + mB + iA * _sAy * _sAy + iB * _sBy * _sBy;

                if (_mass > 0.0f)
                {
                    _mass = 1.0f / _mass;
                }
            }

            // Spring constraint
            _springMass = 0.0f;
            _bias       = 0.0f;
            _gamma      = 0.0f;
            if (Frequency > 0.0f)
            {
                _ax  = Complex.Multiply(ref _localXAxis, ref qA);
                _sAx = MathUtils.Cross(d1 + rA, _ax);
                _sBx = MathUtils.Cross(ref rB, ref _ax);

                float invMass = mA + mB + iA * _sAx * _sAx + iB * _sBx * _sBx;

                if (invMass > 0.0f)
                {
                    _springMass = 1.0f / invMass;

                    float C = Vector2.Dot(d1, _ax);

                    // Frequency
                    float omega = 2.0f * MathHelper.Pi * Frequency;

                    // Damping coefficient
                    float d = 2.0f * _springMass * DampingRatio * omega;

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

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

                    _bias = C * h * k * _gamma;

                    _springMass = invMass + _gamma;
                    if (_springMass > 0.0f)
                    {
                        _springMass = 1.0f / _springMass;
                    }
                }
            }
            else
            {
                _springImpulse = 0.0f;
            }

            // Rotational motor
            if (_enableMotor)
            {
                _motorMass = iA + iB;
                if (_motorMass > 0.0f)
                {
                    _motorMass = 1.0f / _motorMass;
                }
            }
            else
            {
                _motorMass    = 0.0f;
                _motorImpulse = 0.0f;
            }

            if (data.step.warmStarting)
            {
                // Account for variable time step.
                _impulse       *= data.step.dtRatio;
                _springImpulse *= data.step.dtRatio;
                _motorImpulse  *= data.step.dtRatio;

                Vector2 P  = _impulse * _ay + _springImpulse * _ax;
                float   LA = _impulse * _sAy + _springImpulse * _sAx + _motorImpulse;
                float   LB = _impulse * _sBy + _springImpulse * _sBx + _motorImpulse;

                vA -= _invMassA * P;
                wA -= _invIA * LA;

                vB += _invMassB * P;
                wB += _invIB * LB;
            }
            else
            {
                _impulse       = 0.0f;
                _springImpulse = 0.0f;
                _motorImpulse  = 0.0f;
            }

            data.velocities[_indexA].v = vA;
            data.velocities[_indexA].w = wA;
            data.velocities[_indexB].v = vB;
            data.velocities[_indexB].w = wB;
        }
예제 #13
0
        internal override void InitVelocityConstraints(ref SolverData data)
        {
            _indexA       = BodyA.IslandIndex;
            _indexB       = BodyB.IslandIndex;
            _localCenterA = BodyA._sweep.LocalCenter;
            _localCenterB = BodyB._sweep.LocalCenter;
            _invMassA     = BodyA._invMass;
            _invMassB     = BodyB._invMass;
            _invIA        = BodyA._invI;
            _invIB        = BodyB._invI;

            Vector2 cA = data.Positions[_indexA].C;
            float   aA = data.Positions[_indexA].A;
            Vector2 vA = data.Velocities[_indexA].V;
            float   wA = data.Velocities[_indexA].W;

            Vector2 cB = data.Positions[_indexB].C;
            float   aB = data.Positions[_indexB].A;
            Vector2 vB = data.Velocities[_indexB].V;
            float   wB = data.Velocities[_indexB].W;

            Rot qA = new Rot(aA), qB = new Rot(aB);

            _rA = MathUtils.Mul(qA, LocalAnchorA - _localCenterA);
            _rB = MathUtils.Mul(qB, LocalAnchorB - _localCenterB);

            // Get the pulley axes.
            _uA = cA + _rA - WorldAnchorA;
            _uB = cB + _rB - WorldAnchorB;

            float lengthA = _uA.Length();
            float lengthB = _uB.Length();

            if (lengthA > 10.0f * Settings.LinearSlop)
            {
                _uA *= 1.0f / lengthA;
            }
            else
            {
                _uA = Vector2.Zero;
            }

            if (lengthB > 10.0f * Settings.LinearSlop)
            {
                _uB *= 1.0f / lengthB;
            }
            else
            {
                _uB = Vector2.Zero;
            }

            // Compute effective mass.
            float ruA = MathUtils.Cross(_rA, _uA);
            float ruB = MathUtils.Cross(_rB, _uB);

            float mA = _invMassA + _invIA * ruA * ruA;
            float mB = _invMassB + _invIB * ruB * ruB;

            _mass = mA + Ratio * Ratio * mB;

            if (_mass > 0.0f)
            {
                _mass = 1.0f / _mass;
            }

            if (Settings.EnableWarmstarting)
            {
                // Scale impulses to support variable time steps.
                _impulse *= data.Step.DeltaTimeRatio;

                // Warm starting.
                Vector2 PA = -(_impulse) * _uA;
                Vector2 PB = (-Ratio * _impulse) * _uB;

                vA += _invMassA * PA;
                wA += _invIA * MathUtils.Cross(_rA, PA);
                vB += _invMassB * PB;
                wB += _invIB * MathUtils.Cross(_rB, PB);
            }
            else
            {
                _impulse = 0.0f;
            }

            data.Velocities[_indexA].V = vA;
            data.Velocities[_indexA].W = wA;
            data.Velocities[_indexB].V = vB;
            data.Velocities[_indexB].W = wB;
        }
예제 #14
0
 public override bool SolvePositionConstraints(SolverData data)
 {
     return(true);
 }
예제 #15
0
        public override void SolveVelocityConstraints(SolverData data)
        {
            Vec2  vA = data.Velocities[IndexA].V;
            float wA = data.Velocities[IndexA].W;
            Vec2  vB = data.Velocities[IndexB].V;
            float wB = data.Velocities[IndexB].W;

            float mA = InvMassA, mB = InvMassB;
            float iA = InvIA, iB = InvIB;

            float h = data.Step.Dt;

            // Solve angular friction
            {
                float Cdot    = wB - wA;
                float impulse = (-AngularMass) * Cdot;

                float oldImpulse = m_angularImpulse;
                float maxImpulse = h * m_maxTorque;
                m_angularImpulse = MathUtils.Clamp(m_angularImpulse + impulse, -maxImpulse, maxImpulse);
                impulse          = m_angularImpulse - oldImpulse;

                wA -= iA * impulse;
                wB += iB * impulse;
            }

            // Solve linear friction
            {
                Vec2 Cdot = Pool.PopVec2();
                Vec2 temp = Pool.PopVec2();

                Vec2.CrossToOutUnsafe(wA, RA, temp);
                Vec2.CrossToOutUnsafe(wB, RB, Cdot);
                Cdot.AddLocal(vB).SubLocal(vA).SubLocal(temp);

                Vec2 impulse = Pool.PopVec2();
                Mat22.MulToOutUnsafe(LinearMass, Cdot, impulse);
                impulse.NegateLocal();


                Vec2 oldImpulse = Pool.PopVec2();
                oldImpulse.Set(m_linearImpulse);
                m_linearImpulse.AddLocal(impulse);

                float maxImpulse = h * m_maxForce;

                if (m_linearImpulse.LengthSquared() > maxImpulse * maxImpulse)
                {
                    m_linearImpulse.Normalize();
                    m_linearImpulse.MulLocal(maxImpulse);
                }

                impulse.Set(m_linearImpulse).SubLocal(oldImpulse);

                temp.Set(impulse).MulLocal(mA);
                vA.SubLocal(temp);
                wA -= iA * Vec2.Cross(RA, impulse);

                temp.Set(impulse).MulLocal(mB);
                vB.AddLocal(temp);
                wB += iB * Vec2.Cross(RB, impulse);
            }

            data.Velocities[IndexA].V.Set(vA);
            if (data.Velocities[IndexA].W != wA)
            {
                Debug.Assert(data.Velocities[IndexA].W != wA);
            }
            data.Velocities[IndexA].W = wA;
            data.Velocities[IndexB].V.Set(vB);
            data.Velocities[IndexB].W = wB;

            Pool.PushVec2(4);
        }
예제 #16
0
        /// <seealso cref="Joint.initVelocityConstraints(TimeStep)"></seealso>
        public override void InitVelocityConstraints(SolverData data)
        {
            IndexA = BodyA.IslandIndex;
            IndexB = BodyB.IslandIndex;
            LocalCenterA.Set(BodyA.Sweep.LocalCenter);
            LocalCenterB.Set(BodyB.Sweep.LocalCenter);
            InvMassA = BodyA.InvMass;
            InvMassB = BodyB.InvMass;
            InvIA    = BodyA.InvI;
            InvIB    = BodyB.InvI;

            float aA = data.Positions[IndexA].A;
            Vec2  vA = data.Velocities[IndexA].V;
            float wA = data.Velocities[IndexA].W;

            float aB = data.Positions[IndexB].A;
            Vec2  vB = data.Velocities[IndexB].V;
            float wB = data.Velocities[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(LocalCenterA), RA);
            Rot.MulToOutUnsafe(qB, temp.Set(m_localAnchorB).SubLocal(LocalCenterB), 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]

            float mA = InvMassA, mB = InvMassB;
            float iA = InvIA, iB = 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.InvertToOut(LinearMass);

            AngularMass = iA + iB;
            if (AngularMass > 0.0f)
            {
                AngularMass = 1.0f / 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(RA, P) + m_angularImpulse);

                temp.Set(P).MulLocal(mB);
                vB.AddLocal(temp);
                wB += iB * (Vec2.Cross(RB, P) + m_angularImpulse);

                Pool.PushVec2(1);
            }
            else
            {
                m_linearImpulse.SetZero();
                m_angularImpulse = 0.0f;
            }
            data.Velocities[IndexA].V.Set(vA);
            if (data.Velocities[IndexA].W != wA)
            {
                Debug.Assert(data.Velocities[IndexA].W != wA);
            }
            data.Velocities[IndexA].W = wA;
            data.Velocities[IndexB].V.Set(vB);
            data.Velocities[IndexB].W = wB;

            Pool.PushRot(2);
            Pool.PushVec2(1);
            Pool.PushMat22(1);
        }
예제 #17
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;
            float aA = data.positions[m_indexA].a;
            Vec2 vA = data.velocities[m_indexA].v;
            float wA = data.velocities[m_indexA].w;

            // Vec2 cB = data.positions[m_indexB].c;
            float aB = data.positions[m_indexB].a;
            Vec2 vB = data.velocities[m_indexB].v;
            float 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.
            temp.set(m_localAnchorA);
            temp.subLocal(m_localCenterA);
            Rot.mulToOutUnsafe(qA, temp, ref m_rA);
            temp.set(m_localAnchorB);
            temp.subLocal(m_localCenterB);
            Rot.mulToOutUnsafe(qB, temp, ref 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]

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

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

            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.0f)
            {
                m_motorMass = 1.0f/m_motorMass;
            }

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

            if (m_enableLimit && fixedRotation == false)
            {
                float jointAngle = aB - aA - m_referenceAngle;
                if (MathUtils.abs(m_upperAngle - m_lowerAngle) < 2.0f*Settings.angularSlop)
                {
                    m_limitState = LimitState.EQUAL;
                }
                else if (jointAngle <= m_lowerAngle)
                {
                    if (m_limitState != LimitState.AT_LOWER)
                    {
                        m_impulse.z = 0.0f;
                    }
                    m_limitState = LimitState.AT_LOWER;
                }
                else if (jointAngle >= m_upperAngle)
                {
                    if (m_limitState != LimitState.AT_UPPER)
                    {
                        m_impulse.z = 0.0f;
                    }
                    m_limitState = LimitState.AT_UPPER;
                }
                else
                {
                    m_limitState = LimitState.INACTIVE;
                    m_impulse.z = 0.0f;
                }
            }
            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.0f;
            }
            // 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);
        }
예제 #18
0
        internal override void InitVelocityConstraints(ref SolverData data)
        {
            m_indexA       = BodyA.IslandIndex;
            m_indexB       = BodyB.IslandIndex;
            m_localCenterA = BodyA.Sweep.LocalCenter;
            m_localCenterB = BodyB.Sweep.LocalCenter;
            m_invMassA     = BodyA.InvMass;
            m_invMassB     = BodyB.InvMass;
            m_invIA        = BodyA.InvI;
            m_invIB        = BodyB.InvI;

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

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

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

            Rot qA = new Rot(aA), qB = new Rot(aB);

            // Compute the effective masses.
            Vector2 rA = MathUtils.Mul(qA, LocalAnchorA - m_localCenterA);
            Vector2 rB = MathUtils.Mul(qB, LocalAnchorB - m_localCenterB);
            Vector2 d1 = cB + rB - cA - rA;

            // Point to line constraint
            {
                m_ay  = MathUtils.Mul(qA, m_localYAxisA);
                m_sAy = MathUtils.Cross(d1 + rA, m_ay);
                m_sBy = MathUtils.Cross(rB, m_ay);

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

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

            // Spring constraint
            m_springMass = 0.0f;
            m_bias       = 0.0f;
            m_gamma      = 0.0f;
            if (SpringFrequencyHz > 0.0f)
            {
                m_ax  = MathUtils.Mul(qA, m_localXAxisA);
                m_sAx = MathUtils.Cross(d1 + rA, m_ax);
                m_sBx = MathUtils.Cross(rB, m_ax);

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

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

                    float C = Vector2.Dot(d1, m_ax);

                    // Frequency
                    float omega = 2.0f * Settings.Pi * SpringFrequencyHz;

                    // Damping coefficient
                    float d = 2.0f * m_springMass * SpringDampingRatio * omega;

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

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

                    m_bias = C * h * k * m_gamma;

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

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

            if (Settings.EnableWarmstarting)
            {
                // Account for variable time step.
                m_impulse       *= data.step.dtRatio;
                m_springImpulse *= data.step.dtRatio;
                m_motorImpulse  *= data.step.dtRatio;

                Vector2 P  = m_impulse * m_ay + m_springImpulse * m_ax;
                float   LA = m_impulse * m_sAy + m_springImpulse * m_sAx + m_motorImpulse;
                float   LB = m_impulse * m_sBy + m_springImpulse * m_sBx + m_motorImpulse;

                vA -= m_invMassA * P;
                wA -= m_invIA * LA;

                vB += m_invMassB * P;
                wB += m_invIB * LB;
            }
            else
            {
                m_impulse       = 0.0f;
                m_springImpulse = 0.0f;
                m_motorImpulse  = 0.0f;
            }

            data.velocities[m_indexA].v = vA;
            data.velocities[m_indexA].w = wA;
            data.velocities[m_indexB].v = vB;
            data.velocities[m_indexB].w = wB;
        }
예제 #19
0
        public override void solveVelocityConstraints(SolverData data)
        {
            Vec2 vA = data.velocities[m_indexA].v;
            float wA = data.velocities[m_indexA].w;
            Vec2 vB = data.velocities[m_indexB].v;
            float wB = data.velocities[m_indexB].w;

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

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

            // Solve motor constraint.
            if (m_enableMotor && m_limitState != LimitState.EQUAL && fixedRotation == false)
            {
                float Cdot = wB - wA - m_motorSpeed;
                float impulse = -m_motorMass*Cdot;
                float oldImpulse = m_motorImpulse;
                float maxImpulse = data.step.dt*m_maxMotorTorque;
                m_motorImpulse = MathUtils.clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse);
                impulse = m_motorImpulse - oldImpulse;

                wA -= iA*impulse;
                wB += iB*impulse;
            }
            Vec2 temp = pool.popVec2();

            // Solve limit constraint.
            if (m_enableLimit && m_limitState != LimitState.INACTIVE && fixedRotation == false)
            {

                Vec2 Cdot1 = pool.popVec2();
                Vec3 Cdot = pool.popVec3();

                // Solve point-to-point constraint
                Vec2.crossToOutUnsafe(wA, m_rA, ref temp);
                Vec2.crossToOutUnsafe(wB, m_rB, ref Cdot1);

                Cdot1.addLocal(vB);
                Cdot1.subLocal(vA);
                Cdot1.subLocal(temp);

                float Cdot2 = wB - wA;
                Cdot.set(Cdot1.x, Cdot1.y, Cdot2);

                Vec3 impulse = pool.popVec3();
                m_mass.solve33ToOut(Cdot, ref impulse);
                impulse.negateLocal();

                if (m_limitState == LimitState.EQUAL)
                {
                    m_impulse.addLocal(impulse);
                }
                else if (m_limitState == LimitState.AT_LOWER)
                {
                    float newImpulse = m_impulse.z + impulse.z;
                    if (newImpulse < 0.0f)
                    {
                        Vec2 rhs = pool.popVec2();
                        rhs.set(m_mass.ez.x, m_mass.ez.y);
                        rhs.mulLocal(m_impulse.z);
                        rhs.subLocal(Cdot1);
                        m_mass.solve22ToOut(rhs, ref temp);
                        impulse.x = temp.x;
                        impulse.y = temp.y;
                        impulse.z = -m_impulse.z;
                        m_impulse.x += temp.x;
                        m_impulse.y += temp.y;
                        m_impulse.z = 0.0f;
                        pool.pushVec2(1);
                    }
                    else
                    {
                        m_impulse.addLocal(impulse);
                    }
                }
                else if (m_limitState == LimitState.AT_UPPER)
                {
                    float newImpulse = m_impulse.z + impulse.z;
                    if (newImpulse > 0.0f)
                    {
                        Vec2 rhs = pool.popVec2();
                        rhs.set(m_mass.ez.x, m_mass.ez.y);
                        rhs.mulLocal(m_impulse.z);
                        rhs.subLocal(Cdot1);
                        m_mass.solve22ToOut(rhs, ref temp);
                        impulse.x = temp.x;
                        impulse.y = temp.y;
                        impulse.z = -m_impulse.z;
                        m_impulse.x += temp.x;
                        m_impulse.y += temp.y;
                        m_impulse.z = 0.0f;
                        pool.pushVec2(1);
                    }
                    else
                    {
                        m_impulse.addLocal(impulse);
                    }
                }
                Vec2 P = pool.popVec2();

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

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

                vB.x += mB*P.x;
                vB.y += mB*P.y;
                wB += iB*(Vec2.cross(m_rB, P) + impulse.z);

                pool.pushVec2(2);
                pool.pushVec3(2);
            }
            else
            {

                // Solve point-to-point constraint
                Vec2 Cdot = pool.popVec2();
                Vec2 impulse = pool.popVec2();

                Vec2.crossToOutUnsafe(wA, m_rA, ref temp);
                Vec2.crossToOutUnsafe(wB, m_rB, ref Cdot);

                Cdot.addLocal(vB);
                Cdot.subLocal(vA);
                 Cdot.subLocal(temp);
                Cdot.negateLocal();

                m_mass.solve22ToOut(Cdot, ref impulse); // just leave negated

                m_impulse.x += impulse.x;
                m_impulse.y += impulse.y;

                vA.x -= mA*impulse.x;
                vA.y -= mA*impulse.y;
                wA -= iA*Vec2.cross(m_rA, impulse);

                vB.x += mB*impulse.x;
                vB.y += mB*impulse.y;
                wB += iB*Vec2.cross(m_rB, impulse);

                pool.pushVec2(2);
            }

            // 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);
        }
예제 #20
0
        internal override void SolveVelocityConstraints(ref SolverData data)
        {
            float mA = m_invMassA, mB = m_invMassB;
            float iA = m_invIA, iB = m_invIB;

            Vector2 vA = data.velocities[m_indexA].v;
            float   wA = data.velocities[m_indexA].w;
            Vector2 vB = data.velocities[m_indexB].v;
            float   wB = data.velocities[m_indexB].w;

            // Solve spring constraint
            {
                float Cdot    = Vector2.Dot(m_ax, vB - vA) + m_sBx * wB - m_sAx * wA;
                float impulse = -m_springMass * (Cdot + m_bias + m_gamma * m_springImpulse);
                m_springImpulse += impulse;

                Vector2 P  = impulse * m_ax;
                float   LA = impulse * m_sAx;
                float   LB = impulse * m_sBx;

                vA -= mA * P;
                wA -= iA * LA;

                vB += mB * P;
                wB += iB * LB;
            }

            // Solve rotational motor constraint
            {
                float Cdot    = wB - wA - m_motorSpeed;
                float impulse = -m_motorMass * Cdot;

                float oldImpulse = m_motorImpulse;
                float maxImpulse = data.step.dt * m_maxMotorTorque;
                m_motorImpulse = MathUtils.Clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse);
                impulse        = m_motorImpulse - oldImpulse;

                wA -= iA * impulse;
                wB += iB * impulse;
            }

            // Solve point to line constraint
            {
                float Cdot    = Vector2.Dot(m_ay, vB - vA) + m_sBy * wB - m_sAy * wA;
                float impulse = -m_mass * Cdot;
                m_impulse += impulse;

                Vector2 P  = impulse * m_ay;
                float   LA = impulse * m_sAy;
                float   LB = impulse * m_sBy;

                vA -= mA * P;
                wA -= iA * LA;

                vB += mB * P;
                wB += iB * LB;
            }

            data.velocities[m_indexA].v = vA;
            data.velocities[m_indexA].w = wA;
            data.velocities[m_indexB].v = vB;
            data.velocities[m_indexB].w = wB;
        }
예제 #21
0
        internal override void InitVelocityConstraints(ref SolverData data)
        {
            _indexA = _bodyA.IslandIndex;
            _indexB = _bodyB.IslandIndex;
            _indexC = _bodyC.IslandIndex;
            _indexD = _bodyD.IslandIndex;
            _lcA = _bodyA.Sweep.LocalCenter;
            _lcB = _bodyB.Sweep.LocalCenter;
            _lcC = _bodyC.Sweep.LocalCenter;
            _lcD = _bodyD.Sweep.LocalCenter;
            _mA = _bodyA.InvMass;
            _mB = _bodyB.InvMass;
            _mC = _bodyC.InvMass;
            _mD = _bodyD.InvMass;
            _iA = _bodyA.InvI;
            _iB = _bodyB.InvI;
            _iC = _bodyC.InvI;
            _iD = _bodyD.InvI;

            float aA = data.positions[_indexA].a;
            Vector2 vA = data.velocities[_indexA].v;
            float wA = data.velocities[_indexA].w;

            float aB = data.positions[_indexB].a;
            Vector2 vB = data.velocities[_indexB].v;
            float wB = data.velocities[_indexB].w;

            float aC = data.positions[_indexC].a;
            Vector2 vC = data.velocities[_indexC].v;
            float wC = data.velocities[_indexC].w;

            float aD = data.positions[_indexD].a;
            Vector2 vD = data.velocities[_indexD].v;
            float wD = data.velocities[_indexD].w;

            Rot qA = new Rot(aA), qB = new Rot(aB), qC = new Rot(aC), qD = new Rot(aD);

            _mass = 0.0f;

            if (_typeA == JointType.Revolute)
            {
                _JvAC = Vector2.Zero;
                _JwA = 1.0f;
                _JwC = 1.0f;
                _mass += _iA + _iC;
            }
            else
            {
                Vector2 u = MathUtils.Mul(qC, _localAxisC);
                Vector2 rC = MathUtils.Mul(qC, _localAnchorC - _lcC);
                Vector2 rA = MathUtils.Mul(qA, _localAnchorA - _lcA);
                _JvAC = u;
                _JwC = MathUtils.Cross(rC, u);
                _JwA = MathUtils.Cross(rA, u);
                _mass += _mC + _mA + _iC * _JwC * _JwC + _iA * _JwA * _JwA;
            }

            if (_typeB == JointType.Revolute)
            {
                _JvBD = Vector2.Zero;
                _JwB = _ratio;
                _JwD = _ratio;
                _mass += _ratio * _ratio * (_iB + _iD);
            }
            else
            {
                Vector2 u = MathUtils.Mul(qD, _localAxisD);
                Vector2 rD = MathUtils.Mul(qD, _localAnchorD - _lcD);
                Vector2 rB = MathUtils.Mul(qB, _localAnchorB - _lcB);
                _JvBD = _ratio * u;
                _JwD = _ratio * MathUtils.Cross(rD, u);
                _JwB = _ratio * MathUtils.Cross(rB, u);
                _mass += _ratio * _ratio * (_mD + _mB) + _iD * _JwD * _JwD + _iB * _JwB * _JwB;
            }

            // Compute effective mass.
            _mass = _mass > 0.0f ? 1.0f / _mass : 0.0f;

            if (Settings.EnableWarmstarting)
            {
                vA += (_mA * _impulse) * _JvAC;
                wA += _iA * _impulse * _JwA;
                vB += (_mB * _impulse) * _JvBD;
                wB += _iB * _impulse * _JwB;
                vC -= (_mC * _impulse) * _JvAC;
                wC -= _iC * _impulse * _JwC;
                vD -= (_mD * _impulse) * _JvBD;
                wD -= _iD * _impulse * _JwD;
            }
            else
            {
                _impulse = 0.0f;
            }

            data.velocities[_indexA].v = vA;
            data.velocities[_indexA].w = wA;
            data.velocities[_indexB].v = vB;
            data.velocities[_indexB].w = wB;
            data.velocities[_indexC].v = vC;
            data.velocities[_indexC].w = wC;
            data.velocities[_indexD].v = vD;
            data.velocities[_indexD].w = wD;
        }
예제 #22
0
        internal override void InitVelocityConstraints(ref SolverData data)
        {
            _indexA = _bodyA.IslandIndex;
            _indexB = _bodyB.IslandIndex;
            _indexC = _bodyC.IslandIndex;
            _indexD = _bodyD.IslandIndex;
            _lcA    = _bodyA._sweep.LocalCenter;
            _lcB    = _bodyB._sweep.LocalCenter;
            _lcC    = _bodyC._sweep.LocalCenter;
            _lcD    = _bodyD._sweep.LocalCenter;
            _mA     = _bodyA._invMass;
            _mB     = _bodyB._invMass;
            _mC     = _bodyC._invMass;
            _mD     = _bodyD._invMass;
            _iA     = _bodyA._invI;
            _iB     = _bodyB._invI;
            _iC     = _bodyC._invI;
            _iD     = _bodyD._invI;

            float   aA = data.positions[_indexA].a;
            Vector2 vA = data.velocities[_indexA].v;
            float   wA = data.velocities[_indexA].w;

            float   aB = data.positions[_indexB].a;
            Vector2 vB = data.velocities[_indexB].v;
            float   wB = data.velocities[_indexB].w;

            float   aC = data.positions[_indexC].a;
            Vector2 vC = data.velocities[_indexC].v;
            float   wC = data.velocities[_indexC].w;

            float   aD = data.positions[_indexD].a;
            Vector2 vD = data.velocities[_indexD].v;
            float   wD = data.velocities[_indexD].w;

            Rot qA = new Rot(aA), qB = new Rot(aB), qC = new Rot(aC), qD = new Rot(aD);

            _mass = 0.0f;

            if (_typeA == JointType.Revolute)
            {
                _JvAC  = Vector2.Zero;
                _JwA   = 1.0f;
                _JwC   = 1.0f;
                _mass += _iA + _iC;
            }
            else
            {
                Vector2 u  = MathUtils.Mul(qC, _localAxisC);
                Vector2 rC = MathUtils.Mul(qC, _localAnchorC - _lcC);
                Vector2 rA = MathUtils.Mul(qA, _localAnchorA - _lcA);
                _JvAC  = u;
                _JwC   = MathUtils.Cross(rC, u);
                _JwA   = MathUtils.Cross(rA, u);
                _mass += _mC + _mA + _iC * _JwC * _JwC + _iA * _JwA * _JwA;
            }

            if (_typeB == JointType.Revolute)
            {
                _JvBD  = Vector2.Zero;
                _JwB   = _ratio;
                _JwD   = _ratio;
                _mass += _ratio * _ratio * (_iB + _iD);
            }
            else
            {
                Vector2 u  = MathUtils.Mul(qD, _localAxisD);
                Vector2 rD = MathUtils.Mul(qD, _localAnchorD - _lcD);
                Vector2 rB = MathUtils.Mul(qB, _localAnchorB - _lcB);
                _JvBD  = _ratio * u;
                _JwD   = _ratio * MathUtils.Cross(rD, u);
                _JwB   = _ratio * MathUtils.Cross(rB, u);
                _mass += _ratio * _ratio * (_mD + _mB) + _iD * _JwD * _JwD + _iB * _JwB * _JwB;
            }

            // Compute effective mass.
            _mass = _mass > 0.0f ? 1.0f / _mass : 0.0f;

            if (Settings.EnableWarmstarting)
            {
                vA += (_mA * _impulse) * _JvAC;
                wA += _iA * _impulse * _JwA;
                vB += (_mB * _impulse) * _JvBD;
                wB += _iB * _impulse * _JwB;
                vC -= (_mC * _impulse) * _JvAC;
                wC -= _iC * _impulse * _JwC;
                vD -= (_mD * _impulse) * _JvBD;
                wD -= _iD * _impulse * _JwD;
            }
            else
            {
                _impulse = 0.0f;
            }

            data.velocities[_indexA].v = vA;
            data.velocities[_indexA].w = wA;
            data.velocities[_indexB].v = vB;
            data.velocities[_indexB].w = wB;
            data.velocities[_indexC].v = vC;
            data.velocities[_indexC].w = wC;
            data.velocities[_indexD].v = vD;
            data.velocities[_indexD].w = wD;
        }
예제 #23
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;
            float aA = data.positions[m_indexA].a;
            Vec2 cB = data.positions[m_indexB].c;
            float aB = data.positions[m_indexB].a;

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

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

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

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

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

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

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

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

            float mass = mA + m_ratio * m_ratio * mB;

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

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

            float impulse = (-mass) * C;

            PA.set_Renamed(uA).mulLocal(-impulse);
            PB.set_Renamed(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_Renamed(cA);
            data.positions[m_indexA].a = aA;
            data.positions[m_indexB].c.set_Renamed(cB);
            data.positions[m_indexB].a = aB;

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

            return linearError < Settings.linearSlop;
        }
예제 #24
0
        internal override bool SolvePositionConstraints(ref SolverData data)
        {
            Vector2 cA = data.positions[_indexA].c;
            float   aA = data.positions[_indexA].a;
            Vector2 cB = data.positions[_indexB].c;
            float   aB = data.positions[_indexB].a;
            Vector2 cC = data.positions[_indexC].c;
            float   aC = data.positions[_indexC].a;
            Vector2 cD = data.positions[_indexD].c;
            float   aD = data.positions[_indexD].a;

            Rot qA = new Rot(aA), qB = new Rot(aB), qC = new Rot(aC), qD = new Rot(aD);

            const float linearError = 0.0f;

            float coordinateA, coordinateB;

            Vector2 JvAC, JvBD;
            float   JwA, JwB, JwC, JwD;
            float   mass = 0.0f;

            if (_typeA == JointType.Revolute)
            {
                JvAC  = Vector2.Zero;
                JwA   = 1.0f;
                JwC   = 1.0f;
                mass += _iA + _iC;

                coordinateA = aA - aC - _referenceAngleA;
            }
            else
            {
                Vector2 u  = MathUtils.Mul(qC, _localAxisC);
                Vector2 rC = MathUtils.Mul(qC, _localAnchorC - _lcC);
                Vector2 rA = MathUtils.Mul(qA, _localAnchorA - _lcA);
                JvAC  = u;
                JwC   = MathUtils.Cross(rC, u);
                JwA   = MathUtils.Cross(rA, u);
                mass += _mC + _mA + _iC * JwC * JwC + _iA * JwA * JwA;

                Vector2 pC = _localAnchorC - _lcC;
                Vector2 pA = MathUtils.MulT(qC, rA + (cA - cC));
                coordinateA = Vector2.Dot(pA - pC, _localAxisC);
            }

            if (_typeB == JointType.Revolute)
            {
                JvBD  = Vector2.Zero;
                JwB   = _ratio;
                JwD   = _ratio;
                mass += _ratio * _ratio * (_iB + _iD);

                coordinateB = aB - aD - _referenceAngleB;
            }
            else
            {
                Vector2 u  = MathUtils.Mul(qD, _localAxisD);
                Vector2 rD = MathUtils.Mul(qD, _localAnchorD - _lcD);
                Vector2 rB = MathUtils.Mul(qB, _localAnchorB - _lcB);
                JvBD  = _ratio * u;
                JwD   = _ratio * MathUtils.Cross(rD, u);
                JwB   = _ratio * MathUtils.Cross(rB, u);
                mass += _ratio * _ratio * (_mD + _mB) + _iD * JwD * JwD + _iB * JwB * JwB;

                Vector2 pD = _localAnchorD - _lcD;
                Vector2 pB = MathUtils.MulT(qD, rB + (cB - cD));
                coordinateB = Vector2.Dot(pB - pD, _localAxisD);
            }

            float C = (coordinateA + _ratio * coordinateB) - _constant;

            float impulse = 0.0f;

            if (mass > 0.0f)
            {
                impulse = -C / mass;
            }

            cA += _mA * impulse * JvAC;
            aA += _iA * impulse * JwA;
            cB += _mB * impulse * JvBD;
            aB += _iB * impulse * JwB;
            cC -= _mC * impulse * JvAC;
            aC -= _iC * impulse * JwC;
            cD -= _mD * impulse * JvBD;
            aD -= _iD * impulse * JwD;

            data.positions[_indexA].c = cA;
            data.positions[_indexA].a = aA;
            data.positions[_indexB].c = cB;
            data.positions[_indexB].a = aB;
            data.positions[_indexC].c = cC;
            data.positions[_indexC].a = aC;
            data.positions[_indexD].c = cD;
            data.positions[_indexD].a = aD;

            // TODO_ERIN not implemented
            return(linearError < Settings.LinearSlop);
        }
예제 #25
0
        internal override bool SolvePositionConstraints(ref SolverData data)
        {
            Vector2 cA = data.positions[_indexA].c;
            float aA = data.positions[_indexA].a;
            Vector2 cB = data.positions[_indexB].c;
            float aB = data.positions[_indexB].a;

            Rot qA = new Rot(aA), qB = new Rot(aB);

            Vector2 rA = MathUtils.Mul(qA, LocalAnchorA - _localCenterA);
            Vector2 rB = MathUtils.Mul(qB, LocalAnchorB - _localCenterB);
            Vector2 u = cB + rB - cA - rA;

            float length = u.Length(); u.Normalize();
            float C = length - MaxLength;

            C = MathUtils.Clamp(C, 0.0f, Settings.MaxLinearCorrection);

            float impulse = -_mass * C;
            Vector2 P = impulse * u;

            cA -= _invMassA * P;
            aA -= _invIA * MathUtils.Cross(rA, P);
            cB += _invMassB * P;
            aB += _invIB * MathUtils.Cross(rB, P);

            data.positions[_indexA].c = cA;
            data.positions[_indexA].a = aA;
            data.positions[_indexB].c = cB;
            data.positions[_indexB].a = aB;

            return length - MaxLength < Settings.LinearSlop;
        }
        internal override void InitVelocityConstraints(ref SolverData data)
        {
            m_indexA       = BodyA.IslandIndex;
            m_indexB       = BodyB.IslandIndex;
            m_localCenterA = BodyA.Sweep.LocalCenter;
            m_localCenterB = BodyB.Sweep.LocalCenter;
            m_invMassA     = BodyA.InvMass;
            m_invMassB     = BodyB.InvMass;
            m_invIA        = BodyA.InvI;
            m_invIB        = BodyB.InvI;

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

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

            Rot qA = new Rot(aA), qB = new Rot(aB);

            m_rA = MathUtils.Mul(qA, LocalAnchorA - m_localCenterA);
            m_rB = MathUtils.Mul(qB, LocalAnchorB - m_localCenterB);
            _u   = cB + m_rB - cA - m_rA;

            // Handle singularity.
            float length = _u.Length();

            if (length > Settings.LinearSlop)
            {
                _u *= 1.0f / length;
            }
            else
            {
                _u = Vector2.Zero;
            }

            float crAu    = MathUtils.Cross(m_rA, _u);
            float crBu    = MathUtils.Cross(m_rB, _u);
            float invMass = m_invMassA + m_invIA * crAu * crAu + m_invMassB + m_invIB * crBu * crBu;

            // Compute the effective mass matrix.
            _mass = invMass != 0.0f ? 1.0f / invMass : 0.0f;

            if (Frequency > 0.0f)
            {
                float C = length - Length;

                // Frequency
                float omega = 2.0f * Settings.Pi * Frequency;

                // Damping coefficient
                float d = 2.0f * _mass * DampingRatio * omega;

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

                // magic formulas
                float h = data.step.dt;
                _gamma = h * (d + h * k);
                _gamma = _gamma != 0.0f ? 1.0f / _gamma : 0.0f;
                _bias  = C * h * k * _gamma;

                invMass += _gamma;
                _mass    = invMass != 0.0f ? 1.0f / invMass : 0.0f;
            }
            else
            {
                _gamma = 0.0f;
                _bias  = 0.0f;
            }

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

                Vector2 P = _impulse * _u;
                vA -= m_invMassA * P;
                wA -= m_invIA * MathUtils.Cross(m_rA, P);
                vB += m_invMassB * P;
                wB += m_invIB * MathUtils.Cross(m_rB, P);
            }
            else
            {
                _impulse = 0.0f;
            }

            data.velocities[m_indexA].v = vA;
            data.velocities[m_indexA].w = wA;
            data.velocities[m_indexB].v = vB;
            data.velocities[m_indexB].w = wB;
        }
예제 #27
0
        public override void initVelocityConstraints(SolverData data)
        {
            m_indexA = m_bodyA.m_islandIndex;
            m_indexB = m_bodyB.m_islandIndex;
            m_localCenterA.set_Renamed(m_bodyA.m_sweep.localCenter);
            m_localCenterB.set_Renamed(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;
            float aA = data.positions[m_indexA].a;
            Vec2 vA = data.velocities[m_indexA].v;
            float wA = data.velocities[m_indexA].w;

            Vec2 cB = data.positions[m_indexB].c;
            float aB = data.positions[m_indexB].a;
            Vec2 vB = data.velocities[m_indexB].v;
            float 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_Renamed(aA);
            qB.set_Renamed(aB);

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

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

            // Compute motor Jacobian and effective mass.
            {
                Rot.mulToOutUnsafe(qA, m_localXAxisA, m_axis);
                temp.set_Renamed(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.0f)
                {
                    m_motorMass = 1.0f / m_motorMass;
                }
            }

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

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

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

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

            // Compute motor and limit terms.
            if (m_enableLimit)
            {

                float jointTranslation = Vec2.dot(m_axis, d);
                if (MathUtils.abs(m_upperTranslation - m_lowerTranslation) < 2.0f * 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.0f;
                    }
                }
                else if (jointTranslation >= m_upperTranslation)
                {
                    if (m_limitState != LimitState.AT_UPPER)
                    {
                        m_limitState = LimitState.AT_UPPER;
                        m_impulse.z = 0.0f;
                    }
                }
                else
                {
                    m_limitState = LimitState.INACTIVE;
                    m_impulse.z = 0.0f;
                }
            }
            else
            {
                m_limitState = LimitState.INACTIVE;
                m_impulse.z = 0.0f;
            }

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

            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_Renamed(m_axis).mulLocal(m_motorImpulse + m_impulse.z);
                P.set_Renamed(m_perp).mulLocal(m_impulse.x).addLocal(temp);

                float LA = m_impulse.x * m_s1 + m_impulse.y + (m_motorImpulse + m_impulse.z) * m_a1;
                float 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.0f;
            }

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

            pool.pushRot(2);
            pool.pushVec2(4);
        }
예제 #28
0
 public override bool SolvePositionConstraints(SolverData data)
 {
     return ConstrainEdges(data.Step);
 }
        internal override bool SolvePositionConstraints(ref SolverData data)
        {
            Vector2 cA = data.positions[_indexA].c;
            float aA = data.positions[_indexA].a;
            Vector2 cB = data.positions[_indexB].c;
            float aB = data.positions[_indexB].a;

            Rot qA = new Rot(aA), qB = new Rot(aB);

            float mA = _invMassA, mB = _invMassB;
            float iA = _invIA, iB = _invIB;

            Vector2 rA = MathUtils.Mul(qA, LocalAnchorA - _localCenterA);
            Vector2 rB = MathUtils.Mul(qB, LocalAnchorB - _localCenterB);

            float positionError, angularError;

            Mat33 K = new Mat33();
            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 (FrequencyHz > 0.0f)
            {
                Vector2 C1 = cB + rB - cA - rA;

                positionError = C1.Length();
                angularError = 0.0f;

                Vector2 P = -K.Solve22(C1);

                cA -= mA * P;
                aA -= iA * MathUtils.Cross(rA, P);

                cB += mB * P;
                aB += iB * MathUtils.Cross(rB, P);
            }
            else
            {
                Vector2 C1 = cB + rB - cA - rA;
                float C2 = aB - aA - ReferenceAngle;

                positionError = C1.Length();
                angularError = Math.Abs(C2);

                Vector3 C = new Vector3(C1.X, C1.Y, C2);

                Vector3 impulse = -K.Solve33(C);
                Vector2 P = new Vector2(impulse.X, impulse.Y);

                cA -= mA * P;
                aA -= iA * (MathUtils.Cross(rA, P) + impulse.Z);

                cB += mB * P;
                aB += iB * (MathUtils.Cross(rB, P) + impulse.Z);
            }

            data.positions[_indexA].c = cA;
            data.positions[_indexA].a = aA;
            data.positions[_indexB].c = cB;
            data.positions[_indexB].a = aB;

            return positionError <= Settings.LinearSlop && angularError <= Settings.AngularSlop;
        }
예제 #30
0
파일: Joint.cs 프로젝트: tracer0707/OpenGLF
 /// <summary>
 /// Solves the position constraints.
 /// </summary>
 /// <param name="data"></param>
 /// <returns>returns true if the position errors are within tolerance.</returns>
 internal abstract bool SolvePositionConstraints(ref SolverData data);
예제 #31
0
 internal override bool SolvePositionConstraints(ref SolverData data)
 {
     //no position solving for this joint
     return(true);
 }
예제 #32
0
        internal override void SolveVelocityConstraints(ref SolverData data)
        {
            float mA = _invMassA, mB = _invMassB;
            float iA = _invIA, iB = _invIB;

            Vector2 vA = data.Velocities[_indexA].V;
            float   wA = data.Velocities[_indexA].W;
            Vector2 vB = data.Velocities[_indexB].V;
            float   wB = data.Velocities[_indexB].W;

            // Solve spring constraint
            {
                float Cdot    = Vector2.Dot(_ax, vB - vA) + _sBx * wB - _sAx * wA;
                float impulse = -_springMass * (Cdot + _bias + _gamma * _springImpulse);
                _springImpulse += impulse;

                Vector2 P  = impulse * _ax;
                float   LA = impulse * _sAx;
                float   LB = impulse * _sBx;

                vA -= mA * P;
                wA -= iA * LA;

                vB += mB * P;
                wB += iB * LB;
            }

            // Solve rotational motor constraint
            {
                float Cdot    = wB - wA - _motorSpeed;
                float impulse = -_motorMass * Cdot;

                float oldImpulse = _motorImpulse;
                float maxImpulse = data.Step.dt * _maxMotorTorque;
                _motorImpulse = MathUtils.Clamp(_motorImpulse + impulse, -maxImpulse, maxImpulse);
                impulse       = _motorImpulse - oldImpulse;

                wA -= iA * impulse;
                wB += iB * impulse;
            }

            // Solve point to line constraint
            {
                float Cdot    = Vector2.Dot(_ay, vB - vA) + _sBy * wB - _sAy * wA;
                float impulse = -_mass * Cdot;
                _impulse += impulse;

                Vector2 P  = impulse * _ay;
                float   LA = impulse * _sAy;
                float   LB = impulse * _sBy;

                vA -= mA * P;
                wA -= iA * LA;

                vB += mB * P;
                wB += iB * LB;
            }

            data.Velocities[_indexA].V = vA;
            data.Velocities[_indexA].W = wA;
            data.Velocities[_indexB].V = vB;
            data.Velocities[_indexB].W = wB;
        }
예제 #33
0
        public override void SolveVelocityConstraints(SolverData data)
        {
            float crossMassSum = 0.0f;
            float dotMassSum = 0.0f;

            Vec2[] d = Pool.GetVec2Array(Bodies.Length);

            for (int i = 0; i < Bodies.Length; ++i)
            {
                int prev = (i == 0) ? Bodies.Length - 1 : i - 1;
                int next = (i == Bodies.Length - 1) ? 0 : i + 1;
                d[i].Set(Bodies[next].WorldCenter);
                d[i].SubLocal(Bodies[prev].WorldCenter);
                dotMassSum += (d[i].LengthSquared()) / Bodies[i].Mass;
                crossMassSum += Vec2.Cross(Bodies[i].LinearVelocity, d[i]);
            }
            float lambda = (-2.0f) * crossMassSum / dotMassSum;
            // System.out.println(crossMassSum + " " +dotMassSum);
            // lambda = MathUtils.clamp(lambda, -Settings.maxLinearCorrection,
            // Settings.maxLinearCorrection);
            m_impulse += lambda;
            // System.out.println(m_impulse);
            for (int i = 0; i < Bodies.Length; ++i)
            {
                Bodies[i].LinearVelocity.X += Bodies[i].InvMass * d[i].Y * .5f * lambda;
                Bodies[i].LinearVelocity.Y += Bodies[i].InvMass * (-d[i].X) * .5f * lambda;
            }
        }
예제 #34
0
        internal override void InitVelocityConstraints(ref SolverData data)
        {
            _indexA       = BodyA.IslandIndex;
            _indexB       = BodyB.IslandIndex;
            _localCenterA = BodyA._sweep.LocalCenter;
            _localCenterB = BodyB._sweep.LocalCenter;
            _invMassA     = BodyA._invMass;
            _invMassB     = BodyB._invMass;
            _invIA        = BodyA._invI;
            _invIB        = BodyB._invI;

            Vector2 cA = data.positions[_indexA].c;
            float   aA = data.positions[_indexA].a;
            Vector2 vA = data.velocities[_indexA].v;
            float   wA = data.velocities[_indexA].w;

            Vector2 cB = data.positions[_indexB].c;
            float   aB = data.positions[_indexB].a;
            Vector2 vB = data.velocities[_indexB].v;
            float   wB = data.velocities[_indexB].w;

            Rot qA = new Rot(aA), qB = new Rot(aB);

            // Compute the effective masses.
            Vector2 rA = MathUtils.Mul(qA, LocalAnchorA - _localCenterA);
            Vector2 rB = MathUtils.Mul(qB, LocalAnchorB - _localCenterB);
            Vector2 d  = (cB - cA) + rB - rA;

            float mA = _invMassA, mB = _invMassB;
            float iA = _invIA, iB = _invIB;

            // Compute motor Jacobian and effective mass.
            {
                _axis = MathUtils.Mul(qA, LocalXAxis);
                _a1   = MathUtils.Cross(d + rA, _axis);
                _a2   = MathUtils.Cross(rB, _axis);

                _motorMass = mA + mB + iA * _a1 * _a1 + iB * _a2 * _a2;
                if (_motorMass > 0.0f)
                {
                    _motorMass = 1.0f / _motorMass;
                }
            }

            // Prismatic constraint.
            {
                _perp = MathUtils.Mul(qA, _localYAxisA);

                _s1 = MathUtils.Cross(d + rA, _perp);
                _s2 = MathUtils.Cross(rB, _perp);

                float k11 = mA + mB + iA * _s1 * _s1 + iB * _s2 * _s2;
                float k12 = iA * _s1 + iB * _s2;
                float k13 = iA * _s1 * _a1 + iB * _s2 * _a2;
                float k22 = iA + iB;
                if (k22 == 0.0f)
                {
                    // For bodies with fixed rotation.
                    k22 = 1.0f;
                }
                float k23 = iA * _a1 + iB * _a2;
                float k33 = mA + mB + iA * _a1 * _a1 + iB * _a2 * _a2;

                _K.ex = new Vector3(k11, k12, k13);
                _K.ey = new Vector3(k12, k22, k23);
                _K.ez = new Vector3(k13, k23, k33);
            }

            // Compute motor and limit terms.
            if (_enableLimit)
            {
                float jointTranslation = Vector2.Dot(_axis, d);
                if (Math.Abs(_upperTranslation - _lowerTranslation) < 2.0f * Settings.LinearSlop)
                {
                    _limitState = LimitState.Equal;
                }
                else if (jointTranslation <= _lowerTranslation)
                {
                    if (_limitState != LimitState.AtLower)
                    {
                        _limitState = LimitState.AtLower;
                        _impulse.Z  = 0.0f;
                    }
                }
                else if (jointTranslation >= _upperTranslation)
                {
                    if (_limitState != LimitState.AtUpper)
                    {
                        _limitState = LimitState.AtUpper;
                        _impulse.Z  = 0.0f;
                    }
                }
                else
                {
                    _limitState = LimitState.Inactive;
                    _impulse.Z  = 0.0f;
                }
            }
            else
            {
                _limitState = LimitState.Inactive;
                _impulse.Z  = 0.0f;
            }

            if (_enableMotor == false)
            {
                MotorImpulse = 0.0f;
            }

            if (Settings.EnableWarmstarting)
            {
                // Account for variable time step.
                _impulse     *= data.step.dtRatio;
                MotorImpulse *= data.step.dtRatio;

                Vector2 P  = _impulse.X * _perp + (MotorImpulse + _impulse.Z) * _axis;
                float   LA = _impulse.X * _s1 + _impulse.Y + (MotorImpulse + _impulse.Z) * _a1;
                float   LB = _impulse.X * _s2 + _impulse.Y + (MotorImpulse + _impulse.Z) * _a2;

                vA -= mA * P;
                wA -= iA * LA;

                vB += mB * P;
                wB += iB * LB;
            }
            else
            {
                _impulse     = Vector3.Zero;
                MotorImpulse = 0.0f;
            }

            data.velocities[_indexA].v = vA;
            data.velocities[_indexA].w = wA;
            data.velocities[_indexB].v = vB;
            data.velocities[_indexB].w = wB;
        }
예제 #35
0
파일: Joint.cs 프로젝트: tracer0707/OpenGLF
 internal abstract void SolveVelocityConstraints(ref SolverData data);
예제 #36
0
        internal override void SolveVelocityConstraints(ref SolverData data)
        {
            Vector2 vA = data.velocities[_indexA].v;
            float   wA = data.velocities[_indexA].w;
            Vector2 vB = data.velocities[_indexB].v;
            float   wB = data.velocities[_indexB].w;

            float mA = _invMassA, mB = _invMassB;
            float iA = _invIA, iB = _invIB;

            // Solve linear motor constraint.
            if (_enableMotor && _limitState != LimitState.Equal)
            {
                float Cdot       = Vector2.Dot(_axis, vB - vA) + _a2 * wB - _a1 * wA;
                float impulse    = _motorMass * (_motorSpeed - Cdot);
                float oldImpulse = MotorImpulse;
                float maxImpulse = data.step.dt * _maxMotorForce;
                MotorImpulse = MathUtils.Clamp(MotorImpulse + impulse, -maxImpulse, maxImpulse);
                impulse      = MotorImpulse - oldImpulse;

                Vector2 P  = impulse * _axis;
                float   LA = impulse * _a1;
                float   LB = impulse * _a2;

                vA -= mA * P;
                wA -= iA * LA;

                vB += mB * P;
                wB += iB * LB;
            }

            Vector2 Cdot1 = new Vector2();

            Cdot1.X = Vector2.Dot(_perp, vB - vA) + _s2 * wB - _s1 * wA;
            Cdot1.Y = wB - wA;

            if (_enableLimit && _limitState != LimitState.Inactive)
            {
                // Solve prismatic and limit constraint in block form.
                float Cdot2;
                Cdot2 = Vector2.Dot(_axis, vB - vA) + _a2 * wB - _a1 * wA;
                Vector3 Cdot = new Vector3(Cdot1.X, Cdot1.Y, Cdot2);

                Vector3 f1 = _impulse;
                Vector3 df = _K.Solve33(-Cdot);
                _impulse += df;

                if (_limitState == LimitState.AtLower)
                {
                    _impulse.Z = Math.Max(_impulse.Z, 0.0f);
                }
                else if (_limitState == LimitState.AtUpper)
                {
                    _impulse.Z = Math.Min(_impulse.Z, 0.0f);
                }

                // f2(1:2) = invK(1:2,1:2) * (-Cdot(1:2) - K(1:2,3) * (f2(3) - f1(3))) + f1(1:2)
                Vector2 b   = -Cdot1 - (_impulse.Z - f1.Z) * new Vector2(_K.ez.X, _K.ez.Y);
                Vector2 f2r = _K.Solve22(b) + new Vector2(f1.X, f1.Y);
                _impulse.X = f2r.X;
                _impulse.Y = f2r.Y;

                df = _impulse - f1;

                Vector2 P  = df.X * _perp + df.Z * _axis;
                float   LA = df.X * _s1 + df.Y + df.Z * _a1;
                float   LB = df.X * _s2 + df.Y + df.Z * _a2;

                vA -= mA * P;
                wA -= iA * LA;

                vB += mB * P;
                wB += iB * LB;
            }
            else
            {
                // Limit is inactive, just solve the prismatic constraint in block form.
                Vector2 df = _K.Solve22(-Cdot1);
                _impulse.X += df.X;
                _impulse.Y += df.Y;

                Vector2 P  = df.X * _perp;
                float   LA = df.X * _s1 + df.Y;
                float   LB = df.X * _s2 + df.Y;

                vA -= mA * P;
                wA -= iA * LA;

                vB += mB * P;
                wB += iB * LB;
            }

            data.velocities[_indexA].v = vA;
            data.velocities[_indexA].w = wA;
            data.velocities[_indexB].v = vB;
            data.velocities[_indexB].w = wB;
        }
예제 #37
0
        public override bool solvePositionConstraints(SolverData data)
        {
            Rot qA = pool.popRot();
            Rot qB = pool.popRot();
            Vec2 cA = data.positions[m_indexA].c;
            float aA = data.positions[m_indexA].a;
            Vec2 cB = data.positions[m_indexB].c;
            float aB = data.positions[m_indexB].a;

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

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

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

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

                if (m_limitState == LimitState.EQUAL)
                {
                    // Prevent large angular corrections
                    float 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)
                {
                    float C = angle - m_lowerAngle;
                    angularError = -C;

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

                    // Prevent large angular corrections and allow some slop.
                    C = MathUtils.clamp(C - Settings.angularSlop, 0.0f, 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();

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

                float mA = m_invMassA, mB = m_invMassB;
                float 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, ref 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;
        }
예제 #38
0
        internal override bool SolvePositionConstraints(ref SolverData data)
        {
            Vector2 cA = data.positions[_indexA].c;
            float   aA = data.positions[_indexA].a;
            Vector2 cB = data.positions[_indexB].c;
            float   aB = data.positions[_indexB].a;

            Rot qA = new Rot(aA), qB = new Rot(aB);

            float mA = _invMassA, mB = _invMassB;
            float iA = _invIA, iB = _invIB;

            // Compute fresh Jacobians
            Vector2 rA = MathUtils.Mul(qA, LocalAnchorA - _localCenterA);
            Vector2 rB = MathUtils.Mul(qB, LocalAnchorB - _localCenterB);
            Vector2 d  = cB + rB - cA - rA;

            Vector2 axis = MathUtils.Mul(qA, LocalXAxis);
            float   a1   = MathUtils.Cross(d + rA, axis);
            float   a2   = MathUtils.Cross(rB, axis);
            Vector2 perp = MathUtils.Mul(qA, _localYAxisA);

            float s1 = MathUtils.Cross(d + rA, perp);
            float s2 = MathUtils.Cross(rB, perp);

            Vector3 impulse;
            Vector2 C1 = new Vector2();

            C1.X = Vector2.Dot(perp, d);
            C1.Y = aB - aA - ReferenceAngle;

            float linearError  = Math.Abs(C1.X);
            float angularError = Math.Abs(C1.Y);

            bool  active = false;
            float C2     = 0.0f;

            if (_enableLimit)
            {
                float translation = Vector2.Dot(axis, d);
                if (Math.Abs(_upperTranslation - _lowerTranslation) < 2.0f * Settings.LinearSlop)
                {
                    // Prevent large angular corrections
                    C2          = MathUtils.Clamp(translation, -Settings.MaxLinearCorrection, Settings.MaxLinearCorrection);
                    linearError = Math.Max(linearError, Math.Abs(translation));
                    active      = true;
                }
                else if (translation <= _lowerTranslation)
                {
                    // Prevent large linear corrections and allow some slop.
                    C2          = MathUtils.Clamp(translation - _lowerTranslation + Settings.LinearSlop, -Settings.MaxLinearCorrection, 0.0f);
                    linearError = Math.Max(linearError, _lowerTranslation - translation);
                    active      = true;
                }
                else if (translation >= _upperTranslation)
                {
                    // Prevent large linear corrections and allow some slop.
                    C2          = MathUtils.Clamp(translation - _upperTranslation - Settings.LinearSlop, 0.0f, Settings.MaxLinearCorrection);
                    linearError = Math.Max(linearError, translation - _upperTranslation);
                    active      = true;
                }
            }

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

                Mat33 K = new Mat33();
                K.ex = new Vector3(k11, k12, k13);
                K.ey = new Vector3(k12, k22, k23);
                K.ez = new Vector3(k13, k23, k33);

                Vector3 C = new Vector3();
                C.X = C1.X;
                C.Y = C1.Y;
                C.Z = C2;

                impulse = K.Solve33(-C);
            }
            else
            {
                float k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2;
                float k12 = iA * s1 + iB * s2;
                float k22 = iA + iB;
                if (k22 == 0.0f)
                {
                    k22 = 1.0f;
                }

                Mat22 K = new Mat22();
                K.ex = new Vector2(k11, k12);
                K.ey = new Vector2(k12, k22);

                Vector2 impulse1 = K.Solve(-C1);
                impulse   = new Vector3();
                impulse.X = impulse1.X;
                impulse.Y = impulse1.Y;
                impulse.Z = 0.0f;
            }

            Vector2 P  = impulse.X * perp + impulse.Z * axis;
            float   LA = impulse.X * s1 + impulse.Y + impulse.Z * a1;
            float   LB = impulse.X * s2 + impulse.Y + impulse.Z * a2;

            cA -= mA * P;
            aA -= iA * LA;
            cB += mB * P;
            aB += iB * LB;

            data.positions[_indexA].c = cA;
            data.positions[_indexA].a = aA;
            data.positions[_indexB].c = cB;
            data.positions[_indexB].a = aB;

            return(linearError <= Settings.LinearSlop && angularError <= Settings.AngularSlop);
        }
예제 #39
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;

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

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

            Vec2 cB = data.positions[m_indexB].c;
            float aB = data.positions[m_indexB].a;
            Vec2 vB = data.velocities[m_indexB].v;
            float 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.
            temp.set(m_localAnchorA);
            temp.subLocal(m_localCenterA);
            Rot.mulToOutUnsafe(qA, temp , ref rA);
            temp.set(m_localAnchorB);
            temp.subLocal(m_localCenterB);
            Rot.mulToOutUnsafe(qB, temp, ref rB);
            d.set(cB);
            d.addLocal(rB);
            d.subLocal(cA);
            d.subLocal(rA);

            // Point to line constraint
            {
                Rot.mulToOut(qA, m_localYAxisA, ref m_ay);
                temp.set(d);
                temp.addLocal(rA);
                m_sAy = Vec2.cross(temp, 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.0f)
                {
                    m_mass = 1.0f/m_mass;
                }
            }

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

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

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

                    float C = Vec2.dot(d, m_ax);

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

                    // Damping coefficient
                    float da = 2.0f*m_springMass*m_dampingRatio*omega;

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

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

                    m_bias = C*h*k*m_gamma;

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

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

            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;
                float LA = m_impulse*m_sAy + m_springImpulse*m_sAx + m_motorImpulse;
                float 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.0f;
                m_springImpulse = 0.0f;
                m_motorImpulse = 0.0f;
            }
            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;
        }
예제 #40
0
        internal override void InitVelocityConstraints(ref SolverData data)
        {
            _indexA       = BodyA.IslandIndex;
            _indexB       = BodyB.IslandIndex;
            _localCenterA = BodyA._sweep.LocalCenter;
            _localCenterB = BodyB._sweep.LocalCenter;
            _invMassA     = BodyA._invMass;
            _invMassB     = BodyB._invMass;
            _invIA        = BodyA._invI;
            _invIB        = BodyB._invI;

            Vector2 cA = data.positions[_indexA].c;
            float   aA = data.positions[_indexA].a;
            Vector2 vA = data.velocities[_indexA].v;
            float   wA = data.velocities[_indexA].w;

            Vector2 cB = data.positions[_indexB].c;
            float   aB = data.positions[_indexB].a;
            Vector2 vB = data.velocities[_indexB].v;
            float   wB = data.velocities[_indexB].w;

            Complex qA = Complex.FromAngle(aA);
            Complex qB = Complex.FromAngle(aB);

            // Compute the effective mass matrix.
            _rA = -Complex.Multiply(ref _localCenterA, ref qA);
            _rB = -Complex.Multiply(ref _localCenterB, ref qB);

            // 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]

            float mA = _invMassA, mB = _invMassB;
            float iA = _invIA, iB = _invIB;

            Mat22 K = new Mat22();

            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;

            _linearMass = K.Inverse;

            _angularMass = iA + iB;
            if (_angularMass > 0.0f)
            {
                _angularMass = 1.0f / _angularMass;
            }

            _linearError  = cB + _rB - cA - _rA - Complex.Multiply(ref _linearOffset, ref qA);
            _angularError = aB - aA - _angularOffset;

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

                Vector2 P = new Vector2(_linearImpulse.X, _linearImpulse.Y);

                vA -= mA * P;
                wA -= iA * (MathUtils.Cross(ref _rA, ref P) + _angularImpulse);
                vB += mB * P;
                wB += iB * (MathUtils.Cross(ref _rB, ref P) + _angularImpulse);
            }
            else
            {
                _linearImpulse  = Vector2.Zero;
                _angularImpulse = 0.0f;
            }

            data.velocities[_indexA].v = vA;
            data.velocities[_indexA].w = wA;
            data.velocities[_indexB].v = vB;
            data.velocities[_indexB].w = wB;
        }
예제 #41
0
        public override void solveVelocityConstraints(SolverData data)
        {
            float mA = m_invMassA, mB = m_invMassB;
            float iA = m_invIA, iB = m_invIB;

            Vec2 vA = data.velocities[m_indexA].v;
            float wA = data.velocities[m_indexA].w;
            Vec2 vB = data.velocities[m_indexB].v;
            float wB = data.velocities[m_indexB].w;

            Vec2 temp = pool.popVec2();
            Vec2 P = pool.popVec2();

            // Solve spring constraint
            {
                temp.set(vB);
                temp.subLocal(vA);
                float Cdot = Vec2.dot(m_ax, temp) + m_sBx*wB - m_sAx*wA;
                float impulse = -m_springMass*(Cdot + m_bias + m_gamma*m_springImpulse);
                m_springImpulse += impulse;

                P.x = impulse*m_ax.x;
                P.y = impulse*m_ax.y;
                float LA = impulse*m_sAx;
                float LB = impulse*m_sBx;

                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;
            }

            // Solve rotational motor constraint
            {
                float Cdot = wB - wA - m_motorSpeed;
                float impulse = -m_motorMass*Cdot;

                float oldImpulse = m_motorImpulse;
                float maxImpulse = data.step.dt*m_maxMotorTorque;
                m_motorImpulse = MathUtils.clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse);
                impulse = m_motorImpulse - oldImpulse;

                wA -= iA*impulse;
                wB += iB*impulse;
            }

            // Solve point to line constraint
            {
                temp.set(vB);
                temp.subLocal(vA);
                float Cdot = Vec2.dot(m_ay, temp) + m_sBy*wB - m_sAy*wA;
                float impulse = -m_mass*Cdot;
                m_impulse += impulse;

                P.x = impulse*m_ay.x;
                P.y = impulse*m_ay.y;
                float LA = impulse*m_sAy;
                float LB = impulse*m_sBy;

                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(2);

            // data.velocities[m_indexA].v = vA;
            data.velocities[m_indexA].w = wA;
            // data.velocities[m_indexB].v = vB;
            data.velocities[m_indexB].w = wB;
        }
예제 #42
0
 internal override bool SolvePositionConstraints(ref SolverData data)
 {
     return(true);
 }
예제 #43
0
        internal override bool SolvePositionConstraints(ref SolverData data)
        {
            Vector2 cA = data.positions[_indexA].c;
            float aA = data.positions[_indexA].a;
            Vector2 cB = data.positions[_indexB].c;
            float aB = data.positions[_indexB].a;
            Vector2 cC = data.positions[_indexC].c;
            float aC = data.positions[_indexC].a;
            Vector2 cD = data.positions[_indexD].c;
            float aD = data.positions[_indexD].a;

            Rot qA = new Rot(aA), qB = new Rot(aB), qC = new Rot(aC), qD = new Rot(aD);

            const float linearError = 0.0f;

            float coordinateA, coordinateB;

            Vector2 JvAC, JvBD;
            float JwA, JwB, JwC, JwD;
            float mass = 0.0f;

            if (_typeA == JointType.Revolute)
            {
                JvAC = Vector2.Zero;
                JwA = 1.0f;
                JwC = 1.0f;
                mass += _iA + _iC;

                coordinateA = aA - aC - _referenceAngleA;
            }
            else
            {
                Vector2 u = MathUtils.Mul(qC, _localAxisC);
                Vector2 rC = MathUtils.Mul(qC, _localAnchorC - _lcC);
                Vector2 rA = MathUtils.Mul(qA, _localAnchorA - _lcA);
                JvAC = u;
                JwC = MathUtils.Cross(rC, u);
                JwA = MathUtils.Cross(rA, u);
                mass += _mC + _mA + _iC * JwC * JwC + _iA * JwA * JwA;

                Vector2 pC = _localAnchorC - _lcC;
                Vector2 pA = MathUtils.MulT(qC, rA + (cA - cC));
                coordinateA = Vector2.Dot(pA - pC, _localAxisC);
            }

            if (_typeB == JointType.Revolute)
            {
                JvBD = Vector2.Zero;
                JwB = _ratio;
                JwD = _ratio;
                mass += _ratio * _ratio * (_iB + _iD);

                coordinateB = aB - aD - _referenceAngleB;
            }
            else
            {
                Vector2 u = MathUtils.Mul(qD, _localAxisD);
                Vector2 rD = MathUtils.Mul(qD, _localAnchorD - _lcD);
                Vector2 rB = MathUtils.Mul(qB, _localAnchorB - _lcB);
                JvBD = _ratio * u;
                JwD = _ratio * MathUtils.Cross(rD, u);
                JwB = _ratio * MathUtils.Cross(rB, u);
                mass += _ratio * _ratio * (_mD + _mB) + _iD * JwD * JwD + _iB * JwB * JwB;

                Vector2 pD = _localAnchorD - _lcD;
                Vector2 pB = MathUtils.MulT(qD, rB + (cB - cD));
                coordinateB = Vector2.Dot(pB - pD, _localAxisD);
            }

            float C = (coordinateA + _ratio * coordinateB) - _constant;

            float impulse = 0.0f;
            if (mass > 0.0f)
            {
                impulse = -C / mass;
            }

            cA += _mA * impulse * JvAC;
            aA += _iA * impulse * JwA;
            cB += _mB * impulse * JvBD;
            aB += _iB * impulse * JwB;
            cC -= _mC * impulse * JvAC;
            aC -= _iC * impulse * JwC;
            cD -= _mD * impulse * JvBD;
            aD -= _iD * impulse * JwD;

            data.positions[_indexA].c = cA;
            data.positions[_indexA].a = aA;
            data.positions[_indexB].c = cB;
            data.positions[_indexB].a = aB;
            data.positions[_indexC].c = cC;
            data.positions[_indexC].a = aC;
            data.positions[_indexD].c = cD;
            data.positions[_indexD].a = aD;

            // TODO_ERIN not implemented
            return linearError < Settings.LinearSlop;
        }
예제 #44
0
        internal override void InitVelocityConstraints(ref SolverData data)
        {
            _indexA       = BodyA.IslandIndex;
            _indexB       = BodyB.IslandIndex;
            _localCenterA = BodyA._sweep.LocalCenter;
            _localCenterB = BodyB._sweep.LocalCenter;
            _invMassA     = BodyA._invMass;
            _invMassB     = BodyB._invMass;
            _invIA        = BodyA._invI;
            _invIB        = BodyB._invI;

            float   aA = data.Positions[_indexA].A;
            Vector2 vA = data.Velocities[_indexA].V;
            float   wA = data.Velocities[_indexA].W;

            float   aB = data.Positions[_indexB].A;
            Vector2 vB = data.Velocities[_indexB].V;
            float   wB = data.Velocities[_indexB].W;

            Rot qA = new Rot(aA), qB = new Rot(aB);

            _rA = MathUtils.Mul(qA, LocalAnchorA - _localCenterA);
            _rB = MathUtils.Mul(qB, LocalAnchorB - _localCenterB);

            // 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]

            float mA = _invMassA, mB = _invMassB;
            float iA = _invIA, iB = _invIB;

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

            _mass.ex.X = mA + mB + _rA.Y * _rA.Y * iA + _rB.Y * _rB.Y * iB;
            _mass.ey.X = -_rA.Y * _rA.X * iA - _rB.Y * _rB.X * iB;
            _mass.ez.X = -_rA.Y * iA - _rB.Y * iB;
            _mass.ex.Y = _mass.ey.X;
            _mass.ey.Y = mA + mB + _rA.X * _rA.X * iA + _rB.X * _rB.X * iB;
            _mass.ez.Y = _rA.X * iA + _rB.X * iB;
            _mass.ex.Z = _mass.ez.X;
            _mass.ey.Z = _mass.ez.Y;
            _mass.ez.Z = iA + iB;

            _motorMass = iA + iB;
            if (_motorMass > 0.0f)
            {
                _motorMass = 1.0f / _motorMass;
            }

            if (_enableMotor == false || fixedRotation)
            {
                _motorImpulse = 0.0f;
            }

            if (_enableLimit && fixedRotation == false)
            {
                float jointAngle = aB - aA - ReferenceAngle;
                if (Math.Abs(_upperAngle - _lowerAngle) < 2.0f * Settings.AngularSlop)
                {
                    _limitState = LimitState.Equal;
                }
                else if (jointAngle <= _lowerAngle)
                {
                    if (_limitState != LimitState.AtLower)
                    {
                        _impulse.Z = 0.0f;
                    }
                    _limitState = LimitState.AtLower;
                }
                else if (jointAngle >= _upperAngle)
                {
                    if (_limitState != LimitState.AtUpper)
                    {
                        _impulse.Z = 0.0f;
                    }
                    _limitState = LimitState.AtUpper;
                }
                else
                {
                    _limitState = LimitState.Inactive;
                    _impulse.Z  = 0.0f;
                }
            }
            else
            {
                _limitState = LimitState.Inactive;
            }

            if (Settings.EnableWarmstarting)
            {
                // Scale impulses to support a variable time step.
                _impulse      *= data.Step.dtRatio;
                _motorImpulse *= data.Step.dtRatio;

                Vector2 P = new Vector2(_impulse.X, _impulse.Y);

                vA -= mA * P;
                wA -= iA * (MathUtils.Cross(_rA, P) + MotorImpulse + _impulse.Z);

                vB += mB * P;
                wB += iB * (MathUtils.Cross(_rB, P) + MotorImpulse + _impulse.Z);
            }
            else
            {
                _impulse      = Vector3.Zero;
                _motorImpulse = 0.0f;
            }

            data.Velocities[_indexA].V = vA;
            data.Velocities[_indexA].W = wA;
            data.Velocities[_indexB].V = vB;
            data.Velocities[_indexB].W = wB;
        }
예제 #45
0
        public override void initVelocityConstraints(SolverData data)
        {
            m_indexA = m_bodyA.m_islandIndex;
            m_indexB = m_bodyB.m_islandIndex;
            m_localCenterA.set_Renamed(m_bodyA.m_sweep.localCenter);
            m_localCenterB.set_Renamed(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;
            float aA = data.positions[m_indexA].a;
            Vec2 vA = data.velocities[m_indexA].v;
            float wA = data.velocities[m_indexA].w;

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

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

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

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

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

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

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

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

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

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

            m_mass = mA + m_ratio * m_ratio * mB;

            if (m_mass > 0.0f)
            {
                m_mass = 1.0f / 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_Renamed(m_uA).mulLocal(-m_impulse);
                PB.set_Renamed(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.0f;
            }
            data.velocities[m_indexA].v.set_Renamed(vA);
            data.velocities[m_indexA].w = wA;
            data.velocities[m_indexB].v.set_Renamed(vB);
            data.velocities[m_indexB].w = wB;

            pool.pushVec2(1);
            pool.pushRot(2);
        }
예제 #46
0
        internal override void SolveVelocityConstraints(ref SolverData data)
        {
            Vector2 vA = data.Velocities[_indexA].V;
            float   wA = data.Velocities[_indexA].W;
            Vector2 vB = data.Velocities[_indexB].V;
            float   wB = data.Velocities[_indexB].W;

            float mA = _invMassA, mB = _invMassB;
            float iA = _invIA, iB = _invIB;

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

            // Solve motor constraint.
            if (_enableMotor && _limitState != LimitState.Equal && fixedRotation == false)
            {
                float Cdot       = wB - wA - _motorSpeed;
                float impulse    = _motorMass * (-Cdot);
                float oldImpulse = _motorImpulse;
                float maxImpulse = data.Step.dt * _maxMotorTorque;
                _motorImpulse = MathUtils.Clamp(_motorImpulse + impulse, -maxImpulse, maxImpulse);
                impulse       = _motorImpulse - oldImpulse;

                wA -= iA * impulse;
                wB += iB * impulse;
            }

            // Solve limit constraint.
            if (_enableLimit && _limitState != LimitState.Inactive && fixedRotation == false)
            {
                Vector2 Cdot1 = vB + MathUtils.Cross(wB, _rB) - vA - MathUtils.Cross(wA, _rA);
                float   Cdot2 = wB - wA;
                Vector3 Cdot  = new Vector3(Cdot1.X, Cdot1.Y, Cdot2);

                Vector3 impulse = -_mass.Solve33(Cdot);

                if (_limitState == LimitState.Equal)
                {
                    _impulse += impulse;
                }
                else if (_limitState == LimitState.AtLower)
                {
                    float newImpulse = _impulse.Z + impulse.Z;
                    if (newImpulse < 0.0f)
                    {
                        Vector2 rhs     = -Cdot1 + _impulse.Z * new Vector2(_mass.ez.X, _mass.ez.Y);
                        Vector2 reduced = _mass.Solve22(rhs);
                        impulse.X   = reduced.X;
                        impulse.Y   = reduced.Y;
                        impulse.Z   = -_impulse.Z;
                        _impulse.X += reduced.X;
                        _impulse.Y += reduced.Y;
                        _impulse.Z  = 0.0f;
                    }
                    else
                    {
                        _impulse += impulse;
                    }
                }
                else if (_limitState == LimitState.AtUpper)
                {
                    float newImpulse = _impulse.Z + impulse.Z;
                    if (newImpulse > 0.0f)
                    {
                        Vector2 rhs     = -Cdot1 + _impulse.Z * new Vector2(_mass.ez.X, _mass.ez.Y);
                        Vector2 reduced = _mass.Solve22(rhs);
                        impulse.X   = reduced.X;
                        impulse.Y   = reduced.Y;
                        impulse.Z   = -_impulse.Z;
                        _impulse.X += reduced.X;
                        _impulse.Y += reduced.Y;
                        _impulse.Z  = 0.0f;
                    }
                    else
                    {
                        _impulse += impulse;
                    }
                }

                Vector2 P = new Vector2(impulse.X, impulse.Y);

                vA -= mA * P;
                wA -= iA * (MathUtils.Cross(_rA, P) + impulse.Z);

                vB += mB * P;
                wB += iB * (MathUtils.Cross(_rB, P) + impulse.Z);
            }
            else
            {
                // Solve point-to-point constraint
                Vector2 Cdot    = vB + MathUtils.Cross(wB, _rB) - vA - MathUtils.Cross(wA, _rA);
                Vector2 impulse = _mass.Solve22(-Cdot);

                _impulse.X += impulse.X;
                _impulse.Y += impulse.Y;

                vA -= mA * impulse;
                wA -= iA * MathUtils.Cross(_rA, impulse);

                vB += mB * impulse;
                wB += iB * MathUtils.Cross(_rB, impulse);
            }

            data.Velocities[_indexA].V = vA;
            data.Velocities[_indexA].W = wA;
            data.Velocities[_indexB].V = vB;
            data.Velocities[_indexB].W = wB;
        }
예제 #47
0
        public override void solveVelocityConstraints(SolverData data)
        {
            Vec2 vA = data.velocities[m_indexA].v;
            float wA = data.velocities[m_indexA].w;
            Vec2 vB = data.velocities[m_indexB].v;
            float wB = data.velocities[m_indexB].w;

            Vec2 vpA = pool.popVec2();
            Vec2 vpB = pool.popVec2();
            Vec2 PA = pool.popVec2();
            Vec2 PB = pool.popVec2();

            Vec2.crossToOutUnsafe(wA, m_rA, vpA);
            vpA.addLocal(vA);
            Vec2.crossToOutUnsafe(wB, m_rB, vpB);
            vpB.addLocal(vB);

            float Cdot = -Vec2.dot(m_uA, vpA) - m_ratio * Vec2.dot(m_uB, vpB);
            float impulse = (-m_mass) * Cdot;
            m_impulse += impulse;

            PA.set_Renamed(m_uA).mulLocal(-impulse);
            PB.set_Renamed(m_uB).mulLocal((-m_ratio) * 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);

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

            pool.pushVec2(4);
        }
예제 #48
0
        internal override bool SolvePositionConstraints(ref SolverData data)
        {
            Vector2 cA = data.Positions[_indexA].C;
            float   aA = data.Positions[_indexA].A;
            Vector2 cB = data.Positions[_indexB].C;
            float   aB = data.Positions[_indexB].A;

            Rot qA = new Rot(aA), qB = new Rot(aB);

            float angularError = 0.0f;
            float positionError;

            bool fixedRotation = (_invIA + _invIB == 0.0f);

            // Solve angular limit constraint.
            if (_enableLimit && _limitState != LimitState.Inactive && fixedRotation == false)
            {
                float angle        = aB - aA - ReferenceAngle;
                float limitImpulse = 0.0f;

                if (_limitState == LimitState.Equal)
                {
                    // Prevent large angular corrections
                    float C = MathUtils.Clamp(angle - _lowerAngle, -Settings.MaxAngularCorrection, Settings.MaxAngularCorrection);
                    limitImpulse = -_motorMass * C;
                    angularError = Math.Abs(C);
                }
                else if (_limitState == LimitState.AtLower)
                {
                    float C = angle - _lowerAngle;
                    angularError = -C;

                    // Prevent large angular corrections and allow some slop.
                    C            = MathUtils.Clamp(C + Settings.AngularSlop, -Settings.MaxAngularCorrection, 0.0f);
                    limitImpulse = -_motorMass * C;
                }
                else if (_limitState == LimitState.AtUpper)
                {
                    float C = angle - _upperAngle;
                    angularError = C;

                    // Prevent large angular corrections and allow some slop.
                    C            = MathUtils.Clamp(C - Settings.AngularSlop, 0.0f, Settings.MaxAngularCorrection);
                    limitImpulse = -_motorMass * C;
                }

                aA -= _invIA * limitImpulse;
                aB += _invIB * limitImpulse;
            }

            // Solve point-to-point constraint.
            {
                qA.Set(aA);
                qB.Set(aB);
                Vector2 rA = MathUtils.Mul(qA, LocalAnchorA - _localCenterA);
                Vector2 rB = MathUtils.Mul(qB, LocalAnchorB - _localCenterB);

                Vector2 C = cB + rB - cA - rA;
                positionError = C.Length();

                float mA = _invMassA, mB = _invMassB;
                float iA = _invIA, iB = _invIB;

                Mat22 K = new Mat22();
                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;

                Vector2 impulse = -K.Solve(C);

                cA -= mA * impulse;
                aA -= iA * MathUtils.Cross(rA, impulse);

                cB += mB * impulse;
                aB += iB * MathUtils.Cross(rB, impulse);
            }

            data.Positions[_indexA].C = cA;
            data.Positions[_indexA].A = aA;
            data.Positions[_indexB].C = cB;
            data.Positions[_indexB].A = aB;

            return(positionError <= Settings.LinearSlop && angularError <= Settings.AngularSlop);
        }
예제 #49
0
        internal override void SolveVelocityConstraints(ref SolverData data)
        {
            Vector2 vA = data.velocities[_indexA].v;
            float wA = data.velocities[_indexA].w;
            Vector2 vB = data.velocities[_indexB].v;
            float wB = data.velocities[_indexB].w;

            // Cdot = dot(u, v + cross(w, r))
            Vector2 vpA = vA + MathUtils.Cross(wA, _rA);
            Vector2 vpB = vB + MathUtils.Cross(wB, _rB);
            float C = _length - MaxLength;
            float Cdot = Vector2.Dot(_u, vpB - vpA);

            // Predictive constraint.
            if (C < 0.0f)
            {
                Cdot += data.step.inv_dt * C;
            }

            float impulse = -_mass * Cdot;
            float oldImpulse = _impulse;
            _impulse = Math.Min(0.0f, _impulse + impulse);
            impulse = _impulse - oldImpulse;

            Vector2 P = impulse * _u;
            vA -= _invMassA * P;
            wA -= _invIA * MathUtils.Cross(_rA, P);
            vB += _invMassB * P;
            wB += _invIB * MathUtils.Cross(_rB, P);

            data.velocities[_indexA].v = vA;
            data.velocities[_indexA].w = wA;
            data.velocities[_indexB].v = vB;
            data.velocities[_indexB].w = wB;
        }
예제 #50
0
 internal abstract void SolveVelocityConstraints(ref SolverData data);
예제 #51
0
        internal override void InitVelocityConstraints(ref SolverData data)
        {
            Body b1 = BodyA;
            Body b2 = BodyB;

            Transform xf1, xf2;
            b1.GetTransform(out xf1);
            b2.GetTransform(out xf2);

            // Compute the effective mass matrix.
            Vector2 r1 = MathUtils.Mul(ref xf1.q, LocalAnchorA - b1.LocalCenter);
            Vector2 r2 = MathUtils.Mul(ref xf2.q, LocalAnchorB - b2.LocalCenter);
            _u = b2.Sweep.C + r2 - b1.Sweep.C - r1;

            // Handle singularity.
            float length = _u.Length();

            if (length < MaxLength && length > MinLength)
            {
                return;
            }

            if (length > Settings.LinearSlop)
            {
                _u *= 1.0f / length;
            }
            else
            {
                _u = Vector2.Zero;
            }

            float cr1u = MathUtils.Cross(r1, _u);
            float cr2u = MathUtils.Cross(r2, _u);
            float invMass = b1.InvMass + b1.InvI * cr1u * cr1u + b2.InvMass + b2.InvI * cr2u * cr2u;
            Debug.Assert(invMass > Settings.Epsilon);
            _mass = invMass != 0.0f ? 1.0f / invMass : 0.0f;

            if (Frequency > 0.0f)
            {
                float C = length - MaxLength;

                // Frequency
                float omega = 2.0f * Settings.Pi * Frequency;

                // Damping coefficient
                float d = 2.0f * _mass * DampingRatio * omega;

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

                // magic formulas
                _gamma = data.step.dt * (d + data.step.dt * k);
                _gamma = _gamma != 0.0f ? 1.0f / _gamma : 0.0f;
                _bias = C * data.step.dt * k * _gamma;

                _mass = invMass + _gamma;
                _mass = _mass != 0.0f ? 1.0f / _mass : 0.0f;
            }

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

                Vector2 P = _impulse * _u;
                b1.LinearVelocityInternal -= b1.InvMass * P;
                b1.AngularVelocityInternal -= b1.InvI * MathUtils.Cross(r1, P);
                b2.LinearVelocityInternal += b2.InvMass * P;
                b2.AngularVelocityInternal += b2.InvI * MathUtils.Cross(r2, P);
            }
            else
            {
                _impulse = 0.0f;
            }
        }
예제 #52
0
 /// <summary>
 /// Solves the position constraints.
 /// </summary>
 /// <param name="data"></param>
 /// <returns>returns true if the position errors are within tolerance.</returns>
 internal abstract bool SolvePositionConstraints(ref SolverData data);
예제 #53
0
        internal override void SolveVelocityConstraints(ref SolverData data)
        {
            Body b1 = BodyA;
            Body b2 = BodyB;

            Transform xf1, xf2;
            b1.GetTransform(out xf1);
            b2.GetTransform(out xf2);

            Vector2 r1 = MathUtils.Mul(ref xf1.q, LocalAnchorA - b1.LocalCenter);
            Vector2 r2 = MathUtils.Mul(ref xf2.q, LocalAnchorB - b2.LocalCenter);

            Vector2 d = b2.Sweep.C + r2 - b1.Sweep.C - r1;

            float length = d.Length();

            if (length < MaxLength && length > MinLength)
            {
                return;
            }

            // Cdot = dot(u, v + cross(w, r))
            Vector2 v1 = b1.LinearVelocityInternal + MathUtils.Cross(b1.AngularVelocityInternal, r1);
            Vector2 v2 = b2.LinearVelocityInternal + MathUtils.Cross(b2.AngularVelocityInternal, r2);
            float Cdot = Vector2.Dot(_u, v2 - v1);

            float impulse = -_mass * (Cdot + _bias + _gamma * _impulse);
            _impulse += impulse;

            Vector2 P = impulse * _u;
            b1.LinearVelocityInternal -= b1.InvMass * P;
            b1.AngularVelocityInternal -= b1.InvI * MathUtils.Cross(r1, P);
            b2.LinearVelocityInternal += b2.InvMass * P;
            b2.AngularVelocityInternal += b2.InvI * MathUtils.Cross(r2, P);
        }
예제 #54
0
        internal override void InitVelocityConstraints(ref SolverData data)
        {
            _indexA       = BodyA.IslandIndex;
            _indexB       = BodyB.IslandIndex;
            _localCenterA = BodyA._sweep.LocalCenter;
            _localCenterB = BodyB._sweep.LocalCenter;
            _invMassA     = BodyA._invMass;
            _invMassB     = KinematicBodyB ? 0.0f : BodyB._invMass;
            _invIA        = BodyA._invI;
            _invIB        = KinematicBodyB ? 0.0f : BodyB._invI;

            float   aA = data.positions[_indexA].a;
            Vector2 vA = data.velocities[_indexA].v;
            float   wA = data.velocities[_indexA].w;

            float   aB = data.positions[_indexB].a;
            Vector2 vB = data.velocities[_indexB].v;
            float   wB = data.velocities[_indexB].w;

            Rot qA = new Rot(aA), qB = new Rot(aB);

            _rA = MathUtils.Mul(qA, LocalAnchorA - _localCenterA);
            _rB = MathUtils.Mul(qB, LocalAnchorB - _localCenterB);

            // 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]

            float mA = _invMassA, mB = _invMassB;
            float iA = _invIA, iB = _invIB;

            Mat33 K = new Mat33();

            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 (FrequencyHz > 0.0f)
            {
                K.GetInverse22(ref _mass);

                float invM = iA + iB;
                float m    = invM > 0.0f ? 1.0f / invM : 0.0f;

                float C = aB - aA - ReferenceAngle;

                // Frequency
                float omega = 2.0f * Settings.Pi * FrequencyHz;

                // Damping coefficient
                float d = 2.0f * m * DampingRatio * omega;

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

                // magic formulas
                float h = data.step.dt;
                _gamma = h * (d + h * k);
                _gamma = _gamma != 0.0f ? 1.0f / _gamma : 0.0f;
                _bias  = C * h * k * _gamma;

                invM      += _gamma;
                _mass.ez.Z = invM != 0.0f ? 1.0f / invM : 0.0f;
            }
            else
            {
                K.GetSymInverse33(ref _mass);
                _gamma = 0.0f;
                _bias  = 0.0f;
            }

            if (Settings.EnableWarmstarting)
            {
                // Scale impulses to support a variable time step.
                _impulse *= data.step.dtRatio;

                Vector2 P = new Vector2(_impulse.X, _impulse.Y);

                vA -= mA * P;
                wA -= iA * (MathUtils.Cross(_rA, P) + _impulse.Z);

                vB += mB * P;
                wB += iB * (MathUtils.Cross(_rB, P) + _impulse.Z);
            }
            else
            {
                _impulse = Vector3.Zero;
            }

            data.velocities[_indexA].v = vA;
            data.velocities[_indexA].w = wA;
            data.velocities[_indexB].v = vB;
            data.velocities[_indexB].w = wB;
        }
예제 #55
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;
            float aA = data.positions[m_indexA].a;
            Vec2 cB = data.positions[m_indexB].c;
            float aB = data.positions[m_indexB].a;

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

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

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

            Rot.mulToOutUnsafe(qA, m_localXAxisA, axis);
            float a1 = Vec2.cross(temp.set_Renamed(d).addLocal(rA), axis);
            float a2 = Vec2.cross(rB, axis);
            Rot.mulToOutUnsafe(qA, m_localYAxisA, perp);

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

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

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

            bool active = false;
            float C2 = 0.0f;
            if (m_enableLimit)
            {
                float translation = Vec2.dot(axis, d);
                if (MathUtils.abs(m_upperTranslation - m_lowerTranslation) < 2.0f * 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.0f);
                    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.0f, Settings.maxLinearCorrection);
                    linearError = MathUtils.max(linearError, translation - m_upperTranslation);
                    active = true;
                }
            }

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

                Mat33 K = pool.popMat33();
                K.ex.set_Renamed(k11, k12, k13);
                K.ey.set_Renamed(k12, k22, k23);
                K.ez.set_Renamed(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
            {
                float k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2;
                float k12 = iA * s1 + iB * s2;
                float k22 = iA + iB;
                if (k22 == 0.0f)
                {
                    k22 = 1.0f;
                }

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

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

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

                pool.pushMat22(1);
            }

            float Px = impulse.x * perp.x + impulse.z * axis.x;
            float Py = impulse.x * perp.y + impulse.z * axis.y;
            float LA = impulse.x * s1 + impulse.y + impulse.z * a1;
            float 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_Renamed(cA);
            data.positions[m_indexA].a = aA;
            data.positions[m_indexB].c.set_Renamed(cB);
            data.positions[m_indexB].a = aB;

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

            return linearError <= Settings.linearSlop && angularError <= Settings.angularSlop;
        }
예제 #56
0
        internal override bool SolvePositionConstraints(ref SolverData data)
        {
            Vector2 cA = data.positions[_indexA].c;
            float   aA = data.positions[_indexA].a;
            Vector2 cB = data.positions[_indexB].c;
            float   aB = data.positions[_indexB].a;

            Rot qA = new Rot(aA), qB = new Rot(aB);

            float mA = _invMassA, mB = _invMassB;
            float iA = _invIA, iB = _invIB;

            Vector2 rA = MathUtils.Mul(qA, LocalAnchorA - _localCenterA);
            Vector2 rB = MathUtils.Mul(qB, LocalAnchorB - _localCenterB);

            float positionError, angularError;

            Mat33 K = new Mat33();

            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 (FrequencyHz > 0.0f)
            {
                Vector2 C1 = cB + rB - cA - rA;

                positionError = C1.Length();
                angularError  = 0.0f;

                Vector2 P = -K.Solve22(C1);

                cA -= mA * P;
                aA -= iA * MathUtils.Cross(rA, P);

                cB += mB * P;
                aB += iB * MathUtils.Cross(rB, P);
            }
            else
            {
                Vector2 C1 = cB + rB - cA - rA;
                float   C2 = aB - aA - ReferenceAngle;

                positionError = C1.Length();
                angularError  = Math.Abs(C2);

                Vector3 C = new Vector3(C1.X, C1.Y, C2);

                Vector3 impulse = -K.Solve33(C);
                Vector2 P       = new Vector2(impulse.X, impulse.Y);

                cA -= mA * P;
                aA -= iA * (MathUtils.Cross(rA, P) + impulse.Z);

                cB += mB * P;
                aB += iB * (MathUtils.Cross(rB, P) + impulse.Z);
            }

            data.positions[_indexA].c = cA;
            data.positions[_indexA].a = aA;
            data.positions[_indexB].c = cB;
            data.positions[_indexB].a = aB;

            return(positionError <= Settings.LinearSlop && angularError <= Settings.AngularSlop);
        }
        internal override void InitVelocityConstraints(ref SolverData data)
        {
            _indexA = BodyA.IslandIndex;
            _indexB = BodyB.IslandIndex;
            _localCenterA = BodyA._sweep.LocalCenter;
            _localCenterB = BodyB._sweep.LocalCenter;
            _invMassA = BodyA._invMass;
            _invMassB = BodyB._invMass;
            _invIA = BodyA._invI;
            _invIB = BodyB._invI;

            float aA = data.positions[_indexA].a;
            Vector2 vA = data.velocities[_indexA].v;
            float wA = data.velocities[_indexA].w;

            float aB = data.positions[_indexB].a;
            Vector2 vB = data.velocities[_indexB].v;
            float wB = data.velocities[_indexB].w;

            Rot qA = new Rot(aA), qB = new Rot(aB);

            _rA = MathUtils.Mul(qA, LocalAnchorA - _localCenterA);
            _rB = MathUtils.Mul(qB, LocalAnchorB - _localCenterB);

            // 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]

            float mA = _invMassA, mB = _invMassB;
            float iA = _invIA, iB = _invIB;

            Mat33 K = new Mat33();
            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 (FrequencyHz > 0.0f)
            {
                K.GetInverse22(ref _mass);

                float invM = iA + iB;
                float m = invM > 0.0f ? 1.0f / invM : 0.0f;

                float C = aB - aA - ReferenceAngle;

                // Frequency
                float omega = 2.0f * Settings.Pi * FrequencyHz;

                // Damping coefficient
                float d = 2.0f * m * DampingRatio * omega;

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

                // magic formulas
                float h = data.step.dt;
                _gamma = h * (d + h * k);
                _gamma = _gamma != 0.0f ? 1.0f / _gamma : 0.0f;
                _bias = C * h * k * _gamma;

                invM += _gamma;
                _mass.ez.Z = invM != 0.0f ? 1.0f / invM : 0.0f;
            }
            else
            {
                K.GetSymInverse33(ref _mass);
                _gamma = 0.0f;
                _bias = 0.0f;
            }

            if (Settings.EnableWarmstarting)
            {
                // Scale impulses to support a variable time step.
                _impulse *= data.step.dtRatio;

                Vector2 P = new Vector2(_impulse.X, _impulse.Y);

                vA -= mA * P;
                wA -= iA * (MathUtils.Cross(_rA, P) + _impulse.Z);

                vB += mB * P;
                wB += iB * (MathUtils.Cross(_rB, P) + _impulse.Z);
            }
            else
            {
                _impulse = Vector3.Zero;
            }

            data.velocities[_indexA].v = vA;
            data.velocities[_indexA].w = wA;
            data.velocities[_indexB].v = vB;
            data.velocities[_indexB].w = wB;
        }
예제 #58
0
        internal override void InitVelocityConstraints(ref SolverData data)
        {
            _indexA       = BodyA.IslandIndex;
            _localCenterA = BodyA._sweep.LocalCenter;
            _invMassA     = BodyA._invMass;
            _invIA        = BodyA._invI;

            Vector2 cA = data.Positions[_indexA].C;
            float   aA = data.Positions[_indexA].A;
            Vector2 vA = data.Velocities[_indexA].V;
            float   wA = data.Velocities[_indexA].W;

            Rot qA = new Rot(aA);

            float mass = BodyA.Mass;

            // Frequency
            float omega = 2.0f * Settings.Pi * Frequency;

            // Damping coefficient
            float d = 2.0f * mass * DampingRatio * omega;

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

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

            Debug.Assert(d + h * k > Settings.Epsilon);
            _gamma = h * (d + h * k);
            if (_gamma != 0.0f)
            {
                _gamma = 1.0f / _gamma;
            }

            _beta = h * k * _gamma;

            // Compute the effective mass matrix.
            _rA = MathUtils.Mul(qA, LocalAnchorA - _localCenterA);

            // 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 = new Mat22();

            K.ex.X = _invMassA + _invIA * _rA.Y * _rA.Y + _gamma;
            K.ex.Y = -_invIA * _rA.X * _rA.Y;
            K.ey.X = K.ex.Y;
            K.ey.Y = _invMassA + _invIA * _rA.X * _rA.X + _gamma;

            _mass = K.Inverse;

            _C  = cA + _rA - _worldAnchor;
            _C *= _beta;

            // Cheat with some damping
            wA *= 0.98f;

            if (Settings.EnableWarmstarting)
            {
                _impulse *= data.Step.dtRatio;
                vA       += _invMassA * _impulse;
                wA       += _invIA * MathUtils.Cross(_rA, _impulse);
            }
            else
            {
                _impulse = Vector2.Zero;
            }

            data.Velocities[_indexA].V = vA;
            data.Velocities[_indexA].W = wA;
        }
        internal override void SolveVelocityConstraints(ref SolverData data)
        {
            Vector2 vA = data.velocities[_indexA].v;
            float wA = data.velocities[_indexA].w;
            Vector2 vB = data.velocities[_indexB].v;
            float wB = data.velocities[_indexB].w;

            float mA = _invMassA, mB = _invMassB;
            float iA = _invIA, iB = _invIB;

            if (FrequencyHz > 0.0f)
            {
                float Cdot2 = wB - wA;

                float impulse2 = -_mass.ez.Z * (Cdot2 + _bias + _gamma * _impulse.Z);
                _impulse.Z += impulse2;

                wA -= iA * impulse2;
                wB += iB * impulse2;

                Vector2 Cdot1 = vB + MathUtils.Cross(wB, _rB) - vA - MathUtils.Cross(wA, _rA);

                Vector2 impulse1 = -MathUtils.Mul22(_mass, Cdot1);
                _impulse.X += impulse1.X;
                _impulse.Y += impulse1.Y;

                Vector2 P = impulse1;

                vA -= mA * P;
                wA -= iA * MathUtils.Cross(_rA, P);

                vB += mB * P;
                wB += iB * MathUtils.Cross(_rB, P);
            }
            else
            {
                Vector2 Cdot1 = vB + MathUtils.Cross(wB, _rB) - vA - MathUtils.Cross(wA, _rA);
                float Cdot2 = wB - wA;
                Vector3 Cdot = new Vector3(Cdot1.X, Cdot1.Y, Cdot2);

                Vector3 impulse = -MathUtils.Mul(_mass, Cdot);
                _impulse += impulse;

                Vector2 P = new Vector2(impulse.X, impulse.Y);

                vA -= mA * P;
                wA -= iA * (MathUtils.Cross(_rA, P) + impulse.Z);

                vB += mB * P;
                wB += iB * (MathUtils.Cross(_rB, P) + impulse.Z);
            }

            data.velocities[_indexA].v = vA;
            data.velocities[_indexA].w = wA;
            data.velocities[_indexB].v = vB;
            data.velocities[_indexB].w = wB;
        }
예제 #60
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);
        }