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; Vec2 temp = Pool.PopVec2(); // Solve linear motor constraint. if (m_motorEnabled && LimitState != LimitState.Equal) { temp.Set(vB).SubLocal(vA); float Cdot = Vec2.Dot(Axis, temp) + A2 * wB - A1 * wA; float impulse = MotorMass * (m_motorSpeed - Cdot); float oldImpulse = MotorImpulse; float maxImpulse = data.Step.Dt * m_maxMotorForce; MotorImpulse = MathUtils.Clamp(MotorImpulse + impulse, -maxImpulse, maxImpulse); impulse = MotorImpulse - oldImpulse; Vec2 P = Pool.PopVec2(); P.Set(Axis).MulLocal(impulse); float LA = impulse * A1; float LB = impulse * 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(vB).SubLocal(vA); Cdot1.X = Vec2.Dot(Perp, temp) + S2 * wB - S1 * wA; Cdot1.Y = wB - wA; // System.out.println(Cdot1); if (m_limitEnabled && LimitState != LimitState.Inactive) { // Solve prismatic and limit constraint in block form. float Cdot2; temp.Set(vB).SubLocal(vA); Cdot2 = Vec2.Dot(Axis, temp) + A2 * wB - A1 * wA; Vec3 Cdot = Pool.PopVec3(); Cdot.Set(Cdot1.X, Cdot1.Y, Cdot2); Cdot.NegateLocal(); Vec3 f1 = Pool.PopVec3(); Vec3 df = Pool.PopVec3(); f1.Set(Impulse); K.Solve33ToOut(Cdot.NegateLocal(), df); //Cdot.negateLocal(); not used anymore Impulse.AddLocal(df); if (LimitState == LimitState.AtLower) { Impulse.Z = MathUtils.Max(Impulse.Z, 0.0f); } else if (LimitState == LimitState.AtUpper) { Impulse.Z = MathUtils.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) Vec2 b = Pool.PopVec2(); Vec2 f2r = Pool.PopVec2(); temp.Set(K.Ez.X, K.Ez.Y).MulLocal(Impulse.Z - f1.Z); b.Set(Cdot1).NegateLocal().SubLocal(temp); temp.Set(f1.X, f1.Y); K.Solve22ToOut(b, f2r); f2r.AddLocal(temp); Impulse.X = f2r.X; Impulse.Y = f2r.Y; df.Set(Impulse).SubLocal(f1); Vec2 P = Pool.PopVec2(); temp.Set(Axis).MulLocal(df.Z); P.Set(Perp).MulLocal(df.X).AddLocal(temp); float LA = df.X * S1 + df.Y + df.Z * A1; float LB = df.X * S2 + df.Y + df.Z * 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(); K.Solve22ToOut(Cdot1.NegateLocal(), df); Cdot1.NegateLocal(); Impulse.X += df.X; Impulse.Y += df.Y; Vec2 P = Pool.PopVec2(); P.Set(Perp).MulLocal(df.X); float LA = df.X * S1 + df.Y; float LB = df.X * 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(Cdot1); Cdot1.X = Vec2.Dot(Perp, temp.Set(vB).SubLocal(vA)) + S2 * wB - 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(K, df, temp); Cdot1.X += 0.0f; } Pool.PushVec2(3); } data.Velocities[IndexA].V.Set(vA); data.Velocities[IndexA].W = wA; data.Velocities[IndexB].V.Set(vB); data.Velocities[IndexB].W = wB; Pool.PushVec2(2); }
/// <seealso cref="Joint.solvePositionConstraints(float)"></seealso> 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(); Vec2 rA = Pool.PopVec2(); Vec2 rB = Pool.PopVec2(); qA.Set(aA); qB.Set(aB); float mA = m_invMassA, mB = m_invMassB; float iA = m_invIA, iB = m_invIB; Rot.MulToOutUnsafe(qA, temp.Set(LocalAnchorA).SubLocal(m_localCenterA), rA); Rot.MulToOutUnsafe(qB, temp.Set(LocalAnchorB).SubLocal(m_localCenterB), rB); float 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 (Frequency > 0.0f) { C1.Set(cB).AddLocal(rB).SubLocal(cA).SubLocal(rA); positionError = C1.Length(); angularError = 0.0f; 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); float 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); } 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.LINEAR_SLOP && angularError <= Settings.ANGULAR_SLOP); }
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; bool fixedRotation = (iA + iB == 0.0f); // Solve motor constraint. if (m_motorEnabled && LimitState != LimitState.Equal && fixedRotation == false) { float Cdot = wB - wA - m_motorSpeed; float impulse = (-MotorMass) * Cdot; float oldImpulse = MotorImpulse; float maxImpulse = data.Step.Dt * m_maxMotorTorque; MotorImpulse = MathUtils.Clamp(MotorImpulse + impulse, -maxImpulse, maxImpulse); impulse = MotorImpulse - oldImpulse; wA -= iA * impulse; wB += iB * impulse; } Vec2 temp = Pool.PopVec2(); // Solve limit constraint. if (m_limitEnabled && LimitState != LimitState.Inactive && fixedRotation == false) { Vec2 Cdot1 = Pool.PopVec2(); Vec3 Cdot = Pool.PopVec3(); // Solve point-to-point constraint Vec2.CrossToOutUnsafe(wA, RA, temp); Vec2.CrossToOutUnsafe(wB, RB, Cdot1); Cdot1.AddLocal(vB).SubLocal(vA).SubLocal(temp); float Cdot2 = wB - wA; Cdot.Set(Cdot1.X, Cdot1.Y, Cdot2); Vec3 impulse = Pool.PopVec3(); Mass.Solve33ToOut(Cdot, impulse); impulse.NegateLocal(); if (LimitState == LimitState.Equal) { Impulse.AddLocal(impulse); } else if (LimitState == LimitState.AtLower) { float newImpulse = Impulse.Z + impulse.Z; if (newImpulse < 0.0f) { //UPGRADE_NOTE: Final was removed from the declaration of 'rhs '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" Vec2 rhs = Pool.PopVec2(); rhs.Set(Mass.Ez.X, Mass.Ez.Y).MulLocal(Impulse.Z).SubLocal(Cdot1); Mass.Solve22ToOut(rhs, temp); impulse.X = temp.X; impulse.Y = temp.Y; impulse.Z = -Impulse.Z; Impulse.X += temp.X; Impulse.Y += temp.Y; Impulse.Z = 0.0f; Pool.PushVec2(1); } else { Impulse.AddLocal(impulse); } } else if (LimitState == LimitState.AtUpper) { float newImpulse = Impulse.Z + impulse.Z; if (newImpulse > 0.0f) { Vec2 rhs = Pool.PopVec2(); rhs.Set(Mass.Ez.X, Mass.Ez.Y).MulLocal(Impulse.Z).SubLocal(Cdot1); Mass.Solve22ToOut(rhs, temp); impulse.X = temp.X; impulse.Y = temp.Y; impulse.Z = -Impulse.Z; Impulse.X += temp.X; Impulse.Y += temp.Y; Impulse.Z = 0.0f; Pool.PushVec2(1); } else { 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(RA, P) + impulse.Z); vB.X += mB * P.X; vB.Y += mB * P.Y; wB += iB * (Vec2.Cross(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, RA, temp); Vec2.CrossToOutUnsafe(wB, RB, Cdot); Cdot.AddLocal(vB).SubLocal(vA).SubLocal(temp); Mass.Solve22ToOut(Cdot.NegateLocal(), impulse); // just leave negated Impulse.X += impulse.X; Impulse.Y += impulse.Y; vA.X -= mA * impulse.X; vA.Y -= mA * impulse.Y; wA -= iA * Vec2.Cross(RA, impulse); vB.X += mB * impulse.X; vB.Y += mB * impulse.Y; wB += iB * Vec2.Cross(RB, impulse); Pool.PushVec2(2); } data.Velocities[IndexA].V.Set(vA); data.Velocities[IndexA].W = wA; data.Velocities[IndexB].V.Set(vB); data.Velocities[IndexB].W = wB; Pool.PushVec2(1); }