总结Houdini中各方面数据的传递方式
数据在哪几何属性参数,参数表达式PythonVex
Houdini中“数据”的“传递”
在我看来,Houdini中有多处存在着“数据”,并且他们可以相互“传递”。
明面上的“数据”有:
- 几何体的
属性
(Geometry Attribute) - 节点上的
参数
(Parameter)
而这些“数据”可能需要在其他地方引用,如:
- Python节点中的代码
- Vex节点中的代码
如果也将代码中的变量
看做是一个“数据”,那在代码中引用属性/参数
“数据”可以看做是:将属性/参数
“数据”传递到了变量
这个“数据”中。
如果考虑更深层次的开发如:
- 使用HoudiniEngine(或者说HAPI)在游戏引擎或其他美术软件(这里仅谈UE4引擎)的插件中与Houdini进行交互
- 使用HDK(Houdini Development Kit)对Houdini进行功能上的扩展
那么也可以看做是属性/参数
“数据”传递到了C++变量
中。
本篇的目标是:
- 简单讨论各个方面“数据”的基本概念
- 具体列举这些“数据”相互间传递的方式
基本概念
1. 几何体的属性(Geometry Attribute)
可以在Geometry SpreadSheet这个面板中看到:
属性(Attribute)分为:
- 点(Points) A point is simply a point in space as defined by four numbers (X, Y, Z, W).
- 顶点(Vertices) A vertex is a reference to a point. Primitives use vertices to reference points. For example, the corners of a polygon, the center of a sphere, or a control vertex of a spline curve.
- 图元(Primitives) refer to a unit of geometry, lower-level than an object but above points. Houdini supports several different types of primitives
- 全局(Details或者叫Global)
这些数据可以看做是在Houdini中各种运算的最终目标。
有些属性没有显示在界面中,比如高度场的数据,但我也将其归在这一类中。
2. 节点上的参数(Parameter)
参数可以是一个固定的值,或者是一个表达式。(表达式语法参考)
基本上,他们被视作完全由用户定义的数值,在运算中应该是不发生改变的。Python中可以修改参数,但如果这个行为是发生在节点已锁的情况下,则会失败并报错,所以我一般不会在Python中改变参数。
但并不是说参数的值一定是事先确定的,因为表达式可以引用【几何体的属性】而它可能会变化,此时就算节点是已锁的情况下也不会失败或报错。
3. Python节点
Python节点中的代码可以用HOM模块(Houdini Object Model)与Python交互,这是一个功能强大的模块,访问【几何体的属性】或【节点参数】这种基本的功能自然可以做到。(HOM模块代码参考)
但是其中的变量如果看做是一个“数据”,则外部是无法访问,因为它的作用域仅在这个节点的代码片段内。如果外部需要访问,就需要将“数据”转换为外部可以访问的形式了,比如存储为【几何体的属性】是我常用的方式。
4. Vex节点
Vex节点是一种类似“并行”的计算方式,可以选择以哪种属性(点?图元?)为单位来执行。
在代码中也有方式可以引用【几何体的属性】或【节点参数】的数据。速度上相比Python更快。
5. HoudiniEngine
对于不同的游戏引擎/美术软件,开发的环境不一样,例如对于UE4,即是编辑插件C++代码:
我在《简单梳理UE4的Houdini官方插件代码》有过对其的讨论。
6. HDK
此方面我也在学习。
《研究HDK(Houdini Development Kit):起点》讨论了一些关于HDK的基本概念。
《研究HDK(Houdini Development Kit):概括配置一个HDK工程的通用步骤》是具体配置一个新工程的通用步骤。
数据的传递方式
1.1 参数中引用其他参数
比较简单的操作方式是:
- 右键想要被引用的参数选择Copy Parameter
- 右键想要引用别人的参数选择Paste Relative Reference
1.2 参数中访问几何体的属性
在表达式语法参考中可以找到一些访问几何体属性的语法,例如:
上述表示访问../box1
这个节点的几何体的第3
个点属性,属性名为P
。
不过需要注意的是,对于“字符串”类型的属性,所用的表达式和一般的不同,因为“表达式”本身也是个“字符串”,会引起歧义。
- 首先,函数的名字一般是普通版的后面跟着一个s
- 其次,需要用“`”符号包围住表达式,算是对其中的表达式求值,而不是将“表达式”本身的字符看作为字符串。
2.1 Python中操控节点参数
“参数”归属于节点(hou.Node
),可以通过名字来找到参数:
而对于参数(hou.Parm
),有方法对其进行操控:
- 求值:
- 设置:
例子:
# 找到节点
node = hou.pwd().node("../box1");
# 访问参数
parameter = node.parm("sizex");
# 测试打印
print(parameter)
# 参数的值
value = parameter.eval();
# 测试打印
print(value)
2.2 Python中操控几何体的属性
需要先获取节点对应的几何体(hou.Geometry
)。其中有一些与属性相关的操作,例如:
- 获取全局类型的属性:
- 设置全局类型的属性:
- 添加一种新的属性:
而对于全局之外的属性,比如点,则需要获取更细级别的结构如hou.Point
,它有操控属性的方法:
例子:
#获得当前的节点:
node = hou.pwd()
#获得当前节点的几何体
geo = node.geometry()
#遍历所有的点
for p in geo.points():
#打印出“P”属性:
print(p.attribValue("P"))
3.1 Vex中访问参数
Vex有方法可以获取各种类型的参数的值:
例如:
@P.y+=chf("../null1/test");
3.2 Vex中访问几何体的属性
如果是自身节点的几何体的属性,则比较方便,直接用“@”符号即可引用,例如:
@Cd = @P;
如果是其他的几何体,则需要用一些函数
可以通过下面方式找到这个节点:
- 通过输入引脚
- 通过节点路径
例如:
@Cd = point(1,"P",@ptnum);
这段代码表示用1
号输入的几何体的P
属性。另外由于是以点为单位运行,所以可以得到顶点的序号@ptnum
。
下面的代码用路径来引用节点(记住路径名前加op:
)
@Cd = point("op:../box2","P",@ptnum);
可以达到相同的功能:
4.1 使用HAPI操控节点的参数
在HAPI文档中可以找到多个对参数进行获取/设置的函数:
4.2 使用HAPI获取几何体的属性
在HAPI文档中可以找到多个对参数进行获取的函数:
5. HDK
目前我对于HDK的使用还较小。不过可以肯定的是:HDK是相对底层的,对很多东西都有控制,至于获得节点的参数,或者几何体的属性,一定可以做到
总结
总结来说,各方面“数据”之间 获得/修改 的关系如下:
扩展用法
有时候,我需要修改一个节点参数,而这个参数和几何体属性有关。但问题在于:如果我直接在参数表达式中获取几何体属性,我还需要做一些处理,而这些处理如果使用参数表达式的语法会相对麻烦,这时候我倾向的解决方式是:
在Python中获得几何体属性,在此处理我想要的参数的值/表达式,将值/表达式放在一个新的几何体属性中,例如叫“result”,那么参数即可直接读取“result”的结果
这样相当于用比较方便的Python替代参数表达式的逻辑了。
作为以上问题的一个延伸情况:
我的Vex代码内容也是“动态”的,而Vex节点的代码内容实际上也是个“参数”。所以我可以在比较方便的Python中计算出Vex代码,然后存到一个字符串类型的属性中例如叫“Code”,这样Vex节点的代码内容可以直接引用这个“Code”的值。
后续待实验问题
- HAPI中其实不仅有获得几何体属性的方法,也有设置几何体属性的方法。但是我还没有遇到过需要设置几何体属性的需求。关键在于:几何体属性应该被各种节点操作最后Cook出来,如果我使用HAPI对其进行了修改,那么结果到底有谁负责呢?还是说只能在节点冻结的时候才可以?此处后续待实验。
- Python如果修改其他节点的几何体会怎么样?理论上应该不会成功,此处待实验。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)