▉ 把心事装进罐头 ,我们早就学会了不动声色。— 每天翻译一篇教程,这就是我写给houdini的情书。【首发于同名公众号:“致houdini的情书”】
█隐身模式
你在注视深渊,深渊也在注视你:
你在看片,片也在看你。即便是隐身模式下,浏览痕迹和在线追踪技术还是能把的你的行踪暴露无遗。
今天这节内容:
如何如何动态的编织出一张暗网
这一节要实现的效果
.....
▉今天是42岁第028天周四
这是写给houdini的
第054封“情书”
我是geo流程图
我是solver流程图
geometryvop:产生反作用力
我是vex代码
创建curveu属性
//--创建属性curveu:它描述所处曲线的上位置的百分比参数,曲线起点=0,曲线末尾=1,当前曲线很简单只有两点,可以直接用浮点;
@curveu = float(@ptnum);
结算前设置所有prim变量
//primnum指的是所有点所属的prim
i@myprim = @primnum;
创建第一条prim的随机点的seed组hscript
//随机选择第一个prim上一半的点
@myprim ==0 && rand(@ptnum)<0.5;
//设置粒子质量和尺寸
@mass = 1.0; //不需要任何质量产生作用
@pscale = 0.001; //尺寸对碰撞效果至关重要,这里不需要粒子间碰撞
从纱线开始沿着一个方向穿过其它纱线,动态的穿插织出一件布料
//-- 1 首先 搜索半径。
float searchrad = ch("searchrad");
//-- 2 然后 搜索临近点
int nearpnts[] = nearpoints(0,@P,searchrad);
//-- 3 接着 连接最近的那个点,但是在下个prim上
//-- 3a 遍历
foreach(int pnt; nearpnts){
//-- 3b 目标点所在prim的id
int tarmyprim = point(0,"myprim",pnt);
//-- 3c 判断目标点的primid为下一条prim
if(tarmyprim == @myprim+1){
//-- 3d 建立连线
int nprim = addprim(0,"polyline");
addvertex(0,nprim,@ptnum);
addvertex(0,nprim,nprim);
//-- 4a 更新seeds组;当前点移出seeds组;目标点移入seeds组
setpointgroup(0, "seeds", @ptnum, 0, "set");
setpointgroup(0, "seeds", pnt, 1, "set");
//-- 4b 目标点位置;当前点到目标点之间距离*0.5作为restlength长度
vectortarpos = point(0, "P", pnt);
floatdist = length(@P - tarpos);
setprimattrib(0, "restlength", nprim, dist*0.5, "set");
break;
}
}
本节需要注意的知识点:
1
实现纱线织布效果步骤
织布由两组垂直交织的线组成。
1)首先:一组线复制到另一条垂直线的点上。
a)要复制的线resample均匀采样。被复制的线scatter不均匀采样点,增强随机感。
b)被复制线的id顺序被打乱:
//创建curveu属性:@curveu= float(@ptnum);
//sort节点:利用curveu重新排列点序号。
c)重新整理解算需要的属性:
//首先设置一个解算前所有prim的变量
i@myprim = @primnum;
//然后创建第一条prim的随机点的seed组: 随机选择第一个prim上一半的点
@myprim ==0 && rand(@ptnum)<0.5;
//接着 converline1节点所有小的连线线段建立prim
//接着 Rest position节点该属性只复制静止位置
//最后 设置粒子质量和尺寸:
@mass = 1.0; //不需要任何质量产生作用
@pscale = 0.001; //尺寸对碰撞效果至关重要,这里不需要粒子间碰撞
2)然后:进入popnet解算器,实现从这一组线的第一条线开始,寻找下一条线的点进行连接。如此逐帧计算,直至连接成一张网。
a) Source_first_input节点 // Emission Type发射类型:all geometry。//birth只在第一帧取得几何体:$F ==1;
b) popforce节点//产生噪音功能驱动粒子变形 幅度Amplitude=0.05;关键帧:50帧Amplitude=0.05。55帧=0
c)Geovop节点增加阻力抵消popforce剧烈变形的影响
//bind节点Name:rest;type:vector设置静止点。与当前点相减,得到一个与点运动反向的矢量,从而制约点运动的剧烈的幅度。
d)popgrain节点设置约束参数等:提高解算次数:提高constraint iterations值
e)Geowrangle节点 在popsolver前与popforce合并解算:最后制作连接器平行防线的效果:在seeds组中操作;Input1:Myself
// -- 1 首先 搜索半径。
float searchrad = ch("searchrad");
//-- 2 然后 搜索临近点
int nearpnts[] = nearpoints(0,@P,searchrad);
//-- 3 接着 连接最近的那个点,但是在下个prim上
//-- 3a 遍历
foreach(int pnt; nearpnts){
//-- 3b 目标点所在prim的id
int tarmyprim = point(0,"myprim",pnt);
//-- 3c 判断目标点的primid为下一条prim
if(tarmyprim == @myprim+1){
//-- 3d 建立连线
int nprim = addprim(0,"polyline");
addvertex(0,nprim,@ptnum);
addvertex(0,nprim,nprim);
问题1)不加break停止遍历,两条prim的所有点都会连接。
问题2)不更新seeds组的信息,只有前两条线有链接
问题3)不设置新的连接prim的restlength长度,它就会塌陷成长度=0
//-- 4 最后解决上面三个问题
//-- 4a 更新seeds组;当前点移出seeds组;目标点移入seeds组
setpointgroup(0, "seeds", @ptnum, 0, "set");
setpointgroup(0, "seeds", pnt, 1, "set");
//-- 4b 目标点位置;当前点到目标点之间距离*0.5作为restlength长度
vectortarpos = point(0, "P", pnt);
floatdist = length(@P - tarpos);
setprimattrib(0, "restlength", nprim, dist*0.5, "set");
接下来
理论部分
1:如何织出一张布料
从纱线开始沿着一个方向穿过其它纱线,动态的穿插织出一件布料
接下来
开始正式制作
使用软件houdini16.5
2:解算前准备工作
//创建两条垂直线
1)line1 // Direction X =1
2)line2 // Direction z =1
//细分两条线
3)resample // Length=0.006 //作为穿插的纱线
4)scatter // count=100//更为复杂,拷贝第一条line到这条线的点上,让点分布更随机
5)copytopoint
// 问题:id号顺序被打乱
//后面穿插纱线时,需要有顺序的id号
//创建curveu属性,引导id重新排序,最终效果将依赖于此排序
6)pointwrangle //
//--创建属性curveu:它描述所处曲线的上位置的百分比参数,曲线起点=0,曲线末尾=1,当前曲线很简单只有两点,可以直接用浮点;
@curveu = float(@ptnum);
//scatter也将继承此属性。
7)sort // Point sort=By Attribute; 属性:curveu
//一个好的点序列,对于好的prim至关重要,prim也会按照顺序排列
//进入solver之前设置点的prim属性,seed组,restlength,
进入solver之前
设置点的prim属性,seed,restlength
//设置解算前所有prim变量:所有属性的point所属的prim
8)Pointwrangle命名set_myprim //
//primnum指的是所有点所属的prim
i@myprim = @primnum;
//创建这个属性原因:因为我们想从最初的prim开始,每过一帧,寻找下个prim,然后在这个prim上找到目标点
//有了这个属性,接下来可以再第一个prim上建立一些seed point(种子点)
//创建第一条prim的随机点的seed组
9)Groupexpression命名seeds // group:seeds
//随机选择第一个prim上一半的点
@myprim ==0 && rand(@ptnum)<0.5;
//所有小的连线线段建立prim
10)converline1//还创建了restlength属性 //它会告诉solver,线段应该多长。
//在每个点上创建新属性rest,后面作用力将依靠这个rest,该属性只复制静止位置,因此没有动画或动力学。
11)Rest position // 设置实体纹理与几何体的对齐方式,以便纹理在变形时保持在表面上。
//设置粒子质量和尺寸
12)Pointwrangle命名init_pbd //
@mass = 1.0; //不需要任何质量产生作用
@pscale = 0.001; //尺寸对碰撞效果至关重要,这里不需要粒子间碰撞
3:进入popnet生成纺织线
13) popnet
1 设置引入的平行纱线
13-1) Source_first_input
//Emission Type:pbd依赖在primi之上的点作为约束条件。
//ceometry source:用于上下文的几何体,这里意味着它会自动拾取第一个输入上的几何图形。
//这里每一帧都会产生粒子,$F当前帧保持等于1,只在第一帧取得几何体,
13-2) popforce //Amplitude=0.05
//会产生有些噪音的功能,噪音驱动粒子,随着时间推移,粒子被推得幅度越来越大
//关键帧:50帧Amplitude=0.05。55帧=0 // 加点动画限制这种影响,
//增加阻力抵消popforce影响
13-3)Geovop命名Target_force //
13-3a) bind
//Name:rest;type:vector静止position。
13-3b) substract
//连接输入P;粒子在当前位置产生一个矢量和rest point,外力越来越强,
//输出force。
从静止位置产生减去粒子的当前位置,从而在粒子的当前位置和静止点之间生成一个矢量,并且随着远离静止点的点的距离越来越远,反过来对粒子的影响也变得越来越大,越来越强。从而产生了一股把粒子往回拉的力量。
13-4) popgrain // Pop粒子节点将粒子视为小球体,并应用它们之间的交互。这允许防止相互渗透 、内聚力和甚至明确的约束。
把粒子分开,使整个物体像纱线一样
// 加快解算速度
2 穿插的纱线设置
15)Geowrangle命名connect
【注】connect节点在popsolver模拟后运行,然后再次计算所有内容。因为popsolver在此设置中不求解粒子。popgrains节点求解,也就是它的次数。它设置和特殊属性来告诉popsolver这个pbd,然后popsolver再执行了。所以connect连接在merge节点。
a)从纱线开始沿着一个方向穿过其它纱线,动态的穿插织出一件布料
//-- 1 首先 搜索半径。
float searchrad = ch("searchrad");
//-- 2 然后 搜索临近点
int nearpnts[] = nearpoints(0,@P,searchrad);
//-- 3 接着 连接最近的那个点,但是在下个prim上
//-- 3a 遍历
foreach(int pnt; nearpnts){
//-- 3b 目标点所在prim的id
int tarmyprim = point(0,"myprim",pnt);
//-- 3c 判断目标点的primid为下一条prim
if(tarmyprim == @myprim+1){
//-- 3d 建立连线
int nprim = addprim(0,"polyline");
addvertex(0,nprim,@ptnum);
addvertex(0,nprim,nprim);
}
}
连线要在seeds组中进行。我们不希望所有点都连接。
b) Group:seeds。
c)
<问题1>
现在所有点连接,因为 遍历所有点,会连接两条prim的所有点,所以加入break,找到最近的点停止
<问题2>
现在只有前两根连接,因为第一条prim0始终在seed组,它只跟prim1连接。
<问题3>
Break后虽然两条prim连接,但是play后,粘连在一起,
因为
1)第一当前点都在seeds组中,也就是primitive 0这条线上,所以一直就是在计算着prim0和prim1。
2)另外新的连线prim的rest lengh=0,因为没有设置。
d)更新代码
//-- 1 首先 搜索半径。
float searchrad = ch("searchrad");
//-- 2 然后 搜索临近点
int nearpnts[] = nearpoints(0,@P,searchrad);
//-- 3 接着 连接最近的那个点,但是在下个prim上
//-- 3a 遍历
foreach(int pnt; nearpnts){
//-- 3b 目标点所在prim的id
int tarmyprim = point(0,"myprim",pnt);
//-- 3c 判断目标点的primid为下一条prim
if(tarmyprim == @myprim+1){
//-- 3d 建立连线
int nprim = addprim(0,"polyline");
addvertex(0,nprim,@ptnum);
addvertex(0,nprim,nprim);
//-----------增加部分---------
//-- 4a 更新seeds组;当前点移出seeds组;目标点移入seeds组
setpointgroup(0, "seeds", @ptnum, 0, "set");
setpointgroup(0, "seeds", pnt, 1, "set");
//-- 4b 目标点位置;当前点到目标点之间距离*0.5作为restlength长度
vectortarpos = point(0, "P", pnt);
floatdist = length(@P - tarpos);
setprimattrib(0, "restlength", nprim, dist*0.5, "set");
break;
}
}
今天就到这儿了,收功
教程翻译自entagma的网络教程
下一节:20171120 Procedural Modeling Of Water Droplets
本文图片全部原创,版权归原作者所有