This project has moved and is read-only. For the latest updates, please go here.

Calculate Impulse without actually colliding.

Topics: User Forum
Feb 14, 2014 at 2:38 AM
Edited Feb 14, 2014 at 7:04 AM
I have two objects, when they collide with each other I return false in the Fixture.OnCollision event, but call a couple of functions here, I want to calculate a theoretical impulse (what would it have been if we did return true).

What I was doing before (when my two objects were colliding) was in PostSolve calculate:
            float maxImpulse = 0.0f;
            int count = contact.Manifold.PointCount;
            for (int i = 0; i < count; ++i)
                maxImpulse = Math.Max(maxImpulse, impulse.points[i].normalImpulse);
The problem is that now that I am cancelling the collision I can no longer use PostSolve which has access to the calculated impulse. What I would like to do is somehow calculate a theoretical impulse, what would it have been if I had allowed these objects to collide. Any ideas on how to do this?

Edit: Maybe I need to start up another physics simulation and run the collision there, then I can see what the impulse would have been if they did collide. Seems like a lot of overhead though.

Edit: I'm currently just trying to calculate some sort of impulse based on the velocity and mass but it is very over simplified and wont take into account any form of glancing blows.
Feb 17, 2014 at 3:27 AM
Edited Feb 17, 2014 at 11:09 PM
I settled for just using the rough calculation ((v1 * m1) plus (v2 * m2)).Length()

Edit: This calculation results in ridiculous behaviour so instead I am trying (v1 - v2).Length() * m0. Where m0 is the mass of the item you are colliding against. This works slightly better then the formula above.
Feb 1, 2017 at 2:57 AM
That wasn't good enough as it failed to factor in many things so now I am doing the following:
xv2 contactPoint;
    xv2 n;
    FarseerPhysics.Common.FixedArray2<Microsoft.Xna.Framework.Vector2> ps;
    contact.GetWorldManifold(out n, out ps);
    contactPoint = ps[0];

float roughImpulseEstimate = 0;
    float massA = fixtureA.Body.Mass;
    float massB = fixtureB.Body.Mass;
    xv2 centerOfMassA = fixtureA.Body.WorldCenter;
    xv2 centerOfMassB = fixtureB.Body.WorldCenter;
    xv2 normalB = xv2.Zero;
    xv2 centerOfMassAToContact = contactPoint - centerOfMassA;
    xv2 centerOfMassBToContact = contactPoint - centerOfMassB;
    if (contact.Manifold.Type == ManifoldType.Circles)
        normalB = centerOfMassBToContact;
        normalB = contact.Manifold.LocalNormal;
    xv2 impactPointVelocityA = fixtureA.Body.LinearVelocity + (fixtureA.Body.AngularVelocity * centerOfMassAToContact);
    xv2 impactPointVelocityB = fixtureB.Body.LinearVelocity + (fixtureB.Body.AngularVelocity * centerOfMassBToContact);
    xv2 relativeVelocity = impactPointVelocityA - impactPointVelocityB;
    relativeVelocity.Y *= -1f;
    float impulseA = centerOfMassAToContact.LengthSquared() * fixtureA.Body.Mass;
    float impulseB = centerOfMassBToContact.LengthSquared() * fixtureB.Body.Mass;
    float elasticity = 1f;
    float top = -(1f + elasticity) * xv2.Dot(relativeVelocity, normalB);
    float bottom =
        (1f / massA) +
        (1f / massB) +
        ((float)Math.Pow((centerOfMassAToContact.Cross(normalB)), 2) / impulseA) +
        ((float)Math.Pow((centerOfMassBToContact.Cross(normalB)), 2) / impulseB);
    roughImpulseEstimate = Math.Abs(top / bottom);