Houdini学习笔记026_互穿插网格(Dual Mesh)

今天我要讲的是Dual Mesh(双重互穿网络)模型的制作,思路来自Entagma(链接点这里)。原教程是用VOP节点做的,这里我用的是VEX。

为了观察起来方便,我用一个grid模型为例进行讲解。先用remesh节点将其重构成三角形网格面。调节Target Size以及Iteration等参数得到如下结果。

再用divide节点构造多边形,勾选Compute Dual选项即可。

虽然平面所有点的法线方向都是朝y轴正方向,但后面要拓展为其他的模型,还是用normal节点分别添加法线(N)属性。

给两个网格模型设置primitive组,Group Name输入$OS(组名即节点名),Group Type选择Primitives。节点名称可分别取triangle和polygon。

准备工作做好之后,下面就是互穿网络的制作。思路如下图所示,原本两个模型的边是相互交叉的,只需要在每条边上加个中点,往上或往下偏移。只要红线和黑线偏移的方向刚好是相反的,就可以形成互相穿插的网络。

我们先对黑线操作,使用的是point wrangle节点。对于每个点,先获取与其相连的邻点。使用的是neighbours函数写法为:
int npts[ ] = neighbours(0, @ptnum);
该函数返回的是一个数组,数组内是相邻点的编号。如果不用变量表示,改为定义属性(i[ ]@npts)的话,可在Geometry Spreadsheet窗口中查看每个点对应的邻点编号数组。

由于每个点的邻点数目不一样,所以对应的数组长度各不相同。对于x号点,计算其和每个邻点之间的中点时,可以用for循环语句,循环次数就是其邻点数组的长度,可用函数len(npts)表示。所以循环条件可写为:
for(int i = 0; i < len(npts); i++)
第一个点编号是自身,即@ptnum;第二个点编号是npts[i],用point函数分别获取其坐标值为:
vector pos0 = point(0, "P", @ptnum);
vector pos1 = point(0, "P", npts[i]);
计算出中点坐标后,addpoint函数添加中点如下——

接下来让中点沿法线方向移动。原模型是没有中点的,可以用两个点的法线平均一下。并且定义一个可调变量“height”,用来控制偏移的高度。中点的坐标为:
vector pos = (pos0 + pos1) * 0.5 + n * offset;

这里有个问题要注意,现在每个点都会和相邻的点计算中点,相当于每条边中点都重复计算了两次。为了避免这个问题,我们只在邻点编号大于自身编号时才计算中点。也就是加上判断条件:
if(npts[i] > @ptnum){ }
使用addprim函数画线,这里可直接用三个点的编号:
addprim(0, "polyline", @ptnum, midpt, npts[i]);

然后添加delete节点,删除原来的primitive组(triangle),仅保留新创建的线。

另外一个polygon mesh也是同样的处理——

现在有两个问题要解决:
(1)两个mesh网络中,中点偏移的方向应该相反;
(2)同一个mesh网络中,应该有些中点朝法线正向偏移,有些中点朝法线反向偏移。如果所有中点都沿法线正向偏移,最后得到的两个网络也不是互相穿插的。
我们先解决第二个问题。
可以设置一个比例ratio,每个中点生成一个随机数,当这个随机数大于ratio时,朝法线正向;否则朝法线反向。VEX代码如下:

定义默认的浮点变量dir = 1.0,当随机值rd < ratio时,dir = -1.0。可以直接用中点的坐标pos作为随机函数rand的种子,得到不同的随机值rd。
pos += n * offset * dir;
即可得到不同的偏移方向。ratio值控制正反向的比例,值为0时全部正向,为1时全部反向。
再来看第一个问题,怎样让两个网络对应中点的偏移方向相反呢?
这里我采用的是距离判断法,从dual模型的构造可以看出,两个网格每边的中点互为距离最近的点。用nearpoint函数可以找到距离polygon网格每个中点的最近点编号,也就是triangle网格的中点编号。再获取其对应的点坐标,以此为种子生成随机值。当种子相同时,生成的随机数也是相同的。
单独连出一个point wrangle节点,命名为midpoint,相当于第一个point wrangle节点的简化版。目的只是添加中点,不发生偏移。

然后将该节点连接到处理第二个网格模型的point wrangle节点的第二个输入端,如下图所示——

使用nearpoint函数获取最近点,写法为:
int nearpt = nearpoint(1, pos);
因为是要在第一个网格模型(添加中点后)的所有点中搜寻,而它又是连在1号输入端口的,所以nearpoint函数的第一数字写1。最后返回的是点编号。根据点编号获取其坐标值,生成随机数。

之后的步骤如下,分别给两组网络添加不同的颜色,用convert节点转为NURBS曲线。resample之后添加polywire节点,得到如下所示的互穿网络模型。

将初始模型换成bunny,得到结果如下——

最终可调节的参数有中点偏移的高度Height、正反朝向的比例Ratio和线条的粗细Radius。

今天就分享这么多,感谢各位的阅读,下回见~