kunz Difference between revisions of "VEX Wrangle Snippets"

Difference between revisions of "VEX Wrangle Snippets"

From kunz
 
(187 intermediate revisions by the same user not shown)
Line 1: Line 1:
== Iterative Face Insetting ==
== Translate ==
Triangular recursive inset edge divisions, [https://twitter.com/d_gfx/status/1452718124579520512 via @d_gfx], excellent use of [https://www.sidefx.com/docs/houdini/vex/arrays.html arrays]
[[File:vex_offset_position.gif | 340px | right]]
 
Offset the position of geometry
 
 
 
 
 
 
 
 
 
 
 
 
[[:File:vex_offset_position.hiplc|vex_offset_position.hiplc]]
<syntaxhighlight lang='C'>
@P += {1, 0, 0};
</syntaxhighlight>
 
== Taper ==
[[File:taper_vex_001.gif | 340px | right]]
 
 
Reduces the circumference by scaling along the XZ plane based on the height of the geometry.
 
 
 
 
 
[[:File:taper_vex_001.hiplc|taper_vex_001.hiplc]]
 
<syntaxhighlight lang='C'>
<syntaxhighlight lang='C'>
int pts[] = primpoints(0,@primnum); vector pos[];
float taper = relbbox(0,@P).y;
int edge_div_pts[]; vector edge_div_pos[];
// Remap the taper range
foreach( int pt; pts )
taper = fit01(taper, 1, fit01(sin(@Time*PI/5)*0.5+0.5, 2.5, .5));
    append(pos, vector(point(0,'P',pt)));
// Apply the taper by scaling along the X and Y axis
for( int i = 0; i < chi('iterations'); i++ )    {
@P *= set(taper,1,taper);
    resize(edge_div_pts,0); // empty
    resize(edge_div_pos,0); // empty
    for( int j = 0; j < len(pts); j++ ) {
        append(edge_div_pos, lerp( pos[j], pos[(j+1)%len(pts)], chf('div_ratio') ));
        append(edge_div_pts, addpoint(0, edge_div_pos[-1]));
    }
    for (int k = 0; k < len(pts); k++ ) {
        addprim(0, 'poly', pts[k], edge_div_pts[k], edge_div_pts[(k+2)%len(pts)]);
    }
    pts = edge_div_pts;
    pos = edge_div_pos;
}
addprim(0, 'poly', edge_div_pts);
removeprim(0,@primnum,1);
</syntaxhighlight>
</syntaxhighlight>


== Boxify ==
== Boxify ==
Distorts the geometry into a box shape
[[File:vex_boxify_001.gif | 340px | right]]
 
 
Distorts the geometry, morphing it into a box shape
 
[[:File:vex_boxify_001.hiplc|vex_boxify_001.hiplc]]
<syntaxhighlight lang='C'>
<syntaxhighlight lang='C'>
vector centroid = getbbox_center(0);
vector centroid = getbbox_center(0);
Line 35: Line 58:
@P += centroid;
@P += centroid;
</syntaxhighlight>
</syntaxhighlight>


== Spherify ==
== Spherify ==
[[File:vex_spherify_001.gif | 340px | right]]
Distorts the geometry into a sphere shape
Distorts the geometry into a sphere shape
[[File:Spherify.gif|800px]]
 
 
 
 
[[:File:vex_spherify_001.hiplc|vex_spherify_001.hiplc]]
<syntaxhighlight lang='C'>
<syntaxhighlight lang='C'>
vector centroid = getbbox_center(0);
vector centroid = getbbox_center(0);
Line 48: Line 77:
@P *= size;
@P *= size;
@P += centroid;
@P += centroid;
</syntaxhighlight>
== Stretch ==
[[File:vex_stretch_001.gif | 340px | right]]
Stretch the geometry across it's X axis
Add one component of position to itself to stretch the geometry away from it's center.  You can control the amount of stretching by multiplying the position before adding it to itself.
[[:File:vex_stretch_001.hiplc|vex_stretch_001.hiplc]]
<syntaxhighlight lang='C'>
vector centroid = getbbox_center(0);
@P -= centroid;
@P.x += @P.x*chf('amt');
@P += centroid;
</syntaxhighlight>
== Shape Blending ==
[[File:vex_position_blend.gif | 340px | right]]
Blend between point attributes to produce a morph effect
[[:File:vex_position_blend.hiplc|vex_position_blend.hiplc]]
<syntaxhighlight lang='C'>
@P = lerp(@P, @opinput1_P, chf('blend'));
@N = lerp(@N, @opinput1_N, chf('blend'));
</syntaxhighlight>
</syntaxhighlight>


== Snap to Grid ==
== Snap to Grid ==
Snap point positions to a grid
 
[[File:vex_snap_to_grid.gif | 340px | right]]
Snap ([https://en.wikipedia.org/wiki/Quantization_(signal_processing) quantize]) point positions to a grid for a downres effect
 
 
 
 
 
 
 
 
 
 
[[:File:vex_snap_to_grid.hiplc|File:vex_snap_to_grid.hiplc]]
<syntaxhighlight lang='C'>
<syntaxhighlight lang='C'>
float grid_scale = chf('grid_scale'); // try 8
float grid_scale = chf('grid_scale');
@P = rint(@P*grid_scale)/grid_scale;
@P = rint(@P*grid_scale)/grid_scale;
</syntaxhighlight>
== Make 2D ==
[[File:vex_setcomp.gif | 340px | right]]
You can use the setcomp function to zero out a component of a vector, resulting in a two dimensional surface.
[[:File:vex_setcomp.hiplc|vex_setcomp.hiplc]]
<syntaxhighlight lang='C'>
// Set the X component to zero, planar 2D in YZ
setcomp(@P, 0, 0);
</syntaxhighlight>
<syntaxhighlight lang='C'>
// Set the Y component to zero, planar 2D in XZ
setcomp(@P, 0, 1);
</syntaxhighlight>
<syntaxhighlight lang='C'>
// Set the Z component to zero, planar 2D in XY
setcomp(@P, 0, 2);
</syntaxhighlight>
</syntaxhighlight>


== Swizzle Coordinate System ==
== Swizzle Coordinate System ==
Switch between Y up and Z up coordinates
[[File:vex_swizzle_vector_components.gif | 340px | right]]
 
Shuffle the components of a vector using [https://www.sidefx.com/docs/houdini/vex/lang.html#dot-operator swizzle]
 
 
 
 
[[:File:vex_swizzle_vector_components.hiplc|vex_swizzle_vector_components.hiplc]]
<syntaxhighlight lang='C'>
@P = @P.zyx;
</syntaxhighlight>
<!--
Switch between Y up and Z up coordinates using [https://www.sidefx.com/docs/houdini/vex/lang.html#dot-operator swizzle]
<syntaxhighlight lang='C'>
<syntaxhighlight lang='C'>
@P = @P.xzy * set(-1,1,1);
@P = @P.xzy * set(-1,1,1);
</syntaxhighlight>
</syntaxhighlight>
-->


== Twist ==
== Twirl ==
[[File:vex_twirl.gif | 340px | right]]
Twirl the geometry around the Y axis
Twirl the geometry around the Y axis
[[:File:vex_twirl.hiplc|vex_twirl.hiplc]]
<syntaxhighlight lang='C'>
float a = chf('angle') * length(@P * {1, 0, 1});
float u = atan2(@P.x, @P.z);
float r = length(@P * {1, 0, 1});
@P = set(sin(u-a), @P.y, cos(u-a)) * set(r,1,r);
</syntaxhighlight>
<!--
<syntaxhighlight lang='C'>
<syntaxhighlight lang='C'>
float angle = chf('angle');
float angle = chf('angle');
Line 85: Line 220:
v@P = origin + r * set(sin(beta), 0, cos(beta)) + set(0,@P.y,0);
v@P = origin + r * set(sin(beta), 0, cos(beta)) + set(0,@P.y,0);
</syntaxhighlight>
</syntaxhighlight>
alt
<syntaxhighlight lang='C'>
float a = chf('angle') * length(@P * {1, 0, 1});
vector pos = @P;
pos.x = (@P.x * cos(a)) - (@P.z * sin(a));
pos.y = @P.y;
pos.z = (@P.x * sin(a)) + (@P.z * cos(a));
@P = pos;
</syntaxhighlight>
<syntaxhighlight lang='C'>
float a = chf('angle') * length(@P * {1, 0, 1});
@P = set( (@P.x * cos(a)) - (@P.z * sin(a)), @P.y, (@P.x * sin(a)) + (@P.z * cos(a)) );
</syntaxhighlight>
<syntaxhighlight lang='C'>
float a = chf('angle') * length(@P * {1, 0, 1});
vector pos = @P;
float u = atan2(pos.x, pos.z);
float r = length(pos * {1, 0, 1});
pos = set(sin(u-a), pos.y, cos(u-a)) * r;
pos.y = @P.y;
@P = pos;
</syntaxhighlight>
<syntaxhighlight lang='C'>
float a = chf('angle') * length(@P * {1, 0, 1});
float u = atan2(@P.x, @P.z);
float r = length(@P * {1, 0, 1});
@P = set(sin(u-a), @P.y, cos(u-a)) * r;
</syntaxhighlight>
-->


== Peak ==
== Peak ==
Push mesh along the surface normals
[[File:vex_push_surface_along_normals.gif | 340px | right]]
Move the surface along it's normals, producing an inflation effect
 
 
 
 
 
 
 
 
 
 
 
 
[[:File:vex_push_surface_along_normals.hip|vex_push_surface_along_normals.hip]]
 
<syntaxhighlight lang='C'>
<syntaxhighlight lang='C'>
@P += normalize(@P) * chf('scale');
@P += normalize(@P) * chf('scale');
Line 93: Line 280:


== Exploded View ==
== Exploded View ==
Jitter each point by a random spherical direction
[[File:vex_exploded_view.gif | 340px | right]]
Moves each packed piece outward from the geometry centroid
 
 
 
 
 
 
 
 
 
 
 
 
[[:File:vex_exploded_view.hiplc|vex_exploded_view.hiplc]]
 
<syntaxhighlight lang='C'>
<syntaxhighlight lang='C'>
@P += normalize(@P) * chf('scale');
@P += (@P - getbbox_center(0)) * chf('scale');
</syntaxhighlight>
</syntaxhighlight>


== Point Jitter ==
[[File:vex_point_jitter.gif | 340px | right]]
Move each point in a random direction with a spherical distribution
[[:File:vex_point_jitter.hip|vex_point_jitter.hip]]


== Point Jitter ==
Jitter each point by a random spherical direction
<syntaxhighlight lang='C'>
<syntaxhighlight lang='C'>
@P += sample_sphere_uniform(rand(@elemnum+chf('seed'))) * chf('scale');
@P += sample_sphere_uniform(rand(@elemnum+chf('seed'))) * chf('scale');
Line 106: Line 321:


== Plexus Effect ==
== Plexus Effect ==
[[File:vex_plexus.gif | 340px | right]]
Connect nearby points
Connect nearby points
[[:File:vex_plexus.hiplc|vex_plexus.hiplc]]
<syntaxhighlight lang='C'>
<syntaxhighlight lang='C'>
foreach(int pt; nearpoints(0, @P, 0.5, 250))    {
foreach(int pt; nearpoints(0, @P, 0.15, 10))    {
     if(pt > @ptnum)
     if(pt > @ptnum)
         addprim(0, 'polyline', @ptnum, pt);
         addprim(0, 'polyline', @ptnum, pt);
Line 146: Line 371:


== Random Color from Normal Direction ==
== Random Color from Normal Direction ==
Generate random colors based on the surface normal
[[File:vex_rand_color_from_normal_direction.gif | 340px | right]]
Generate random colors based on the surface normal, adjust the multiplier to control the amount of colors
 
 
 
 
 
 
 
 
 
 
 
[[:File:vex_rand_color_from_normal_direction.hiplc|vex_rand_color_from_normal_direction.hiplc]]
 
<syntaxhighlight lang='C'>
v@Cd = rand(rint(@N*2));
</syntaxhighlight>
 
== Group Unshared Edges ==
<syntaxhighlight lang='C'>
int isBorderEdge(int pt0, pt1)  {  // test border using half edges
    int hedge = pointhedge(0, pt0, pt1); // try finding hedge
    if (hedge == -1 )  {
        hedge = pointhedge(0, pt1, pt0);  // try reversed hedge
        if (hedge == -1 ) return -1;  // invalid hedge
    }
    return hedge_equivcount(0, hedge) == 1; // 1 if border edge
}
 
int pps[] = primpoints(0,@primnum); // current primitive's points
for(int i = 0; i<len(pps);  i++)  {
    int pt0 = pps[i]; // current pt
    int pt1 = pps[(i-1)%len(pps)]; // next point
    if( isBorderEdge(pt0, pt1) ) { setpointgroup(0, 'border', pps[i], 1); }
}
</syntaxhighlight>
 
 
== Iterative Face Insetting ==
Recursive divide and inset edges, [https://twitter.com/d_gfx/status/1452718124579520512 via @d_gfx], excellent use of [https://www.sidefx.com/docs/houdini/vex/arrays.html arrays]
<syntaxhighlight lang='C'>
int pts[] = primpoints(0,@primnum); vector pos[];
int edge_div_pts[]; vector edge_div_pos[];
foreach( int pt; pts )
    append(pos, vector(point(0,'P',pt)));
for( int i = 0; i < chi('iterations'); i++ )    {
    resize(edge_div_pts,0); // empty
    resize(edge_div_pos,0); // empty
    for( int j = 0; j < len(pts); j++ ) {
        append(edge_div_pos, lerp( pos[j], pos[(j+1)%len(pts)], chf('div_ratio') ));
        append(edge_div_pts, addpoint(0, edge_div_pos[-1])); // [-1] grabs the last item from an array
    }
    for (int k = 0; k < len(pts); k++ ) {
        addprim(0, 'poly', pts[k], edge_div_pts[k], edge_div_pts[(k+2)%len(pts)]);
    }
    pts = edge_div_pts;
    pos = edge_div_pos;
}
addprim(0, 'poly', edge_div_pts);
removeprim(0,@primnum,1); // Remove the input prim and any points belonging to it
</syntaxhighlight>
 
== Iridescent Color Function ==
[[File:vex_iridescent.gif | 340px | right]]
 
 
Produce an iridescent color ramp from any varying value, [https://www.shadertoy.com/view/XlcBR7 from shadertoy]
 
 
 
 
 
 
 
 
 
[[:File:vex_iridescent.hiplc|vex_iridescent.hiplc]]
 
<syntaxhighlight lang='C'>
float amt = dot(@N, set(0,1,0))*0.5+0.5;
v@Cd =  (0.5 + 0.5 * cos( PI*2*( amt + set(0,1,2)/3) ) );
</syntaxhighlight>
 
== Rainbow Colors from HSV Colorspace ==
[[File:vex_hsvtorgb_rainbow_001.gif | 340px | right]]
 
 
You can easily control the hue, while keeping the saturation and value the same using the [https://www.sidefx.com/docs/houdini/vex/functions/hsvtorgb.html hsvtorgb] function.
 
This allows you to easily create rainbows, gradients, perform hue rotations and produce complimentary colors.
 
 
 
 
 
 
 
 
 
[[:File:vex_hsvtorgb_rainbow_001.hiplc|vex_hsvtorgb_rainbow_001.hiplc]]
 
<syntaxhighlight lang='C'>
v@Cd = hsvtorgb( set(relbbox(0,@P).z - @Time/5 + dot(@N,set(0,1,0))/2, 1, 1));
</syntaxhighlight>
 
== Rainbow Cycle with frac function ==
[[File:rainbow_cycle_w_frac_VEX.gif | 340px | right]]
 
 
Using the [https://www.sidefx.com/docs/houdini/vex/functions/frac.html frac] function, you can cycle through a rainbow over a desired amount of elements.
 
This is then offset by adding the current time to the fractional value, which produces the scrolling effect.
 
 
 
 
 
 
[[:File:vex_frac_rainbow_cycle_001.hiplc|vex_frac_rainbow_cycle_001.hiplc]]
 
<syntaxhighlight lang='C'>
v@Cd = hsvtorgb(set(frac(@elemnum/8.0)+@Time/10, 1, 1));
</syntaxhighlight>
 
== Loop Over All Attributes ==
<syntaxhighlight lang='C'>
string pt_attrs[] = detailintrinsic(1,'pointattributes');
foreach( string pt_attr; pt_attrs ) {
    if( pt_attr ~= 'attr_name*' ) {
        setpointgroup(0, pt_attr, @ptnum, 1);
    }
}
</syntaxhighlight>
 
== Remove Faces Across Bounding Box ==
<syntaxhighlight lang='C'>
if( relbbox(0,@P).x < rand(@primnum) )
    removeprim(0,@primnum,1);
</syntaxhighlight>
 
== Torus Knot ==
[[File:vex_torus_knot_001.gif | 340px | right]]
 
[https://prideout.net/knotgl/ Online Knot Viewer]
 
[[:File:vex_torus_knot_001.hiplc|vex_torus_knot_001.hiplc]]
<syntaxhighlight lang='C'>
float u = float(@ptnum)/(@numpt-1);
u += @Time/10.0;
u %= 1.0;
u *= PI * 2;
float r = 2.0;
float q = 2;
float p = 3;
f@u = u;
@P.x += cos(u*q) * (cos(u*p)+r);
@P.y += sin(u*q) * (cos(u*p)+r);
@P.z += sin(u*p);
</syntaxhighlight>
 
== Remap Grid to Circle ==
 
[[File:vex_map_grid_to_circle.gif | 340px | right]]
 
 
Working with polar coordinates to map a square onto a circle.
 
 
 
 
 
[[:File:vex_map_grid_to_circle.hiplc|vex_map_grid_to_circle.hiplc]]
<syntaxhighlight lang='C'>
@P += {0.5, 0.5, 0}; // Remap the grid to zero to one range
float theta = @P.x;
float radius = @P.y/2;
@P = 0;
@P.x = sin(theta*PI*2 ) * radius;
@P.y = cos(theta*PI*2 ) * radius;
</syntaxhighlight>
 
== Remap Grid to Sphere ==
 
[[File:vex_map_grid_to_sphere.gif | 340px | right]]
 
 
Working with polar coordinates to map a square onto a sphere.
 
 
 
 
 
[[:File:vex_map_grid_to_sphere.hiplc|vex_map_grid_to_sphere.hiplc]]
<syntaxhighlight lang='C'>
@P += {0.5, 0.5, 0}; // Remap the grid to zero to one range
float phi = @P.x;
float theta = 1.0-@P.y;
@P.x = sin(theta*PI*1 ) * cos(phi*PI*2 )/2;
@P.z = sin(theta*PI*1 ) * sin(phi*PI*2 )/2;
@P.y = cos(theta*PI*1 )/2;
</syntaxhighlight>
 
== Make a Quad ==
<syntaxhighlight lang='C'>
int prim = addprim(0,'poly');
addvertex(0,prim,addpoint(0,set(0,0,0)) );
addvertex(0,prim,addpoint(0,set(1,0,0)) );
addvertex(0,prim,addpoint(0,set(1,0,1)) );
addvertex(0,prim,addpoint(0,set(0,0,1)) );
</syntaxhighlight>
 
== Make a Grid ==
<syntaxhighlight lang='C'>
for(int i = 0; i<8; i++)    {
    for(int j = 0; j<8; j++)    {
        int prim = addprim(0,'poly');
        addvertex(0,prim,addpoint(0,set(i,0,j)) );
        addvertex(0,prim,addpoint(0,set(i+1,0,j)) );
        addvertex(0,prim,addpoint(0,set(i+1,0,j+1)) );
        addvertex(0,prim,addpoint(0,set(i,0,j+1)) );
    }
}
</syntaxhighlight>
 
== Make a Circle ==
[[File:vex_make_circle.gif | 300px | right]]
 
This example shows how you can generate a circle or N sided polygon using a for loop, sin and cos.
 
Run the code in detail mode with an attribute wrangle.
 
This is essentially the same idea as the [https://www.sidefx.com/docs/houdini/nodes/sop/circle.html circle] node but hopefully a beneficial example to see how this type of geometry is generated via VEX.
 
[[:File:vex_make_circle_001.hiplc|vex_make_circle_001.hiplc]]
 
<syntaxhighlight lang='C'>
<syntaxhighlight lang='C'>
v@Cd = rand(rint(v@N*8));
int prim = addprim(0,'poly');
int seg = chi('segments');
for( int i = 0; i<seg; i++ )  {
    float u = float(i)/seg * 2*PI;
    addvertex(0, prim, addpoint(0, set(sin(u),0,cos(u))) );
}
</syntaxhighlight>
</syntaxhighlight>
== Groups to Attribute ==
[https://zybrand.xyz/groups-to-attribute-with-vex From zybrand]
<syntaxhighlight lang='C'>
//convert numbered groups to a numbered attribute
string groups[] = detailintrinsic(0, "primitivegroups");
int prim = @primnum;
string elemnum;
foreach(string i; groups)
{
    //if the current primitive is in group i
    if(inprimgroup(0,i,prim) == 1)
    {
        elemnum = re_find(r"\d{3,6}",i);
    }
}
s@number = elemnum;
</syntaxhighlight>
== Looping Curl Noise ==
[[File:2022_12_11_looping_curl_noise.gif | 340px | right]]
It's possible to achieve seamless looping animation from curl noise by blending between two noises.
In this example one noise function is evaluated at the current time, and a second noise function is evaluated at the time shifted back by the desired loop duration.
The result of these two noise functions are blended from one to the other over the duration.
[[:File:vex_looping_noises.hiplc|vex_looping_noises.hiplc]]
<syntaxhighlight lang='C'>
// Position x Frequency
vector p = @P*0.5;
// Speed
float s = 0.5;
// Loop Length (in seconds)
float l = 5;
// Time % duration
float t = (@Time%l);
// Blending
vector v0 = curlgxnoise(p + set(0,0,0,t*s));
vector v1 = curlgxnoise(p + set(0,0,0,(t-l)*s));
@P += lerp(v0,v1,frac(@Time/l)) * 0.35;
</syntaxhighlight>
<!--== Make a Grid ==
for(int j = 0; j<4; j++)    {
    int prim = addprim(0,'poly');
    addvertex(0,prim,addpoint(0,set(i,0,j)) );
    addvertex(0,prim,addpoint(0,set(i+1,0,j)) );
    addvertex(0,prim,addpoint(0,set(i+1,0,j+1)) );
    addvertex(0,prim,addpoint(0,set(i,0,j+1)) );
}-->

Latest revision as of 10:05, 3 October 2024

Translate

vex offset position.gif

Offset the position of geometry







vex_offset_position.hiplc

@P += {1, 0, 0};

Taper

taper vex 001.gif


Reduces the circumference by scaling along the XZ plane based on the height of the geometry.



taper_vex_001.hiplc

float taper = relbbox(0,@P).y;
// Remap the taper range
taper = fit01(taper, 1, fit01(sin(@Time*PI/5)*0.5+0.5, 2.5, .5));
// Apply the taper by scaling along the X and Y axis
@P *= set(taper,1,taper);


Boxify

vex boxify 001.gif


Distorts the geometry, morphing it into a box shape

vex_boxify_001.hiplc

vector centroid = getbbox_center(0);
vector size = getbbox_size(0);
size = min(size); // Largest component
@P -= centroid;
@P *= (1.0/size);
@P = lerp(@P, @P+clamp(normalize(@P)*1.75,vector(-1),vector(1)) * (1.0-length(max(abs(@P)))), chf('blend'));
@P *= size;
@P += centroid;


Spherify

vex spherify 001.gif

Distorts the geometry into a sphere shape



vex_spherify_001.hiplc

vector centroid = getbbox_center(0);
vector size = getbbox_size(0);
size = min(size); // Largest component
@P -= centroid;
@P *= (1.0/size);
@P = lerp(@P, normalize(@P), chf('blend'));
@P *= size;
@P += centroid;

Stretch

vex stretch 001.gif

Stretch the geometry across it's X axis

Add one component of position to itself to stretch the geometry away from it's center. You can control the amount of stretching by multiplying the position before adding it to itself.



vex_stretch_001.hiplc

vector centroid = getbbox_center(0);
@P -= centroid;
@P.x += @P.x*chf('amt');
@P += centroid;

Shape Blending

vex position blend.gif

Blend between point attributes to produce a morph effect






vex_position_blend.hiplc

@P = lerp(@P, @opinput1_P, chf('blend'));
@N = lerp(@N, @opinput1_N, chf('blend'));

Snap to Grid

vex snap to grid.gif

Snap (quantize) point positions to a grid for a downres effect






File:vex_snap_to_grid.hiplc

float grid_scale = chf('grid_scale');
@P = rint(@P*grid_scale)/grid_scale;

Make 2D

vex setcomp.gif

You can use the setcomp function to zero out a component of a vector, resulting in a two dimensional surface.


vex_setcomp.hiplc

// Set the X component to zero, planar 2D in YZ
setcomp(@P, 0, 0);
// Set the Y component to zero, planar 2D in XZ
setcomp(@P, 0, 1);
// Set the Z component to zero, planar 2D in XY
setcomp(@P, 0, 2);

Swizzle Coordinate System

vex swizzle vector components.gif

Shuffle the components of a vector using swizzle



vex_swizzle_vector_components.hiplc

@P = @P.zyx;

Twirl

vex twirl.gif

Twirl the geometry around the Y axis





vex_twirl.hiplc

float a = chf('angle') * length(@P * {1, 0, 1});
float u = atan2(@P.x, @P.z);
float r = length(@P * {1, 0, 1});
@P = set(sin(u-a), @P.y, cos(u-a)) * set(r,1,r);



Peak

vex push surface along normals.gif

Move the surface along it's normals, producing an inflation effect







vex_push_surface_along_normals.hip

@P += normalize(@P) * chf('scale');

Exploded View

vex exploded view.gif

Moves each packed piece outward from the geometry centroid







vex_exploded_view.hiplc

@P += (@P - getbbox_center(0)) * chf('scale');

Point Jitter

vex point jitter.gif

Move each point in a random direction with a spherical distribution






vex_point_jitter.hip

@P += sample_sphere_uniform(rand(@elemnum+chf('seed'))) * chf('scale');

Plexus Effect

vex plexus.gif

Connect nearby points





vex_plexus.hiplc

foreach(int pt; nearpoints(0, @P, 0.15, 10))    {
    if(pt > @ptnum)
        addprim(0, 'polyline', @ptnum, pt);
}

Connect to Nearest Point

Draw a line to the closest point of the second input

addprim(0, 'polyline', @ptnum, addpoint(0, vector(point(1,'P',nearpoint(1,@P)))) );

Connect to Closest Surface Position

Draw a line to the closest surface position

addprim(0, 'polyline', @ptnum, addpoint(0, minpos(1,@P) );

Randomize the Rotation of Packed Primitives

Update the transform intrinsic to a random orientation

vector r = sample_direction_uniform(rand(@primnum));
matrix3 x = primintrinsic(0,'transform',i@primnum);
rotate(x, PI*pow(rand(@primnum-666),0.5), r);
setprimintrinsic(0,'transform',i@primnum,x);

Randomize the Scale of Packed Primitives

Update the transform intrinsic to a apply a random scale

vector s = rand(i@primnum);
s = s.yyy;  // Uniform Scale
matrix3 x = primintrinsic(0,'transform',i@primnum);
scale(x, s);
setprimintrinsic(0,'transform',i@primnum,x);

Random Color from Normal Direction

vex rand color from normal direction.gif

Generate random colors based on the surface normal, adjust the multiplier to control the amount of colors






vex_rand_color_from_normal_direction.hiplc

v@Cd = rand(rint(@N*2));

Group Unshared Edges

int isBorderEdge(int pt0, pt1)  {   // test border using half edges
    int hedge = pointhedge(0, pt0, pt1); // try finding hedge
    if (hedge == -1 )   {
        hedge = pointhedge(0, pt1, pt0);  // try reversed hedge
        if (hedge == -1 ) return -1;  // invalid hedge
    }
    return hedge_equivcount(0, hedge) == 1; // 1 if border edge
}

int pps[] = primpoints(0,@primnum); // current primitive's points
for(int i = 0; i<len(pps);  i++)   {
    int pt0 = pps[i]; // current pt
    int pt1 = pps[(i-1)%len(pps)]; // next point
    if( isBorderEdge(pt0, pt1) ) { setpointgroup(0, 'border', pps[i], 1); }
}


Iterative Face Insetting

Recursive divide and inset edges, via @d_gfx, excellent use of arrays

int pts[] = primpoints(0,@primnum); vector pos[];
int edge_div_pts[]; vector edge_div_pos[];
foreach( int pt; pts ) 
    append(pos, vector(point(0,'P',pt)));
for( int i = 0; i < chi('iterations'); i++ )    {
    resize(edge_div_pts,0); // empty
    resize(edge_div_pos,0); // empty
    for( int j = 0; j < len(pts); j++ ) {
        append(edge_div_pos, lerp( pos[j], pos[(j+1)%len(pts)], chf('div_ratio') ));
        append(edge_div_pts, addpoint(0, edge_div_pos[-1])); // [-1] grabs the last item from an array
    }
    for (int k = 0; k < len(pts); k++ ) {
        addprim(0, 'poly', pts[k], edge_div_pts[k], edge_div_pts[(k+2)%len(pts)]);
    }
    pts = edge_div_pts;
    pos = edge_div_pos;
}
addprim(0, 'poly', edge_div_pts);
removeprim(0,@primnum,1); // Remove the input prim and any points belonging to it

Iridescent Color Function

vex iridescent.gif


Produce an iridescent color ramp from any varying value, from shadertoy





vex_iridescent.hiplc

float amt = dot(@N, set(0,1,0))*0.5+0.5;
v@Cd =  (0.5 + 0.5 * cos( PI*2*( amt + set(0,1,2)/3) ) );

Rainbow Colors from HSV Colorspace

vex hsvtorgb rainbow 001.gif


You can easily control the hue, while keeping the saturation and value the same using the hsvtorgb function.

This allows you to easily create rainbows, gradients, perform hue rotations and produce complimentary colors.





vex_hsvtorgb_rainbow_001.hiplc

v@Cd = hsvtorgb( set(relbbox(0,@P).z - @Time/5 + dot(@N,set(0,1,0))/2, 1, 1));

Rainbow Cycle with frac function

rainbow cycle w frac VEX.gif


Using the frac function, you can cycle through a rainbow over a desired amount of elements.

This is then offset by adding the current time to the fractional value, which produces the scrolling effect.




vex_frac_rainbow_cycle_001.hiplc

v@Cd = hsvtorgb(set(frac(@elemnum/8.0)+@Time/10, 1, 1));

Loop Over All Attributes

string pt_attrs[] = detailintrinsic(1,'pointattributes');
foreach( string pt_attr; pt_attrs ) {
    if( pt_attr ~= 'attr_name*' ) {
        setpointgroup(0, pt_attr, @ptnum, 1);
    }
}

Remove Faces Across Bounding Box

if( relbbox(0,@P).x < rand(@primnum) )
    removeprim(0,@primnum,1);

Torus Knot

vex torus knot 001.gif

Online Knot Viewer

vex_torus_knot_001.hiplc

float u = float(@ptnum)/(@numpt-1);
u += @Time/10.0;
u %= 1.0;
u *= PI * 2;
float r = 2.0;
float q = 2;
float p = 3;
f@u = u;
@P.x += cos(u*q) * (cos(u*p)+r);
@P.y += sin(u*q) * (cos(u*p)+r);
@P.z += sin(u*p);

Remap Grid to Circle

vex map grid to circle.gif


Working with polar coordinates to map a square onto a circle.



vex_map_grid_to_circle.hiplc

@P += {0.5, 0.5, 0}; // Remap the grid to zero to one range
float theta = @P.x;
float radius = @P.y/2;
@P = 0;
@P.x = sin(theta*PI*2 ) * radius;
@P.y = cos(theta*PI*2 ) * radius;

Remap Grid to Sphere

vex map grid to sphere.gif


Working with polar coordinates to map a square onto a sphere.



vex_map_grid_to_sphere.hiplc

@P += {0.5, 0.5, 0}; // Remap the grid to zero to one range
float phi = @P.x;
float theta = 1.0-@P.y;
@P.x = sin(theta*PI*1 ) * cos(phi*PI*2 )/2;
@P.z = sin(theta*PI*1 ) * sin(phi*PI*2 )/2;
@P.y = cos(theta*PI*1 )/2;

Make a Quad

int prim = addprim(0,'poly');
addvertex(0,prim,addpoint(0,set(0,0,0)) );
addvertex(0,prim,addpoint(0,set(1,0,0)) );
addvertex(0,prim,addpoint(0,set(1,0,1)) );
addvertex(0,prim,addpoint(0,set(0,0,1)) );

Make a Grid

for(int i = 0; i<8; i++)    {
    for(int j = 0; j<8; j++)    {
        int prim = addprim(0,'poly');
        addvertex(0,prim,addpoint(0,set(i,0,j)) );
        addvertex(0,prim,addpoint(0,set(i+1,0,j)) );
        addvertex(0,prim,addpoint(0,set(i+1,0,j+1)) );
        addvertex(0,prim,addpoint(0,set(i,0,j+1)) );
    }
}

Make a Circle

vex make circle.gif

This example shows how you can generate a circle or N sided polygon using a for loop, sin and cos.

Run the code in detail mode with an attribute wrangle.

This is essentially the same idea as the circle node but hopefully a beneficial example to see how this type of geometry is generated via VEX.

vex_make_circle_001.hiplc

int prim = addprim(0,'poly');
int seg = chi('segments');
for( int i = 0; i<seg; i++ )  {
    float u = float(i)/seg * 2*PI;
    addvertex(0, prim, addpoint(0, set(sin(u),0,cos(u))) );
}

Groups to Attribute

From zybrand

//convert numbered groups to a numbered attribute
string groups[] = detailintrinsic(0, "primitivegroups");
int prim = @primnum;
string elemnum;

foreach(string i; groups)
{
    //if the current primitive is in group i
    if(inprimgroup(0,i,prim) == 1)
    {
        elemnum = re_find(r"\d{3,6}",i);
    }
}
s@number = elemnum;


Looping Curl Noise

2022 12 11 looping curl noise.gif


It's possible to achieve seamless looping animation from curl noise by blending between two noises.

In this example one noise function is evaluated at the current time, and a second noise function is evaluated at the time shifted back by the desired loop duration.

The result of these two noise functions are blended from one to the other over the duration.




vex_looping_noises.hiplc

// Position x Frequency
vector p = @P*0.5;
// Speed
float s = 0.5;
// Loop Length (in seconds)
float l = 5;
// Time % duration
float t = (@Time%l);
// Blending
vector v0 = curlgxnoise(p + set(0,0,0,t*s));
vector v1 = curlgxnoise(p + set(0,0,0,(t-l)*s));
@P += lerp(v0,v1,frac(@Time/l)) * 0.35;