Houdini·笔记

记录一些建模中的普适方法

获取边界

经常需要获取某片区域的边界,然后根据边界建立围墙之类的东西。使用group即可获取边界。通过unshared edge获取所有只有一个primitive相连的edge。

删除几何体/面内部的edge

divide提供remove shared edges功能。

※ Lab提供剪影节点也可以获取无内部边的整体prim,但是不知道为什么法线的方向无法确定,所以不建议使用吧…

关于随机和噪音

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

属性转换

末尾延伸线段

用途:制作电线杆时需要在最末一个电线杆处延伸一小段电线制作断开电线的效果。

Dopnet从获取输入物体路径

op:`opinputpath("../",0)`//数字0表示input0,相应的其他输入用对应数字表示

垂坠效果

目前看到有三做法——pop solverwire solver+constraint networkvellum

pop solver

wire solver

做起来还麻烦的,虽然houdini提供了constraint network节点,但constraint相关的信息都得手工添加到各个点上,比如制作垂坠线网(下图),需要根据官网文档,向point添加anchor_id,constraint_name,constrint_type属性,以定义哪些点是固定锚点。(不太确定这是不是最简单的做法,参考的是Entagma的Houdini18教程)

hip文件

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

copytopoint无overlap