原视频:https://www.youtube.com/playlist?list=PLzRzqTjuGIDhiXsP0hN3qBxAZ6lkVfGDI
Bili:Houdini最强VEX算法教程 - VEX for Algorithmic Design_哔哩哔哩_bilibili
Houdini版本:19.5
直接看这篇吧,非常详细易懂:
(上面这篇文章,有个函数似乎注释有误,看看有没眼尖的找出来~)
下面仅是对视频案例的一些代码的解释及补充
1、Exercise—对偶网格
根据输入的点序号,按顺序遍历这个点所在的所有面。获取这些面的中心点,最后中心点与中心相连,形成一个多边形。
原理大概是这样子啦:图片来自知乎@刘鹏云,
eg.①先上结果:
②节点连接如下,
③类型为Points的dual_mesh代码为,
int hedge = pointhedge(0, @ptnum); //返回以该点为起点的边序号,有多条边则返回最小边的序号
int ncount = neighbourcount(0, @ptnum); //当前点的相邻点数量
int poly = addprim(0, 'poly'); //创建一个空的几何体
for(int i=0; i<ncount; i++){ //对这些相邻点进行操作
int prim = hedge_prim(0, hedge); //输入半边序号,返回边所在的面序号
vector pos = prim(0, 'P', prim); //所在面的中心点
int npt = addpoint(0, pos); //在这个中心点位置创建点
addvertex(0, poly, npt); //增加顶点,将顶点添加到几何体中的基元
hedge = hedge_prev(0, hedge); //返回上一条边的序号
hedge = hedge_nextequiv(0, hedge); //返回共线的另一个半边序号,如果不共线,那就返回原值.
}
int prims[] = pointprims(0, @ptnum);
foreach(int pr; prims){ //顺序把数组prims的值给pr,执行下面代码
removeprim(0, pr, 1);
}
removepoint(0, @ptnum);
④拓展:
根据dual_mesh原理,还可以做些穿插的东西,比如下面图片这种东西,
传送连接在这:Houdini学习笔记026_互穿插网格(Dual Mesh),
2、Exercise—网格细分
大概是与上面相反,这次大概是面中心点位置与面的顶点位置相连(最终结果看上去是这回事,但是连接方式略微不同)。
eg.①先上结果,
②类型为Primitives的subdivide节点代码为,
//面中心点与面的顶点相连,使用半边等函数去遍历取顶点,然后连接中心点
int hedge = primhedge(0, @primnum); //返回该面包含的(最小)边序号
int start = hedge; //用作后面循环结束的条件,边是否已经遍历了一遍
//可结合下面的图去理解代码
while(hedge != -1){
vector pos = @P;
int cpt1 = addpoint(0, pos); //该面的中心点位置
int nhedge = hedge_nextequiv(0, hedge); //返回共线的另一个半边序号(如果不共线,那就返回原值)
int nprim = hedge_prim(0, nhedge); //该半边所在的面序号
vector pos2 = prim(0, 'P', nprim); //面中心点
int cpt2 = addpoint(0, pos2);
int srcpt = hedge_srcpoint(0, hedge); //该半边所在的的起始点序号@ptnum/相当于上一条半边的末点序号
int tri = addprim(0, 'poly', cpt1, srcpt, cpt2);
hedge = hedge_next(0, hedge); //下一条半边序号
if(hedge == start){ //该面的半边都遍历完了,退出循环
break;
}
}
removeprim(0, @primnum, 1); //旧去新来
while循环的单个循环示意图,
3、Exercise—倒角
比如,对box进行倒角步骤,
①分两次进行,对点进行倒角,对面进行倒角;
②然后merge在一起,(可以再用fuse节点融并相同点);
③使用Foreach-number循环,进行多次倒角;
④感兴趣的,还可以大概上个色;
eg.最终结果大概是这样子的,
具体操作如下:
老规矩,先上示例结果:核心节点及效果如下
① 以box为例,进行点倒角,(就一个Polygon的box节点+PointWrangle节点),
// corner_bevel1节点
int hedge = pointhedge(0, @ptnum); //当前点所在的半边
int ncount = neighbourcount(0, @ptnum); //当前点点相邻的点数量
int poly = addprim(0, 'poly'); //创建个空几何体
for(int i=0; i<ncount; i++){ //当前点与相邻点之间,进行"点倒角"
int dstpt = hedge_dstpoint(0, hedge); //该半边的 目标/末 的点序号@ptnum
vector dstpos = point(0, 'P', dstpt); //当前点与相邻点的距离,循环遍历
vector pos = @P + (dstpos - @P) * chf('ratio'); //新位置=当前点+方向+自定义距离,ratio范围设为0~0.5
int npt = addpoint(0, pos);
addvertex(0, poly, npt); //添加顶点信息
hedge = hedge_prev(0, hedge); //上一条半边序号
hedge = hedge_nextequiv(0, hedge); //共线的另一条半边序号,无则返回原值
}
int prims[] = pointprims(0, @ptnum);
foreach(int pr; prims){ //顺序把数组prims的值给pr,执行下面代码
removeprim(0, pr, 1);
}
removepoint(0, @ptnum); //也可以使用fuse节点
原理大概是这个样子啦,图片来自知乎@刘鹏云,
②对box进行面倒角,(就一个Polygon的box节点+PrimitiveWrangle节点),
// face_bevel1节点
int hedge = primhedge(0, @primnum); //面所在的半边
int start = hedge; //是否已经把当前面的边遍历一遍
v@pos = set(0,1,0);
float ratio = chf('ratio'); //倒角比率,范围0~0.5
int poly = addprim(0, 'poly'); //创建个空几何体
while(hedge != -1){
int src = hedge_srcpoint(0, hedge); //半边所在的起始点序号@ptnum
int dst = hedge_dstpoint(0, hedge); //半边所在的目标点/末点的点序号@ptnum
vector srcpos = point(0, 'P', src); //半边起始点坐标
vector dstpos = point(0, 'P', dst); //半边末点坐标
vector pos1 = srcpos + (dstpos - srcpos) * ratio; //新位置1=半边起始点+半边方向*自定义距离,ratio范围0~0.5
vector pos2 = dstpos + (srcpos - dstpos) * ratio; //新位置2=半边起始点+半边方向*自定义距离,ratio范围0~0.5
int pt1 = addpoint(0, pos1); //新位置1创建点
int pt2 = addpoint(0, pos2); //新位置2创建点
addvertex(0, poly, pt1);
addvertex(0, poly, pt2);
hedge = hedge_next(0, hedge); //下一条半边
if(hedge == start){
break;
}
}
removeprim(0, @primnum, 1);
原理大概是这个样子啦,图片来自知乎@刘鹏云,
③结果为:ratio=0.3条件下,
④给节点加个Foreach-number循环,上色,整体节点及设置如下,