static void EstimateCrushing(cpBody body, cpArbiter arb, ref CrushingContext context) { cpVect j = arb.TotalImpulse(); context.magnitudeSum += (float)cpVect.cpvlength(j); context.vectorSum = cpVect.cpvadd(context.vectorSum, j); }
public override void Update(float dt) { base.Update(dt); space.Step(dt); SetSubTitle("Place objects on the scale to weigh them. The ball marks the shapes it's sitting on.\n"); // Sum the total impulse applied to the scale from all collision pairs in the contact graph. // If your compiler supports blocks, your life is a little easier. // You can use the "Block" versions of the functions without needing the callbacks above. cpVect impulseSum = cpVect.Zero; scaleStaticBody.EachArbiter( (a, o) => ScaleIterator(scaleStaticBody, a, ref impulseSum) , null); // Force is the impulse divided by the timestep. float force = cpVect.cpvlength(impulseSum) / dt; // Weight can be found similarly from the gravity vector. cpVect g = space.GetGravity(); // cpSpaceGetGravity(); float weight = cpVect.cpvdot(g, impulseSum) / (cpVect.cpvlengthsq(g) * dt); SetSubTitle(string.Format("Total force: {0}, Total weight: {1}. ", force, weight)); // Highlight and count the number of shapes the ball is touching. int count = 0; ballBody.EachArbiter((a, o) => BallIterator(ballBody, a, ref count), null); SetSubTitle(string.Format("The ball is touching {0} shapes.", count)); CrushingContext crush = new CrushingContext(0.0f, cpVect.Zero); ballBody.EachArbiter((a, o) => EstimateCrushing(ballBody, a, ref crush), null); float crushForce = (crush.magnitudeSum - cpVect.cpvlength(crush.vectorSum)) * dt; if (crushForce > 10.0f) { SetSubTitle(string.Format("The ball is being crushed. (f: {0})", crushForce)); } else { SetSubTitle(string.Format("The ball is not being crushed. (f: {0})", crushForce)); } draw.Clear(); }