Jump to content

Move points through the "center" of a SDF

konstantin magnus

Recommended Posts

SDF is a scalar field. You could add a Volume Analysis SOP (Gradient), which will give you the "normal" direction of your SDF, and then use this normal vector to push the particles to the center of your sdf (POP Advect by Volumes)

You could also generate Collision from your sdf, to keep your particles inside the tunnels.

But I think, that those forces will be too tricky to keep the particles in the center of those "tunnels" and art-direct their speed. I would rather fake it in SOPs ... generate centerlines, smooth, multiplicate them, give them some position noise, Slide points along edges (as Matt does it here)


The "generation of centerlines" issue remind me of this link:


Unfortunately I am not skilled enough to reproduce that "centerline" setup and source is not included there.

Edited by ikoon
Link to comment
Share on other sites

If those tunnels are not animated, you could separate it into more steps:

- somehow manage to keep the particles inside the tunnels, and make them reach their goal, even if their speed and behavior is not exactly what you like
- generate their trails (Timeshift to the end and loong Trail)
- finetune these trails in SOPs (Smooth, Resample, Point jitter ... and VDB Advect Points can also help to push them into the center of tunnels)
- finally Slide points along edges, so you can art direct the speed


l am curious about other approaches, this is interesting topic.

Link to comment
Share on other sites

Hi, I just throw some ideas, maybe it is redudant with what Mangi posted (can't open the file being at work) :

- initial setting of particles : I would create a thin box that intersect with your SDF pipes (vdb combine), then scatter a lot of points within this intersection (thousands, let's say), and then use the Cluster points, with output set on Average Points, and the number of clusters set on the number of SDF pipes you have. That should do the trick.

- advect the particles along the SDF pipes : you can indeed try to use a POP Curve. Maybe you can also build a VDB with a velocity based on the SDF : the gradient of the SDF should give you a vector field that goes toward the surface, and from there you can build a new vector field perpendicular to this one, that will follow the "flow". From there you advect the particles using this vector field (VDB Advect POints, inside a SOP Solver).

Edited by StepbyStepVFX
  • Like 1
Link to comment
Share on other sites

Just to complete a bit, once you have the gradient of the SDF (using a first VDB analysis set on gradient), calculate the curl of the gradient : this should give you the vector field that goes along with the flow. That being said, this vector may be infinite at the center of the VDB... so maybe normalize the curl vector field using a new VDB analysis.

My maths on curl calculation in cylindrical coordinates are a bit rusty, but with vectors that are Vtheta = constant, Vrad = constant and Vz=0; the curl should be oriented only in z with Curl.z = constant/radius... whcih goes toward infinity when radius goes to 0.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites


2 hours ago, ikoon said:

The "generation of centerlines" issue remind me of this link:

Yes, this is exactly what I am after. I dont necessarily need to move points along gradients, creating those center lines right away would be even better.


Edited by konstantin magnus
Link to comment
Share on other sites

Alright, I created a simple volume crawler.



After cutting a slice its basically a solver taking volumesample()s based on directions from sample_direction_cone(), always moving points towards the lowest density.

int samples = chi('samples');
float ln = chf('ray_length');
float angle = chf('ray_angle');

vector pos_next = vector(0.0);
float dens = 1.0;
for(int i = 0; i < samples; i++){
    float v = i / float(samples);
    vector2 u = rand(v);
    vector dir = sample_direction_cone(v@N, angle, u);
    vector pos = v@P + (dir * ln);
    float dens_curr = volumesample(1, 0, pos);
    if(dens_curr < dens){
        pos_next = pos;
        dens = dens_curr;

v@N = normalize(pos_next - v@P); 
v@P = pos_next;


Has anyone implemented a more mathematical, more robust or more straight-forward solution to this problem in Houdini?




Edited by konstantin magnus
  • Like 4
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...