How do I take care of collisions which have small relative velocities, however exterior forces reminiscent of gravity?
Think about a situation with a field in 2D, rotated 30 levels, and positioned on the bottom.
Gravity acts on the field, transferring it down into the bottom, and inflicting a collision.
The collision is resolved utilizing an impulse based mostly collision decision mannequin, however as a result of the relative velocity of the field on the level of collision is near 0, the impulse could be very small.
This appears to trigger the field to take a seat on its edge for an unnaturally lengthy interval, till it lastly builds up sufficient angular velocity to fall again onto its aspect.
It appears like my collision decision mannequin is lacking a part that may account for the impact of exterior forces like gravity on a collision that takes place with low relative velocity. Is there an accurate solution to account for this?
Sharing some code beneath in case there’s a bug:
float Simulator::calculateCollisionImpulse(const CollisionDetails &collision, const glm::vec2 ®ular,
const glm::vec2 &relative_velocity,
const glm::vec2 &relative_a, const glm::vec2 &relative_b,
float total_mass) {
BodyId id_a = collision.bodyA();
BodyId id_b = collision.bodyB();
RigidBody& body_a = m_bodies[id_a];
RigidBody& body_b = m_bodies[id_b];
float impulse_force = glm::dot(relative_velocity, regular);
float inertia_magnitude_a = body_a.invert_moment * Vec2Utilities::cross2(relative_a, regular);
float inertia_magnitude_b = body_b.invert_moment * Vec2Utilities::cross2(relative_b, regular);
// Compute cross product: inertia x relative_position
glm::vec2 inertia_a = {-inertia_magnitude_a * relative_a.y,inertia_magnitude_a * relative_a.x};
glm::vec2 inertia_b = {-inertia_magnitude_b * relative_b.y,inertia_magnitude_b * relative_b.x};
// Whole angular momentum within the path of collision
float angular_effect = glm::dot(inertia_a + inertia_b, regular);
// Calculate whole impulse
const float restitution = body_a.restitution * body_b.restitution;
return (-(1.0f + restitution) * impulse_force) / (total_mass + angular_effect);
}
void Simulator::applyCollisionImpulse(const CollisionDetails &collision, const glm::vec2 ®ular,
const glm::vec2 &relative_a, const glm::vec2 &relative_b,
float impulse) {
BodyId id_a = collision.bodyA();
BodyId id_b = collision.bodyB();
glm::vec2 full_impulse = regular * impulse;
addImpulse(id_a, full_impulse);
addImpulse(id_b, -full_impulse);
addAngularImpulse(id_a, Vec2Utilities::cross2(relative_a, full_impulse));
addAngularImpulse(id_b, Vec2Utilities::cross2(relative_b, -full_impulse));
}