matter-js
matter-js copied to clipboard
Very light bodies can move very heavy bodies
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) {...}
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.
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;
}`
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.