VEX-Wrangles

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

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

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

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;

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

Steps builder

Phylotaxi formation

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!

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

Round off float to nearest integer

Searched this for a long time and finally its so simple.. use rint(float) instead of int(float) , For Ex : int(0.8) will return 0 and rint(0.8) will return 1

rint means round to nearest integer

see also ceil and floor 

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:

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


#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

# hasprimattrib

    check if the primitive has this attribute - hasprimattrib(opfullpath("../PATH"),"attribute")

# strcmp

    CHECK IF INPUT 0 IS CONNECTED TO NOTHING - !strcmp(opinputpath("..", 0), "") - \

# printf

sprintf

    Formats a string like printf but returns the result as a string instead of printing it.

# itoa

    converts integer to string

    Dont know why its itoa but i remember this like "Integer to alphabets"

# smooth

    Smooth the given "amout" , and clamp it between given two values.

# match

This function returns 1 if the subject matches the pattern specified, or 0 if the subject doesn’t match.

best vex refrence

https://github.com/jtomori/vex_tutorial

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);