matter-js icon indicating copy to clipboard operation
matter-js copied to clipboard

Very light bodies can move very heavy bodies

Open fominvic81 opened this issue 4 years ago • 3 comments

When a light body crashes into a heavy one, it penetrates into the middle of the heavy one with great speed, then the engine pushes both bodies away from each other, each by half an immersion, and thus if a mosquito-weighted body crashes into a body whose mass is Earth's mass, then it can move it, and without appling force.

This can be corrected if the body with more mass is pushed away with less force, for example: var k = bodyA.mass/bodyB.mass; if (bodyA.isStatic) {...} if (bodyB.isStatic) {...}

fominvic81 avatar Jun 22 '20 08:06 fominvic81

As it stands in a deep collision like this, the position solver does not take in to account relative mass or velocity, it applies that correction equally (the velocity solver does take this into account though). There potentially an improvement to be made here though but would require some investigation, thanks for raising.

liabru avatar Sep 12 '20 21:09 liabru

In my project I've managed to fix it by adding massFactor in Resolver.js, function solvePosition:

      `if (!(bodyA.isStatic || bodyA.isSleeping)) {
            const massFactor = 2 * bodyB.mass / (bodyA.mass + bodyB.mass);
            contactShare = Resolver._positionDampen / bodyA.totalContacts;
            bodyA.positionImpulse.x += normal.x * positionImpulse * contactShare * massFactor;
            bodyA.positionImpulse.y += normal.y * positionImpulse * contactShare * massFactor;
        }

        if (!(bodyB.isStatic || bodyB.isSleeping)) {
            const massFactor = 2 * bodyA.mass / (bodyA.mass + bodyB.mass);
            contactShare = Resolver._positionDampen / bodyB.totalContacts;
            bodyB.positionImpulse.x -= normal.x * positionImpulse * contactShare * massFactor;
            bodyB.positionImpulse.y -= normal.y * positionImpulse * contactShare * massFactor;
        }`

podprad avatar Jan 15 '21 19:01 podprad

Working on this again I start to remember why it wasn't originally implemented that way, I'll explain as it's kind of unexpected.

By design the position solver only cares about resolving the geometric overlap (since bodies are all equally rigid), while the collision response is left to the velocity solver. Normally you'd expect a massive object to physically destroy a very small object in collision, but in a rigid body simulation this can't happen.

So when small bodies have deep collisions with massive ones, the solver must drastically separate both bodies somehow, which it does geometrically. This normally works very well, but in these extreme cases the solution becomes too ambiguous, leading to unintuitive results.

I have some ideas to improve this that will help in these cases, which I'll post here if there's progress.

liabru avatar Feb 13 '21 12:02 liabru