liabru / matter-js

a 2D rigid body physics engine for the web ▲● ■
MIT License
16.88k stars 1.97k forks source link

Restitution doesn't seem right sometimes #305

Open TiagoMarinho opened 8 years ago

TiagoMarinho commented 8 years ago

In the following gif both cats share the same physics properties.

two cats fall at a gelatine block, the left one is rotated 90 degrees and doesn't bounce

Cats' restitution is set as 0.1 Ground restitution is set as 0.8

Everything was created using the Matter.Bodies.rectangle.create(x,y,w,h,o) constructor.

The cats bounce normally unless their rotation is set to an angle between 71 and 109 degrees (~1.22 to ~1.91 radians). As soon as the rotation goes to 70 or 110 degrees the cats bounce normally.

Here's a fiddle for reproducing this.

Is that expected behavior?

I've also noticed that static bodies' restitution doesn't play a role in physics simulation. Is that correct?

liabru commented 8 years ago

Is that expected behavior?

This is something I've noticed too. It seems expected that in a 'perfect rigid body simulation' both orientations should just bounce to exactly the same height, but I'm not entirely sure.

Try this: get a plastic pen, hold it vertically and drop it on to a hard table from about 10cm. I could get it to bounce about 1cm back up. Now try the same but drop the pen exactly horizontally and it basically doesn't bounce at all. I'm not sure though if this is more of a materials related effect or if an infinitely rigid body should act the same...

In the engine though I think the reason behind this is the effect of angular momentum, which increases over distance (given that the impacts are calculated at the corners). We can actually test this out by disabling any rotation with the inertia = Infinity trick:

var body1 = Matter.Bodies.rectangle(100,0,10,40, {inertia: Infinity})
body1.restitution = 1
var degrees = 90
Matter.Body.setAngle(body1, degrees / 180 * Math.PI)
var body2 = Matter.Bodies.rectangle(200,0,10,40, {inertia: Infinity})
body2.restitution = 1
var degrees = 0
Matter.Body.setAngle(body2, degrees / 180 * Math.PI)
var body3 = Matter.Bodies.rectangle(100,400,300,100, {inertia: Infinity})
body3.restitution = 1

Now they both (almost) bounce the same! Strangely though, they also seem to bounce forever (but this may be due to neglecting angular effects).

If anyone has any thoughts on this, please drop a comment :)

I've also noticed that static bodies' restitution doesn't play a role in physics simulation. Is that correct?

This is a bit of a tricky issue but it is intentional to make things more intuitive for common cases (see that thread). I could review this if it's causing problems though?

TiagoMarinho commented 8 years ago

Setting inertia to infinity solves my problem entirely, but while your explanation on why this could be expected behavior seems right to me, I don't get why this problem only happens for my simulation when the left rectangle is set to an angle EXACTLY between -71 and -109, and as soon as it go to -70 or -110 (same applies for positive rotations) the restitution fixes itself. Here's a demo:

-80° (it looks like this since -109°): oct-22-2016 02-51-12

-71°: oct-22-2016 02-48-32

-70°: oct-22-2016 02-48-07

Seen from this perspective this looks like unexpected behavior, doesn't it? Anyway, not a big issue after all, just a little weird collision response. Feel free to close the issue if you think this is not a bug at all.

Also, I'm okay with the static bodies' predefined restitution.

rsmmnt commented 5 years ago

So, what about restitution of static bodies?

I have a static rectangle with restitution 0.999 and circle with restitution 0.1, according to docs restitution on collision should be max(bodyA.restitution, bodyB.restitution), but circle doesn't bounce back and sticks.

When circle's restitution is 0.99 it bounces back well, so I guess restitution on collision is the circle's restitution.

I just need to make circle-circle collisions closer to inelastic and circle- static rectangle collisions elastic. How can I do that?

rsmmnt commented 5 years ago

little update - i figured it out, if you create a body like this: var rect = Matter.Bodies.rectangle(x, y, width, height, { isStatic: true, restitution: 0.9 }

restitution is set to 0 anyway, you should modify restitution manually after body creation

hbkmadness commented 5 years ago

little update - i figured it out, if you create a body like this: var rect = Matter.Bodies.rectangle(x, y, width, height, { isStatic: true, restitution: 0.9 }

restitution is set to 0 anyway, you should modify restitution manually after body creation

THIS is so important and should be said in the documentation, that setting isStatic automatically overrides properties. I needed a lot of time until I actually find out this answer. Thanks!