Esempio n. 1
0
		/// Solve A * x = b, where b is a column vector. This is more efficient
		/// than computing the inverse in one-shot cases.
		public Vec3 Solve33(Vec3 b) {
			float det = Utilities.Dot(ex, Utilities.Cross(ey, ez));
			if (det != 0.0f) {
				det = 1.0f / det;
			}
			Vec3 x;
			x.X = det * Utilities.Dot(b, Utilities.Cross(ey, ez));
			x.Y = det * Utilities.Dot(ex, Utilities.Cross(b, ez));
			x.Z = det * Utilities.Dot(ex, Utilities.Cross(ey, b));
			return x;
		}
Esempio n. 2
0
		/// Negate this vector.
		public static Vec3 operator -(Vec3 other) { 
			Vec3 v = new Vec3(); 
			v.Set(-other.X, -other.Y, -other.Z); 
			return v; 
		}
Esempio n. 3
0
		/// Construct this matrix using columns.
		public Mat33(Vec3 c1, Vec3 c2, Vec3 c3)
		{
			ex = c1;
			ey = c2;
			ez = c3;
		}
Esempio n. 4
0
        internal 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.e_equalLimits && 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 = Utilities.Clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse);
                impulse        = m_motorImpulse - oldImpulse;

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

            // Solve limit constraint.
            if (m_enableLimit && m_limitState != LimitState.e_inactiveLimit && fixedRotation == false)
            {
                Vec2  Cdot1 = vB + Utilities.Cross(wB, m_rB) - vA - Utilities.Cross(wA, m_rA);
                float Cdot2 = wB - wA;
                Vec3  Cdot  = new Vec3(Cdot1.X, Cdot1.Y, Cdot2);

                Vec3 impulse = -m_mass.Solve33(Cdot);

                if (m_limitState == LimitState.e_equalLimits)
                {
                    m_impulse += impulse;
                }
                else if (m_limitState == LimitState.e_atLowerLimit)
                {
                    float newImpulse = m_impulse.Z + impulse.Z;
                    if (newImpulse < 0.0f)
                    {
                        Vec2 rhs     = -Cdot1 + m_impulse.Z * new Vec2(m_mass.ez.X, m_mass.ez.Y);
                        Vec2 reduced = m_mass.Solve22(rhs);
                        impulse.X    = reduced.X;
                        impulse.Y    = reduced.Y;
                        impulse.Z    = -m_impulse.Z;
                        m_impulse.X += reduced.X;
                        m_impulse.Y += reduced.Y;
                        m_impulse.Z  = 0.0f;
                    }
                    else
                    {
                        m_impulse += impulse;
                    }
                }
                else if (m_limitState == LimitState.e_atUpperLimit)
                {
                    float newImpulse = m_impulse.Z + impulse.Z;
                    if (newImpulse > 0.0f)
                    {
                        Vec2 rhs     = -Cdot1 + m_impulse.Z * new Vec2(m_mass.ez.X, m_mass.ez.Y);
                        Vec2 reduced = m_mass.Solve22(rhs);
                        impulse.X    = reduced.X;
                        impulse.Y    = reduced.Y;
                        impulse.Z    = -m_impulse.Z;
                        m_impulse.X += reduced.X;
                        m_impulse.Y += reduced.Y;
                        m_impulse.Z  = 0.0f;
                    }
                    else
                    {
                        m_impulse += impulse;
                    }
                }

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

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

                vB += mB * P;
                wB += iB * (Utilities.Cross(m_rB, P) + impulse.Z);
            }
            else
            {
                // Solve point-to-point constraint
                Vec2 Cdot    = vB + Utilities.Cross(wB, m_rB) - vA - Utilities.Cross(wA, m_rA);
                Vec2 impulse = m_mass.Solve22(-Cdot);

                m_impulse.X += impulse.X;
                m_impulse.Y += impulse.Y;

                vA -= mA * impulse;
                wA -= iA * Utilities.Cross(m_rA, impulse);

                vB += mB * impulse;
                wB += iB * Utilities.Cross(m_rB, impulse);
            }

            data.velocities[m_indexA].v = vA;
            data.velocities[m_indexA].w = wA;
            data.velocities[m_indexB].v = vB;
            data.velocities[m_indexB].w = wB;
        }
