## 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)),

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

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

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.