前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用 VEX 表达式

使用 VEX 表达式

作者头像
南郭先生
发布2022-04-25 13:53:06
2.5K0
发布2022-04-25 13:53:06
举报
文章被收录于专栏:Google DartGoogle Dart

概述

Houdini 中的几个节点允许您编写简短的 VEX 表达式或 VEX 代码片段。 例如,Attrib Wrangle几何节点; Geometry Wrangle、Gas Field Wrangle 动力学节点和粒子动力学节点。

这些 VEX 表达式在通过节点的每个元素(point, particle, edge, primitive, voxel,取决于节点类型)上运行。 该代码可以读取节点参数和几何属性的值,并设置特殊变量来更改输入几何中的值。

提示 Python SOP 类似,但允许您使用 Python 片段编辑几何图形。

为什么使用 VEX 进行临时修改?

  • 出于性能原因,Houdini 正在转向使用 VEX 对属性进行临时几何修改,而不是对局部变量和外部通道引用进行操作的 HScript 表达式。
  • 与 HScript 表达式和局部变量相比,使用 VEX 和属性具有主要的性能优势。它运行速度更快,并自动支持线程和并行计算。
  • 直接处理属性而不是局部变量实际上具有一些易于使用的优点,因为局部变量的命名可能与底层属性的名称不一致,并且节点与节点之间不一致。
  • 在 HScript 表达式中,获取尚未在节点中设置局部变量映射的属性的值是一件苦差事(例如,point(opinputpath(".",0), $PT, "my_var", 0))。在 VEX 中,这要容易得多:v@my_var。由于 Houdini 中的技术工作通常围绕属性展开,因此这实际上可以使 VEX 表达式比等效的 HScript 表达式简单得多。
  • 与在较晚节点上使用外部引用到较早节点上的数据相比,将关于属性的信息向下传递到网络对于并行处理来说本质上更友好。
  • 目前,已编译的 SOP 块内部支持 VEX 操作,但无法编译使用局部变量的 HScript 表达式。
  • VEX 已经获得了大多数 HScript 表达式函数的等价物,并且更易于用于数组和字符串处理之类的事情,具有类似 Python 的数组/字符串切片和类似 Python 的字典等便利。

随着用户处理越来越大和越来越复杂的几何图形,线程和并行处理对于获得可接受的性能变得越来越重要。这个简单的事实就是为什么 VEX 只会被更广泛地用于替换 HScript 表达式以进行临时几何操作的原因。

HScript 可能始终可用于某些比 VEX 更方便的工作。然而,对于几何操作,wrangling 和 VEX/VOPs 是前进的方向,值得学习新的工作流程。

语法

VEX snippet参数允许您输入 VEX 代码片段。请参阅 VEX 函数列表。VEX 有上下文的概念。某些函数仅在某些上下文中可用(例如,用于在 SOP 上下文中访问几何信息的函数)。 VEX 代码段在 CVEX 上下文中运行。

注意:

  • 每条语句都必须以分号 (;) 结尾!
  • // 和 /* ... */ 可用于注释。
  • 在 VEX 中,sin 和 cos 等三角函数使用弧度,而不是度数。
  • 矢量属性被处理为@v.x 而不是 VX。也就是说,您会得到一个 @v 向量值,您可以使用点表示法访问其 x、y 或 z 分量,而不是获得三个单独的变量 VX、VY 和 VZ。
  • rand 应用于向量变量时会产生向量噪声。这可能出乎意料,就像在力示例中一样,您可能期望力的所有分量都由 @id 随机化。使用 float() 强制转换为标量。

访问参数值

在代码片段中,您可以使用参数的内部名称作为变量名称来读取/写入节点上的参数值。要获取参数的内部 ID,请将鼠标悬停在参数编辑器中的参数名称上。工具提示将显示参数:id。比如在Particle Color DOP中,Color参数的ID就是color。

代码语言:javascript
复制
color = @Cd;

多分量参数作为向量访问。例如,Position 参数的内部名称为 t:

代码语言:javascript
复制
// Set the translation
t = {0, 1, 0};

