Using VEX expressions

Overview

Houdini에 있는 몇몇  노드들은 짧은 VEX expression들 도는 VEX 코드의 snippet들을 작성할 수 있게 한다. 예를 들어, Point Wrangle, Attrib Wrangle geometry node; Geometry Wrangle, Gas Field Wrangle dynamics node, particle dynamics node.

이들 VEX expressions는 노드를 통해 각 엘레먼트에서 실행된다 (노드 타입을 기반해 point, particle, edge, primitive, voxel). 코드는 노드 파라미터들과 geometry attribute들의 값들을 읽을 수 있고, 인풋 geometry에 값을 변경하기 위한 특별한 변수들을 설정할 수 있다.

 

** Tip **

Python SOP은 이와 유사하지만 Python snippet을 사용해 geometry를 편집하게 한다.

Syntax

VEX snnipet 파라미터는 VEX 코드의 snippet을 입력할 수 있게 한다.

VEX는 “context”의 컨셉을 가지고 있다. 몇몇 함수들은 특정 context에서만 사용이 가능하다 (예를 들어, SOP context에서 geometry 정보에 접근하는 함수들). VEX snippet은 CVEX context에서 실행한다.

Gotchas

  • 각 문장은 세미콜론 (;) 으로 끝나야만 한다.
  • // 와 /* … */ 은 주석을 다는데 사용된다.
  • VEX에서, sin과 cos 같은 삼각함수ㅜ들은 radian을 사용한다. degree를 사용하지 않는다.
  • Vector attribute들은 $VX가 아닌 @v.x으로 다루어 진다. 즉, 세 개의 독립된 변수 $VX, $VY, $VZ가 아닌, 닷(.) 부호를 사용해서 x, y, z 컴포넌트에 접근할 수 있는 @v vector 값을 얻게 된다.
  • rand가 vector 변수에 적용될 때 vector noise를 제공하게 된다. 이는 뜻밖일 수 있지만, force의 예를 보면, force의 모든 컴포넌트들이 @id를 통해 동일하게 랜덤화되도록 예상할 수 있다. float()를 사용해 force에 scalar 값을 캐스트 한다.

Accessing parameter values

snippet에서 parameter_id를 사용해 노드에 파라미터의 값을 읽고/쓸 수 있다. 파라미터의 내부 ID를 얻으려면, parameter editor에서 파라미터 이름에 마우스를 올린다. 툴팁이 파라미터 : id를 보여줄 것이다. 예를 들어, Particle Color DOP에서 Color 파라미터의 ID는 color다.

color = @Cd

다중 컴포넌트 파라미터들은 vector로 접근된다. 예를 들어, Position 파라미터는 내부 이름 t를 가지고 있다 :

1
2
// Set the translation
= {010};
cs

사용자는 닷 연산자를 사용해 파라미터의 개별 컴포넌트들에 접근할 수 있다 :

1
2
// Move one unit along the X axis
t.x = t.x + 1;
cs

 

** Note **

사용자가 생성한 파라미터의 값에 접근하려면 chv() vex 함수를 사용한다.

Accessing geometry attributes

snippet에서, @attribute_name을 사용해 attribute의 값을 읽고/쓸수 있다. 예를 들어, P (위치) attribute를 읽거나 작성하려고 한다면, VEX 코드에서 @P를 사용한다.

  • 만약 노드가 하나 이상의 인풋을 가지고 있다면, opinputnum_을 이름의 접두에 붙여 다른 인풋으로부터 attribute를 얻을 수 있다. 예를들여 v@opinput1_P.
  • particle DOP은 particle attribute에 접근할 수 있지만 그것을 변경하지는 못한다. 대신 각 파티클별로 파라미터 값들을 다양화하는 것을 통해 파티클들에 영향을 줄 수 있다.
  • Volume Wrangle 노드에서 @volume_name을 사용해 볼륨을 읽거나 쓸 수 있다.
  • VEX code에 작성한 @attribute가 존재하지 않는다면, Houdini는 그 attribute를 생성할 것이다. (Volume Wrangle 노드는 이 방식으로 새로운 볼륨들을 만들지 않을 것이다).

Houdini는 적절한 VEX 데이타타입을 사용해 특정 attribute들을 캐스트 할줄 안다. 다음 테이블은 자동적으로 캐스트하는 알려진 attribute들을 리스트화 했다. (만약 사용자가 @opinputn_name을 사용해 다른 인풋에 접근한자면, 자동 캐스팅은 작동하지 않는다).

VEX type Attribute names
vector (3 floats) @P, @accel, @center, @dPdx, @dPdy, @dPdz, @Cd, @N,
@scale, @force, @rest, @torque, @up, @uv, @v
vector4 (4 floats) @backtrack, @orient, @rot
int @id, @ix, @iy, @iz, @nextid, @pstate, @resx, @resy, @resz,
@ptnum, @vtxnum, @primnum, @numpt, @numvtx, @numprim, @group_*
string @name, @instance

모든 다른 @ 레퍼런스들은 float로 캐스트한다. attribute에 대한 VEX 데이터타입을 수동으로 지정하려면, 사용자는 @ 부호 앞에 타입을 표시하는 문자를 하나 추가해야만 한다. 예를 들어, foo attribute를 string으로 캐스트하려면, s@foo를 사용할 수 있다.

다음 테이블은 사용가능한 데이터타입들과 그에 상응하는 문자들을 리스트화 했다.

VEX type Syntax
float f@name
vector2 (2 floats) u@name
vector (3 floats) v@name
vector4 (4 floats) p@name
int i@name
matrix2 (2×2 floats) 2@name
matrix3 (3×3 floats) 3@name
matrix (4×4 floats) 4@name
string s@name

Arrays

[ ]를 다음처럼 추가하는 것으로 배열들을 바인드 할 수 있다 .

i[]@connected_pts = neighbours(0, @ptnum);

예를 들어, 아래 코드는 foo attribute를 vector로 불러오고 P attribute에 그 것을 복사한다. 사용자는 P attribute의 타입을 지정할 필요가 없다. 왜냐하면 Houdini 자동적으로 캐스트하는 이미 알려진 attribute 중 하나이기 때문이다.

@P = v@foo;

다음 코드는 Cd attribute의 x 컴포넌트를 whitewater attribute의 값에 설정한다. 사용자는 Cd attribute가 이미 알려진 attribute 중 하나이기 때문에 타입을 지정할 필요가 없다. whitewater attribute는 float이고 알려지지 않은 attribute들은 자동적으로 float로 캐스트 되기 때문에 타입을 지정할 필요가 없다.

@Cd.x = @whitewater;

 

** Tip **

사용자가 attribute를 코드에 처음 조회하는 경우에만 타입 문자를 지정해야만 한다.

 

또한 사용자는 명확하게  attribute를 바인딩을 프로토타입할 수 있다. 이 것은 attribute가 바인드 되지 않았다면 사용될 attribute의 디폴트 값을 지정할 수 있게도 한다. attribute가 생성되었다면, 이 디폴트 값으로 설정될 것이다.

 

** Note **

string attribute들은 현재 생성되었을 때 디폴트들을 적절하게 설정하지 않는다.

 

이 것은 그 것들을 변수로 선언하는 것으로 해낼 수 있다. 선언은 라인의 시작지점에서 시작되어야만 한다. 한 라인에서 하나의 변수만이 선언될 수 있다. 디폴트 값은 상수 값이어야만 하고, 3*5와 같은 계산된 값들은 파라미터 리스트에서 사용가능한 초기화들이 아니기 때문에 실패할 것이다.

아래의 코드는 vector 타입의 foo attribute를 생성할 것이다. 인풋에 존재하지 않는다면, 디폴트 값은 {1, 3, 5}로 설정될 것이다.

vector @foo = 1, 3, };

이러한 방식으로 선언을 한 다음 v@foo 문법을 사용할 필요가 없고, @foo는 지정이 된 타입으로 충분할 것이다.

