Houdini·笔记
记录一些建模中的普适方法
获取边界
经常需要获取某片区域的边界,然后根据边界建立围墙之类的东西。使用group
即可获取边界。通过unshared edge获取所有只有一个primitive相连的edge。
删除几何体/面内部的edge
divide
提供remove shared edges功能。
※ Lab提供剪影节点也可以获取无内部边的整体prim,但是不知道为什么法线的方向无法确定,所以不建议使用吧…
关于随机和噪音
-
attribute randomize
:添加变量,并为变量赋予随机值,可设置变量名、变量维度、各维度范围 -
attribute noise
:设置噪音 -
point jitter
:在原位置周围轻微随机位移
Collapse into subnet
把节点们打包成subnet的快捷键——shift + C
。
随机选取指定数量不重复元素
sort
节点对对象进行random
排序,然后group by range
选取需要的数量。
在primitive中心添加point
attribute wranggle
节点,run over primitive
——
addpoint(0, @P);//添加中心点
removeprim(0, @primnum, 1);//顺便移除primitive
在SOP中使用attribute
attribute和variable是不互通的,需要使用point函数读取attribute数据。
point(surface_node, point_number, attribute, index)
prim(surface_node, prim_num, attrib_name, attrib_index)
示例——
point('../alfx', 0, 'awsl', 0) //获取名为alfx的sop节点下创建的名为awsl的节点
获取相邻线段的半程向量
@N = normalize(@N);
int nei[] = neighbours(0,@ptnum);//获取相邻点数量,用作index
if(nei[1]!=0){//第一个点不作修改
vector next = point(0,'N',nei[1]);//获取下一个相邻点的方向
@N = next + @N;//求半程向量
}
旋转控制
根据设定的轴向进行旋转。
float angle = ch("angle")*4;
matrix rot = ident();
vector axis = {0,1,0};
rotate(rot, angle , axis);
vector rotateP = @P * rot;
@N = rotateP;
foreach Group
属性转换
-
Attribute Transfer
:不同节点间属性转换 -
Attribute Promote
:同节点属性类别转换
末尾延伸线段
用途:制作电线杆时需要在最末一个电线杆处延伸一小段电线制作断开电线的效果。
Dopnet从获取输入物体路径
op:`opinputpath("../",0)`//数字0表示input0,相应的其他输入用对应数字表示
垂坠效果
目前看到有三做法——pop solver
,wire solver
+constraint network
,vellum
。
pop solver
wire solver
做起来还麻烦的,虽然houdini提供了constraint network
节点,但constraint相关的信息都得手工添加到各个点上,比如制作垂坠线网(下图),需要根据官网文档,向point添加anchor_id,constraint_name,constrint_type属性,以定义哪些点是固定锚点。(不太确定这是不是最简单的做法,参考的是Entagma的Houdini18教程)
vellum
vellum做起来是最快的,节点只需要vellum constraint
+ vellumsolver
即可。之前电线杆工具中断裂电线处的下垂模拟就是用vellum的Hair模式做的,所有参数都在表面结点,操作很简单。
groupbyrange获取节点属性
使用detail获取节点作为range filter的参数可行,但是用point则不行,会报错bad data。这里不知道为什么啦,也不是啥大问题,用attribute promote
改一下类别即可。
获取线段头尾
在对多个线段进行resample后,顶点的index会发生改变。这里希望可以获取每个线段的头尾,可以在resample前为头尾添加属性,值为$PT
,
点的沿线排序
在对线段进行重分段或加点操作后,线段上的point/prim ID会变得乱七八糟,此时常需要按照沿曲线方向对point进行重新排序。使用polypath
将线段上的prim合并为1个,再用carve
重新分段即可获得沿线方向的ID排序,之后再用convertline
分割prim即可复原为原有结构。
获取线段交叉点
curvesect
可以。intersectionanalysis
更方便,可以生成多条直线的交叉点。
平面翻转
primitive的法线朝向由构成prim的点的排序决定——比如,顺时针,法线方向朝上;逆时针,法线方向朝下。
很多时候需要统一prim的朝向,例如所有prim的y轴方向为正。可以使用group
根据normal筛选出y轴不为正的prim,然后对其reverse
。
删除face保留edge
polycut
节点,Point模式,strategy:cut。
array相关vex语法
i@size =len(i[]@arrayname);//获取array长度
foreach (int num; @interprim) {
//num,获取array中数据
}
从外层文件读取路径(python)
这个用于从工具参数的object list读取物体路径到内层object merge
节点作为输入模组。
for n in hou.selectedNodes(): # 选中操作对象...emmm这里加着一行可以防止误操作
n = hou.node('/obj/Pole/Pole_Generator') # 获取工具node
p = n.parent()
if n.type().name() == 'subnet': # 判断一下名字,检查一下
objnum = hou.parm(n.path()+"/numobj").eval() # 获取object list中的物体数量
for x in range(0,objnum-1): # 生成objnum个object merge节点,并依次赋予路径
objnode = hou.node(hou.parm(n.path()+"/objpath"+str(x)).eval()) # 获取list中对应x的路径名
m = p.createNode('object_merge',"AlfxTest"+str(x)) # 创建object merge并标号命名
m.moveToGoodPosition() # 移动到新建m节点
hou.parm(m.path()+"/objpath1").set(hou.parm(n.path()+"/objpath"+str(x)).eval()) # 赋予物体路径
创建subnet,,往里面装list物体,最后输出到外部switch——
for n in hou.selectedNodes():
n = hou.node('/obj/Pole/Pole_Generator')
w = n.parent()
p = w.createNode('subnet',"ObjectList")
s = w.createNode('switch')
if n.type().name() == 'subnet':
objnum = hou.parm(n.path()+"/numobj").eval()
for x in range(0,objnum):
m = p.createNode('object_merge',"AlfxTest"+str(x))
# objnode = hou.node(hou.parm(n.path()+"/objpath"+str(x)).eval())
m.moveToGoodPosition()
hou.parm(m.path()+"/objpath1").set(hou.parm(n.path()+"/objpath"+str(x)).eval())
o = p.createNode('output',"output"+str(x+1))
o.setInput(0,m)
onode = hou.parm(p.path()+"/output"+str(x+1))
s.setInput(x,p,x)
# print x
参数调用callback script
教程看这个,照着做即可→教程
注意要先create digital assets,否则出错文件可能会废…尝试前先备份文件!!!
删除面保留点
add
节点→勾选remove geometry but keep the points