Jump to content
ParticleSkull

VEX - foreach - I don't get it

Recommended Posts

Posted (edited)

Hey guys, 

I never got how does a foreach works in vex (at all!), can someone please explain me this?

It does the same thing as the For-Each Loop node?

Edited by ParticleSkull

Share this post


Link to post
Share on other sites

Hello Alvaro. The foreach() is intended to loop over items of an array. Those items are usually numbers, but you can have array of vectors, matrices etc. Those numbers can be @id of neigbouring primitives, which you stored in some upstream wrangle, or so.

Here is a nice explanation with an example:

http://www.tokeru.com/cgwiki/index.php?title=JoyOfVex13

  • Like 1

Share this post


Link to post
Share on other sites

So I got this from entagma, I think it's simple enough for a starting point. It works just like an attribute transfer:
 

vector pos = point(1, "P" , 0);

int points[] = pcfind(0 , "P" , pos , ch("radius") , 300);

foreach(int point ; points)
{
    setpointattrib(0 , "Cd" , point , {1,0,0});
}

The forach part starts at 6:20

and I transcripted what Moritz says:

Quote

 

what foreach needs is: first a variable which will contain an individual list entry when we loop through our array (int point;)

and it needs the array name, which we should loop through. in our case "points" without those curly brackets.

...

This construct will run a given number of times. it will run exactly as many times as there are elements in points
for each one it will copy an individual element from points into the variable called point so one after another we will go through the whole array and point will
contain each individual entry of the array, a single entry at a time.

 

I feel like it sounds dumb but i think i need to understand the very basic concept of this.
So we have foreach(int point ; points)  - what does the first (int point) and the second element (points) does?

int point is the number of points I have and the foreach will run points for each one of the points?

  • Like 1

Share this post


Link to post
Share on other sites
Posted (edited)

As regards entagma example:

vector pos = point(1, "P" , 0);

int points[] = pcfind(0 , "P" , pos , ch("radius") , 300);
// the above line creates a variable ... an array of integers "points" 
// and saves numbers of closest points in the array
// now points store something like this:
// {25,2684,654,489,9846,64} up to 300 items

foreach(int point ; points)
// the above line creates a temporary variable, single integer "point"
// we already have points

{
    setpointattrib(0 , "Cd" , point , {1,0,0});
    // in step 0, point equals 25
    // in step 1, point equals 2684
    // in step 2, point equals 654
    // etc for each member of points

}

 

Edited by ikoon
  • Thanks 1

Share this post


Link to post
Share on other sites

Jiri, this is perfect, thank you very much!

I might have some other questions later but right now what comes to my mind is: can I see the points attribute, like what im getting from pcfind? I tried to make it like i@points[] = pcfind... but it gives m an error

Share this post


Link to post
Share on other sites
Posted (edited)

There is a specific syntax to create attribute arrays:

i[]@name to create array of integers
f[]@name to create array of floats

I have more examples here, I hope that all are valid :) but you will see the pattern:
http://lex.ikoon.cz/vex-arrays-and-matrices/

 

So if you want to store an attribute and see it in the Geometry spreadsheet, just add this line:

int points[] = pcfind(0 , "P" , pos , ch("radius") , 300);
i[]@points = points; //add this line

 

Btw for me those [] were quite confusing. And still are.
When working with variable array, you write name[] only when you are defining it. Then use just the name.
When working with attribute array, you write i[]@name even when you are reading from it.

Edited by ikoon
  • Thanks 1

Share this post


Link to post
Share on other sites

Thx Jiri, I can see the array attribute now ;)
Nice, your website looks useful! thx for sharing it all

I still cant get some things into my mind but I'm already understanding it way better then before.
So, you said:

foreach(int point ; points)
// the above line creates a temporary variable, single integer "point"
// we already have points

//the above line creates a temporary variable, single integer"point"

what is this variable? what it does in the setpointattrib?

For me it looks like the the point variable is just getting the values of the pcfind as well (is it? it looks weird now that its written)

  • Like 1

Share this post


Link to post
Share on other sites
Posted (edited)

That entagma example could be rewritten into this (if I assume those numbers are those close points)

A.

int points[] = {25,2684,654,489,9846,64};

foreach(int point ; points)
{
    setpointattrib(0 , "Cd" , point , {1,0,0});
}

 

B. And the following code does exactly the same thing as whole A does. So, the foreach() does in fact this:
 

setpointattrib(0 , "Cd" , 25   , {1,0,0});
setpointattrib(0 , "Cd" , 2684 , {1,0,0});
setpointattrib(0 , "Cd" , 654  , {1,0,0});
setpointattrib(0 , "Cd" , 489  , {1,0,0});
setpointattrib(0 , "Cd" , 9846 , {1,0,0});
setpointattrib(0 , "Cd" , 64   , {1,0,0});

My english is poor :) I wanted to say that A = B.

Third argument of the setpointattrib() is the number of the point to set the attribute on: http://www.sidefx.com/docs/houdini/vex/functions/setpointattrib.html

Edited by ikoon
  • Like 1

Share this post


Link to post
Share on other sites

I have tried the method you were talking about, and it works. So here we have C. which does the same as A and B. So you were right:

 

vector pos = point(1, "P" , 0);

foreach(int point ;    pcfind(0 , "P" , pos , ch("radius") , 300)    )
{
    setpointattrib(0 , "Cd" , point , {1,0,0});
}

 

  • Like 1

Share this post


Link to post
Share on other sites

Btw there is also D. which does the same as A B and C:

foreach(int point ;   {25,2684,654,489,9846,64}   )
{
    setpointattrib(0 , "Cd" , point , {1,0,0});
}

It works, but it throws a warning. Houdini reads 25, 2684, 654 etc as floats ... and stores them into "int point" is an integer.

  • Like 1

Share this post


Link to post
Share on other sites

This is awesome, now it makes perfect sense. It couldn't be more clear 
Thank you very much :D

Now I'll try some complex examples to see how it goes

 

thx!

Share this post


Link to post
Share on other sites

You are most welcome. You do great and inspiring work, I am glad I was helpful with my little vex knowledge :) good luck with your amazing work!

Share this post


Link to post
Share on other sites

you can also put in a third argument in the foreach, the index you are running over.
 

//run over primitives, use this on a polyline and you will get the order of the points
int primpts[] = primpoints(0,@primnum);

foreach(int index;int i;primpts){
	setpointattrib(0,"index",i,index,"set");
	}

 

 

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×