Houdini VEX sink
· Houdini MOC · Houdini VEX · Houdini VEX reference · #note/sink · #code/vex
TOC
Data types
int | Integer values |
float | Floating point scalar values |
vector2 | Two floating point values |
vector | Three floating point values |
vector4 | Four floating point values. |
array | A list of values |
struct | A fixed set of named values (class) |
matrix2 | { {1,0}, {0,1} } |
matrix3 | { {1,0,0}, {0,1,0}, {0,0,1} } |
matrix | { {1,0,0,0}, {0,1,0,0}, {0,0,1,0}, {0,0,0,1} } |
string | A string of characters |
dict | A dictionary mapping string s to other VEX data types |
bsdf | A bidirectional scattering distribution function |
Vectors
@v = {1, 1, 1}
v@v = set(x, y, z)
Specifying VEX Data Types
The following characters are used to cast to the corresponding data type.
float f@name // Floating point scalar values.
vector2 u@name // Two floating point values. Could be used to store 2D positions.
vector3 v@name // Three floating point values. Usually positions, directions, normals, UVW or colors.
vector4 p@name // Four floating point values. Usually rotation quaternions, or color and alpha (RGBA).
int i@name // Integer values (VEX uses 32 bit integers).
matrix2 2@name // Four floating point values representing a 2D rotation matrix.
matrix3 3@name // Nine floating point values representing a 3D rotation matrix or 2D transform matrix.
matrix 4@name // Sixteen floating point values representing a 3D transform matrix.
string s@name // A string of characters.
1/100 results in integer, 1/100.0 results in float. See #Operator type interactions
Type casting
int a, b;
float c;
c = (float)a / (float)b; // float(a) is unnecessary
// type cast a function
float n;
n = noise(noise(P));
n = noise(vector(noise(P)));
Operators
Dot operator
// vector
v = set(v.x, v.y, v.z);
v = set(v.r, v.g, v.b);
// vector2
v2 = set(v2.x, v2.y);
v2 = set(v2.u, v2.v);
// vector4 forth element
f = v4.a;
f = v4.w;
// matricies
m[0][0] = m.xx;
m[2][2] = m.zz;
m[3][0] = m.ax;
//components
v.zyx = set(v.z, v.y, v.x);
v4.bgab = set(v4.b, v4.g, v4.a, v4.b);
Comparisons
The logical (&&, ||, and !)
and bitwise (& |, ^, and ~)
operators are only defined for integers
All bool operations are casted to integers!
Operator type interactions
float * int = float
int * float = int
vector * scalar = vector
v2 * v4 = v4
**Important!!!**
The “missing” component(s) on the smaller vector are filled in as {0.0, 0.0, 0.0, 1.0}
Pragmas
#pragma opname noise_surf
#pragma oplabel "Noisy Surface"
#pragma label clr "Color"
#pragma label frequency "Frequency"
#pragma hint clr color
#pragma range frequency 0.1 10
surface noise_surf(vector clr = {1,1,1}; float frequency = 1; export vector nml = {0,0,0})
{
Cf = clr * (float(noise(frequency * P)) + 0.5) * diffuse(normalize(N));
nml = normalize(N)*0.5 + 0.5;
}
Channel Shortcut Syntax
This is used to hint at the data type of auto generated wrangle parameters.
ch('flt1'); // Float
chf('flt2'); // Float
chi('int'); // Integer
chv('vecparm'); // Vector 3
chp('quat'); // Vector 4 / Quaternion
ch3('m3'); // 3x3 Matrix
ch4('m4'); // 4x4 Matrix
chs('str'); // String
chramp('r', x); // Spline Ramp
vector(chramp('c', x)); // RGB Ramp
VEX Snippets
Sampling functions
Random Directed Vectors
Source
Sample Direction Uniform
Sample Direction Uniform
This is a great way of getting “random” vectors but you need the vectors to be “clamped” to a certain range of “spread”.
To illustrate this, we’ll use a buncha points on a grid and “shoot” (aka move) them out “randomly” using sample
functions.
vector2 u = rand(@ptnum);
@P = sample_direction_uniform(u);
Sample Hemisphere
This function takes a center
and a bias
. Think of “center” in sample functions as “direction” – so {0, 1, 0}
is up, {0, -1, 0}
is down – and bias
is simply the “angle of spread”.
vector2 uv = rand(@ptnum);
float bias = @Frame;
@P = sample_hemisphere({0, 0, 0}, bias, uv);
Sample Direction Cone
This is probably the most useful, instead of bias
we just use angle
instead to achieve something similar. This time, we’ll scatter upwards using {0, 1, 0}
as the center.
vector2 uv = rand(@ptnum);
float angle = 90; // the "spread" of the cone @P = sample_direction_cone({0, 1, 0}, radians(angle), uv);
We could imagine using this to shoot out random particles, so instead of @P
we could assign it to @v
as initial velocity to a DOP – while constraining how far they spread.
But what happens if we want the magnitudes to be the same? Right now, we have some vectors that are ahead of others because it’s a dome-like spread.
We achieve this by only varying v
in the uv
.
vector2 uv = set(1, rand(@ptnum));
@P = sample_direction_cone({1,0,0}, radians(angle), uv);
Now the values are “clamped” along whichever axis the center is on e.g. all the points have the same @P.x
value – since we are scattering in {1, 0, 0}
.
Another way of thinking about this, if we have particles getting shot out in +x
direction, they can only vary/wiggle up-down (y) or left-right (z) but how far they go (x) is always the same across all points.
At radians(90)
the vectors are perpendicular to the projection plane. We can use this to randomly scatter lines that are perfectly flat on the ground but point in different directions:
// Before a Copy to Points SOP
@N = sample_direction_cone({0, 1, 0}, radians(90), set(1, rand(@ptnum)));
Sample Hypersphere Uniform
This is a quick way to randomly rotate a bunch of girls around in a Copy to Points e.g. get a random @orient.
@orient = sample_hypersphere_uniform(rand(@ptnum));
Remapping attribs
parm*=rand(@id+38+ch("seed"));
//random number, linear spread
parm=fit01(rand(@id+31+ch("seed")),ch("min"),ch("max"));
//particle age -> Ease in - Ease out
parm*=smooth(ch("start"), ch("end"),@nage);
//parameter change in a certain time range
parm=fit(@Frame, ch("start"), ch("end"), ch("start_value"), ch("end_value"));
//connect params
parm=fit(@P.y, ch("low"), ch("high"), ch("low_value"), ch("high_value"));
//param from age by multiplier
parm*=chramp("parm",@nage);
//param from a particle speed
parm=fit(length(@v),ch("speedmin"),ch("speedmax"), ch("valuemin"), ch("valuemax"));
Orientation
// orient your points towards your velocity vector:
@orient = dihedral({0,0,1} ,@v);