Ordered POP Emission

Hello,

So I actually ran into problems with my initial solution. So I will now present a more reliable solution. If you would like to see my initial attempt, it will still be in the post, just further down.

So, the issue at hand is that I need to get a series of points to pop into existence and then pop out. I also need it to be in a specific order.

So to get this going I first ordered the points. This can be done with the Enumerate and Sort sop nodes. This creates an index attribute that is in whatever order is determined by the sort. This can also be swapped out for a preexisting order, like if you are visualizing some data and the data has a timestamp.

Next I needed to remap that index (or whatever other attribute you are using to determine the order of the emission) to fit between 0 and 1. I did this in an Attribute Remap node.

Then I made an integer attribute called i@spent. This would be if you want it to stop emitting after 1 cycle. If you need the emission to keep cycling through the order, then you can omit this step.

Next I used a Solver. This is because just using a wrangle did not save the updates to the spent attribute.

Inside the Solver I used a wrangle that does most of the work for this set up.

float maxFrame = chf("max_frame");
float minFrame = chf("min_frame");

f@fitTime = efit(float(@Frame), minFrame, maxFrame, 0, 1);
f@fitNextTime = efit(float(@Frame+1), minFrame, maxFrame, 0, 1);

if (i@spent == 0 && @order <= (f@fitNextTime % 1) && @order >= (f@fitTime % 1)) {
    i@e = 1;
} else {
    i@e = 0;
}

if (i@e == 1) {
    i@spent = 1;
}

This wrangle uses channel floats to decide the frame range the emission cycle will take. Then it fits that range between 0 and 1 and as the frame count updates, it will mark the points who’s order value lines up with the frame value (after both have been mapped 0-1) with an integer attribute i@e = 1. All other points stay with i@e = 0.

Then there is the if statement that determines if a point is spent, simply by checking if its i@e value is 1. This section can should be removed if you want the emission to be cyclical.

After this the I left the solver and grouped all points with an active i@e attribute in a group called emit. You could definitely rework this to have the group be assigned in the solver wrangle. I just did not do that.

Finally I put this into a popnet. Here the important things are in the POP Source.

In the Source tab make sure that you need to have the Emission Type option be set to All Points, the Geometry Source to wherever the previously set up stream of nodes leads to (in my case I just plugged it into the first context of the popnet), the Source Group to whatever the group made in the Group Expression is called, and that the Group Type is Points.

Also in the Birth tab, make sure you are only using Impulse Activation and that its set to 1. You could also set it to a higher number if you want multiple to get emitted from each point.

And that is it.

Now the points will emit from the POP net in the ordered determined at the beginning. The emission will be evenly spaced throughout the time range chosen in the wrangle inside the solver. Life can also be added with the attribute f@life before the POPnet. This will determine how long the points stay in the scene after spawning.

Also here is the final node chain.


DISCLAIMER: You are now reading the outdated solution to this problem! There is still some interesting stuff here, but I would not using this for your ordered pop emission tasks!

Hello,

So while working on a larger project in Houdini, I ran into a problem where I had a large set of particles representing an event in time, each at a specific location with a specific duration.

I wanted each of those particles to pop into existence, at their location, in the chronological order of the events. I also needed the points to be on screen for as long as their duration.

I decided to work out the problem in a smaller project, as not to get bogged down by the elements and attributes in the original.

There are surely plenty of ways to do this, but the way I framed the problem was that I had a point cloud with an order to each point, and I wanted to cycle through each point in the order and have them be in the scene for the length of their duration and then die.

The duration and death part led me to use a POP Solver. You can pretty easily set the life of a particle before simulating it, by adding a float attribute called life. For my example I used a point wrangle but you can use any attribute creation method.

Just in case you need it, here is how I set the life attribute in a point wrangle.

// This would be if you have a duration attrib you want to use
f@life = f@durationAttribName;

// For this example I just used a constant
f@life = 4;

As a side note, I remember hearing in a tutorial somewhere that the attribute create node is faster than using a wrangle. I did not use one here out of habit, but it could be useful if you are making attributes with constant values or other simple things.

Anyway, now for the main problem. Getting the points to spawn in order.

For my example, I used the point number as the order, but you can use any attribute, as long as it is incremented by values of 1 so that there are no phantom particles the algorithm will wait for (unless that is what you are going for).

What I relied on was the Source Group option in the POP Source. This is used when using the Points Emission Type and limits the points used to emit particles to whichever are in the designated group.

With this, all I needed was a way to have the group cycle through each point in the order I wanted.

To do this I used another point wrangle:

// In my example this channel float is set to 3
float hold = chf("hold_frames")+1;

if (@ptnum == (((@Frame-1)/hold) % @numpt)-1) {
    i@e = 1;
}

The hold variable sets the number of frames between each particle spawn.

The important equation here is the @Frame % @numpt which will cycle through each point repeatedly. The hold variable adds substeps to this cycle, giving frames where the equation will yield a decimal value and will not satisfy the if conditional.

I would recommend using the Enumerate SOP to get an order starting at zero and counting up, this will get it to start at the first point and repeat back to the first point once it counts all the way through.

After this I used a group expression with the following expression:

i@e == 1

Also, a quick reminder to set the group type to Points. I often forget to do this and have a small heart attack trying to figure out why my expression is not working.

I then used that group in the Source Group section of the POP Source.

Everything else on the Pop Source is the same.

Here I have the example and the node tree, you can also download the scene file here

Previous
Previous

3D Wave Interference

Next
Next

About Me