首页 > 解决方案 > Ball to Ball Collision resolution Stick together

问题描述

If have the following code which simulates a ball to Ball collision. My problem is, that the balls bounce against each other. I want to have the balls stick together like snow particles. Does anyone know how to do that?

/**
 * Rotates coordinate system for velocities
 *
 * Takes velocities and alters them as if the coordinate system they're on was rotated
 *
 * @param  Object | velocity | The velocity of an individual particle
 * @param  Float  | angle    | The angle of collision between two objects in radians
 * @return Object | The altered x and y velocities after the coordinate system has been rotated
 */

glm::vec3 rotateVel(glm::vec3 vel, float angle) {
    glm::vec3 rotatedVelocities = {
        vel.x * std::cos(angle) - vel.y * std::sin(angle),
        vel.x * std::sin(angle) + vel.y * std::cos(angle),
        0
    };

    return rotatedVelocities;
}

/**
 * Swaps out two colliding particles' x and y velocities after running through
 * an elastic collision reaction equation
 *
 * @param  Object | particle      | A particle object with x and y coordinates, plus velocity
 * @param  Object | otherParticle | A particle object with x and y coordinates, plus velocity
 * @return Null | Does not return a value
 */

void resolveCollision(Particle& particle, Particle& otherParticle) {
    float xVelocityDiff = particle.speed.x - otherParticle.speed.x;
    float yVelocityDiff = particle.speed.y - otherParticle.speed.y;

    float xDist = otherParticle.pos.x - particle.pos.x;
    float yDist = otherParticle.pos.y - particle.pos.y;

    // Prevent accidental overlap of particles
    if (xVelocityDiff * xDist + yVelocityDiff * yDist >= 0) {

        // Grab angle between the two colliding particles
        float angle = -std::atan2(otherParticle.pos.y - particle.pos.y, otherParticle.pos.x - particle.pos.x);

        // Store mass in var for better readability in collision equation
        float m1 = particle.mass;
        float m2 = otherParticle.mass;

        // Velocity before equation
        glm::vec3 u1 = rotateVel(particle.speed, angle);
        glm::vec3 u2 = rotateVel(otherParticle.speed, angle);

        // Velocity after 1d collision equation
        glm::vec3 v1(u1.x * (m1 - m2) / (m1 + m2) + u2.x * 2 * m2 / (m1 + m2),
            u1.y,
            0.0);
        glm::vec3 v2(u2.x * (m1 - m2) / (m1 + m2) + u1.x * 2 * m2 / (m1 + m2),
            u2.y,
            0.0);

        // Final velocity after rotating axis back to original location
        glm::vec3 vFinal1 = rotateVel(v1, -angle);
        glm::vec3 vFinal2 = rotateVel(v2, -angle);

        // Swap particle velocities for realistic bounce effect
        particle.speed.x = vFinal1.x *0.5;
        particle.speed.y = vFinal1.y * 0.5;

        otherParticle.speed.x = vFinal2.x * 0.5;
        otherParticle.speed.y = vFinal2.y * 0.5;
    }
}

I understand the code but don't know where to change it to get the result I want.

标签: c++graphicscollision-detectionglm-math

解决方案


void resolveCollision(Particle& particle, Particle& otherParticle) {
    float xVelocityDiff = particle.speed.x - otherParticle.speed.x;
    float yVelocityDiff = particle.speed.y - otherParticle.speed.y;

    float xDist = otherParticle.pos.x - particle.pos.x;
    float yDist = otherParticle.pos.y - particle.pos.y;

    // Prevent accidental overlap of particles
    if (xVelocityDiff * xDist + yVelocityDiff * yDist >= 0) {

        // Grab angle between the two colliding particles
        float angle = -std::atan2(otherParticle.pos.y - particle.pos.y, otherParticle.pos.x - particle.pos.x);

        // Store mass in var for better readability in collision equation
        float m1 = particle.mass;
        float m2 = otherParticle.mass;

        // Velocity before equation
        glm::vec3 u1 = rotateVel(particle.speed, angle);
        glm::vec3 u2 = rotateVel(otherParticle.speed, angle);

        // Velocity after 1d collision equation
        glm::vec3 v1(u1.x * (m1 - m2) / (m1 + m2) + u2.x * 2 * m2 / (m1 + m2),
            u1.y,
            0.0);
        glm::vec3 v2(u2.x * (m1 - m2) / (m1 + m2) + u1.x * 2 * m2 / (m1 + m2),
            u2.y,
            0.0);

        // Final velocity after rotating axis back to original location
        glm::vec3 vFinal1 = rotateVel(v1, -angle);
        glm::vec3 vFinal2 = rotateVel(v2, -angle);

        // Swap particle velocities for realistic bounce effect
        particle.speed.x = vFinal1.x;
        particle.speed.y = vFinal1.y;

        otherParticle.speed.x = vFinal1.x;
        otherParticle.speed.y = vFinal1.y;
    }
}

This solution worked for me.


推荐阅读