您可以使用点运算符访问参数的各个组件:

代码语言:javascript
复制
// Move one unit along the X axis
t.x = t.x + 1;

注: 要访问用户创建的参数的值,请使用chv函数。

访问几何属性和信息

在代码片段中,您可以使用@attribute_name 读取/写入属性的值。例如,要读取或写入P(位置)属性,请在VEX 代码中使用@P。

  • 粒子 DOP 可以访问粒子属性但不能修改它们。相反,它们通过改变每个粒子的参数值​​来影响粒子。请参阅编写粒子 VEX 表达式
  • 在 Volume Wrangle 节点中,您可以使用 @volume_name 读取或写入Volume。
  • 如果您在 VEX 代码中写入 @attribute 并且该属性不存在,Houdini 将创建它。 (Volume Wrangle 节点不会以这种方式创建新Volume。)
  • Houdini 提供了一些可以在代码片段中使用的类似属性的变量。 @elemnum 包含正在处理的当前元素的编号。 @numelem 包含几何/列表中元素的总数。请参阅下面的索引变量
  • 某些节点可能会提供额外的类似属性的变量,您可以读取这些变量以获取有关几何的计算信息。例如,在 Volume Wrangle 节点中,您可以使用 @center 来获取体积的中心。
  • Houdini 知道使用适当的 VEX 数据类型来转换一些常用属性。下面的已知属性表列出了 Houdini 可以自动转换的属性。
  • Houdini 假定所有其它 @ 引用都是float类型的,除非您手动指定不同的类型。要为属性手动指定 VEX 数据类型,请在 @ 符号前添加一个表示该类型的字符。例如,要将 foo 属性转换为字符串,您可以使用 s@foo。

注 如果您使用 @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。

例如,要获取片段中当前点附近的点列表:

代码语言:javascript
复制
int nbors[] = neighbours(0, @ptnum)

要从曲线上当前点对面的点读取属性:

代码语言:javascript
复制
vector opposite_color = point(0, "Cd", (@numpt - 1) - @ptnum )

数组

您可以通过附加 [] 来绑定数组,如

代码语言:javascript
复制
i[]@connected_pts = neighbours(0, @ptnum);

例如,以下代码将 foo 属性作为向量加载并将其复制到 P(位置)属性。您不需要指定 P 属性的类型,因为它是 Houdini 自动转换的已知属性之一。

代码语言:javascript
复制
@P = v@foo;

下面的代码将Cd属性的x分量设置为whitewater属性的值。不需要指定Cd属性的类型,因为它是已知属性之一。不需要指定whitewater的类型属性因为它是一个浮点数,未知属性会自动转换为浮点数。

代码语言:javascript
复制
@Cd.x = @whitewater;

提示 您只需在第一次引用代码中的属性时指定类型字符。

您还可以显式原型属性绑定。这允许您还指定属性的默认值,如果该属性未绑定,则将使用该默认值。如果创建了一个属性,它也会被设置为这个默认值。

注 字符串属性在创建时当前未正确设置其默认值。

这是通过将它们声明为变量来完成的。声明必须从行首开始。一行中只能声明一个变量。默认值必须是一个常量值,像 3*5 这样的计算值将失败,因为它们不是参数列表中的有效初始值设定项。

下面将创建一个向量类型的 foo 属性。如果它在输入中不存在,则默认值将设置为 { 1, 3, 5 }。

代码语言:javascript
复制
vector @foo = { 1, 3, 5 };

以这种方式声明之后,就没有必要使用 v@foosyntax,@foo 就足够了,因为已经指定了类型。

以这种方式原型化的属性将优先于任何内联定义(例如 v@foo)。将来不匹配的类型或不匹配的默认值可能会被视为错误。

有关更多信息,请参阅 POP 属性页面。

声明属性

您可以在使用它们之前指定属性的类型和默认值,如下所示:

代码语言:javascript
复制
float @mass = 1;
vector @up = {0, 1, 0};