이 방식으로 프로토타입된 attribute들은 모든 인라인 정의(예 v@foo)보다 높은 우선권을 가질 것이다. 이후에 일치하지 않는 타입들 혹은 디폴트들은 오류로 간주될 것이다.

Declaring attributes

다음과 같이 attribute를 사용하기 전에 attribute의 디폴트 값과 타입을 지정할 수 있다 :

1
2
float @mass = 1;
vector @up = {010};
cs

이 것은 두 가지 방법으로 유용할 수 있다 :

  • 이는 디폴트 값을 변수에 준다 : attribute (예 @mass)가 존재한다면, 할당이 무시될 것이다. attribute가 존재하지 않는다면, 할당을 사용할 것이다.
  • 이는 attribute의 데이터 타입을 지정한다. @up과 같은 attribute의 타입을 선언한 후에 사용자는 v@up대신 @up을 사용할 수 있다.

사용자는 등호 (=) 의 오른쪽에서는 어떠한 계산도 할 수 없다. 다음 문법들은 오류이다 :

1
2
float @mass = / area;  // Error
vector @up = set(010);  // Error
cs

 

Accessing globals

HScript expressions와 다르게 사용자들은 $F와 같은 전역 변수들을 사용할 수 없다.

VOP에서 Time과 Frame과 같은 변수들을 VEX snippet에서 사용하기 위해 전역 노드로부터 연결할 수 있다.

사용자는 다음 내장 변수들을 사용할 수 있다 :

@Time

Float time ($T)

@Frame

Flaot frame ($FF)

@SimTime

Float simulation time ($ST), DOP context에서만 나타난다.

@SimFrame

Float simulation frame ($SF), DOP context에서만 나타난다.

@TimeInc

Float time step (1/$FPS)

Creating geometry

Attrib Wrangle과 같은 특정 노드들 안에 VEX snippet을 가진 geometry를 생성할 수 있다. geometry를 생성할수 있으려면, 노드는 cvex context에서 실행되어야만 한다. 즉 Point Wrangle은 sop context에서 실행되기 때문에 geometry를 생성할 수 없다.

addpoint, addprim, addvertex 함수들은 point, primitive, vertex를 생성할 수 있게 한다. 사용자들은  setattrib와 setprimvertex를 사용해 geometry를 변경할 수 있다. removepoint와 removeprim으로 geometry를 제거할 수 있다. setpointgroup과 setprimgroup을 사용해 그룹 멤버쉽을 설정할 수 있다. setprimintrinsic을 사용해 sphere primitive의 transform과 같은 것들을 변경할 수 있다.

setattrib를 사용하기 보단 바이드된 변수들을 사용해 현재 엘레먼트의 attribute를 설정하는게 더 빠르다. (예, @name = val). setattrib는 만약 사용자가 다른 엘레먼트들에 attribute를 설정할 필요가 있을 때만 사용한다. 만약 setattrib를 사용하고 다른 소스 point들에서 point를 변경한다면, mode 아규먼트를 “add”로 설정해 결과를 합성한다.

geometry 생성 함수는 병렬로 실행될 수 있다. 모든 변화들은 대기 행렬로 만들어지고 VEX 코드가 모든 존재하는 geometry에 반복된 다음에 적용된다. 이 의미는 setattrib는 바인드한 변수들(예, @name = val)을 통해 만든 변화들을 덮어쓰게 될 것이다.

geometry 생성 함수에 대한 첫 번째 아규먼트는 생성을 위한 목표를 지정하는  “geometry handle”이다. (이 것은 현재 geometry에 쓰기의 대안으로 파일에 쓰기를 지원하는 경향이 있다). 현재 geometry를 지정하기 위해 geoself()를 첫 번째 아규먼트로 사용한다.

addpoint(geoself(), {0, 1, 0});

addprim 함수는 polygon(“poly”)  또는 polyline(“polyline”)을 생성할 수 있다. 만약 polygon을 생성하면, addvertex를 사용해 point들에 vertex들을 추가해 줘야만 한다. Houdini는 point에 vertex들이 없는 polygon에 대해 크래쉬가 발생한다.

