粒子(布)到球体的碰撞

Particle (cloth) to sphere collision

向布料模拟添加球体约束的正确方法是什么?

我正在尝试添加一个球体(或胶囊)来约束 Skeel Lee's cloth simulation source code,但我不确定如何正确地进行。

我创建了一个相当简单的约束,"kicks" 粒子以相反的方向(与朝向中心的矢量相反)从球体中退回:

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;
}

然后我在现有代码中插入方法:

ApplyForces();
Integrate();

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

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

碰撞代码在这种情况下工作得很好(C 是球体的中心,P 是当前粒子位置,P' 是解析位置):

但是如果粒子移动得很快就会出现问题,因为粒子基本上会跳到球体的另一边(P1是之前的位置,P2是现在的位置, P' 是我认为应该解决的方式),而不是 return 回到以前的位置:

由于这是布料模拟,在这种情况下布料基本上会跳过球体,而不是"stopped"球体。

现在,我可以尝试 return 朝前一个点的方向移动,但由于球体也可能在移动,我不确定 P1 是否是一个有效位置(以及它是否会使感觉)。此外,它似乎在计算上更昂贵 - 我应该这样做吗?

像布一样的东西卡在障碍物的错误一侧并卡在那里并不少见。更常见的是,当检测到碰撞时,快速移动的物体重叠太多。

一个常见的解决方案是,在检测到碰撞时,将上一步细分,直到碰撞不太严重,然后再解决。我想你会发现在你的情况下尝试检测碰撞有多深是困难的,但是如果你可以限制系统中球体的最高速度你可以二进制分割碰撞发生固定次数的帧并假设它会足够好吗?

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

等...

您是否准备好接受它有时会出错,还是必须始终是一个好结果?