Search code examples
algorithmsimulationphysicscollisionparticles

Particle (cloth) to sphere collision


What is the proper way to add a sphere constraint to a cloth sim?

I am trying to add a sphere (or capsule) constraing to Skeel Lee's cloth simulation source code, but I am not sure how to do it properly.

I created a rather simple constraint which "kicks" the particle back out of the sphere in the opposite direction (opposite from the vector towards the center):

void SatisfySphereConstraints()
{
    foreach (var simObj in this.simObjects)
        simObj.CurrPosition += SphereConstraint(simObj.CurrPosition, _center, _radius);
}

Vector3 SphereConstraint(Vector3 position, Vector3 center, float radius)
{
    var delta = position - center;
    var distance = delta.Length();
    if (distance < radius)
        return (radius - distance) * delta / distance;

    return Vector3.Zero;
}

And then I inserted the method in the existing code:

ApplyForces();
Integrate();

for (var i = 0; i < constraintIterations; i++)
{
    foreach (Constraint constraint in constraints)
        constraint.SatisfyConstraint();

    SatisfySphereConstraints(); // <-- I added it here
}

The collision code works fairly well for situations like this (C is the center of the sphere, P is the current particle position, P' is the resolved position):

Satisfying sphere constraints for slow particles

But the problem occurs if particles are moving very quickly, because then the particle basically jumps to the other side of the sphere (P1 is the previous position, P2 is the current position, P' is how I think it should be resolved), instead of returning back to the previous position:

Satisfying sphere constraints for fast particles

Since this is a cloth simulation, the cloth basically jumps over the sphere in that case, instead of being "stopped" by the sphere.

Now, I could try to return in the direction of the previous point, but since the sphere might also be moving, I am not sure if P1 is even a valid position (and if it will make sense). Also, it seems to be more computationally expensive - is this how I am supposed to do it, or not?


Solution

  • Cloth like things snapping to the wrong side of an obstacle and getting stuck there is not too uncommon. Even more common is fast moving objects overlapping way too much when the collision is detected.

    A common solution is, on detecting a collision, sub divide the previous step until the collision is less severe and then resolve it. I think you will find trying to detect how deep the collision is to be difficult in your case, but if you could limit the top speed of spheres in your system you could binary split the frames in which collisions occur a fixed number of times and assume it will be good enough?

    if (it collides at time T and didn't at T-1)
        if (it collides at T-0.5)
            try T-0.75
        else
            try T-0.25
    

    etc...

    Are you prepared to accept that it will sometimes be wrong, or does it have to be always a good result?