欢迎光临散文网 会员登陆 & 注册

Houdini学习笔记034_扩散限制凝聚(DLA)

2022-09-22 14:23 作者:独孤嘌呤  | 我要投稿

今天给大家带来的是经典的Diffusion-Limited Aggregation算法(简称DLA),最终效果如下——

DLA算法是由T. A. Witten和L. M. Sander于1981年提出的,其基本思路是:

(1)选择一个初始粒子作为种子,在远离种子的任意位置随机生成一个粒子,并让其做无规行走;

(2)直到运动的粒子和种子接触后停止,成为聚集体的一部分;

(3)随机生成新的粒子,重复上述过程。

最后就可以得到一个DLA团簇。

具体在Houdini中实现时,最终形状会受到三个因素的影响,分别是:①种子的位置;②生成粒子的位置;③无规行走的算法。这里我采取的思路如下——

在一片区域内散布点作为初始粒子(称之为food),种子位于区域的中心(称之为seed)。对于food,每走一步都会随机产生新的行走方向,并判断它和聚集体的最近距离。如果该距离小于某个临界值,则自动成为聚集体的一部分。直到所有food都成为聚集体的一部分为止。

为简便起见,我们从一个二维平面开始。

scatter节点散布点(如100个),group节点设定点组为food(Group Type选择points)。

另外用add节点在原点位置处添加一个种子,将其点组设为seed。准备工作就完成了。

两组点merge后,用solver节点开始解算。

solver节点中创建point wrangle节点,先自定义几个参数:

其中,steplength是粒子每步行走的距离,critical是判断粒子是否成为聚集体一部分的临界距离,randseed是产生随机方向的种子(为避免与seed点组混淆,前面加rand以示区分)。

这个节点是用来让food组内的点随机移动,并判断和聚集体的距离的。所以Group可选择food。先用rand函数生成一个随机方向,之所以减去{0.5, 0.5, 0.5}是因为rand产生的随机数值范围在0~1,减去0.5后范围变成-0.5~0.5,粒子朝各个方向运动的随机概率才一致。normalize函数用来将其归一化。

这里让randdir.y = 0,保证点只在xz平面上移动。随机移动后,点的位置变为:

回到solver节点播放后结果如下,粒子朝各个方向随机扩散。

为了防止粒子越跑越远,可以添加如下条件,当粒子超出grid的边界框时,会从另一边重新进入grid的范围。相当于grid相对的边界是连通的,粒子永远也跑不出去。

这里用到了getbbox函数,分别获取每个方向上最大、最小边界,以及各方向的尺寸。括号内的1表示获取的是1号输入端的对象,这里需要将grid连接到solver节点的1号端口。然后将节点内部的Input_1连接到point wrangle节点的1号端口。

下面的代码是用来限定粒子的运动区域的,if语句后面只有一句时,可以省略花括号。

然后需要判断粒子到聚集体的最近距离,因为聚集体是在不断增加的,需要有一个属性或变量来记录聚集体中点的编号。可以在前面加一个attribute wrangle节点,设置一个seeds[ ]数组。VEX代码如下:

后面就可以用detail函数来调用该属性:

先假设seeds[0]是距离粒子最近的点,求出距离mindis作为最小距离。

然后对聚集体中所有点求与粒子的距离,找到最近的那一个。计算出真正的最小距离mindis。

最后,将mindis和临界距离critical进行比较,如果小于临界距离,那么该粒子就成为聚集体的一部分。对应的,将其点组从food转移到seed,并且在该点与距离聚集体最近的点之间生成连线。

现在,我将自定义参数step length和critical distance的值均设为0.1,scatter节点散布的点数量改为2000,solver节点每次解算的步数Sub Steps设为20,运行结果如下:

根据距初始种子(这里为原点)的距离给每个点加一个col属性:

再根据该属性进行着色:

拓展成三维的也很简单,大家可以自己尝试~

以上我所用的方法是先生成全部粒子,然后让其做随机运动。也有逐步生成粒子的方法,以及其他额外的限制条件,以后我们有机会再讲。今天的内容到此为止,感谢大家的阅读,下回见~

Houdini学习笔记034_扩散限制凝聚(DLA)的评论 (共 条)

分享到微博请遵守国家法律