BONUS: Houdini Array and Foreach Explanation

Continuing from the Armor Plate Offset Breakdown post, I’m going to elaborate on some programming and VEX epiphanies I had while struggling to implement that effect. Just for the sake of demonstration for this bonus article I’ll be using the same screenshot here:

I still don’t perfectly know how to wrap my head around foreach and arrays, but the more I explain it the better I get it, so here goes:

Here’s a basic rundown of what the goal we are trying to accomplish:

  1. We have a bunch of cubes floating around, separated from each other. We want to run code on all the points inside a particular cube, without affecting any other cubes.
  2. We can create an @id point attribute per cube, so cube 0 will have an @id of 0 for example. And all the points inside that cube will have an @id attribute of 0.
  3. We want to take all of the points inside a certain @id and average all their point positions to be the same, essentially collapsing them on top of each other. Then we use that as the UV for the cubes.

We are addressing 1 and 2 by creating the @id point attribute. By connecting all our cube geometry to a connectivity SOP node, and setting the attribute name to id.

Now to do 3, we’ll need a foreach loop in order to cycle an operation across collections of point attribute data, one at a time. So unlike normally in VEX, where code runs on all points one at a time, you can run on specific sets of points all at once. It takes a few moments to wrap your head around this if you aren’t familiar with programming logic, or as I like to call it, being “math brained”.

It gets easier to understand if we keep going. For our foreach function to work, we need two variables/attributes. We need an empty integer variable that the foreach will use to count each “cycle”. You can think of this like when you are counting the number of items in an inventory, you need to write down what you’ve already counted so you don’t forget. So this variable is empty because it’s like a piece of blank paper you are giving the code to write down it’s counting. On the image above, that’s the “int ct;” line. “ct” stands for count.

And the second thing we need is an array that is filled with all of the data we want our “count” variable to, well, count. I called this “counts[]”. The brackets [ ] mean that this variable is an array. Arrays are confusing in Houdini, because they store multiple sets of data inside them. Kind of like how vectors store three different components, arrays can store as many components as you set them to have. This looks very different from typical attribute data however, and this can trip you up if you are inexperienced like me. I'll use the @id data to show the difference between that and an array.

So if we think of one of our floating cubes with @id point attribute, we can identify each point inside “cube 0”; in this case those points are 0,1,4,5,52,53,54, and 55. So each of those have an @id of 0, because they are inside “cube 0”. But what we need is to run code ON these points all at the same time, so we have to create a new variable/attribute that is an array holding all these points. In the picture above, you can see that each point in “cube 0” has an array that is a list of all the other points also inside “cube 0”. You can also notice that the array has a specific order that matches the order of the points, this is an important quality of arrays, they store data in an order that doesn’t necessarily have to be from small to large.

But, how do we get these points inside an array? You need to use this function called findattribval. It does what you think, it finds the value of an attribute, but then it outputs the point number that belongs to that value. But it has two important uses, from the documentation:

So if you use findattribval inside of an array variable, you can get ALL of the point numbers for a certain value. This is perfect for us, because now we can ask findattribval:

Return all the point numbers inside our geometry, with a point class, with @id attribute, based on the @id number.

So now we will have an array that contains every point number belonging to a certain @id value, but assigned to each point number with that @id number.

AND NOW that we have both a counter variable, and an array for it to count, we can plug in to our foreach loop. On cycle 0, the counter variable will run our code on each point number inside the array at once, instead of one at a time.

For additional help on arrays, here’s a fantastic video from David Kahl who has a lot of other great resources for VEX tricks that are pretty hard to find online: