Need help with this quick vex

   3012   13   2
User Avatar
Member
310 posts
Joined: July 2012
Offline
I'm trying to figure out the vex for something that would follow these rules procedurally;

“I want to keep group “collided” when there are 0-299 points in the group. When there are 300 points in the group, I want to delete points 0-299. When there are 600 points in the group, I want to delete 300-599. When there are 900 points in the group, I want to delete 600-899, and so on.”

Been stuck on this for a few days
User Avatar
Member
806 posts
Joined: Oct. 2016
Offline
Moin, nameless colleague,

question: Do you re-index the points or do you want to delete “arbitrary” points?
I am not really following the logic you are describing:

- if you have 299 points, all is fine
- if you have 300 points, you delete 300, so you end up with 0, fine.
- if you have 600 points, you first delete 300 (because you have 300 points as well), giving you 300 in the result, so nothing happens, because you already deleted 300 and now you don't have 600?
- same at 900?

… OR: Do you want to check EXACTLY for 300, 600, 900? That would make slightly more sense on the logic side.

Do you, in the end, want to have 0 points (which somehow seems to be what you are describing) or do you want to have 300 points less after the operation, if you have more than 299 points, no matter what?

Marc
---
Out of here. Being called a dick after having supported Houdini users for years is over my paygrade.
I will work for money, but NOT for "you have to provide people with free products" Indie-artists.
Good bye.
https://www.marc-albrecht.de [www.marc-albrecht.de]
User Avatar
Member
402 posts
Joined: June 2014
Offline
Hello hello,

is this the kind of thing?

if(@ptnum < (@numpt / 300) * 300)
    removepoint(0, @ptnum);
Henry Dean
User Avatar
Member
806 posts
Joined: Oct. 2016
Offline
That's one way to interpret the logic, but I am really unsure if this is what she/he meant, as it would everything “up to” a 300-modulo.
---
Out of here. Being called a dick after having supported Houdini users for years is over my paygrade.
I will work for money, but NOT for "you have to provide people with free products" Indie-artists.
Good bye.
https://www.marc-albrecht.de [www.marc-albrecht.de]
User Avatar
Member
310 posts
Joined: July 2012
Offline
Thanks for the responses guys! I think I explained what I am looking to do a little bit incorrectly, so i'll try again, and upload a Hip file this time to help. Basically I have 300 points emitted from a circle intermittently, that move outwards until they collide with the ceiling and walls of a room. Once I have all 300 points hit the wall, I want to delete those collided points, and not all collided points, since some of the new collided points are from the next “Wave” of points. I hope that makes sense. Any and all help is very much appreciated!

Attachments:
Flow AnimationV3_Test.hip (679.7 KB)

User Avatar
Member
806 posts
Joined: Oct. 2016
Offline
Hi,

if I read your graph correctly, you are creating a “collided” group already, so you can check if a point/particle is member of that group. You would then either have to iterate over all points up to a “current max point ID” to see if all have been eliminated so you could advance “current max point ID” to the next group of 300 (which is way too CPU costly) or count down a counter that tells the code how many points/particles within the current 300 group have been killed.

Storing values in a solver based setup is what I am doing in my convoluted “Create an automated animation rig” tutorial, but I feel like you know how to do that already.

So, *if* I understand you correctly, what I would do is:

- set a variable containing the current “ID group” (which would be 300 in the beginning, then 600 after one group-step is reached … and so on)
- set a variable to 300 that gets decreased everytime a point/particle gets set to group “collided”
- once this second variable reaches 0, increase “ID group” (from 300 to 600 to 900) and reset the counter to 300

I hope this makes sense.

Marc
---
Out of here. Being called a dick after having supported Houdini users for years is over my paygrade.
I will work for money, but NOT for "you have to provide people with free products" Indie-artists.
Good bye.
https://www.marc-albrecht.de [www.marc-albrecht.de]
User Avatar
Member
310 posts
Joined: July 2012
Offline
That made sense.. it just might be pretty hard for me to pull off. I've only done something like that once, and it was pretty difficult then, but I'll try and pull up that project file and work off of it. I assumed the answer would be something like that, but I hoped there was something easier. Thanks for the help!
User Avatar
Member
806 posts
Joined: Oct. 2016
Offline
I'll try to come up with a simplified graph tomorrow (hopefully)!

Marc
---
Out of here. Being called a dick after having supported Houdini users for years is over my paygrade.
I will work for money, but NOT for "you have to provide people with free products" Indie-artists.
Good bye.
https://www.marc-albrecht.de [www.marc-albrecht.de]
User Avatar
Member
310 posts
Joined: July 2012
Offline
Too kind of you, but much appreciated!
User Avatar
Member
806 posts
Joined: Oct. 2016
Offline
Hi,

