0

I'm using Farseer Physics Engine 3.3.1 in a very simple XNA 4 test game. (Note: I'm also tagging this Box2D, because Farseer is a direct port of Box2D and I will happily accept Box2D answers that solve this problem.)

In this game, I'm creating two bodies. The first body is created using BodyFactory.CreateCircle and BodyType.Dynamic. This body can be moved around using the keyboard (which sets Body.LinearVelocity). The second body is created using BodyFactory.CreateRectangle and BodyType.Static. This body is static and never moves.

Then I'm using this code to calculate the force of collision when the two bodies collide:

staticBody.FixtureList[0].AfterCollision += new AfterCollisionEventHandler(AfterCollision);

protected void AfterCollision(Fixture fixtureA, Fixture fixtureB, Contact contact)
{
    float maxImpulse = 0f;
    for (int i = 0; i < contact.Manifold.PointCount; i++)
        maxImpulse = Math.Max(maxImpulse, contact.Manifold.Points[i].NormalImpulse);

    // maxImpulse should contain the force of the collision
}

This code works great if both of these bodies are set to IgnoreCCD=true. I can calculate the force of collision between them 100% reliably. Perfect.

But here's the problem: If I set the bodies to IgnoreCCD=false, that code becomes wildly unpredictable. AfterCollision is called reliably, but for some reason the NormalImpulse is 0 about 75% of the time, so only about one in four collisions is registered. Worse still, the NormalImpulse seems to be zero for completely random reasons. The dynamic body can collide with the static body 10 times in a row in virtually exactly the same way, and only 2 or 3 of the hits will register with a NormalImpulse greater than zero. Setting IgnoreCCD=true on both bodies instantly solves the problem, but then I lose continuous physics detection.

Why is this happening and how can I fix it?


Here's a link to a simple XNA 4 solution that demonstrates this problem in action: http://www.mediafire.com/?a1w242q9sna54j4

Michael
  • 1,968
  • 4
  • 24
  • 40

1 Answers1

0

Although I haven't tried this so I'm not in a position to give a definitive answer, I think this excerpt from the Box2D source code may be relevant:

/// This lets you inspect a contact after the solver is finished. This is useful
/// for inspecting impulses.
/// Note: the contact manifold does not include time of impact impulses, which can be
/// arbitrarily large if the sub-step is small. Hence the impulse is provided explicitly
/// in a separate data structure.
/// Note: this is only called for contacts that are touching, solid, and awake.
virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse)
{
    B2_NOT_USED(contact);
    B2_NOT_USED(impulse);
}

This is probably what the AfterContact is based on, and it's saying that that the intermediate results from all the impulses used to push the body back to the original first contact location for CCD (time of impact impulses) are basically not available to you :(

iforce2d
  • 8,194
  • 3
  • 29
  • 40