# VEX functions for procedural modeling

calendar_today

29.05.2022

label

VEX

mouse

Houdini 19.0

### 1 Introduction

An ongoing collection of VEX functions useful for procedural modeling.

### 2 Shape

Creates shapes based on `u`, eg. the `curveu` attribute from the resample node, or a component of the UV coordinates from the sweep node.
Recommended values: `center` 0.5; `weight` <= 0.5; `power` > 0.0; `amount` > 0.0.

``````float center = chf('center');
float weight = chf('weight');
float power = chf('power');
float amount = chf('amount');

function float shape(float c, w, p, a, u){
u = abs(u - c);
if(u > w) return 0.0;
u /= w;
float d = 1.0 - u * u * (3.0 - 2.0 * u);
d = pow(d, p) * a;
return d;
}

float u = vertexprimindex(0, i@vtxnum) / (primvertexcount(0, i@primnum) - 1.0);

v@P.y = shape(center, weight, power, amount, u);``````

### 3 Smooth minimum

Calculates the smooth `k` minimum of two distances `a` and `b`.

``````function float smooth_min(float a, b, k){
float h = max(k - abs(a - b), 0.0) / k;
float d = min(a, b) - h * h * h * k * (1.0 / 6.0);
return d;
}``````

### 4 Point density

Measures point density within a certain radius.

``````// POINT WRANGLE
int samples = chi('samples');

int pts[] = pcfind(0, 'P', v@P, radius, samples);
float dens = len(pts) / float(samples);

f@dens = dens;``````

### 5 Curve U

Parametric U on curve:

``float u = vertexcurveparam(0, i@vtxnum);``

Symmetrical U:

``float us = 1.0 - abs(u - 0.5) * 2.0;``

### 6 Maximize UVs proportionally

``````// vertex wrangle
string geo_uv = geounwrap(0, 'uv');
vector bb = relbbox(geo_uv, v@uv);
vector size = getbbox_size(geo_uv);
float aspect = size.y / size.x;
bb.y *= aspect;
v@uv = bb;``````

### 7 Ping pong

``````float u = v@P.x;
v@P.y = 1.0 - abs((abs(u) % (2.0)) - 1.0);``````

### 8 Smoothly shorten curves

This will shorten and cubicly interpolate in-between point positions an open curve by a custom percentage.

``````float amount = chf('amount');

float u = vertexcurveparam(0, i@vtxnum);
float um = fit01(u, amount, 1.0 - amount);
vector uvw = set(um, 0.0, 0.0);

int pts[] = expandpointgroup(0, '*');
insert(pts, 0, 0);
append(pts, npoints(0)-1);

vector pos[];
foreach(int pt; pts){
vector pos_pt = point(0, 'P', pt);
append(pos, pos_pt);
}

v@P = spline('cubic', um, pos);``````

### 9 Average value of point attribute

Detail wrangle. Optionally replace `*` with group name.

``````int pts[] = expandpointgroup(0, '*');

float values[] = {};
foreach(int pt; pts){
float val = point(0, 'val', pt);
append(values, val);
}
f@val_avg = avg(values);``````

### 10 Accumulate point values

Prepend a promote node from points to primitives for a random float value named `h` with the promotion method set to "Array of all". Next, add a point wrangle that sums slices of the array:

``````float h[] = prim(0, 'h', i@primnum);
float s = sum(h[0:i@ptnum+1]);
v@P.y = s;``````