Go Procedural:Houdini VEX Baiscs

Use vex to manipulate geometry in Sop node Attribute Wrangle.

Note:This article does not cover the use of shader

Basic types

Type Example Attribute Syntax
int 21, -3, 0x31, 0b1001, 0212, 1_000_000 i@name
float 21.3, -3.2, 1.0, 0.000_000_1 f@name
vector2 {0,0}, {0.3,0.5} u@name
vector {0,0,0}, {0.3,0.5,-0.5} v@name
vector4 {0,0,0,1}, {0.3,0.5,-0.5,0.2} p@name
array { 1, 2, 3, 4, 5, 6, 7, 8 } type[]@name
struct struct Transform {vector p, r, s; } Transform t = { {0,0,0},{0,0,0},{1,1,1} };
matrix2 { {1,0}, {0,1} } 2@name
matrix3 { {1,0,0}, {0,1,0}, {0,0,1} } 3@name
matrix { {1,0,0,0}, {0,1,0,0}, {0,0,1,0}, {0,0,0,1} } 4@name
string "hello world" s@name

Accessing geometry attributes

Read or write the value of an attribute using @attribute_name if it’s a known attributes. Otherwise a custom defined attribute should define the type first, or it’s a float as default.

1
2
3
4
5
6
7
8
9
10
11
@foo; // float
v@bar // vector

// defined in last node;
v@rest_P = @P;

////////

// used in next node:
// @P = @rest_P; // error, rest_p is float as default.
@P = v@rest_P // correct.

The following table lists known attributes that are automatically cast.

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

Accessing globals

Variable Describe
@Time Float time ($T)
@Frame Float frame ($FF)
@SimTime Float simulation time ($ST), only present in DOP contexts.
@SimFrame Float simulation frame ($SF), only present in DOP contexts.
@TimeInc Float time step (1/$FPS)

Accessing individual components of a vector, matrix or struct

0 1 2 3
u v
x y z w
r g b a

Examples:

1
2
3
4
5
@uv.u, @uv.v;
@P.x, @P.y, @P.z;
@Cd.r, @Cd.g, @Cd.b;
v.xxx == set(v[0], v[0], v[0])
c.bgra == set(c[2], c[1], c[0], c[3])

Assign value

Use {} to composite with only literal value, use set() to composite with variable.
Examples:

1
2
3
4
5
6
7
vector v;
v = {0,1,0};
vector v2 = v;
//vector v3 = {0, v2.y, 0}; // error
vector v3 = set(0, v2.y, 0);
matrix3 m1 = {{1,0,0}, {0,1,0}, {0,0,1}};
matrix3 m2 = set({1,0,0}, v, {0,0,1});

Array

Declaring array types

To declare an array variable, the general form is member_type var_name[]:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
float   my_array[];
// v is a single vector, vector_array is an array of vectors
vector v, vector_array[];
string str_array[];

// To specify a literal array, use curly braces, with the array members separated by commas:

vector an_array[] = { {1, 2, 3}, {2, 3, 4}, {4, 5, 6} };

vector[] rgb_array()
{
return { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} };
}

//If you specify scalars where a vector is expected, the compiler assigns the scalar value to all components of the vector:

vector an_array[] = { 1, 2, 3};
// an_array[] == { {1, 1, 1}, {2, 2, 2}, {3, 3, 3} }

//The array() function creates an array from its arguments.
int my_array[] = array(1, 2, 3, 4, 5);

//You can use array() to generate an array of any type. To force array() to generate vectors (for example):

v[]@attr_name = vector[](array(value1, value2, ...));

Accessing and setting array values

Use arrayname[index] to look up a value by its position in the array.
Python-style indexing is used. This means negative indices refer to positions from the end of the array.

1
2
3
4
5
6
7
8
9
10
int nums[] = { 0, 1, 2, 3, 4, 5 };
int n = nums[10]; // Returns 0
int b = nums[-2]; // Returns 4

string strs[] = { };
string s = strs[20]; // Returns ""

//You can also assign values using the square brackets notation:
float nums[] = { };
nums[0] = 3.14;

Slicing Arrays

The square-brackets can be used to extract sub-arrays using the Python slicing notation.str_name[start:end:step]

1
2
3
4
5
int nums[] = { 0, 1, 2, 3, 4, 5 };
int start[] = nums[0:2]; // { 0, 1 }
int end[] = nums[-2:]; // { 4, 5 }
int rev[] = nums[::-1]; // { 5, 4, 3, 2, 1, 0 }
int odd[] = nums[1::2]; // { 1, 3, 5 }

The slice function is the equivalent for using the slice-based square brackets notation.

1
2
3
4
5
6
7
8
9
10
11
12
<type>[] slice(<type>s[], int start, int end)
<type>[] slice(<type>s[], int start, int end, int step)
// Extracts a sub-array from a larger array.
string slice(string s, int hasstart, int start, int hasend, int end, int hasstep, int step)
<type>[] slice(<type>array[], int hasstart, int start, int hasend, int end, int hasstep, int step)

// Examples
int[] nums = {10, 20, 30, 40, 50, 60};
slice(nums, 1, 3) == {20, 30}; // nums[1:3]
slice(nums, 1, -1) == {20, 30, 30, 40, 50}; // nums[1:-1]
slice(nums, 0, len(nums), 2) == {20, 40, 60}; // nums[0:len(nums):2]
slice(nums, 0, 0, 0, 0, 1, 2) == {20, 40, 60}; // nums[::2]

Looping over an array

Use foreach.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
foreach ([element_type] value; array) statement;
foreach (index, value; array) statement;
foreach (int index; element_type value; array) statement;

string days[] = { "Mon", "Tue", "Wed", "Thu", "Fri" };

foreach (string name; days) {
printf("%s\n", name);
}

string name2;
foreach (name2; days) {
printf("%s\n", name2);
}

foreach (int i; string name3; days) {
printf("Day number %d is %s.\n", i, name3);
}

int index; string name4;
foreach (index, name4; days) {
printf("Day number %d is %s.\n", index, name4);
}

Useful functions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int arr[] = {3, 5, 6, 7, 4};
len(arr); // 5
append(arr, 8); // == push
//push(arr, 8); // arr == {3, 5, 6, 7, 4, 8}
insert(arr, 1, 2); // arr == {3, 2, 5, 6, 7, 4, 8}
int arr2[] = sort(arr); // arr2 == {2, 3, 4, 5, 6, 7, 8}
int arr3[] = argsort(arr); // arr3 == {1, 0, 5, 2, 3, 4, 6}
int arr4[] = reorder(arr, arr3);// arr4 == arr2;
int arr5[] = reverse(arr); // arr5 == {8, 4, 7, 6, 5, 2, 3}
isvalidindex(arr, 3); // 1
isvalidindex(arr, 30); // 0
int v1 = pop(arr); // v1 == 8, arr == {3, 2, 5, 6, 7, 4}
int v2 = pop(arr, 2); // == removeindex
//int v2 = removeindex(arr, 2); // v2 == 5, arr == {3, 2, 6, 7, 4}
int v3 = removevalue(arr, 10); // v3 == 0;
int v4 = removevalue(arr, 4); // v4 == 1, arr == {3, 2, 6, 7}
resize(arr, 8); // arr == {3, 2, 6, 7, 0, 0, 0, 0}