Impulses causing both objects to drift in normal direction when in contact.

Started by
20 comments, last by Spa8nky 14 years, 1 month ago
I may have messed you up by using HasInfiniteMass where you had HasFinateMass (I misread), but it probably doesn't affect the results you're seeing.

In any case, you apparently changed HasFiniteMass to HasInfiniteMass. Did you reverse the logic for "if( !HasFinateMass )" to "if( HasInfinateMass )"?
Quote:Position is the world position of the shape. Centre no longer exists as a property as it has been replace by Position.

Just to see the changes you've made (it's getting a little difficult to follow at this point), could you post the "collision resolving" code as you now have it?

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Advertisement
The collision response code is a follows:

            // Collect all contacts from collision detection then solve them one by one            List<Contact2D> contacts = detector.contact_List;            // Iterate backwards through contacts so they can be removed from the list in the same loop            for (int i = contacts.Count - 1; i >= 0; i--)            {                Contact2D contact = contacts;                RigidBody2D a = contact.body[0];                               RigidBody2D b = contact.body[1];                                // Correct collision shape positions                a.Shape.Position += contacts.normal * contacts.penetration;                b.Shape.Position += -contacts.normal * contacts.penetration;                                // Coefficient of restitution                float e = 0.9f; // BOING!                // Calculate relative velocity                Vector2 velocity_Relative = a.Velocity - b.Velocity;                // Calculate scalar impulse                float j = -(1f + e) * Vector2.Dot(velocity_Relative, contact.normal);                // The following is not needed if normal is normalised (unit length):                //j /= Vector2.Dot(contact.normal, contact.normal * (a.Mass_Inverse + b.Mass_Inverse));                // Calculate vector impulse                Vector2 impulse = j * contact.normal;                // Add impulse force at contact point for each body                a.ApplyImpulse(impulse, contact.point);                // Negate the force for the opposite body (Newton's Third Law)                b.ApplyImpulse(-impulse, contact.point);                // Remove this contact now that it has been resolved                contacts.RemoveAt(i);            }


The impulse is applied inside the body class as follows:

        public void ApplyImpulse(Vector2 impulse, Vector2 point)        {            // v2 = v1 + j/m * n            velocity_Linear += mass_Inverse * impulse;        }


The only other aspect of collision response is at the end of the body's Integrate() method:

            // Update the shape             shape.Position = position;            shape.Rotation = rotation;


Thanks again.
I'm thinking at this point (your code's just a bit too convoluted for me to keep straight just from inspection), you should start checking each step (or small sequence of steps) to make sure it's doing what you expect - set breakpoints or output debug statements for the important steps.

It seems the most obvious place to start is to check shape positions in your collision routine to ensure they move away from the collision position as you want them to do, before you apply any other forces.

If that's as expected, check the positions after 1 or 2 forces have been applied.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

If I add a small epsilon value to the impulse and remove the correction of the shapes from the collision resolution stage then that stops the drifting but causes object b to stutter a very small amount on the surface of a.

            for (int i = contacts.Count - 1; i >= 0; i--)            {                Contact2D contact = contacts;                RigidBody2D a = contact.body[0];                // Solid object                RigidBody2D b = contact.body[1];                // Man                // Correct collision shape positions                //a.Shape.Position += contacts.normal * contacts.penetration;                //b.Shape.Position += -contacts.normal * contacts.penetration;                // Coefficient of restitution                float e = 0.9f; // BOING!                // Calculate relative velocity                Vector2 velocity_Relative = a.Velocity - b.Velocity;                // Calculate scalar impulse                float j = -(1f + e) * Vector2.Dot(velocity_Relative, contact.normal);                j += 0.01f;        // SMALL EPSILON VALUE                // The following is not needed if normal is normalised (unit length):                //j /= Vector2.Dot(contact.normal, contact.normal * (a.Mass_Inverse + b.Mass_Inverse));                // Calculate vector impulse                Vector2 impulse = j * contact.normal;                // Add impulse force at contact point for each body                a.ApplyImpulse(impulse, contact.point);                // Negate the force for the opposite body (Newton's Third Law)                b.ApplyImpulse(-impulse, contact.point);                // Remove this contact now that it has been resolved                contacts.RemoveAt(i);            }


Should I perhaps test with a projected shape position instead of the shape's current position?

Any thoughts welcome.
Quote:but causes object b to stutter a very small amount on the surface of a.
Due to bouncing from gravity?

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Yes, I believe so. Gravity pulls b into a and the collision is resolved each frame which causes the bouncing only for gravity to pull b into a again.

Any ideas how I can minimize this effect?
Actually, that's consistent with physical phenomena. Eventually it should dampen out. Maybe reduce the force due to gravity (only in the vertical direction, of course) when there's a collision, limiting that portion of the rebound, as if you're making the objects just a little bit "sticky" when they're in contact.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

I can lower the coefficient of restitution, is that what you mean?
Quote:Original post by Spa8nky
I can lower the coefficient of restitution, is that what you mean?

Yep. I didn't see anywhere in your code where you apply it.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

It is applied when resolving collisions:

                // Coefficient of restitution                float e = 0.9f; // BOING!                // Calculate relative velocity                Vector2 velocity_Relative = a.Velocity - b.Velocity;                // Calculate scalar impulse                float j = -(1f + e) * Vector2.Dot(velocity_Relative, contact.normal);                j += 0.01f;        // SMALL EPSILON VALUE


Object b will now slowly sink into vertical walls also if I push in the direction of the wall! What could be the cause of this behaviour?

This topic is closed to new replies.

Advertisement