How to find the velocity of 2 colliding rigid bodies?

87 views Asked by At

So I'm jumping into a physics engine. The colliders for now are spheres and planes. I've found the depth of the collision and the normal at point of contact easy enough, but for the life of me I can not wrap my head around the distribution of energy.

The Bodies contain a Collider, a Mass, a Force vector (velocity * mass), an Elasticity value (0 no bounce, 1 complete bounce) and a Friction value (0 slippery sausage, 1 momentum vampire) I've googled to hell and back and everything comes up with 1D and 2D simplifications, but I've been simply unable to adapt these to 3D.

Edit: I tried following this page: http://www.plasmaphysics.org.uk/collision3d.htm. It seemed so simple but for some reason I still have no bounce with an elasticity of 1.

My implementation is below:

var v = new vec3(
    (body.force.x + other.force.x) / totalMass,
    (body.force.y + other.force.y) / totalMass,
    (body.force.z + other.force.z) / totalMass
    );
body.force.set(
    ((velA.x - v.x) * elasticity + v.x) * body.mass,
    ((velA.y - v.y) * elasticity + v.y) * body.mass,
    ((velA.z - v.z) * elasticity + v.z) * body.mass
    );
other.force.set(
    ((velB.x - v.x) * elasticity + v.x) * other.mass,
    ((velB.y - v.y) * elasticity + v.y) * other.mass,
    ((velB.z - v.z) * elasticity + v.z) * other.mass
    );

For elasticity I have tried both multiplying the elasticity of both bodies and getting the average of them; no change.

1

There are 1 answers

0
user1175522 On BEST ANSWER

So a nights sleep, a bit of thinking and great help taken from the N+ physics explanation page I've hashed something together which works, though not necessarily physically accurate, for the sake of debugging it is split between many variables, but I have commented to the best of my ability.

    //we have detected a collision between A) body B) other
        //note: for the sake of making things easier to think about,
        //      anything moving into or along the collision normal is
        //      referred to as vertical, anything perpendicular to
        //      the collision normal, is referred to as horizontal.
    //minimum translation required to resolve the collision
var mta = collision.normal.clone().multiplyScalar(collision.length);
    //the total mass involved in the collision
var totalMass = body.mass + other.mass;
    //the ratio of the mass belonging to body
var ratioA = body.mass / totalMass;
    //the ratio of the mass belonging to other
var ratioB = other.mass / totalMass;
    //the average elasticity of the collision
var elasticity = (body.elasticity + other.elasticity) / 2.0;
    //the friction of the collision
        //note: average works, but low values have strong effects,
        //      it is easier to work with if they are multiplied
var friction = body.friction * other.friction;
    //the vertical force of body
var vertA = -body.force.clone().normalize().dot(collision.normal);
    //the horizontal force of body
var horrA = 1.0 - Math.abs(vertA);
    //the vertical force of other
var vertB = -other.force.clone().normalize().dot(collision.normal);
    //the horizontal force of other
var horrB = 1.0 - Math.abs(vertB);
    //the amount of force applied on body
var forceA = body.force.length();
    //the amount of force applied on other
var forceB = other.force.length();
    //the amount of vertical force applied on body
var vForceA = forceA * vertA;
    //the amount of vertical force applied on other
var vForceB = forceB * vertB;
    //the amount of horizontal force applied on body
var hForceA = forceA * horrA;
    //the amount of horizontal force applied on other
var hForceB = forceB * horrB;
    //the total vertical force of the collision
var verticalForce = (vForceA + vForceB) * elasticity;
    //remove all vertical force from body
    //resulting in a horizontal force vector
body.force.add(collision.normal.clone().multiplyScalar(forceA * vertA));
    //apply friction to the horizontal force vector of body
body.force.add(body.force.clone().normalize().multiplyScalar(-friction * hForceA * body.imass));
    //apply the new vertical force to body
body.force.add(collision.normal.clone().multiplyScalar(verticalForce * ratioA));
    //remove all vertical force from other
    //resulting in a horizontal force vector
other.force.add(collision.normal.clone().multiplyScalar(-forceB * vertB));
    //apply friction to the horizontal force vector of other
other.force.add(other.force.clone().normalize().multiplyScalar(-friction * hForceB * other.imass));
    //apply the new vertical force to other
other.force.add(collision.normal.clone().multiplyScalar(-verticalForce * ratioB));
    //resolve collision taking into consideration mass
body.transform.position.sub(mta.clone().multiplyScalar(ratioA));
other.transform.position.add(mta.clone().multiplyScalar(ratioB));