Как найти скорость 2 сталкивающихся твердых тел?
Так что я прыгаю в физический движок. Коллайдерами пока являются сферы и плоскости. Я обнаружил, что глубина столкновения и норма в точке контакта достаточно легки, но за свою жизнь я не могу обернуться вокруг распределения энергии.
Тела содержат коллайдер, массу, вектор силы (скорость * масса), значение упругости (0 без отскока, 1 полный отскок) и значение трения (0 скользкая колбаса, 1 импульс-вампир). Я гуглил в ад и назад, и все приходит с 1D и 2D упрощениями, но я просто не смог приспособить их к 3D.
Изменить: я пытался перейти на эту страницу: http://www.plasmaphysics.org.uk/collision3d.htm. Это казалось таким простым, но по какой-то причине у меня до сих пор нет отскока с эластичностью 1.
Моя реализация ниже:
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
);
Для упругости я попытался как умножить упругость обоих тел, так и получить их среднее; без изменений.
1 ответ
Итак, ночной сон, немного размышлений и большая помощь, взятые со страницы объяснения физики N+, я собрал кое-что вместе, которое работает, хотя и не обязательно физически, ради отладки, оно разбито на множество переменных, но я прокомментировал в меру своих возможностей.
//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));