I just wanted to post a little bit about the Creep POP in Houdini because I’ve had such a hell of a time getting it to do anything useful.

I was trying to create the effect of raindrops sliding down glass. In Maya, this is a pretty simple thing- enable Needs Parent UV on the emitter, create Goal UV attributes on the particles, and set goalU=parentU and goalV=parentV on the creation expression. The particles stick to the object, and then you can work from there.

Houdini, as it usually does, makes things a little more complicated. The Creep POP looks for two important attributes: POSPRIM and POSUV. It wants to know what primitive to stick to, and what UV coordinates on that primitive to stick to. Of course, when emitting a particle randomly on a surface, you rarely have any idea what those numbers are, so we’ll have to use some expressions to create them manually.

Here goes. On the Source POP you’re emitting from, set up a birth group (leave Preserve Group off) and call it something like “justBorn.” We’ll create the attributes only on the brand new particles so they know what their starting position should be for the Creep. Next we’ll create two Attribute POPs. The first one we’ll use to create POSPRIM, so we know what primitive on the source geometry the particle was emitted from. On the first Attribute POP, set the Source Group to “justBorn”, the type to Integer, and the name to “posprim.” The expression for the value looks like this:

xyzdist($TX,$TY,$TZ,"../path_to_emitter",-1,3)

Here’s what this is doing. xyzdist() can return a number of things about an object based on a position in space; in this case, we’re querying based on the position of each new particle, $TX $TY $TZ. We want to get values based on the object we’re emitting from, which is ../path_to_emitter. The -1 means that we just want to return values based on the nearest primitive we can find. If we used any other value, it would return values specifically from one primitive. The 3 means that we just want to return a primitive number, and nothing else.

If you check the Details View now and run your simulation a bit, you should see that each new particle now remembers what primitive it was emitted from via our new POSPRIM attribute.

Now we have to take care of POSUV, which is done in a very similar manner. On your second Attribute POP, again set the Source Group to “justBorn.” This time the type is Float and the size is 2 (since we’re dealing with a UV coordinate) and the name is “posuv.”

Here’s the expressions for this one. The first expression goes into the first Value slot, and the second expression goes to the second Value.

xyzdist($TX,$TY,$TZ,"../path_to_emitter",$POSPRIM,1)

xyzdist($TX,$TY,$TZ,"../path_to_emitter",$POSPRIM,2)

It’s almost exactly the same expression every time… the difference between these expressions and the first one is that now we’re looking for U and V coordinates for a specific primitive based on our location. Since we have POSPRIM to tell us which primitive we should be sampling for every point, we can use the values 1 and 2 at the end of the expression to return U and V coordinates, respectively, based on our position. Now every particle knows what primitive it was emitted from, and the UV coordinates it was emitted from exactly. Check the expression help for xyzdist() to get a better idea of what kinds of things you can return from this expression.

Now you can just drop down a Creep POP and use the default local variables $POSPRIM and $POSUVU/V for the Prim Number and Prim UV. If you want to use forces to drive the particles, set the Behavior to Slide and use whatever force you want to push the particles along the surface. It’s not so bad once you do it a few times; it’s just too bad this behavior doesn’t have a quicker setup.

Categories: Houdini

Related Posts

Houdini

A Long-Winded Guide to Houdini Instancing

On the Houdini Discord server(s) I keep seeing the same kinds of questions over and over again, mostly related to instancing. The most common questions asked seem to be: “How do I randomly rotate/scale my Read more…

Houdini

The joy of xyzdist() and primuv()

I’m going to try to make a nice easy introduction to my two favorite functions in Houdini VEX (besides fit01 and chramp of course): xyzdist and primuv. These functions are at the core of a Read more…

Houdini

Branching circuits experiment

My good friend and motion graphics bromance, Eli Guerron, asked me to help him create a procedural system of branching circuits that would look something like a schematic drawing. I stupidly thought this would be Read more…