25

我正在尝试实现用于在 JavaScript 中模拟流体的Clavet 方法,所以调试是一场噩梦,这就是我在这里问的原因,希望经历过同样事情的人能告诉我我做错了什么。

到目前为止,我的工作正常:

粒子基本上起作用

但是我有两个问题:

1)由于在这种方法中,所有东西都有点“偏移”半步,我不确定如何正确地将粒子从墙上反弹。现在,我获取粒子的位置和之前的位置,并将它们围绕交叉的墙壁翻转,然后通过反弹因子围绕交叉点进行缩放。

我的反思方法

我的逻辑告诉我这应该有效。算法的下一步是更新粒子速度,所以我也反映了之前的位置。但在实践中,这给了我一个我不明白的结果:

反射力太大

这显示了粒子上的“力”。墙壁反射了太多的力量,这让一切都保持在永恒的运动中。

本文中的公式 4.58 显然显示了一种防止这种情况的方法,但我无法让它发挥作用。

论文中还有一些我没有得到的东西,比如“我们只想反映碰撞中省略的速度”的意思。为什么?有人可以把这些东西给我吗?

2)即使不涉及墙壁,模拟也会周期性地“爆炸”。这种情况在更高的压力下发生得更多:

爆炸模拟

JavaScript,所以有但我已经检查了代码,没有除以零或我可以想象发生 NaN 的情况。

我在报纸上看到过一些关于 sim 不稳定的讨论,我想知道是不是这样。这部文学作品中的大部分内容都超出了我的理解范围。

据我所知(我认为),消除不稳定性的方法之一是粘度,但我添加了它,但它对爆炸没有帮助:

粘度不能防止爆炸

我可以发布代码,但在开始工作的第一阶段,现在有点难以阅读。

最后一个问题:我如何弄清楚如何从这种方法中的伪常数转换为物理单位?

编辑:我发现 sim 偶尔会冻结,似乎它确实在某处产生了 NaN,但 Chrome 捕捉到它为时已晚。

4

2 回答 2

3

显然这里有很多。我敢肯定我不能全部回答,但这里有一些重要的观点:

关于墙壁:您实施的称为动量镜。在压力下的流体中,动量镜用于吸引具有某种负表面张力的粒子(因为没有粒子超出它来排斥靠近边界的粒子)。那里的粒子越紧密,就会产生更大的力,也更有可能导致数值问题(特别是因为它们的隐形传态往往会赋予它们潜在的能量)。

关于恢复系数:碰撞周围的简单线性缩放会在撞击时产生切向力,这对于动量镜来说并不典型,但确实倾向于产生物理上逼真的无滑移条件。

关于您链接的第二篇论文:我认为他们正在尝试根据他们的点投影做一些智能的事情。但是,我不知道为什么它们只是投射回表面(而不是计算碰撞时间,然后根据之后(降低的)新速度计算新位置)。

于 2017-09-18T07:38:00.917 回答
3

假设这是一个没有严格物理意义的 cg 项目......

首先,您应该真正考虑为您的模拟代码使用固定的时间步长,否则您将得到不稳定的(和视觉上令人不安的)行为,因为 dt (和 error )抖动。如果您无法根据最终要求获得一致的帧速率,则应在非固定时间点内插而不是模拟位置。

关于你的墙计算,这显然取决于你最终想要达到的效果;因此,如果您应用或多或少的动量保持镜像条件(就像您现在所做的那样),即使应用了阻尼,粒子也会继续“循环”。如果您希望流体以某种方式“粘”在墙上,则需要引入壁力或其他更强的耗散效应。

我运行了您的代码,并在设置一致的 dt 和调整粘度并将壁计算简化为更简单“if (p.px < left) p.px = left + (left - p.px)*canvas.wallBounce; else if ()..." 条件我得到一个很好的“放松”行为(如果这是你要找的)。更新以前的位置也会适得其反,因为可以说它会增加墙壁的“反射性”。

于 2017-09-19T09:21:59.873 回答