Houdini 中的几个节点允许您编写简短的 VEX 表达式或 VEX 代码片段。 例如,Attrib Wrangle几何节点; Geometry Wrangle、Gas Field Wrangle 动力学节点和粒子动力学节点。
这些 VEX 表达式在通过节点的每个元素(point, particle, edge, primitive, voxel,取决于节点类型)上运行。 该代码可以读取节点参数和几何属性的值,并设置特殊变量来更改输入几何中的值。
提示 Python SOP 类似,但允许您使用 Python 片段编辑几何图形。
随着用户处理越来越大和越来越复杂的几何图形,线程和并行处理对于获得可接受的性能变得越来越重要。这个简单的事实就是为什么 VEX 只会被更广泛地用于替换 HScript 表达式以进行临时几何操作的原因。
HScript 可能始终可用于某些比 VEX 更方便的工作。然而,对于几何操作,wrangling 和 VEX/VOPs 是前进的方向,值得学习新的工作流程。
VEX snippet参数允许您输入 VEX 代码片段。请参阅 VEX 函数列表。VEX 有上下文的概念。某些函数仅在某些上下文中可用(例如,用于在 SOP 上下文中访问几何信息的函数)。 VEX 代码段在 CVEX 上下文中运行。
注意:
在代码片段中,您可以使用参数的内部名称作为变量名称来读取/写入节点上的参数值。要获取参数的内部 ID,请将鼠标悬停在参数编辑器中的参数名称上。工具提示将显示参数:id。比如在Particle Color DOP中,Color参数的ID就是color。
color = @Cd;
多分量参数作为向量访问。例如,Position 参数的内部名称为 t:
// Set the translation
t = {0, 1, 0};
您可以使用点运算符访问参数的各个组件:
// Move one unit along the X axis
t.x = t.x + 1;
注: 要访问用户创建的参数的值,请使用chv函数。
在代码片段中,您可以使用@attribute_name 读取/写入属性的值。例如,要读取或写入P(位置)属性,请在VEX 代码中使用@P。
注 如果您使用 @opinput n _ name 访问不同的输入,则自动转换不起作用。在这种情况下,您必须始终指定类型。
下表列出了可用的数据类型和相应的字符。
VEX类型 | 句法 |
---|---|
float | f@ name |
vector2 | u@ name |
vector | v@ name |
vector4 | p@ name |
int | i@ name |
matrix2 | 2@ name |
matrix3 | 3@ name |
matrix | 4@ name |
string | s@ name |
dict | d@ name |
如果节点有多个输入,您可以通过在名称前加上 opinput inputnum _ 前缀来从不同的输入获取属性,例如 v@opinput1_P。这从编号输入(其中第一个输入为输入 0,第二个输入为 1,以此类推)上的相同元素(点/基元/顶点)读取命名属性。
相同的元素可能是另一个输入中具有相同索引的元素(例如,当您处理第 10 个点时,@opinput1_P 会在第二个输入中为您提供第 10 个点的 P 属性)。
但是,节点可以有一个 Attribute to Match 参数,让您可以根据属性值匹配相同的元素。例如,如果您使用 id 作为要匹配的属性,并且您正在处理属性 id 设置为 12 的多边形,那么@opinput1_P 将在第二个输入中为您提供多边形上的 P 属性,该多边形的 id 也设置为 12。检查您在其中编写代码段的节点的参数。
@elemnum 当前元素的编号。 @numelem 当前几何体/列表中的元素总数。
注: 最后一个元素的元素编号是@numelem - 1,因为第一项编号为0。
例如,要获取片段中当前点附近的点列表:
int nbors[] = neighbours(0, @ptnum)
要从曲线上当前点对面的点读取属性:
vector opposite_color = point(0, "Cd", (@numpt - 1) - @ptnum )
您可以通过附加 [] 来绑定数组,如
i[]@connected_pts = neighbours(0, @ptnum);
例如,以下代码将 foo 属性作为向量加载并将其复制到 P(位置)属性。您不需要指定 P 属性的类型,因为它是 Houdini 自动转换的已知属性之一。
@P = v@foo;
下面的代码将Cd属性的x分量设置为whitewater属性的值。不需要指定Cd属性的类型,因为它是已知属性之一。不需要指定whitewater的类型属性因为它是一个浮点数,未知属性会自动转换为浮点数。
@Cd.x = @whitewater;
提示 您只需在第一次引用代码中的属性时指定类型字符。
您还可以显式原型属性绑定。这允许您还指定属性的默认值,如果该属性未绑定,则将使用该默认值。如果创建了一个属性,它也会被设置为这个默认值。
注 字符串属性在创建时当前未正确设置其默认值。
这是通过将它们声明为变量来完成的。声明必须从行首开始。一行中只能声明一个变量。默认值必须是一个常量值,像 3*5 这样的计算值将失败,因为它们不是参数列表中的有效初始值设定项。
下面将创建一个向量类型的 foo 属性。如果它在输入中不存在,则默认值将设置为 { 1, 3, 5 }。
vector @foo = { 1, 3, 5 };
以这种方式声明之后,就没有必要使用 v@foosyntax,@foo 就足够了,因为已经指定了类型。
以这种方式原型化的属性将优先于任何内联定义(例如 v@foo)。将来不匹配的类型或不匹配的默认值可能会被视为错误。
有关更多信息,请参阅 POP 属性页面。
您可以在使用它们之前指定属性的类型和默认值,如下所示:
float @mass = 1;
vector @up = {0, 1, 0};
有两个方面的作用:
您不能在等号 (=) 的右侧进行任何计算。以下是语法错误:
float @mass = 1 / area; // Error
vector @up = set(0, 1, 0); // Error
与 HScript 表达式不同,您不能使用 $F 等全局变量。在 VOP 中,您可以从 Globalsnode 连接诸如时间和帧之类的变量,以在 VEX 片段中使用它们。
您可以使用以下隐式变量:
您可以在某些节点(例如 Attrib Wrangle)中使用 VEX 片段创建几何体。
addpoint、addprim 和 addvertex 函数允许您创建点、图元和顶点。您可以使用 setattrib 和 setprimvertex 更改几何图形。您可以使用 removepoint 和 removeprim 删除几何。要设置组成员身份,请使用 setpointgroup 和 setprimgroup。使用 setprimintrinsic 来修改诸如球体基元变换之类的东西。
使用绑定变量(例如 @name = val)而不是 setattrib 在当前元素上设置属性更快。仅当您需要在其他元素上设置属性时才使用 setattrib。如果您正在使用 setattrib 并且正在修改来自不同源点的点,请将mode参数设置为add以合成结果。
几何创建函数可以并行运行。在您的 VEX 代码迭代所有现有几何体后,所有更改都会排队并应用。这意味着 setattrib 将覆盖您通过绑定变量(例如 @name = val)所做的更改。
几何创建函数的第一个参数是几何句柄,它指定创建的目标(这是为了支持写入文件作为写入当前几何的替代方法)。使用 geoself() 作为第一个参数来指定当前几何。
addpoint(geoself(), {0, 1, 0});
addprim 函数当前可以生成多边形(“poly”)或折线(“polyline”)。如果创建多边形,则必须使用 addvertex 向点添加顶点。 Houdini 可能会在有点但没有顶点的多边形上崩溃。
int p1 = addpoint(geoself(), {0, 1, 0});
int p2 = addpoint(geoself(), {1, 1, 0});
int p3 = addpoint(geoself(), {1, 1, 1});
int prim = addprim(geoself(), "poly");
addvertex(geoself(), prim, p1);
addvertex(geoself(), prim, p2);
addvertex(geoself(), prim, p3);
请参阅 VEX 几何函数。
@group_ groupname 形式的特殊虚拟属性允许您获取或设置当前元素的组成员关系。 您可以通过检查@group_ name == 1 来检查当前点/边/基元/粒子是否在命名组中。
您可以通过设置虚拟@group_name 属性向组添加或删除当前点/边/图元。将该属性设置为 1(或任何非零值)会将当前元素放入该组中。将该属性设置为 0 将从该组中删除当前元素。
您可以使用 VEX 函数语法将自己的函数定义为 VEX 代码段的一部分。例如:
float mysquare(float a)
{
return a * a;
}
windresist = mysquare(windresist);
在代码片段中找到的任何 #include 指令将自动移到生成的 VEX 函数之外,因此将按预期运行。
确定是否存在用于属性绑定的参数是通过在预处理完成后简单扫描代码来完成的。此预处理仅在代码片段上完成;但是,并且不处理任何#include 文件。因此,它可能会被依赖于 #includes 的 #ifdef 指令混淆。
在多行编辑器中编辑时,您可以按 Ctrl + Enter 提交更改并更新 Houdini。
VEX 片段在每一帧(或在模拟网络中,每个时间步)运行。
您可以使用 return 语句提前退出代码段。例如,以下 VEX 只会在全新粒子上将 Windresist 设置为 0:
if (@age > 0) return;
// If @age was > 0, we returned above, so this line
// only runs for particles where @age == 0
windresist = 0;