Houdini Grain 学习笔记
// Grain 使用PBD算法,说白了就是先更新位置,再更新速度,Houddini Masterclass Grain 中的案例有一些简单的实现(最基本的原理)
比如跟新位置(这里为了简化Jeff 把粒子的pscale大小都看成一样),如果粒子有重合, 直接更改位置
int n[] = pcfind(0, 'P', @P, @pscale*2, 100); vector change = 0; float weight = 0; foreach (int npt; n) { if (npt == @ptnum) continue; vector op = point(0, 'P', npt); float d = length(op - @P); if (d < @pscale*2) { change += normalize(@P-op) * (@pscale*2-d)/2; weight += 1; } } @P += change / weight;
如果考虑质量的话,大概的算法:
int n[] = pcfind(0, 'P', @P, @pscale*2, 100); vector change = 0; float weight = 0; foreach (int npt; n) { if (npt == @ptnum) continue; vector op = point(0, 'P', npt); float d = length(op - @P); if (d < @pscale*2) { float omass = point(0, 'mass', npt); float ratio = omass / (@mass + omass); change += normalize(@P-op) * (@pscale*2-d) * ratio; weight += 1; } } @P += change / weight;
然后再根据位置的变化更新速度
if (i@has_pprevious) @v = (@P - v@pprevious) / @TimeInc;
注意POP Grain 节点会在粒子上添加一个属性 ispbd 值为1 , 这样POP Solver 就 不会更新P (位置) ,只在POP Grain 节点中更新
// Grain 中mass为0时的 特殊意义
如果粒子的属性mass值为0(特殊值),代表的意义是粒子质量无穷大,这样根据上面的算式
float ratio = omass / (@mass + omass); change += normalize(@P-op) * (@pscale*2-d) * ratio;
omass 是搜到的附近的粒子的质量,@mass 是粒子自身的质量,@mass无穷大, ratio无穷接近0
在试验中,在grainsource节点后选中上面的粒子,建组zero_mass
然后在popnet 中,popwrangle,
第一句 float @mass = 1 必不可少啊(Bug ), 他的作用是为所有的粒子声明创建一个属性,初始值为1,看起来只给zero_mass组里面的操作,实际不是:(
下面一句才是只是对zero_mass组里的粒子操作,mass值为0
这样,上面的粒子静止,下面的粒子由于重力散开, 图为结算第一帧和第14帧对比