有两个方面的作用:

  • 它为变量提供一个默认值:如果属性(例如@mass)存在,则忽略赋值。如果该属性不存在,则使用赋值。
  • 它指定属性的数据类型。像这样声明@up 属性的类型后,您可以使用@up 而不是v@up。

您不能在等号 (=) 的右侧进行任何计算。以下是语法错误:

代码语言:javascript
复制
float @mass = 1 / area;  // Error
vector @up = set(0, 1, 0);  // Error

全局访问

与 HScript 表达式不同,您不能使用 $F 等全局变量。在 VOP 中,您可以从 Globalsnode 连接诸如时间和帧之类的变量,以在 VEX 片段中使用它们。

您可以使用以下隐式变量:

  1. @Time float类型的时间($T)
  2. @Frame float类型的帧($FF)
  3. @SimTime float类型的模拟时间 ($ST),仅存在于 DOP 上下文中。
  4. @SimFrame float类型的模拟帧 ($SF),仅存在于 DOP 上下文中。
  5. @TimeInc float类型的时间步长 (1/$FPS)

创建几何

您可以在某些节点(例如 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() 作为第一个参数来指定当前几何。

代码语言:javascript
复制
addpoint(geoself(), {0, 1, 0});

addprim 函数当前可以生成多边形(“poly”)或折线(“polyline”)。如果创建多边形,则必须使用 addvertex 向点添加顶点。 Houdini 可能会在有点但没有顶点的多边形上崩溃。

代码语言:javascript
复制
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);
  • 您可以使用 vertexpoint、pointvertex、vertexprim、vertexnext、vertexprev 和 primvertexcount 检查几何的拓扑。
  • 您可以使用 pc* 函数(pcopen、pcnumfound、pciterate、pcimport 等)从点云文件中读取数据。

几何遍历函数

请参阅 VEX 几何函数

访问组成员关系

@group_ groupname 形式的特殊虚拟属性允许您获取或设置当前元素的组成员关系。 您可以通过检查@group_ name == 1 来检查当前点/边/基元/粒子是否在命名组中。

您可以通过设置虚拟@group_name 属性向组添加或删除当前点/边/图元。将该属性设置为 1(或任何非零值)会将当前元素放入该组中。将该属性设置为 0 将从该组中删除当前元素。

用户自定义函数

您可以使用 VEX 函数语法将自己的函数定义为 VEX 代码段的一部分。例如:

代码语言:javascript
复制
float mysquare(float a)
{
  return a * a;
}

windresist = mysquare(windresist);

include 指令

在代码片段中找到的任何 #include 指令将自动移到生成的 VEX 函数之外,因此将按预期运行。

确定是否存在用于属性绑定的参数是通过在预处理完成后简单扫描代码来完成的。此预处理仅在代码片段上完成;但是,并且不处理任何#include 文件。因此,它可能会被依赖于 #includes 的 #ifdef 指令混淆。

提示

在多行编辑器中编辑时,您可以按 Ctrl + Enter 提交更改并更新 Houdini。

VEX 片段在每一帧(或在模拟网络中,每个时间步)运行。

您可以使用 return 语句提前退出代码段。例如,以下 VEX 只会在全新粒子上将 Windresist 设置为 0:

代码语言:javascript
复制
if (@age > 0) return;

// If @age was > 0, we returned above, so this line
// only runs for particles where @age == 0
windresist = 0;
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022/03/24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 为什么使用 VEX 进行临时修改?
  • 语法
    • 访问参数值
      • 访问几何属性和信息
        • 访问其它输入的属性
          • 索引参数
            • 数组
              • 声明属性
                • 全局访问
                  • 创建几何
                    • 几何遍历函数
                      • 访问组成员关系
                      • 用户自定义函数
                      • include 指令
                      • 提示
                  相关产品与服务
                  GPU 云服务器
                  GPU 云服务器(Cloud GPU Service,GPU)是提供 GPU 算力的弹性计算服务,具有超强的并行计算能力,作为 IaaS 层的尖兵利器,服务于深度学习训练、科学计算、图形图像处理、视频编解码等场景。腾讯云随时提供触手可得的算力,有效缓解您的计算压力,提升业务效率与竞争力。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档