ok, this is by far not as elegant as I planned to, but I haven't dealt with solvers in POPs yet, so I beg your forgiveness for the somewhat dirty solution.

The following VEX code can be hooked up to the source_geo node emitting the points (after DOP I/O import), no additional attributes needed, as it only deals with attributes provided by the simulation already:

int hit=0; // counter for found hits
for(int pointnum=0;pointnum<i@numpt;pointnum+=300) // pointnum is "each point in current frame", checked in chunks of 300
    {
    if(pointnum+300>i@numpt)  // safety check: If we are trying to address more points than available, bail out
        break;
    hit=0;
    for(int i=0;i<300;i++) // 300 points per chunk
        {
        if(point(0,"hittotal",pointnum+i)>0) hit++; // if point no. i within chunk checked has at least 1 hit, increase number of points with hits
        } // loop through points in chunk
    if(hit>=300) // do we have 300 hits within this chunk (300 points)?
        {
        for(int i=0;i<pointnum+300;i++) removepoint(0,i); // remove all points within this current chunk
        } // 300 hits found
        else break; // we do not yet have 300 hits within this pulse group, no need to waste CPU cycles
    }

Attached is a very simple example, emitting 300 points every 2 seconds (with 24fps at least), including the wrangle.

I hope this is of some help!

Marc

P.S. I am running over detail, so the code only gets executed once per frame to limit the CPU cost. Like I said: Not elegant … but there are people out there who like dirty
Edited by malbrecht - April 5, 2017 15:17:27

Attachments:
pulsecount.hip (402.9 KB)

---
Out of here. Being called a dick after having supported Houdini users for years is over my paygrade.
I will work for money, but NOT for "you have to provide people with free products" Indie-artists.
Good bye.
https://www.marc-albrecht.de [www.marc-albrecht.de]
User Avatar
Member
310 posts
Joined: July 2012
Offline
You are the man! Thanks! I will dissect your code, and hopefully learn a lot. Many thanks.
User Avatar
Staff
6270 posts
Joined: July 2005
Online
This line:

    else break; // we do not yet have 300 hits within this pulse group, no need to waste CPU cycles

unfortunately doesn't work if you have many pulse groups active. It is possible for an earlier pulse group to be still live; but a later pulses group to have hit 300 points.

This is actually an interesting case where By Numbers can be useful. You can set the number count to:
ceil(npoints(0)/300)
Then you can have your wrangle only run over 300 points, not the full range:

int hit=0; // counter for found hits
int pointnum = @elemnum*300;
if(pointnum+300>i@numpt)  // safety check: If we are trying to address more points than available, bail out
    return;
    
hit=0;
for(int i=0;i<300;i++) // 300 points per chunk
{
    if(point(0,"hittotal",pointnum+i)>0) hit++; // if point no. i within chunk checked has at least 1 hit, increase number of points with hits
} // loop through points in chunk
if(hit>=300) // do we have 300 hits within this chunk (300 points)?
{
    for(int i=0;i<pointnum+300;i++) removepoint(0,i); // remove all points within this current chunk
} // 300 hits found

This cuts a lot of interpreter overhead as it can run in SIMD as soon as you have more than one pulse group. I had to push up to 3 million particles before things got slow enough to care, but I saw it improve from 0.9sec to 0.1sec.

Attachments:
pulsecount_bynumber.hip (410.1 KB)

User Avatar
Member
806 posts
Joined: Oct. 2016
Offline
Thanks, Jeff!

Hmm … I have to rethink that “break” thing, I guess. I feel like it should be correct, if the task is to “stick” to the lowest “chunk” until it gets cleared out completely (which was my understanding). You are correct, of course, if “any chunk” is allowed to get cleared out, once all of its points have hits! But if the logic is to exclusively go “lowest chunk first”, then the break should be correct … or should it be?

I also had the idea of limiting the “removepoint” part to just the chunk we are currently dealing with, because (as defined by the outline), chunks are supposed to get deleted “bottom up”, so NOTHING in a lower chunk should be still there, once we start deleting from a higher one (which should reduce CPU cycles as well).

I loved this one, because it got me thinking - give me more like that :-)

Marc
---
Out of here. Being called a dick after having supported Houdini users for years is over my paygrade.
I will work for money, but NOT for "you have to provide people with free products" Indie-artists.
Good bye.
https://www.marc-albrecht.de [www.marc-albrecht.de]
User Avatar
Staff
6270 posts
Joined: July 2005
Online
malbrecht
But if the logic is to exclusively go “lowest chunk first”, then the break should be correct …

That is correct, I think I didn't understand the requirements properly. In this case you can't use the run over numbers as you need to early exit. But the good news is the early exit is fast, so it still scales nicely.
  • Quick Links