# how to handle interpenetration?

This topic is 4916 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi. I've been working on a rigid body physics engine (in 2D only) for a project I'm working on, and all my algorithms are working great except for the one which handles interpenetration between bodies. The method I'm currently using basically undoes the calculations performed in the last update, and then recalculates but with a smaller time step. It repeats this until the collision detection algorithm says there's no longer any interpenetration. This sounds good on paper, but in practice all that happens is the bodies get stuck on each other, both totally motionless. I usually have to ctrl-alt-delete out of the program. Here's the code for the algorithm:
ZcRigidBody2DCollision collision = ZcRigidBody2DCollision(rigid_body1, rigid_body2);
int status = collision.determine_status();

if (status == ZC_RIGIDBODY2D_COLLISION_STATUS_TOUCHING)
collision.calculate_reactions();
else if (status == ZC_RIGIDBODY2D_COLLISION_STATUS_INTERPENETRATING) {

float delta_time_copy = delta_time;
ZcRigidBody2D rigid_body1_copy = rigid_body1;
ZcRigidBody2D rigid_body2_copy = rigid_body2;

for (bool done = false; (!done) && (delta_time > 0.0001f);) {

ZcVector2D temp = rigid_body1_copy.get_linear_velocity();
temp *= -1;
rigid_body1_copy.set_linear_velocity(temp);
temp = rigid_body1_copy.get_sum_forces().get_force_vector();
temp *= -1;
rigid_body1_copy.get_sum_forces().set_force_vector(temp);
temp = rigid_body1_copy.get_friction_force().get_force_vector();
temp *= -1;
rigid_body1_copy.get_friction_force().set_force_vector(temp);

temp = rigid_body2_copy.get_linear_velocity();
temp *= -1;
rigid_body2_copy.set_linear_velocity(temp);
temp = rigid_body2_copy.get_sum_forces().get_force_vector();
temp *= -1;
rigid_body2_copy.get_sum_forces().set_force_vector(temp);
temp = rigid_body2_copy.get_friction_force().get_force_vector();
temp *= -1;
rigid_body2_copy.get_friction_force().set_force_vector(temp);

rigid_body1_copy.simulate(delta_time_copy);
rigid_body2_copy.simulate(delta_time_copy);

delta_time_copy /= 2;

rigid_body1_copy.get_linear_velocity();
temp *= -1;
rigid_body1_copy.set_linear_velocity(temp);
temp = rigid_body1_copy.get_sum_forces().get_force_vector();
temp *= -1;
rigid_body1_copy.get_sum_forces().set_force_vector(temp);
temp = rigid_body1_copy.get_friction_force().get_force_vector();
temp *= -1;
rigid_body1_copy.get_friction_force().set_force_vector(temp);

temp = rigid_body2_copy.get_linear_velocity();
temp *= -1;
rigid_body2_copy.set_linear_velocity(temp);
temp = rigid_body2_copy.get_sum_forces().get_force_vector();
temp *= -1;
rigid_body2_copy.get_sum_forces().set_force_vector(temp);
temp = rigid_body2_copy.get_friction_force().get_force_vector();
temp *= -1;
rigid_body2_copy.get_friction_force().set_force_vector(temp);

rigid_body1_copy.simulate(delta_time_copy);
rigid_body2_copy.simulate(delta_time_copy);

rigid_body1 = rigid_body1_copy;
rigid_body2 = rigid_body2_copy;

collision.set_rigid_body1(rigid_body1);
collision.set_rigid_body2(rigid_body2);

status = collision.determine_status();

if (status != ZC_RIGIDBODY2D_COLLISION_STATUS_INTERPENETRATING)
done = true;
} // end for

collision.calculate_reactions();
} // end if


This code was taken from a program I have written specifically to test the rigid body physics system. rigid_body1 and rigid_body2 are both objects of type ZcRigidBody2D, which is a class describing a single rigid body in 2 dimensions. It also provides functionality for updating the body's properties. Class ZcRigidBody2DCollision is basically an encapsulation of the collision detection and response algorithms (which I am sure both work properly; I have rigourously tested each.), and it's constructor takes as arguments the two bodies which were involved in the collision. ZcRigidBody2DCollision::determine_status() is the collision detection algorithm, and ZcRigidBody2DCollision::calculate_reactions() is the collision response algorithm. Can somebody please, please help me out. I presume what's happening is the program is getting stuck in the 'for' loop in the code above, but I'm not sure why. Any help would be GREATLY appreciated!

##### Share on other sites
I think it's a bad idea in general. Is that stuff working when objects are already inter-penetrating? Then you'll go into infinite loop.

Maybe deal with inter-penetrations as collisions or contacts and use a post-process to remove or reduce to the best of your abilities inter-penetrations. Then you'll run only one physics iteration per objects, which will be a lot lot faster.

##### Share on other sites
BTW, this is a MAJOR pain in the ass when doing rigid body dynamics. it's not easily solved, and usually approximated (badly, as far as my methods are concerned).

to stop interpenetration, you have to setup constraints and such and solve them globally. hmmmm.... Pain....

##### Share on other sites
I guess this pain is why David Wu and others argue that penalty-based methods aren't so bad after all. But, of course, then you have to use an implicit integrator.

##### Share on other sites
Hey olii, I found an article you wrote a while back that discusses using seperation planes to test for collisions. You then talk about how you can use that algorithm to push objects out of each other. I think I'm going to try and incorporate this algorithm into my current system, and see if that works.

BTW, it's a great article!

##### Share on other sites
you have to be careful though. Calculating penetration vectors can be tricky for non-convex objects. It relies on getting the MTD (minimum translational distance) to push objects apart, which is fine with convex objects, but for concave objects, can lead to weird results if done naively (objects creeping along surfaces, or just moving plane wrong, or slowly getting sucked inside another object).

hence the problem, as far as I'm concerned, with doing arbitrary mesh collisions. Easy to detect, pain to work with good contacts.

##### Share on other sites
Okay. After much work, I have come to the somewhat dissapointing conclusion that, due to the nature of my engine, I just can't use seperation planes. Are there any other good methods for stopping interpenetration? Perhaps something which is performed after collision response?

##### Share on other sites

http://www.harveycartel.org/metanet/tutorials/tutorialA.html

It seems they have done a reasonable job of 2d rigid body physics. If you can live with spheres ( or ellipsoids with a tiny bit of work ), olii has a great demo :

http://www.members.lycos.co.uk/olivierrenault/rigid.zip

• 34
• 12
• 10
• 9
• 9
• ### Forum Statistics

• Total Topics
631354
• Total Posts
2999507
×