1
2
3
4
5
6
7
8
int p1 = addpoint(geoself(), {010});
int p2 = addpoint(geoself(), {110});
int p3 = addpoint(geoself(), {111});
int prim = addprim(geoself(), “poly”);
addvertex(geoself(), prim, p1);
addvertex(geoself(), prim, p2);
addvertex(geoself(), prim, p3);
cs
  • Attrib Wrangle 같은 노드들은 인풋을 필요로하고, 그렇지 않으면 오류를 발생시킨다. 만약 사용자가 비어있는 geometry에서부터 시작하고자 한다면, Null SOP을 연결시킨다.
  • geometry의 토폴로지를 vertexpoint, pointvertex, vertexprim, vertexnext, vertexprev, primvertexcount를 사용해 점검할 수 있다.
  • 사용자는 pc* 함수들을 사용해 포인트 클라우드 파일들을 읽을 수 있다. (pcopen, pcnumfound, pciterate, pcimport, 등).

Geometry traversal functions

VEX geometry functions를 본다.

Accessing group membership

@group_groupname 형태의 특별한 가상 attribute는 사용자가 현재 엘레먼트에 대한 그룹 멤버십을 얻거나 설정하게 한다.

@group_name == 1인지 확인하는 것으로 현재 point/edge/primitive/particle이 명명화된 그룹 안에 있는지 확인 할 수 있다.

가상 @group_name attribute 를 설정해 그룹에서 현재 point/edge/primitive를 추가하거나 제거할 수 있다. attribute를 1로 설정하는 것은 (혹은 0이 아닌 값) 현재 엘레먼트를 그 그룹으로 넣는다.

User-defined functions

사용자는 VEX 함수 문법을 사용해 VEX snippet의 일부분으로 사용자들만의 함수들을 정의 할 수 있다. 예를 들어 :

1
2
3
4
5
6
float mysquare(float a)
{
  return a * a;
}
windresist = mysquare(windresist);
cs

Includes

code snippet에서 발견되는 모든 #include 명령들은 자동적으로 생성된 VEX 함수 밖으로 이동될 것이어서, 예상한대로 될 것이다.

파라미터가 attribute 바인딩에 대해 나타내는 것을 경정하는 것은 프리 프로세싱이 완료된 다음 코드의 간단한 스캔을 거쳐 완료된다. 이 프리 프로세싱은 code snippet에서만 완료된다; 그러나, 어떠한 #include 파일들도 프로세스 하지 않는다. 그러므로 #include를 기반으로 하는 #ifdef 명령 때문에 혼란스러울 수 있다.

Tips

  • 다중 라인 편집기에서 편집을 할 때 Ctrl + Enter 키를 눌러 변경사항을 “졀정”하고 Houdini를 업데이트 할 수 있다.
  • VEX snippet은 매 프레임마다 실행된다. (또는 시뮬레아션 네트워크에서, 모든 타임 스텝마다).
  • return 문장을 사용해 일찍 snippet을 퇴장할 수 있다. 예를 들어, 다음 VEX는 완전히 새로운 particle들에 windresist만을 0으로 설정할 것이다 :
    1
    2
    3
    4
    5
    if (@age > 0return;
    // If @age was > 0, we returned above, so this line
    // only runs for particles where @age == 0
    windresist = 0;
    cs

Troubleshooting error messages

Your code Problem
force += 2 Syntax error, unexpected '}', expecting ';'

Each statement must end with a semicolon (;)

@v += force SRead-only expression given for read/write parameter

Particle nodes cannot modify particle attributes.

x = { 0, @y, 0} Syntax error, unexpected identifier, expecting '}'.

You cannot have varying arguments to the {} vector constructor. Use set() instead: x = set(0, @y, 0);.

x = set(0, $F, 0); Doesn't animate.

While $F will be evaluated, VOP networks are not time dependent so it won’t animate. Use @Frame instead.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s