我采用PBD算法来模拟软体,主要遵循四步,先执行presolve,然后执行solveedge,再执行solvevolume,最后执行postsolve,如果不执行最后一步的话,我的物体是可以正常按照重力下落的,但是加上最后一步就会动一下就卡住不懂了,这是为什么?附代码如下:
public void preSolve(float dt)
{
for(int i=0;i<pos.Count;i++)
{
velocity[i] += gravity * dt;
prePos[i] = pos[i];
pos[i] += velocity[i] * dt;
//collision处理,当y<0时把pos挪到0
//if(pos[i].y<0)
//{
// pos[i] = prePos[i];
//}
}
}
float edgeCompliance = 100f;
//边约束
public void SolveEdge(float dt)
{
float alpha = edgeCompliance / dt / dt;
Vector3 grads = Vector3.zero;
for(int i=0;i<edgeContaint.Count;i++)
{
int p1 = edgeContaint[i].a;
int p2 = edgeContaint[i].b;
float length = edgeContaint[i].length;
grads = pos[p1] - pos[p2];
float dis = grads.magnitude;
grads = grads.normalized;
float C = dis - length;
float w = 2;//我这里就假设质量都为1了
float s = -C/(w + alpha);
pos[p1] += grads * s;
pos[p2] += grads * (-s);
}
}
float volumeCompliance = 0;
public void SolveVolume(float dt)
{
float alpha = volumeCompliance / dt / dt;
List<Vector3> grads = new List<Vector3>(new Vector3[4]);
for(int i=0;i<tetContaint.Count;i++)
{
int x1 = tetContaint[i].a;
int x2 = tetContaint[i].b;
int x3 = tetContaint[i].c;
int x4 = tetContaint[i].d;
float initVolume = tetContaint[i].initVolume;//初始的体积
float curVolume = ComputeVolume(x1, x2, x3, x4);//当前的体积
grads[0] = Vector3.Cross(pos[x4] - pos[x2], pos[x3] - pos[x2]);
grads[1] = Vector3.Cross(pos[x3] - pos[x1], pos[x4] - pos[x1]);
grads[2] = Vector3.Cross(pos[x4] - pos[x1], pos[x2] - pos[x1]);
grads[3] = Vector3.Cross(pos[x2] - pos[x1], pos[x3] - pos[x1]);
float d1 = grads[0].magnitude;
float d2 = grads[1].magnitude;
float d3 = grads[2].magnitude;
float d4 = grads[3].magnitude;
float w = Mathf.Sqrt(d1) + Mathf.Sqrt(d2) + Mathf.Sqrt(d3) + Mathf.Sqrt(d4);//这里也是把质量当作1,如果不为1,每个点还需要×质量的倒数
float C = (curVolume - initVolume) * 6;
float s = -C / (w + alpha);
pos[x1] += s * grads[0];
pos[x2] += s * grads[1];
pos[x3] += s * grads[2];
pos[x4] += s * grads[3];
}
}
public void PostSolve(float dt)
{
for(int i=0;i<pos.Count;i++)
{
velocity[i] = (pos[i] - prePos[i]) / dt;
}
}
你的代码看起来是在实现PBD(Position Based Dynamics)算法,这是一种常用于物理模拟的方法,特别是在模拟软体动力学时。你的问题是在执行PostSolve步骤后,物体会停止移动。这可能是由于多种原因,以下是一些可能的原因:
约束解决的顺序:在PBD中,约束的解决顺序可能会影响最终的结果。你可能需要尝试不同的解决顺序,或者在一个迭代中多次解决约束。
约束的弹性:在你的代码中,你使用了edgeCompliance
和volumeCompliance
来表示约束的弹性。这些值可能需要进行调整。如果它们太大或太小,可能会导致物体停止移动。
碰撞处理:你的代码中有一段处理碰撞的代码被注释掉了。如果物体在运动过程中碰到了其他物体或者场景的边界,没有正确的碰撞处理可能会导致物体停止移动。
时间步长:你的代码中使用了dt
作为时间步长。如果这个值太大或者太小,也可能会影响物体的运动。
初始条件:物体的初始位置和速度可能会影响其运动。你可能需要检查这些初始条件是否设置得合理。
以上只是一些可能的原因,具体的问题可能需要你根据你的应用场景和需求进行调试和分析。如果你能提供更多的信息,例如你的物体的初始状态,你的场景设置,以及你期望的结果,我可能能提供更具体的建议。