I simply want to separate two Geoms.

Jun 26, 2009 at 2:04 PM
Edited Jun 26, 2009 at 2:05 PM

Hi, I'm having a bit of trouble here. I'm trying to have certain Geoms respond to collisions depending on what they are colliding with. Some of them will bounce naturally using the physics algorithms already in the system, but for other Geoms I simply want to separate them from the Geoms they are colliding with. I don't want the Bodies of these Geoms to have different velocities once they are separated, which is what the system does now.  Is there anyway to do this without editing the source code of the engine?

I realize that I can control how two Geoms respond by doing my own collision logic within OnCollision() and returning false.  Is there anyway I can simply separate two Geoms using the information sent to the OnCollision() function?

Thanks in advance! I'm really enjoying the engine, and I can see that the developers put a lot of effort into it.

Jun 26, 2009 at 4:37 PM

> I don't want the Bodies of these Geoms to have different velocities once they are separated

i don't quite understand what you mean by that but try the OnSeparation() event and set the g1 and g2.Body.LinearVelocity to what you want

Jun 26, 2009 at 4:42 PM

Sorry, let me try to explain it a bit better...

Say that you throw a ball at a wall. After the ball hits the wall, it is first separated from the wall and then bounces off of it. I simply want it so that when two types of Geoms collide into each other they only separate, not bounce.

Jun 26, 2009 at 4:50 PM

so the ball sticks to the wall?

Jun 26, 2009 at 5:02 PM

Without any other force applied, yes. I'm sorry, I'm not really good at explaining things.

Jun 26, 2009 at 5:11 PM

I assume that turning the restituionCoefficient to 0 on the geometry isn't a solution, because you only want it to happen with collisions with certain other geometries, correct? 

I also think that there would be 2 ways to handle a non-bounce... One would be for the objects to "stick" to each other (which would basically set both velocities to 0 on a collision), and the other would be to have no bounce, but still have some of the original velocity left over?  Imagine a ball hitting a flat surface at a 45 degree angle.  Would it hit the wall and stop, or would it start "rolling" along the wall?

Jun 26, 2009 at 5:33 PM
Edited Jun 26, 2009 at 5:35 PM

I assume that turning the restituionCoefficient to 0 on the geometry isn't a solution, because you only want it to happen with collisions with certain other geometries, correct?

Yes, exactly.

I also think that there would be 2 ways to handle a non-bounce... One would be for the objects to "stick" to each other (which would basically set both velocities to 0 on a collision), and the other would be to have no bounce, but still have some of the original velocity left over?  Imagine a ball hitting a flat surface at a 45 degree angle.  Would it hit the wall and stop, or would it start "rolling" along the wall?

I'm trying to set up a system where a collision's response is determined based on the type of Geoms that are in the collision. By default, though, I would simply like to have a function that just separates the Geoms from each other without changing the velocity each of the Geoms' Bodies had before the collision. After they have been separated, though, the Geoms could react in many different ways, such as the two ways you mentioned. They could also, for example, pick a random angle that is facing away from the collision normal and bounce in that direction, bounce in the direction of the collision normal no matter what, move in opposite directions perpendicular to the collision normal, etc. 

But for now, all I'm looking for is a way to simply separate the two Geoms while maintaining the Geoms' Bodies' velocities that they had before the collision.  I'm just looking for a way to separate the Geoms from each other without changing anything else. That's it.

Also, thanks for your reply.

 

Jun 27, 2009 at 9:27 AM

Jerky might be able to help you, he devised a solution that ought to work very well for making bodies "stick" on a wall.

Jun 27, 2009 at 9:57 AM

If you figure something out, Kon, can you post it here?  I'm interested in a solution to this too.

Jun 27, 2009 at 11:18 AM

I always wanted a way to make objects sticky

so they could go up walls and stuff but yer post it here if anyone finds a good soultion and mabey make a patch if its something that could be added to farseer

Coordinator
Jun 27, 2009 at 5:26 PM

As RogueCommanderIX posted, Jerky has stickiness applied to geometries. He simply create joints at the collisionpoints. Take a look at his great blog where he posted his progress and how to make those sticky geometries.

As for the no-bounce solution. You can subscribe to the OnCollision event and set the RestitutionCoefficient to 0 on both geometries, in the OnSeparation event you set the restituion coefficient back to their original values. Farseer Handle the collisions and fire the collision events way before any physics are calculated, that makes it possible to change physics properties on the fly depending on collisions.

It is just an idea - try it out.

Jun 29, 2009 at 11:57 PM
Edited Jun 30, 2009 at 12:19 AM

