VEX-Wrangles
Contents
Move by frame number
float p[] = {8.78, 8.19, 7.31, 7.23};
float o[] = {0, 136, 273, 409, 545};
float frames[] = {100, 200, 300, 400, 500};
foreach(int i; float frame; frames){
if (@Frame >= frame){
@P.x += o[i] / 20;
@P.z += p[i] * 2;
}
else break;
}
Rotate each packed primitive
//----------rotate each packed primitives (for ex: fractured pieces of RBD sim)--------//
// store the current rotation matrix of each packed prims
matrix3 trns = primintrinsic(0,"transform",@primnum);
//Create a matrix and variable to manipulate
matrix3 m = ident();
vector axis = chv("axis");
float angle = radians(ch("angle"));
// rotate the matrix and apply it to the original matrix
rotate(m,angle,axis);
trns *= m;
// modify the prim intrinsic
setattrib(0, "primintrinsic", "transform", @ptnum, @primnum, trns, "set");
Get transforms from alembic:
//connect alembic cache in 2nt input
matrix m = primintrinsic(1,"packedfulltransform",0);
//get full transformation
@P *= m;
//get only the position;
//@P += cracktransform(0, 0, 0, 0, m);
//get only the rotation:
//v@rot = radians(cracktransform(0,0,1,0,m));
//p@orient = eulertoquaternion(@rot,0);
//m = qconvert(p@orient);
//@P *= m;
//another way to get only rotation
//setcomp(m,0,3,0);
//setcomp(m,0,3,1);
//setcomp(m,0,3,2);
//setcomp(m,0,3,3);
//@P *= m;
Attribute Transfer with wrangle:
string attrib = chs("attribute");
int handle = pcopen(1,"P",@P,ch("rad"),chi("maxpts"));
@`chs("attribute")` = pcfilter(handle,chs("attribute"));
Get available point attribs as a list:
s[]@attribs = detailintrinsic(0, "pointattributes");
BBox Related
Normalize Geometry using bounding box
wrangle this on point level
connect geo on 1st input
vector min,size,scale;
min = getbbox_min(0);
size = getbbox_size(0);
scale = 1/max(size);
matrix m = maketransform(0,0,0,0,scale);
@P -= min ;
@P *= m ;
Normalize Geometry using bounding box and move centroid to origin
wrangle this on point level
connect geo on 1st input
vector size,scale,center,relP;
matrix m;
size = getbbox_size(0);
center = getbbox_center(0);
relP = @P - center;
scale = 1/max(size);
m = maketransform(0,0,0,0,scale);
@P = relP * m;
Fit a geometry inside a bounding box
wrangle this in point level
connect geo on 1st input
connect bbox geo in 2nd input
vector srcBBmin , srcBBmax;
vector destBBmin , destBBmax;
srcBBmin = getbbox_min(0);
srcBBmax = getbbox_max(0);
destBBmin = getbbox_min(1);
destBBmax = getbbox_max(1);
v@P = fit(v@P,srcBBmin,srcBBmax,destBBmin,destBBmax);
Delete by bounding box:
Connect a bound sop in 2nd input and adjust its size to delete whatever outside that. run on primitive mode(can me modified easily for points)
vector min, max;
getbbox(1, min, max);
if (@P.x < min.x || @P.x > max.x ||
@P.y < min.y || @P.y > max.y ||
@P.z < min.z || @P.z > max.z){
removeprim(0, @primnum, 1);
}
Matrix and quaternion related
#maketransform - Builds a 3×3 or 4×4 transform matrix.
#cracktransform - returns value of rotation scale or translate from a matrix
#qconvert - Converts quaternion into a matrix
To Convert a Vector to matrix:
such as converting a normal to a matrix and then to quaternion for getting orient
matrix3 m = maketransform(@N,@up);
p@orient = quaternion(m);
To Rotate a vector by a matrix;
just multiply the vector by the matrix, example below
turn on velocity visualization on points
vector up = {0,1,0};
vector dir = {1,0,0};
float ga = 137.5;
matrix3 m = maketransform(dir,up);
float inc = @Frame;
float angle = (ga*inc);
rotate(m,angle,up);
@v = dir;
@v *= m;
Getting proper orientation from a vector for when copying objects over points:
vector dir = @`chs("initial_vector")`; // initial vector it can be N or v or custom vector attrib
float rampDriver = @`chs("rampDirver")`; // this can be something like "curveu" to offset the rotations
vector up = {0,1,0.001};
vector temp = cross(dir,up);
//create natrix from vector
matrix3 m = maketransform(dir,temp);
vector axis = normalize(dir);
float angle = 1;
//set rotation to the matrix
angle *= chramp("twist",rampDriver) * ch("twist_count");
angle += radians(ch("rotation"));
rotate(m,angle,axis);
//convert the rotated matrix into quaternion @orient attrib
p@orient = quaternion(m);
Custom curveu attribute based on vertex
//run this on a curve with pointwrange to get a curveu //attribute
float value;
float nvtx;
float vtxid;
nvtx = primvertexcount(0,@primnum);
vtxid = vertexprimindex(0, @vtxnum);
value = vtxid/(nvtx-1);
@curveu = value;
Simple spiral
create attribute wrangle , connect nothing
run over > detail(only once)
add below code
then create add sop set to polygon > by group
Steps builder
Phylotaxi formation
add detail wrangle , paste this , set angle interval to 137.5(which is golden angle)
Helper for wedging
create a seperate attrib wrangle and set it to detail mode.paste the code.
set values for wedging and then link the detail attrib "value" to the parameter you want to wedge. on the wedge node>channel link the iteration channel of this channel
Linear resample
Color loop
Connect nearest point(s)
Group n number of points randomly
Set pscale based on distance to the closest point:
Infection:
set infection = 1 for start points
add the point into infList
put a solver sop and wrangle inside and infect!
Same function different names
nearpoints & pcfind:
http://www.sidefx.com/docs/houdini/vex/functions/nearpoints.html
http://www.sidefx.com/docs/houdini/vex/functions/pcfind.html
If statement in single line:
(condition != 1) ? iftrue : iffalse;
Find attribute value:
Usefull for finding matching points on other inputs based on certain attr
int matching_pt = findattribval(@OpInput2, “point”, “id”, @id);
Color By point density
int maxPts = chi("maxPts");
i@nearCount = len(nearpoints(0,@P,ch("rad"),maxPts));
v@Cd = chramp("color",float(@nearCount)/float(maxPts));
Point Jitter along surface:
very handy snippet from Konstantin Magnus
int seed = chi('seed');
vector shift = rand(@ptnum + seed);
int prims_nb[] = pointprims(0, @ptnum);
float prims_num = 1 / float( len(prims_nb) );
int prim_choose = int( floor(shift.z / prims_num) );
int prim = prims_nb[prim_choose];
vector pos = primuv(0, "P", prim, shift);
@t = prims_num; @P = pos;
stickPoints to animated mesh
int primID;
vector primUV ,tempP;
// Offset the points inside the geometry
vector pointOffset = @P - (@N * .1);
// use the offset points to shoot a ray along the normal , To query UV info off the mesh ( static mesh )
primID = intersect(1,pointOffset,@N,tempP,primUV.x,primUV.y);
// Use the UV information, to query the pos information off the animated mesh,
@P = primuv(2,"P",primID,primUV);
Collision deformer using Gradient
To move points to the surface of an sdf, add the sdf's gradient multiplied by the absolute value of the sdf value to the point's position
Connect the sdf volume with gradient field in the 2nd input
dont forgot to fill the interior of the sdf
vector grad = volumegradient(1, 0, @P);
@dist = volumesample(1, 0, @P);
if(@dist <= 0){
@P -= normalize(grad) * @dist;
}
Curve equations
// test it in a curve
float npt = (@numpt-1) ;
float pt01 = @ptnum/npt ;
float amp = ch("amp") ;
float curv = ch("curv") ;
//linear range
//@P.y = amp*pt01 ;
//linear with small rand
//@P.y = amp*pt01 + 0.5*rand(@ptnum) ;
//sharp mountain
//@P.y = 2*amp*(0.5 - abs(0.5-pt01)) ;
//smooth mountain
//@P.y = 4*amp*pt01*(1-pt01) ;
//ease in mountain
//@P.y = pow(amp*(0.5-abs(0.5-pt01)), curv) ;
//exponentail decay
//@P.y = amp/pow(2.718, curv*pt01) ;
//ease in
//@P.y = amp*pt01*pt01*pt01 ;
//ease out
//@P.y = amp*(1-pt01)*(pt01-1) + amp ;
//ease in-out
//@P.y = -amp*(0.333*pow(pt01, 3) - 0.5*pow(pt01, 2)) ;
//cubic
//@P.y = amp*pow(pt01-0.5, 3) + 0.125*amp ;
//cubic sine wave
@P.y = amp*pt01*(pt01-0.5)*(1-pt01) ;
Debug your 3d models - visualize tris,and ngons
// run it on primitive wrangle and set colors for each type
int pts[] = primpoints(0,@primnum);
@Cd = 0;
if (len(pts) < 3){
@Cd = chv("lines");
}
if (len(pts) == 3){
@Cd = chv("tris");
}
if (len(pts) == 4){
@Cd = chv("polygons");
}
if (len(pts) == 5){
@Cd = chv("petagons");
}
if (len(pts) > 5){
@Cd = chv("ngons");
}
Find the longest or shortest edge length for each primitive
// run this on primitive mode
int pts[] = primpoints(0,@primnum);
int p1 = pts[0];
int p2 = pts[1];
int p4 = pts[3];
vector pp1 = point(0,"P",p1);
vector pp2 = point(0,"P",p2);
vector pp4 = point(0,"P",p4);
float a = length(pp1 - pp2);
float b = length(pp1 - pp4);
vector2 size = set(a,b);
f@longest = max(size); // longest edge length
f@shortest = min(size); // shortest edge length
Mid point of an edge
vector center = (p0+p1)/2;
Noise in Wrangle
vector scale = set(ch('scaleX'), ch('scaleY'), ch('scaleZ'));
vector noise = vector(onoise(@P * scale, chi('turb'), ch('rough'), ch('atten')));
noise *= ch('mult');
@Cd = noise;
Remove Lonely points
For simulations like wet sand or snow,in some cases we might need to delete the points whichever is not clumped together .
Simple vex function will do the work
nearpoints() will give the list of points around current point and then we get the total number of points around the point using len() function so we get number of points around each points. we can delete the points which having less points around it.
if (len(nearpoints(0,@P,ch("distance"))) < ch("threshold")){
removepoint(0,@ptnum);
}
XYZ dist VOP
Takes two inputs lets say input A and input B Find the distance between the points on A and the closest position on the surface of B,
No matter what the total number of points is. It will also return the parametric uv of the closest primitive and its index.
To add points to prim centers
Run the wrangle in primitive mode
addpoint(0,@P);
removeprim(0,@primnum,1);// delete the prims
Equalent of $FPS in vex
1/@TimeInc
Where @TimeInc is the time between frames or substeps
Get Random Direction
At first every time I need a random vector like a random direction for copying something in points or random direction for velocity I usually build it like this
vector randomDir = set(fit01(rand(@ptnum+ch('seed')+2),-1,1),fit01(rand(@ptnum+ch('seed')+3),-1,1),fit01(rand(@ptnum+ch('seed')+5),-1,1));
This works fine for me , But There is a very simple solution for this which I dont know at that time.
The "rand()" function will automatically gives you 3dimentional value if you store it in a vector.
For example:
float myrandom = rand(@ptnum);
will give you random floats between 0-1 , if you store it in vector then it will return a random vector like the below
vector myrandom = rand(@ptnum);
this will give you random directional vector, But Wait your directional vectors will get values from 0 - 1 in each component
that means for V.x random 0-1 and so on , which will give you only random positive directions, you can take that and fit it between -1 , 1
which will give you full 360 random directional vectors. final code should look something like this
vector myrandom = fit01(rand(@ptnum),-1,1);
below will do the trick in one line
v@N = (rand(@ptnum+ch("seed1"))-{0.5,0.5,0.5})*2;
Normals towards nearest neighbour
int handle = pcopen(0, 'P', @P, ch('radius'), 2);
vector closeP;
while(pciterate(handle)){
pcimport(handle, "P", closeP);
@N = closeP - @P;
}
Get bounding box center
// this will get the bounding box center
vector min, max;
getbbox(min, max);
vector center = (min+max)/2;
Create grid
MUST RUN THE Wrangle SOp in 'Detail' mode
//add points
int pt0 = addpoint(0,{0,0,0});
int pt1 = addpoint(0,{0,1,0});
int pt2 = addpoint(0,{0,1,1});
int pt3 = addpoint(0,{0,0,1});
//add primitives
int prim0 = addprim(0,"poly"); // "polyline" for lines or curves
//add vertices which will connect the points and prims
int vert0 = addvertex(0,prim0,pt0);
int vert1 = addvertex(0,prim0,pt1);
int vert2 = addvertex(0,prim0,pt2);
int vert3 = addvertex(0,prim0,pt3);
For generating primitives lines or polys in vex
first we need to create a primitive using addprim function
then add vertices to describe which point the primitive is connected
Example:
add two points in a scene and drop a detail wrangle
int prim = addprim(0,"polyline");
addvertex(0,prim,0);
addvertex(0,prim,1);
Group By Attribute
string grp_name = sprintf("name_%g", @attribute);
setpointgroup(0, grp_name, @ptnum, 1, "set");
Misc Useful fucntions
Builds a 3×3 or 4×4 transform matrix.
returns value of rotation scale or translate from a matrix
Converts quaternion into a matrix
check if the primitive has this attribute - hasprimattrib(opfullpath("../PATH"),"attribute")
CHECK IF INPUT 0 IS CONNECTED TO NOTHING - !strcmp(opinputpath("..", 0), "") - \
Formats a string like printf but returns the result as a string instead of printing it.
converts integer to string
Dont know why its itoa but i remember this like "Integer to alphabets"
Smooth the given "amout" , and clamp it between given two values.
This function returns 1 if the subject matches the pattern specified, or 0 if the subject doesn’t match.
best vex refrence
Create points in the average point position of bunch of close points
I used this trick to get a curve from the given tube , which is exaclty in the center of the the tube!
What i did is type this in pointwrangle and deleted the original points then used add sop for connecting the points which is created by the point wrangle and then fused them !
i[]@np = nearpoints(0,@P,ch("dist"));
i[]@npp ;
foreach(int n ; @np){
v@nPP += point(0,"P",n);
}
v@nPP /= len(@np);
addpoint(0,@nPP);
Delete by Cam Frustrum
v@ndcP= toNDC(chs("cam"),v@P);
float padding = chf("padding");
float nearclip = chf("nearclip");
if(v@ndcP.x > (1 + padding) || v@ndcP.x < (0 - padding) || v@ndcP.y > (1 + padding) || v@ndcpos12321.y < (0 - padding) || -v@ndcP.z < nearclip){
removepoint(0,@ptnum);
}
Scale RBD Packed Primitives
vector scale = fit01(rand(@ptnum), ch("min"), ch("max"));
matrix3 transform = primintrinsic(0, "transform", @primnum);
matrix scalem = maketransform(0, 0, {0,0,0}, {0,0,0}, scale, @P);
transform *= matrix3(scalem);
setprimintrinsic(0, "transform", @primnum, transform);