Sign in to follow this  

how to handle interpenetration?

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
Have you looked at this page :

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

Share this post


Link to post
Share on other sites

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

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this