Friday, March 14, 2025
HomeGame developmentc++ - Collision response with exterior forces & small relative velocities

c++ – Collision response with exterior forces & small relative velocities


How do I cope with collisions which have small relative velocities, however exterior forces resembling gravity?

Think about a situation with a field in 2D, rotated 30 levels, and positioned on the bottom.

enter image description here

Gravity acts on the field, transferring it down into the bottom, and inflicting a collision.
The collision is resolved utilizing an impulse primarily based collision decision mannequin, however as a result of the relative velocity of the field on the level of collision is near 0, the impulse may be very small.

This appears to trigger the field to sit down 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 element 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 option to account for this?

Sharing some code beneath in case there’s a bug:

float Simulator::calculateCollisionImpulse(const CollisionDetails &collision, const glm::vec2 &regular,
                                     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};

    // Complete angular momentum within the route 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 &regular,
                                      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));
}



Supply hyperlink

RELATED ARTICLES

Most Popular

Recent Comments