Esempio n. 5
0
		internal 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.e_equalLimits && 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 = Utilities.Clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse);
				impulse = m_motorImpulse - oldImpulse;

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

			// Solve limit constraint.
			if (m_enableLimit && m_limitState != LimitState.e_inactiveLimit && fixedRotation == false)
			{
				Vec2 Cdot1 = vB + Utilities.Cross(wB, m_rB) - vA - Utilities.Cross(wA, m_rA);
				float Cdot2 = wB - wA;
				Vec3 Cdot = new Vec3(Cdot1.X, Cdot1.Y, Cdot2);

				Vec3 impulse = -m_mass.Solve33(Cdot);

				if (m_limitState ==LimitState.e_equalLimits)
				{
					m_impulse += impulse;
				}
				else if (m_limitState == LimitState.e_atLowerLimit)
				{
					float newImpulse = m_impulse.Z + impulse.Z;
					if (newImpulse < 0.0f)
					{
						Vec2 rhs = -Cdot1 + m_impulse.Z * new Vec2(m_mass.ez.X, m_mass.ez.Y);
						Vec2 reduced = m_mass.Solve22(rhs);
						impulse.X = reduced.X;
						impulse.Y = reduced.Y;
						impulse.Z = -m_impulse.Z;
						m_impulse.X += reduced.X;
						m_impulse.Y += reduced.Y;
						m_impulse.Z = 0.0f;
					}
					else
					{
						m_impulse += impulse;
					}
				}
				else if (m_limitState == LimitState.e_atUpperLimit)
				{
					float newImpulse = m_impulse.Z + impulse.Z;
					if (newImpulse > 0.0f)
					{
						Vec2 rhs = -Cdot1 + m_impulse.Z * new Vec2(m_mass.ez.X, m_mass.ez.Y);
						Vec2 reduced = m_mass.Solve22(rhs);
						impulse.X = reduced.X;
						impulse.Y = reduced.Y;
						impulse.Z = -m_impulse.Z;
						m_impulse.X += reduced.X;
						m_impulse.Y += reduced.Y;
						m_impulse.Z = 0.0f;
					}
					else
					{
						m_impulse += impulse;
					}
				}

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

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

				vB += mB * P;
				wB += iB * (Utilities.Cross(m_rB, P) + impulse.Z);
			}
			else
			{
				// Solve point-to-point constraint
				Vec2 Cdot = vB + Utilities.Cross(wB, m_rB) - vA - Utilities.Cross(wA, m_rA);
				Vec2 impulse = m_mass.Solve22(-Cdot);

				m_impulse.X += impulse.X;
				m_impulse.Y += impulse.Y;

				vA -= mA * impulse;
				wA -= iA * Utilities.Cross(m_rA, impulse);

				vB += mB * impulse;
				wB += iB * Utilities.Cross(m_rB, impulse);
			}

			data.velocities[m_indexA].v = vA;
			data.velocities[m_indexA].w = wA;
			data.velocities[m_indexB].v = vB;
			data.velocities[m_indexB].w = wB;
		}
Esempio n. 6
0
		/// Perform the dot product on two vectors.
		public static float Dot(Vec3 a, Vec3 b)
		{
			return a.X * b.X + a.Y * b.Y + a.Z * b.Z;
		}
Esempio n. 7
0
		/// Perform the cross product on two vectors.
		public static Vec3 Cross(Vec3 a, Vec3 b)
		{
			return new Vec3(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X);
		}
