SPH in a weekend

  做物理不懂流体,就好比打 dota 不玩卡尔,缺少一种品味的美。于是花了几天时间补了一下,虽然玩的烂但是好歹能放出民工三连的水平。

  读完以后感觉粒子这个东西是真的好用啊。凡是解析方法要搞一堆积分的东西,换成粒子瞬间就简单好多,梯度也好算了。

  已经有非常多介绍 sph 算法推导过程的文章了,最原始的论文链接也放在这,就只简单讲下算法的思路了,网页上敲公式也是累死人。
Matthias Muller, SIGGRAPH 2003

  简而言之,原先你要模拟流体,就需要求解大名鼎鼎的 Navier-Stokes 方程,长这样:
\rho(\frac{\partial \pmb{v}}{\partial t} + \pmb{v} \cdot \nabla \pmb{v})=-\nabla p + \rho \pmb{g} + \mu \nabla^2 \pmb{v}

  这是一个 force-based 模型,右侧三项分别是 f_{pressure},, f_{external}, f_{viscosity}。左侧是动量对 t, x, y, z 的全导数拆解,等价于动量的变化。简单来说就是 mv=ft 的流体版。

   现在我们换粒子解决这个方程的求解,简单方便。

  模拟上存在两个视角,Euler 和 Lagrangian。Euler methods 求解连续的场,例如速度场 v(x,y,z,t)。而 Lagrangian 方法求解离散的粒子。这篇文章比较清楚地总结了两种方法的优缺点。SPH_2017 对于一片规则的水域,可以采用网格法求解场,但是对于经常需要产生碰撞、形变的水体,粒子方法比网格法有着明显优势。

  SPH 全称是 Smoothed Particle Hydrodynamics,Smoothed 是一个重要的特性,这使得每个粒子的特性都可以由临近的粒子计算得出。从而产生了邻域核函数的应用。N-S 方程右侧的两个梯度都可以用核函数的方式进行重写,从而得到简单的求梯度公式。论文中列的很清晰,这里不再赘述。

  既然要 in a weekend 那么我们就撸起袖子开干,发挥面向 google 编程的优秀传统。

  在 github 上看了几个 sph 相关的代码库。SplishSplash 是工业化做的比较好的,但是不能满足我们 in a weekend 快速阅读实现的需求。所以又找了一个 [SPH-3D-Fluid-Simulation] (https://github.com/saeedmahani/SPH-3D-Fluid-Simulation)。这个项目写的很 easy,课程作业的难度。ok 就是它了,拿来改改。Visual studio, 启动!

sph_demo.gif

  能运行,效果还凑合,那我们直接进行一个代码的读。

  首先是基础流程,所有物理模拟都是类似这个。这里建了一个网格主要用来做邻域的圈定,每个粒子只需要计算邻域粒子的影响。

PARTICLE_SYSTEM::stepVerlet(double dt)
calculateAcceleration()  // 更新所有粒子的加速度

//用加速度更新速度 位置 (Verlet)
VEC3D newPosition = particle.position() + particle.velocity()*dt + particle.acceleration()*dt*dt;
VEC3D newVelocity = (newPosition - particle.position()) / dt;

updateGrid()  //粒子移动后更新所有网格中保存的粒子

  求 density , pressure,参考 Matthias 论文 式(3) , (12)

for particle 的所有邻域粒子 neighborParticle:
    VEC3D diffPosition = particle.position() - neighborParticle.position();
    double radiusSquared = diffPosition.dot(diffPosition);
    particle.density() += Wpoly6(radiusSquared);

particle.density() *= PARTICLE_MASS;
particle.pressure() = GAS_STIFFNESS * (particle.density() - REST_DENSITY);

  各种核函数及其梯度:

Wpoly6, Wpoly6Gradient, Wpoly6Laplacian : Matthias 论文 式(20) 
WspikyGradient : Matthias 论文 式(21) 
WviscosityLaplacian: Matthias 论文 式(22)

  然后计算 N-S 右侧。对于 p0 粒子有:

for p0 的所有邻域粒子 p1:
    f_pressure += p0.pressure/pow(p0.density,2)  +  
                    p1.pressure/pow(p1.density,2) * spikyGradient;
    f_viscosity += (p1.v - p0.v) * WviscosityLaplacian(rsqd) / p1.density;

  对于表面张力要特殊处理。计算表面粒子与表面张力如下。

for p0 的所有邻域粒子 p1:
    colorFieldNormal += poly6Gradient / p1.density;
    colorFieldLaplacian += Wpoly6Laplacian(rsqd) / p1.density;

colorFieldNormalMagnitude = colorFieldNormal.magnitude();
if (colorFieldNormalMagnitude > SURFACE_THRESHOLD) {
    particle.flag() = true;
    f_surface = -SURFACE_TENSION * colorFieldNormal / colorFieldNormalMagnitude * colorFieldLaplacian;

  汇总计算加速度

f_gravity(0.0, particle.density() * -9.80665, 0.0);
particle.acceleration() = 
(f_pressure + f_viscosity + f_surface + f_gravity) / particle.density();

  上面跑完就是一个 SPH 的完整流程了。公式很复杂,但流程其实很简单。

  至于渲染,其实粒子可以视为一种点云,而点云在点的数量比较少的情况下,可以通过 marching cubes 方法通过查找等值面来将点云重建为 mesh。然后就可以走正常的渲染了。这也是很经典的方法了,至于有没有其他的特技,就交给更专业的人吧。

  SPH in a weekend,跑通收工。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355

推荐阅读更多精彩内容