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.
​