Esempio n. 8
0
		internal 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 = new Rot(aA);
			Rot qB = new Rot(aB);

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

			// Compute fresh Jacobians
			Vec2 rA = Utilities.Mul(qA, m_localAnchorA - m_localCenterA);
			Vec2 rB = Utilities.Mul(qB, m_localAnchorB - m_localCenterB);
			Vec2 d = cB + rB - cA - rA;

			Vec2 axis = Utilities.Mul(qA, m_localXAxisA);
			float a1 = Utilities.Cross(d + rA, axis);
			float a2 = Utilities.Cross(rB, axis);
			Vec2 perp = Utilities.Mul(qA, m_localYAxisA);

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

			Vec3 impulse;
			Vec2 C1;
			C1.X = Utilities.Dot(perp, d);
			C1.Y = aB - aA - m_referenceAngle;

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

			bool active = false;
			float C2 = 0.0f;
			if (m_enableLimit)
			{
				float translation = Utilities.Dot(axis, d);
				if (Math.Abs(m_upperTranslation - m_lowerTranslation) < 2.0f *Settings._linearSlop)
				{
					// Prevent large angular corrections
					C2 = Utilities.Clamp(translation, -Settings._maxLinearCorrection, Settings._maxLinearCorrection);
					linearError = Math.Max(linearError, Math.Abs(translation));
					active = true;
				}
				else if (translation <= m_lowerTranslation)
				{
					// Prevent large linear corrections and allow some slop.
					C2 = Utilities.Clamp(translation - m_lowerTranslation + Settings._linearSlop, -Settings._maxLinearCorrection, 0.0f);
					linearError = Math.Max(linearError, m_lowerTranslation - translation);
					active = true;
				}
				else if (translation >= m_upperTranslation)
				{
					// Prevent large linear corrections and allow some slop.
					C2 = Utilities.Clamp(translation - m_upperTranslation - Settings._linearSlop, 0.0f, Settings._maxLinearCorrection);
					linearError = Math.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 = new Mat33();
				K.ex.Set(k11, k12, k13);
				K.ey.Set(k12, k22, k23);
				K.ez.Set(k13, k23, k33);

				Vec3 C = new Vec3();
				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.Set(k11, k12);
				K.ey.Set(k12, k22);

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

			Vec2 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[m_indexA].c = cA;
			data.positions[m_indexA].a = aA;
			data.positions[m_indexB].c = cB;
			data.positions[m_indexB].a = aB;

			return linearError <= Settings._linearSlop && angularError <= Settings._angularSlop;
		}
Esempio n. 9
0
		/// Multiply a matrix times a vector.
		public static Vec3 Mul(Mat33 A, Vec3 v)
		{
			return v.X * A.ex + v.Y * A.ey + v.Z * A.ez;
		}
Esempio n. 10
0
		internal 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;

			// Solve linear motor constraint.
			if (m_enableMotor && m_limitState != LimitState.e_equalLimits)
			{
				float Cdot = Utilities.Dot(m_axis, vB - vA) + 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 = Utilities.Clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse);
				impulse = m_motorImpulse - oldImpulse;

				Vec2 P = impulse * m_axis;
				float LA = impulse * m_a1;
				float LB = impulse * m_a2;

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

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

			Vec2 Cdot1;
			Cdot1.X = Utilities.Dot(m_perp, vB - vA) + m_s2 * wB - m_s1 * wA;
			Cdot1.Y = wB - wA;

			if (m_enableLimit && m_limitState != LimitState.e_inactiveLimit)
			{
				// Solve prismatic and limit constraint in block form.
				float Cdot2;
				Cdot2 = Utilities.Dot(m_axis, vB - vA) + m_a2 * wB - m_a1 * wA;
				Vec3 Cdot = new Vec3(Cdot1.X, Cdot1.Y, Cdot2);

				Vec3 f1 = m_impulse;
				Vec3 df =  m_K.Solve33(-Cdot);
				m_impulse += df;

				if (m_limitState == LimitState.e_atLowerLimit)
				{
					m_impulse.Z = Math.Max(m_impulse.Z, 0.0f);
				}
				else if (m_limitState == LimitState.e_atUpperLimit)
				{
					m_impulse.Z = Math.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 = -Cdot1 - (m_impulse.Z - f1.Z) * new Vec2(m_K.ez.X, m_K.ez.Y);
				Vec2 f2r = m_K.Solve22(b) + new Vec2(f1.X, f1.Y);
				m_impulse.X = f2r.X;
				m_impulse.Y = f2r.Y;

				df = m_impulse - f1;

				Vec2 P = df.X * m_perp + df.Z * m_axis;
				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 -= mA * P;
				wA -= iA * LA;

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

				Vec2 P = df.X * m_perp;
				float LA = df.X * m_s1 + df.Y;
				float LB = df.X * m_s2 + df.Y;

				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;
		}
Esempio n. 11
0
        internal 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 = new Rot(aA);
            Rot qB = new Rot(aB);

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

            // Compute fresh Jacobians
            Vec2 rA = Utilities.Mul(qA, m_localAnchorA - m_localCenterA);
            Vec2 rB = Utilities.Mul(qB, m_localAnchorB - m_localCenterB);
            Vec2 d  = cB + rB - cA - rA;

            Vec2  axis = Utilities.Mul(qA, m_localXAxisA);
            float a1   = Utilities.Cross(d + rA, axis);
            float a2   = Utilities.Cross(rB, axis);
            Vec2  perp = Utilities.Mul(qA, m_localYAxisA);

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

            Vec3 impulse;
            Vec2 C1;

            C1.X = Utilities.Dot(perp, d);
            C1.Y = aB - aA - m_referenceAngle;

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

            bool  active = false;
            float C2     = 0.0f;

            if (m_enableLimit)
            {
                float translation = Utilities.Dot(axis, d);
                if (Math.Abs(m_upperTranslation - m_lowerTranslation) < 2.0f * Settings._linearSlop)
                {
                    // Prevent large angular corrections
                    C2          = Utilities.Clamp(translation, -Settings._maxLinearCorrection, Settings._maxLinearCorrection);
                    linearError = Math.Max(linearError, Math.Abs(translation));
                    active      = true;
                }
                else if (translation <= m_lowerTranslation)
                {
                    // Prevent large linear corrections and allow some slop.
                    C2          = Utilities.Clamp(translation - m_lowerTranslation + Settings._linearSlop, -Settings._maxLinearCorrection, 0.0f);
                    linearError = Math.Max(linearError, m_lowerTranslation - translation);
                    active      = true;
                }
                else if (translation >= m_upperTranslation)
                {
                    // Prevent large linear corrections and allow some slop.
                    C2          = Utilities.Clamp(translation - m_upperTranslation - Settings._linearSlop, 0.0f, Settings._maxLinearCorrection);
                    linearError = Math.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 = new Mat33();
                K.ex.Set(k11, k12, k13);
                K.ey.Set(k12, k22, k23);
                K.ez.Set(k13, k23, k33);

                Vec3 C = new Vec3();
                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.Set(k11, k12);
                K.ey.Set(k12, k22);

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

            Vec2  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[m_indexA].c = cA;
            data.positions[m_indexA].a = aA;
            data.positions[m_indexB].c = cB;
            data.positions[m_indexB].a = aB;

            return(linearError <= Settings._linearSlop && angularError <= Settings._angularSlop);
        }
Esempio n. 12
0
        internal 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;

            // Solve linear motor constraint.
            if (m_enableMotor && m_limitState != LimitState.e_equalLimits)
            {
                float Cdot       = Utilities.Dot(m_axis, vB - vA) + 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 = Utilities.Clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse);
                impulse        = m_motorImpulse - oldImpulse;

                Vec2  P  = impulse * m_axis;
                float LA = impulse * m_a1;
                float LB = impulse * m_a2;

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

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

            Vec2 Cdot1;

            Cdot1.X = Utilities.Dot(m_perp, vB - vA) + m_s2 * wB - m_s1 * wA;
            Cdot1.Y = wB - wA;

            if (m_enableLimit && m_limitState != LimitState.e_inactiveLimit)
            {
                // Solve prismatic and limit constraint in block form.
                float Cdot2;
                Cdot2 = Utilities.Dot(m_axis, vB - vA) + m_a2 * wB - m_a1 * wA;
                Vec3 Cdot = new Vec3(Cdot1.X, Cdot1.Y, Cdot2);

                Vec3 f1 = m_impulse;
                Vec3 df = m_K.Solve33(-Cdot);
                m_impulse += df;

                if (m_limitState == LimitState.e_atLowerLimit)
                {
                    m_impulse.Z = Math.Max(m_impulse.Z, 0.0f);
                }
                else if (m_limitState == LimitState.e_atUpperLimit)
                {
                    m_impulse.Z = Math.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   = -Cdot1 - (m_impulse.Z - f1.Z) * new Vec2(m_K.ez.X, m_K.ez.Y);
                Vec2 f2r = m_K.Solve22(b) + new Vec2(f1.X, f1.Y);
                m_impulse.X = f2r.X;
                m_impulse.Y = f2r.Y;

                df = m_impulse - f1;

                Vec2  P  = df.X * m_perp + df.Z * m_axis;
                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 -= mA * P;
                wA -= iA * LA;

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

                Vec2  P  = df.X * m_perp;
                float LA = df.X * m_s1 + df.Y;
                float LB = df.X * m_s2 + df.Y;

                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;
        }
Esempio n. 13
0
		internal 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 = new Rot(aA);
			Rot qB = new Rot(aB);

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

			Vec2 rA = Utilities.Mul(qA, m_localAnchorA - m_localCenterA);
			Vec2 rB = Utilities.Mul(qB, m_localAnchorB - m_localCenterB);

			float positionError, angularError;

			Mat33 K;
			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.0f)
			{
				Vec2 C1 =  cB + rB - cA - rA;

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

				Vec2 P = -K.Solve22(C1);

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

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

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

				Vec3 C = new Vec3(C1.X, C1.Y, C2);
	
				Vec3 impulse = -K.Solve33(C);
				Vec2 P = new Vec2(impulse.X, impulse.Y);

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

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

			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 positionError <=Settings._linearSlop && angularError <= Settings._angularSlop;
		}
Esempio n. 14
0
		internal 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;

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

				float impulse2 = -m_mass.ez.Z * (Cdot2 + m_bias + m_gamma * m_impulse.Z);
				m_impulse.Z += impulse2;

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

				Vec2 Cdot1 = vB + Utilities.Cross(wB, m_rB) - vA - Utilities.Cross(wA, m_rA);

				Vec2 impulse1 = -Utilities.Mul22(m_mass, Cdot1);
				m_impulse.X += impulse1.X;
				m_impulse.Y += impulse1.Y;

				Vec2 P = impulse1;

				vA -= mA * P;
				wA -= iA * Utilities.Cross(m_rA, P);

				vB += mB * P;
				wB += iB * Utilities.Cross(m_rB, P);
			}
			else
			{
				Vec2 Cdot1 = vB + Utilities.Cross(wB, m_rB) - vA - Utilities.Cross(wA, m_rA);
				float Cdot2 = wB - wA;
				Vec3 Cdot = new Vec3(Cdot1.X, Cdot1.Y, Cdot2);

				Vec3 impulse = -Utilities.Mul(m_mass, Cdot);
				m_impulse += impulse;

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

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

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

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