Setting the RestitutionCoefficient to 0 on both Geoms still wouldn't give me the behavior I'm looking for as both Bodies would still have different velocities than what they started with.

After examining the source code, I found that there is an internal Vector2 called "linearVelocityBias" that simply pushes the two Geoms apart without doing anything else. Since it is internal, you have to calculate it yourself in order to use it. 

Let P_final be the position of a Geom after a collision and P_initial be the position before a collision. Likewise for V_final for velocity. dt is the change in time between frames.

Vector2 linearVelocityBias = ((P_final - P_initial) / dt) - V_final;

Now to find the separated position P_separation, you must simply do this:

Vector2 P_separation = P_initial + (linearVelocityBias * dt);

myGeom.Body.Position = P_separation;

Using this, I decided on a work-around to get the Geoms separated.

  • First make a class that will store collision data. I will call such a class CollisionWrapper in this explanation.
  • In OnCollision(), make a new CollisionWrapper that stores the data of the two colliding objects before any physics modifications have taken place.  This CollisionWrapper should store the Geoms involved in the collisions as well as the associated Vector2s and floats that dictate the position and rotation of each respective Geom's Body.
    • Add the new CollisionWrapper to a list that holds all "special" collisions for that frame.
  • Let the physics engine treat the two Geoms like any other normal physics object.
  • After the physics engine is done, go through each CollisionWrapper in the CollisionWrapper list.
    • Using the above formulas, calculate the linearVelocityBias for each Geom and apply it to their respective bodies.
    • Get the old velocities, rotation, etc. from the Collision Wrapper that each Geom's Body had before the collision took place. Replace each Geom's Body's current velocity, rotation, etc. with their old values.
  • At this point the all "special" Geoms are separated, and their bodies still retain their old velocities, rotation, etc. Any "special" collision response can now be applied to the Geoms.
  • Clear the CollisionWrapper list.

If you directly apply this method, you may notice that the objects involved seem to "jitter" around a bit. I haven't really been able to find a reliable way to eliminate this effect, but the following order in an application's Update() method seems to work somewhat well.

  • First update each Geom's position on your own using dt, the change in time between frames.
  • Update the physics engine. This will move the Geoms as if they haven't been moved for that frame as well as separate them.
  • Since the physics engine moved the Geoms, you'll have to update each Geom on your own again but with -dt this time. If you do not do this, it will appear as if every Body is moving at twice the velocity that they should move. This makes it so that the physics engine only separated each Geom.
    • This means that after you moved the Geoms back you no longer have to calcuate P_separation as each Geom's Body's position is, in fact, their respective P_separation for that frame.
  • You'll also need to reset any "special" Bodies to have the velocities that they had before the physics engine was updated.
  • At this point the "special" Geoms are separated and their respective Bodies still have their old velocities. You can now go and apply any "special" collision logic.

And yes, I'm aware that I used Geom and Body interchangeably when I shouldn't have, but my sentences seem to become more awkward if I don't.

Coordinator
Jun 30, 2009 at 3:18 AM

The physics engine was not designed to retain the velocity of bodies after they have collided. A collision reaction will produce a velocity other than what was given initially unless you have 100% restitution. Then the velocity will be the same, just reversed.

Anyway, You have to remember than a collision happens when there is an overlap. We let two geometries "collide" and they actually overlap a bit, then we calculate how much they overlap, separate them and apply the physics necessary to give it a proper reaction. The separation is calculated on each contact. A contact is a point (one of the polygonpoints) that touches or intersects the other geometry. The contacts are avaliable in the ContactList when you subscribe to the OnCollision event. You gain access to data such as where the contact is located and how much separation it has. You could simply subscribe to the OnCollision delegate, separate the two geometries and return false (telling the engine to not calculate physics).

This will produce some jitter. It is like this: A----------C---B
Where A is the initial position, B is the next position and C is the corrected position. Remember that a collision will only get reported when two geometries overlap, not before they touch.

This jitter however is very small and can't normally be seen. I hope you found a working solution, if you have any further questions, don't hessitate to ask.

Jun 30, 2009 at 5:38 AM
Edited Jun 30, 2009 at 5:39 AM

Hey, I'm still paying attention, just haven't had much time lately.  Work and new baby have been busy. 

I ended up creating an enum inside the geom class (along with many other things), to help me differentiate between the different types of objects in my simulator.  That allowed me to create custom logic between types of enums (eg. if geom1.type == ground and geom2.type == block, etc).  I am no expert, by any means, but so far that has let me do what I want.  I can elaborate if someone wishes.  I hope to get back to programming soon.  I'll keep an eye on what Kon is doing, it sounds like we could benefit each other.

Cheers,