How to avoid particles glitching together in an el

2019-07-21 00:59发布

Here is a short video in which can be seen that groups of two (maybe more) particles are glitched into each other.

The source-code can be found here.

And this is the code I use to calculate the collisions with:

function collisionPhysics()
{
    for (var i = 0; i < N - 1; ++i)
    {
        for (var j = i + 1; j < N; ++j)
        {
            var Dx = objects[j].x - objects[i].x;    // Difference in X direction between objects[i] and objects[j].
            var Dy = objects[j].y - objects[i].y;    // Difference in Y direction between objects[i] and objects[j].
            var D2 = Dx * Dx + Dy * Dy;              // Distance between objects[i] and objects[j] squared.

            if (D2 <= (objects[i].rad + objects[j].rad) * (objects[i].rad + objects[j].rad))    // Colision check could be inserted here, reusing D2.
            {
                var delta = 2 * (Dx * (objects[i].Vx - objects[j].Vx) + Dy * (objects[i].Vy - objects[j].Vy)) / (D2 * (objects[i].m + objects[j].m));
                objects[i].Vx += -objects[i].m * delta * Dx;
                objects[i].Vy += -objects[i].m * delta * Dy;
                objects[j].Vx +=  objects[j].m * delta * Dx;
                objects[j].Vy +=  objects[j].m * delta * Dy;
            }
        }
    }
}

Edit 2013/04/06: The issue nwellcome mentioned was causing the strange behavior. And this adjusted function should solve this, not sure if it could be improve performance wise but it works:

function collisionPhysics()
{
    for (var i = 0; i < N - 1; ++i)
    {
        for (var j = i + 1; j < N; ++j)
        {
            var Dx = objects[j].x - objects[i].x + timeStep * (objects[j].u - objects[i].u);
            var Dy = objects[j].y - objects[i].y + timeStep * (objects[j].v - objects[i].v);
            var D2 = Dx * Dx + Dy * Dy;              // Distance between objects[i] and objects[j] squared.

            if (D2 <= (objects[i].r + objects[j].r) * (objects[i].r + objects[j].r))    // Colision check could be inserted here, reusing D2.
            {
                objects[i].col = true;
                objects[j].col = true;
                var dx = objects[j].x - objects[i].x;
                var dy = objects[j].y - objects[i].y;
                var du = objects[j].u - objects[i].u;
                var dv = objects[j].v - objects[i].v;
                var dr = objects[j].r + objects[i].r;
                var dt = (-Math.sqrt(2 * dx * du * dy * dv - du * du * (dy * dy - dr * dr) - dv * dv * (dx * dx - dr * dr)) - dx * du - dy * dv) / (du * du + dv * dv);
                Dx = objects[j].x - objects[i].x + dt * (objects[j].u - objects[i].u);
                Dy = objects[j].y - objects[i].y + dt * (objects[j].v - objects[i].v);
                D2 = Dx * Dx + Dy * Dy;
                var delta = 2 * (Dx * (objects[i].u - objects[j].u) + Dy * (objects[i].v - objects[j].v)) / (D2 * (objects[i].m + objects[j].m));
                objects[i].u += -objects[i].m * delta * Dx;
                objects[i].v += -objects[i].m * delta * Dy;
                objects[j].u +=  objects[j].m * delta * Dx;
                objects[j].v +=  objects[j].m * delta * Dy;
                objects[i].x += (timeStep - dt) * objects[i].u;
                objects[i].y += (timeStep - dt) * objects[i].v; 
                objects[j].x += (timeStep - dt) * objects[j].u;
                objects[j].y += (timeStep - dt) * objects[j].v;
            }
        }
    }
}

1条回答
淡お忘
2楼-- · 2019-07-21 01:50

The problem is your method of collision resolution doesn't ensure that the particles won't still intersect at the beginning of the next frame.

When you find a collision, you need to work backward to the point in time when collision between boundary of the particles happened and resolve the collision from there. Refer to this game development answer to a similar question for a method of doing that.

查看更多
登录 后发表回答