▉一生最好是少年,一年最好是青春— 每天翻译一篇教程,这就是我写给houdini的情书。【首发于同名公众号:“致houdini的情书”】
█青春的羽翼展开双翅,它带上了你的过去,带上了你的伤疤,飞向了过去。
有的人老了,但他还年轻:
青春不只是人生的一段时期,也是心灵的一种状态。容颜会老,但心态仍可以冲动,热血,和保持初心!
今天这一节的内容:
如何用primitive卷成很多螺旋纸再拼成一只青春小鸟?
.....
▉今天是42岁第01天周六
这是写给houdini的
第042封“情书”
我是geo流程图
我是vex表达式
v@ctr = @P;
设置prim中心点位置变量
//---线上所有点的列表---
int npts[] = primpoints(0,@primnum);
//---线上所有点的数量---
int numpts = len(npts);
//---初始化最短距离---
float mindist = 1000000;
//---求出线上所有点的位置和它们到中心点的距离---
foreach(int npt; npts){
vector npos = point(0,"P",npt);//首先求每个点的位置
float dist = distance(v@P,npos);//距离=中心点-线上每个点
//---对所有点到中心距离与最短距离做判断---
if(dist < mindist)
mindist = dist; //找到最短距离
}
//---最后输出 最短距离输出和点的总数---
f@dist = mindist;
i@numpts = numpts;
创建距离中心点最短距离dist属性
//---首先定义一个“宽度”的可调参数---
float width =chf(”Paper_Thickness”); //设置Paper Thinkness=0.002
//---提取单独prim的所有点列表,点的数量---
int npts[] =primpoints(0,@primnum);
intnumpts = len(npts);
//--单独prim里纸张可以卷的圈数=dist/width--
int maxnum =int(f@dist/ width);
//--建立新的primline线--
int newprim =addprim(0,"polyline");
//---建立新的primline的Cd,颜色被转移过来---
setprimattrib(0,"Cd",newprim,v@Cd);
// --计数变量--
float n =0;
//---prim线上所有点乘“maxnum”圈数---
for( int i =0; i foreach( int npt; npts){ //---点相对于中心点的移动幅度与“圈数*点数”构成反比关系,圈数越多,点数越多移动幅度越小--- float offsetamp= n/(maxnum*numpts); // 用计数变量作为分子 ,偏移量随着计数而增大, //---当前点的位置---- vector pos= point(0, "P",npt); //--从“点的位置”指向“中心”的方向矢量-- vector offset = v@ctr -npos; //v@ctr=中心点 //---点最终的位置--- npos += offsetamp* offset; //--根据新的位置创建新的点-- int newpt = addpoint(0,npos); //---创建顶点--- addvertex(0,newprim,newpt); // 在跑完一次foreach后,增加点数 n++ } } //---最后移出原来的primline--- removeprim(0,i@primnum,1); //1表示如果没有其他prim引用它们,则prim所拥有的点将被删除。 建立螺旋效果 f@zscale = fit01(rand(@primnum+345),0.5,1.5); 建立要给zscale随机映射值 [email protected] = pos.y+chramp("y_ramp",f@curveu)*(noise(f@curveu*8+@class*17)*0.05-0.025); 创建每组螺旋Y轴的随机起伏 本节需要注意的知识点: 1 根据贴图创建单元prim组成几何体 1)两个grid贴图,一个是边缘图,一个是原图 2) 对边缘图使用Cd撒点; 3)再用voronoifracture骨折节点在一个grid分裂 4)转换原图Cd属性为primitive类 5)用attribtransfer把原图Cd传递过来。 6)delete节点用表达式:(@[email protected][email protected])/3>0.9。保留彩色部分 7)最后重新采样,smooth平滑 2 获得线上点到中心最短距离步骤 1) primpoints函数:求得所有点列表 2)len函数:求得线上点的总数 3) 对最短距离mindist初始化一个很大的值 4)foreach遍历每个点: a)point函数:获得每个点的位置变量npos b)distance函数:点到中心距离变量dist c)if判断,只要dist小于初始值,mindist=dist 5)输出最短距离:f@dist= mindist 8)输出点的总数:i@numpts = numpts; 3 创建卷曲primline效果步骤 1)为了求圈数创建可调宽度变量:width 2)提取单独Primi的所有点列表npts,点总数numpts; 3)单独prim里可以卷的最大圈数:maxnum=dist/width; 4)建立新的primline:addprim函数 5)setprimattrib函数把前面的prim颜色属性转移给新的primline设置的Cd属性: setprimattrib(0,"Cd",newprim,v@Cd) 6)初始计数变量n=0 7)设置“创建primline圈数”的循环次数:for循环语句内i 7-1)foreach遍历每个prim内的所有点执行创建prim的命令 a)创建向中心移动幅度变量offsetamp=运行次数n / 圈数maxnum*总点数numpts,圈数,总点数少的移动幅度大,反之,移动幅度小; b)创建当前点位置变量npos:point(0,"P",npt) c)创建“当前点指向中心“方向矢量offset=“中心点位置”v@ctr-“点的位置”npos d)点的最终位置npos +=offsetamp*offset; e)根据点位置使用addpoint函数创建新的点:newpt:addpoint(0,npos) f)addvertex函数创建顶点:addvertex(0,newprim,newpt) g)跑完一次foreach函数,增加点数:n++ 8)最后removeprim函数移出原来的primline:removeprim(0,i@primnum,1);1表示如果没有其他prim引用它们,则prim所拥有的点将被删除。 4 如何根据zscale随机挤压螺旋 1)primwrangle:建立zscale变量,用fit和rand建立随机映射范围 f@zscale = fit01(rand(@primnum+345),0.5,1.5); 2)attribpromote节点: a)调用zscale b)转换Primitive 为Point。 3)polyextrude 节点: a)挤压模式point Normal b)Local Control面板下勾选:Distance Scale:zscale。 5 如何挤压螺旋的中心 1)resample勾选建立curveu属性,它创建一个“点属性”,用于存储“重新采样点”的“单位曲线”参数值。 2)pointwrangle借助curveu属性创建y轴的变化 vector pos = v@P; [email protected] = pos.y+chramp("y_ramp",f@curveu)*.03; 6 随机挤压螺旋中心 1)connectivity节点:为每一组连接的prim或点创建一个具有唯一值的属性。该属性的默认名称是class。 2)增加noise函数:增加噪音频率调用@curveu乘某数值比如8, 同时,为了防止每个单独的prim中每个点之间的噪声是相同的,还要加偏移值,可以使用存储在类里的连结性信息。 [email protected] = pos.y+chramp("y_ramp",f@curveu)*(noise(f@curveu*8+@class*17)*0.05-0.025); 接下来 理论部分 问题1:螺旋状卷纸形成原理 01)要形成一卷密集的卷纸,我们必须考虑纸张的厚度 02)一个任意的形状,如果想用一个纸螺旋来填充它,就必须计算出,可以用多少圈纸来填充它 03)首先我们要找出 最接近形状中心的点。 04)然后,我们取这个距离除以纸的厚度,得到可以卷成那个形状最大的旋转次数。 05)接下来创建形成螺旋需要的新的点,。我们将创建的“新点的数量”=“转弯数”*“primitive中的点数”。 06)然后把所有这些点连接起来,形成一条螺旋形的线。但这样的形状有些不自然。 07)所以接下来需要将螺旋线上的点向中心逐步靠拢;这时需要“指向圆心的矢量”乘“偏移量(0~1的因子)”而偏移量又取决于点在螺旋线上的位置。 08)随后路径上的每个点在这个矢量方向上向中心点移动;而移动数量有所不同, 螺旋线开始的点只会向中心轻微移动,而螺旋线末端的点将完全移动移动。 08) 接下来 开始正式制作 使用软件houdini16.5 问题2:如何根据贴图创建单元prim组成几何体 0)处理图片:照亮边缘 //photoshop滤镜库/照亮边缘 a) ; 1)grid // 2)attribfrommap1 // 源图 3)attribfrommap2// 边缘图 4)scatter1 5)grid2 // 外框 6)voronoifracture1 // 骨折 7)attribpromote1//Cd属性从point转成primitive类 8)attribtransfer1 // 传递Cd属性 9)delete1 // 只保留彩色部分 (@[email protected][email protected])/3>0.9 // 灰度值>0.9 10)resample1 // 采样线段 11)smooth1 // 平滑线段 12)resample1 // 再次采样线段 问题3:如何创建螺旋线 A)给每个单元格增加中心属性 13)primwrangle重命名set_center v@ctr = @P; B)把prim从面转成线 14)primitive: C)找出线上的点到中心最短距离 15)primwrangle重命名find_min_distance //输出距离中心最短距离dist和点的总数 //---线上所有点的列表--- int npts[] = primpoints(0,@primnum); //---线上所有点的数量--- int numpts = len(npts); //---初始化最短距离--- float mindist = 1000000; //---求出线上所有点的位置和它们到中心点的距离--- foreach(int npt; npts){ vector npos = point(0,"P",npt);//首先求每个点的位置 float dist = distance(v@P,npos);//距离=中心点-线上每个点 //---对所有点到中心距离与最短距离做判断--- if(dist < mindist) mindist = dist; //找到最短距离 } //---最后输出 最短距离输出和点的总数--- f@dist = mindist; i@numpts = numpts; 16)attribpromote2//转换dist属性的类型,取最小值; 17) primwrangle重命名create_spirals//建立螺旋效果 //---首先定义一个“宽度”的可调参数--- float width =chf(”Paper_Thickness”); //设置Paper Thinkness=0.002 //---提取单独prim的所有点列表,点的数量--- int npts[] =primpoints(0,@primnum); intnumpts = len(npts); //--单独prim里纸张可以卷的圈数=dist/width-- int maxnum =int(f@dist/ width); //--建立新的primline线-- int newprim =addprim(0,"polyline"); //---建立新的primline的Cd,颜色被转移过来--- setprimattrib(0,"Cd",newprim,v@Cd); // --计数变量-- float n =0; //---prim线上所有点乘“maxnum”圈数--- for( int i =0; i foreach( int npt; npts){ //---点相对于中心点的移动幅度与“圈数*点数”构成反比关系,圈数越多,点数越多移动幅度越小--- float offsetamp= n/(maxnum*numpts); // 用计数变量作为分子 ,偏移量随着计数而增大, //---当前点的位置---- vector pos= point(0, "P",npt); //--从“点的位置”指向“中心”的方向矢量-- vector offset = v@ctr -npos; //v@ctr=中心点 //---点最终的位置--- npos += offsetamp* offset; //--根据新的位置创建新的点-- int newpt = addpoint(0,npos); //---创建顶点--- addvertex(0,newprim,newpt); // 在跑完一次foreach后,增加点数 n++ } } //---最后移出原来的primline--- removeprim(0,i@primnum,1); //1表示如果没有其他prim引用它们,则prim所拥有的点将被删除。 现在产生了螺旋的卷纸效果。 18) resample //再次采样 a)增加曲线curceU属性; 采样前 采样后 b)curveU属性值=0时,从point的id=0开始。追后一个点curveU=1. 19) smooth2 // 问题4:如何根据zscale随机挤压螺旋 19) primwrangle4命名set_Zscale //建立随机的zscale值,映射范围0.5~1.5 f@zscale = fit01(rand(@primnum+345),0.5,1.5); 20) polyextrude1 //选择point Normal 20) attribpromote3 //转换zscale的类为point zscale起作用了 问题5:如何让螺旋中心凸起 22 ) pointwrangle重命名randomize_y_pos // vector pos = v@P; //增加一个渐变参数 [email protected] = pos.y+chramp("y_ramp",f@curveu)*.03;//因为chramp返回值很大,所以乘一个很小的值 问题6:如何让螺旋中心凸起更随机 21) connectivity1// 为每一组连接的prim或点创建一个具有唯一值的属性。或者说唯一ID,该属性的默认名称是class。 22 ) randomize_y_pos // 增加一个noise函数,增加噪音频率调用@curveu乘某数值比如8, 同时,为了防止每个单独的prim中每个点之间的噪声是相同的,还要加偏移值,可以使用存储在类里的连结性信息。 [email protected] = pos.y+chramp("y_ramp",f@curveu)*(noise(f@curveu*8+@class*17)*0.05-0.025); (noise(f@curveu*8+@class*17)*0.05; (noise(f@curveu*8+@class)*0.05; (noise(f@curveu+@class)*0.05; (noise(f@curveu*8+@class)*0.05-0.025; 今天就到这儿了,收功 教程翻译自entagma的网络教程 下一节:20170619 Knitting in 3d - Building a UV Deformer