▉ 吾日二省吾身 。— 每天翻译一篇教程,这就是我写给houdini的情书。【首发于同名公众号:“致houdini的情书”】
█ “ 人生之不如意,十之八九,不如就常想一二 ”
前言不搭后语
首先
制作步骤
设置动态,创建一个自定义分割逻辑 而不是两个sub solver,一个处理geo,一个处理constraint geo。
在DopNetwork层级下,放下一个sop solver 更模糊的方式影响vellum;因为我们要对sop的几何体完全控制。
sopsolver中每件事都是按照时间步骤来进行。运行一遍再回到sopsolver上一次的步骤框架。
小节提要
A06
处理左半边分裂细胞,复制右边并输出
A)修正平面拓扑结构 B)偏移一点中间平面 C)扭曲测试 D)复制右半边细胞
B01
sop solver创建分割状态
创建两个分流 1)分裂;2)不分裂
B02
B02 分裂的循环设置
上回
○ 节点 ○



❖ 小问题 ❖上一节说到
blur之后,平面内部拓扑结构不再均匀分布
❖ 小目标A ❖
修正一下平面的“拓扑结构”
? 解决方案 ?
27-15)relax1 :
○只针对平面里的点:Points to Relax=inside_hull
现在平面的拓扑结构解决
❖ 新问题❖
平面边缘以外的拓扑结构“被打乱”。
主要因为勾选了:Use Normal Attribute
❖ 解决方案❖
A) 属性模糊:好很多但它松弛了所有点
27-16)attribblur_N1:模糊法线
B)创建“mask属性”只影响“平面”内部
27-15)relax1:
a)清除“inside_hull”这个组的选择
A)创建两个属性值
27-17)pointwrangle:命名_relax_mask
a) @relax_mask =1;
27-18)pointwrangle:命名_relax_mask1
a) @relax_mask =0;
b) <27-4>作为输入
这两个属性值之间过渡
B)过渡这两个值
27-20)visualize1:视觉化relax_mask
27-19)attribtransfer2
C)线性插值移动两个值范围内的点
27-21)pointwrangle1:
a)“接口2”连接relax;“接口1”连接attribtransfer。
b)lerp线性插值函数类似mix节点。
@P= lerp(@P,v@opinput1_P,@relax_mask)//第3个参数=bias偏差值相当于mask
27-22)Normal::


❖ 分析 ❖
因为“一对半个细胞”模拟张可能会相交
❖小目标❖
所以把中间部分分开一点
? 解决方案 ?
使用N来偏移一下平面位置
a)27-23)attribtransfer:
“接口2”连<27-7>传递N;
b)27-24)attribwrangle:
27-25)Normal:重置法线。
❖小总结❖
当前装置目的:在任何情况下,细胞的定向&变形,会有多个変形细胞,除了原点为中心的细胞。接下来做个“扭曲测试”



❖ 具体操作 ❖
27-26)transform1:
27-27)attribnoise1:
27-28)switch1命名switch_test_deformation

❖当前完成了细胞的左半边。
❖ 接下来·小目标 ❖
复制细胞右半边
? 解决方案 ?
A)for-loop循环;
B)直接关联复制
a)选中所有“左半边”节点
b)右键: Create Reference Copy
c)27-29)groupcombine_inside_hull1:
❖ 接下来输出细胞的“左右两半” ❖
○ 节点 ○
cell_setup层级

❖ 具体操作 ❖
28)null命名OUT_cell_l
29)null命名OUT_cell_r
30)merge合并
❖ 小目标 ❖
保存asset所作的改变
○ 右键cell_splitter“Save Node Type”
接下来段动
? 制作动画 ?
○ 实现“细胞分裂”并随时间动态的变形。
○ 在一定age细胞会分裂成两半并自我复制
B01 sop solver创建分割状态
○ 节点 ○

❖ 准备 ❖
B01)sopsolver_GEO:
❖ 小目标 ❖
添加一个阻力,除此之外不需要其他力
B02)popdrag1
//当细胞分裂时,它们会互相排斥,阻力有效牵制它们。vellum基本是作用在geo的点上。
? 开始 ?
sopsolver层级
B01-01)Output:
○ 连接dop_geometry
❖ 小目标 ❖
引入age属性属性。
在某时分裂细胞,留下分裂部分vellum模拟
? 解决方案 ?
B01-02)pointwrangle1:命名pointwrangle_age
@age_f += 1; //--每一帧增加一
❖ 分析 ❖
//如果一个细胞进入一个“分裂组”,它将会被分裂。否则它停留在“不受影响”的“正常组”
B01-03)pointwrangle:命名_split_age_group_temp
i@group_split = 0; //现在所有都在split组
❖ 小目标 ❖


1)分裂;2)不分裂
❖ 分析 ❖
有多个细胞的情况下,可能有一些不受影响,一些细胞到达“分裂age”,进入正确的分流
? 操作 ?
B01-04)attribwrangle1命名_keep_split_grp
//--1 判断不分裂,移出geo
if(i@group_split == 0) removepoint(0,@ptnum,1);
B01-05)attribwrangle1命名blast_split_grp1
//--1 分裂的geo移除
if(i@group_split == 1) removepoint(0,@ptnum,1);
B01-06)Null命名IN_SIM_GEO
B01-07)cell_splitter1
B01-08)OUT_cell_l
B01-09)OUT_cell_r
接下来段动
? 分析 ?
1) 确保分裂功能在每个细胞中正常运行。
2) 因为asset资产已经被设计成只在一个cell细胞上运行。
3)接下来会有多个细胞会进入sopsolver里分裂分流里。
? 小目标 ?
○ 需要把分裂流封装在一个foreach循环中
○ 节点 ○

○ 具体操作 ○
B05-12)For-Each Named Primitive:
B01-13)attribpromote1:
○ 节点 ○

○ 解决方案 ○
❖ 小目标 ❖
根据age创建分裂事件
? 具体操作 ?
B01-14)attribwrangle:命名split_age_group
//--1 每一帧重新设定一个split group,然后再分配
i@group_split = 0;
//--2 定义一个初始的split edge,如果只有一个细胞时,定义某时分裂它
float init_split_age = chf("init_split_age");
//--3 需要知道在模拟中有多少个细胞要处理
// int num_cells = 0;
//--4 加入最大细胞数
int num_cells = detail(0,"cell_id_max",0)+1;
❖ 小目标 ❖
直观的观察ID的方法
B01-15)attribpromote命名_cell_id_max
a)转成“detail”类;
这样能看到几何体上所有属性。
所以如果有多个cell_id;加入有0,1,2,3.如果把promote方法设成最大值,它会选择3。
b)保留原来的cell_id属性,改名cell_id_max
c)改变输入的细胞数:把cell_id_max加入<B01-14>代码中
❖ 小目标 ❖
开始实现实际的功能
//--------------B 开始实现实际的功能----------------
//--1 初始细胞
if(num_cells<2){
//--当一个细胞分裂,应该等于分裂的年龄
@split_age_f = init_split_age;
//--检查当前年龄age_f = 分裂年龄时,进入分裂组
if(@age_f == @split_age_f) i@group_split = 1;
}
//--2 再定义一个不止一个细胞,初始之后的行为。
else{
if(@age_f >= @split_age_f) i@group_split = 1;
}
接下来段动
○ 自定义分割逻辑

公众号:微信号