/// <summary> /// Perform one solver iteration. Returns true if converged. /// </summary> /// <param name="baumgarte"></param> /// <returns></returns> public bool Solve(float baumgarte) { float minSeparation = 0.0f; for (int i = 0; i < _count; ++i) { TOIConstraint c = _constraints[i]; Body bodyA = c.bodyA; Body bodyB = c.bodyB; float massA = bodyA._mass; float massB = bodyB._mass; // Only the TOI body should move. if (bodyA == _toiBody) { massB = 0.0f; } else { massA = 0.0f; } float invMassA = massA * bodyA._invMass; float invIA = massA * bodyA._invI; float invMassB = massB * bodyB._invMass; float invIB = massB * bodyB._invI; // Solve normal constraints for (int j = 0; j < c.pointCount; ++j) { TOISolverManifold psm = new TOISolverManifold(ref c, j); Vector2 normal = psm.normal; Vector2 point = psm.point; float separation = psm.separation; Vector2 rA = point - bodyA._sweep.c; Vector2 rB = point - bodyB._sweep.c; // Track max constraint error. minSeparation = Math.Min(minSeparation, separation); // Prevent large corrections and allow slop. float C = MathUtils.Clamp(baumgarte * (separation + Settings.b2_linearSlop), -Settings.b2_maxLinearCorrection, 0.0f); // Compute the effective mass. float rnA = MathUtils.Cross(rA, normal); float rnB = MathUtils.Cross(rB, normal); float K = invMassA + invMassB + invIA * rnA * rnA + invIB * rnB * rnB; // Compute normal impulse float impulse = K > 0.0f ? -C / K : 0.0f; Vector2 P = impulse * normal; bodyA._sweep.c -= invMassA * P; bodyA._sweep.a -= invIA * MathUtils.Cross(rA, P); bodyA.SynchronizeTransform(); bodyB._sweep.c += invMassB * P; bodyB._sweep.a += invIB * MathUtils.Cross(rB, P); bodyB.SynchronizeTransform(); } } // We can't expect minSpeparation >= -b2_linearSlop because we don't // push the separation above -b2_linearSlop. return(minSeparation >= -1.5f * Settings.b2_linearSlop); }
/// <summary> /// Perform one solver iteration. Returns true if converged. /// </summary> /// <param name="baumgarte"></param> /// <returns></returns> public bool Solve(float baumgarte) { float minSeparation = 0.0f; for (int i = 0; i < _count; ++i) { TOIConstraint c = _constraints[i]; Body bodyA = c.bodyA; Body bodyB = c.bodyB; float massA = bodyA._mass; float massB = bodyB._mass; // Only the TOI body should move. if (bodyA == _toiBody) { massB = 0.0f; } else { massA = 0.0f; } float invMassA = massA * bodyA._invMass; float invIA = massA * bodyA._invI; float invMassB = massB * bodyB._invMass; float invIB = massB * bodyB._invI; // Solve normal constraints for (int j = 0; j < c.pointCount; ++j) { TOISolverManifold psm = new TOISolverManifold(ref c, j); Vector2 normal = psm.normal; Vector2 point = psm.point; float separation = psm.separation; Vector2 rA = point - bodyA._sweep.c; Vector2 rB = point - bodyB._sweep.c; // Track max constraint error. minSeparation = Math.Min(minSeparation, separation); // Prevent large corrections and allow slop. float C = MathUtils.Clamp(baumgarte * (separation + Settings.b2_linearSlop), -Settings.b2_maxLinearCorrection, 0.0f); // Compute the effective mass. float rnA = MathUtils.Cross(rA, normal); float rnB = MathUtils.Cross(rB, normal); float K = invMassA + invMassB + invIA * rnA * rnA + invIB * rnB * rnB; // Compute normal impulse float impulse = K > 0.0f ? -C / K : 0.0f; Vector2 P = impulse * normal; bodyA._sweep.c -= invMassA * P; bodyA._sweep.a -= invIA * MathUtils.Cross(rA, P); bodyA.SynchronizeTransform(); bodyB._sweep.c += invMassB * P; bodyB._sweep.a += invIB * MathUtils.Cross(rB, P); bodyB.SynchronizeTransform(); } } // We can't expect minSpeparation >= -b2_linearSlop because we don't // push the separation above -b2_linearSlop. return minSeparation >= -1.5f * Settings.b2_linearSlop; }