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;
Vec2 cA = data.Positions[IndexA].C;
float aA = data.Positions[IndexA].A;
Vec2 vA = data.Velocities[IndexA].V;
float wA = data.Velocities[IndexA].W;
Vec2 cB = data.Positions[IndexB].C;
float aB = data.Positions[IndexB].A;
Vec2 vB = data.Velocities[IndexB].V;
float wB = data.Velocities[IndexB].W;
Rot qA = Pool.PopRot();
Rot qB = Pool.PopRot();
qA.Set(aA);
qB.Set(aB);
// use m_u as temporary variable
Rot.MulToOutUnsafe(qA, U.Set(LocalAnchorA).SubLocal(LocalCenterA), RA);
Rot.MulToOutUnsafe(qB, U.Set(LocalAnchorB).SubLocal(LocalCenterB), RB);
U.Set(cB).AddLocal(RB).SubLocal(cA).SubLocal(RA);
Pool.PushRot(2);
// Handle singularity.
float length = U.Length();
if (length > Settings.LINEAR_SLOP)
{
U.X *= 1.0f / length;
U.Y *= 1.0f / length;
}
else
{
U.Set(0.0f, 0.0f);
}
float crAu = Vec2.Cross(RA, U);
float crBu = Vec2.Cross(RB, U);
float invMass = InvMassA + InvIA * crAu * crAu + InvMassB + InvIB * crBu * crBu;
// Compute the effective mass matrix.
Mass = invMass != 0.0f ? 1.0f / invMass : 0.0f;
if (FrequencyHz > 0.0f)
{
float C = length - Length;
// Frequency
float omega = 2.0f * MathUtils.PI * FrequencyHz;
// 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 (data.Step.WarmStarting)
{
// Scale the impulse to support a variable time step.
Impulse *= data.Step.DtRatio;
Vec2 P = Pool.PopVec2();
P.Set(U).MulLocal(Impulse);
vA.X -= InvMassA * P.X;
vA.Y -= InvMassA * P.Y;
wA -= InvIA * Vec2.Cross(RA, P);
vB.X += InvMassB * P.X;
vB.Y += InvMassB * P.Y;
wB += InvIB * Vec2.Cross(RB, P);
Pool.PushVec2(1);
}
else
{
Impulse = 0.0f;
}
data.Velocities[IndexA].V.Set(vA);
data.Velocities[IndexA].W = wA;
data.Velocities[IndexB].V.Set(vB);
data.Velocities[IndexB].W = wB;
}