Houdini学习笔记024_VEX曲面编织
学习笔记和教程最大的区别在于,会记录一些我在操作中试错的过程。包括遇到问题后尝试解决的思路和方法。特别是在写VEX脚本时,warning时不时就会冒出来探望我一下。然后我会想方设法拒绝它的拜访,哪儿凉快哪儿待着去。
上一篇当中讲解了平面编织结构的VEX做法,这次我们稍加拓展,将平面换成曲面。当然,还是做纵横交错的简单编织图案。
对于曲面而言,由于各局部朝向都不一样,所以不能直接用简单的移动来定义坐标点的位置。很显然,要和法线方向结合起来。这里我给grid(15×15)添加mountain节点,调节参数得到随机起伏状。

首先我们应确认uv方向的点数。平面的分段是设置好的,但如果是一个外部导入的曲面,怎么获取两个方向的点数呢?比较简单的是直接显示点序号查看:很容易看出u方向有0~14共15个点,v方向为225/15=15个点。

能不能直接用导入的曲面生成这两个数值呢?因为这里我们设定曲面是四边形网格状的,假设uv方向各有x和y个点,可以根据总的点数和面数来解如下所示的方程组。

计算结果可以用Attribute Wrangle节点设为Detail属性,如下图所示(x和y)——

比如我将初始grid的分段设为16和18,在wrangle节点的detail属性中可以看到x和y的值分别为18和16。由于上面方程组的解x和y的值是可以互换的,对应的网格面长宽比可能大于1,也可能小于1。应该有办法确认,这里我就不再拓展了。后面如果结果有问题,把这两个值对调一下应该就OK了。

接下来我们沿用上一篇的思路,先画出一条波浪折线。方法是在原有的点基础上让其沿法线方向偏移一定高度得到新的点。使用Point Wrangle节点,Run Over方式改为Detail (only once)。将属性@x和@y分别赋值给numu和numv。

参照之前的教程,定义一个points数组用于接收addpoint函数的返回值,后面画线用。resize函数设置其长度为numu。for循环中用point函数分别获取第i个点的坐标和法线。

现在需要定义一个偏移值,可以写为:
float offset = chf("height");
并让原来的点坐标沿法线方向发生偏移:
pos += normal * offset;

接下来的VEX脚本和之前一样:
int ptid = addpoint(0, pos);
points[i] = ptid;

写完之后调整height的数值,发现点的位置并没有发生偏移。因为默认的平面是没有法线属性的。只需要添加normal节点,将其指定给point就可以了。

让其发生交错也很容易,在pos +=一句后面乘上系数pow(-1, i)即可。最后用addprim函数画线,上一篇中讲过,不再赘述。

下面写for循环嵌套从一条线得到多条线,有两个地方要注意,一个是pow(-1, i+j)得到每行交错的波浪线,另一个是循环内获取点编号为i+j*numu。

另外一个方向也是很容易实现的,只需要将上述代码稍加修改即可(主要是点的编号获取)。

最后代码整理优化如下(如果有问题,将初始的numu和numv对调一下)——
int numu = int(@x);
int numv = int(@y);
int ptu [];
resize(ptu, numu);
float offset = chf("height");
for(int j = 0; j < numv; j++){
for(int i = 0; i < numu; i++){
vector pos = point(0,"P",i+j*numu);
vector normal = point(0,"N",i+j*numu);
pos += normal * offset * pow(-1, i+j);
int ptid = addpoint(0, pos);
ptu[i] = ptid;
}
addprim(0, "polyline", ptu);
}
int ptv [];
resize(ptv, numv);
for(int j = 0; j < numu; j++){
for(int i = 0; i < numv; i++){
vector pos = point(0,"P",j+i*numu);
vector normal = point(0,"N",j+i*numu);
pos += normal * offset * pow(-1, i+j+1);
int ptid = addpoint(0, pos);
ptv[i] = ptid;
}
addprim(0, "polyline", ptv);
}
后面的步骤比较简单,这里就简单介绍下。由于最后我们要得到的是线,可以用delete节点删除原来的面。Entity选择Primitives,Operation选择Delete by Range。删除的范围从0~254。254也就是(x-1)(y-1)-1的值。可以用detail函数获取,写法为:
(detail("../calculate_x_y", "x", 0) - 1) * (detail("../calculate_x_y", "x", 0) - 1) - 1
注意这里末尾就不要加分号了,calculate_x_y是我前面定义的节点名称,你也可以定义为别的。

怎么删除边缘的四条波浪线不用我再讲一遍了吧,包括接下来的操作请参考上一篇。

最后的最后,用null节点设定两个参数进行最终的调节(编织纤维的起伏高度height和半径radius)。设置方法参考笔记10。

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