VEX Sheet #2

Attribute Wrangle:

To Group Corner Points in a point cluster:

  • int nbs[] = neighbours(0, @ptnum);

  • vector

  • dir0 = normalize(@P - point(0, "P", nbs[0])),

  • dir1 = normalize(@P - point(0, "P", nbs[1]));

  • i@group_corners = acos(dot(dir0, dir1)) < chf("threshold");

Working with bad geometry? Remove duplicate polygons with this:

  • for (int i = @primnum + 1; i < @numprim; i++) { if (abs(length(@P - vector(prim(0, "P", i)))) < 0.001) removeprim(0, @primnum, 1); }

To create a rest position with a time shift at frame 1, and then compare the attributes in a wrangle and set the rest position per chosen frame:

  • if ( @Frame == 1 ) {

  • }

  • v@rest = @P;

  • }

  • if ( v@rest == @P ) {

  • i@foo = 1;

The syntax to format/pack position+time to a curlnoise:

  • float ns = chf("noiseScale"); vector4 vn = set(@P.x*ns , @P.y*ns , @P.z*ns , @ Time); @Cd = curlnoise(vn);

To convert a number (ex: "1234") into a string, and then split that string into 4 different strings of "1", "2", "3" and "4":

- Create empty array
- Get the length of string: https://www.sidefx.com/docs/houdini/vex/functions/strlen.html
- In for loop, push() character to array

  • string str = "test"; string str_array[]; for(int i = 0; i < strlen(str); i++){ push(str_array, str[i]); }; s[]@test = str_array;

Then you can access specific indexes in that array:

  • string str = "12345";

  • // create empty integer array

  • int int_array[];

  • // for each character of that number, convert to int and push to array

  • for(int i = 0; i < strlen(str); i++){

  • push(int_array, atoi(str[i]));

  • };

  • // set array to attribute

  • i[]@test = int_array;

  • // get index from that attribute/array if you like

  • i@val0 = @test[0];

You can create an id attribute for each new point that comes into a sop solver:

  • //you can do it outside before your Sop Solver.

  • i@id = @ptnum;

To Remap repeating Ids in VEX Run this code on Detail level:

  • // Create Empty Array, count Variables and MmxId.

  • int list_array[] = {};

  • int count, Count_A;

  • int maxId = 0;

  • // Store all current ids into the Array.

  • for (count = 0; count < npoints(0); count++) {

  • // finding the id based on the current count(same as @ptnum).

  • // then add it to the Array.

  • int ptId = pointattrib(0, "id", count, 1);

  • append(list_array, ptId); }

  • // Finding the current Max value (id) in the array.

  • maxId = max(list_array);

  • // loop over each point

  • for (count = 0; count < len(list_array); count++) {

  • // for each point, Loop over all points

  • for (Count_A = 0; Count_A < len(list_array); Count_A++) {

  • // Checking to see if the values already exist.

  • if ((list_array[count] == list_array[Count_A]) && (count != Count_A)) {

  • // Increase the maxId and add it to the current loop Point.

  • maxId ++;

  • list_array[Count_A] = maxId;

  • }

  • }

  • }

To set an attribute once when a point exists. For example if you work with SOP solvers and you want to have some attributes update every frame and others be copied off and kept as a reference that doesn't change. You can group them together like this:

 

  • int justBorn = @active == 1 && @opinput1_active == 0 ;

  • setpointgroup(0, "justBorn", @ptnum, justBorn) ;

You can fetch the iteration of a for each loop in vex like this:

  • detail("../foreach_count1", "iteration", 0)

POP Wrangle:

To control the initial velocity of particles are already moving based on velocity on frame 1:

  • @P -= v@v/24

  • //if you don't have substeps or if you have substeps then multiply the number of substeps with 24)

  • //make sure the pop wrangle only runs at the first frame of the sim.