Body Attractor Tutorial PDF Print E-mail
Written by Sergey Shlyaev   
Wednesday, 08 February 2012 10:34

Body Attractor

In this tutorial we’ll look into body attractor that shapes water into any form you want.



The idea of body attractor is the same as with point attractor. We compute custom channel that points from water particle to attraction point and use it as acceleration or force field.



The only difference is that we have lots of points and use their positions with body attractor.


For example, let’s shape water into famous Stanford bunny model.

Download EMP file here: bunnyMesh.emp

Download NI file here(basically just point attractor):

For a detailed description of operators please read first part – Point Attractor Tutorial.

Add Emp-Read op to graph and load bunny model.

Add Mesh-Volume op after Emp-Read to convert poly model into volume.

To use model’s vertices as attraction points we need world positions of them. So add Point.position channel into Channels field of Mesh-Volume op.


After we converted model into volume we need to export position field from it.

Add Field-Export op after Mesh-Volume name it “Field-Export-position” and in ‘Field channel’ field write “position”.


Finally plug output of Field-Export into our “particle_nel_compute_field-p_value” Partice-Channel op where we compute custom acceleration.

Now graph looks like this:


We need to take into account this new field when computing custom acceleration.

This is very easy, going from 0-Particle.position[0] for point attractor to :'f'-Particle.position[0] for body attractor.

This is where all magic happens.

Now our expression is like this:


If you run the sim now you’ll see that particles are definetely forming some part of the bunny but this is only part of it.

Download Video: MP4, HTML5 Video Player by VideoJS


To form a whole bunny we need to spread water particles more evenly around the model, so they have different positions on bunny to land.

To do this let’s add initial velocity to our liquid.

Place Field-Constant op in graph, I’ve used <<0,1,0>> as initial velocity and plug it into ‘v’ input of Liquid-Emit-Distance op.


Now the sim looks like this:

Download Video: MP4, HTML5 Video Player by VideoJS


Doesn’t shape very well. We need to increase attraction force.

Add Field-Scale after Field-Particle-Splat and set scaling value.

Something like 15 works well.

Run the sim.

Download Video: MP4, HTML5 Video Player by VideoJS

Now water ideally shapes into our model.

Advantages of this setup:

  • To achieve morphing effects you do not need to do anything with source objects.
  • If using several objects they may be of any topology and completely different from each other. One object may be polymodel and other may be particles etc.
  • Poor topology may also work. Bunny model has holes at the bottom.
  • It’s cool!


  • May require manual tweaking and adjusting parameters.

That is all for our tutorial. Hope you enjoy it!


If using “Accumulate” splatting method instead of “Weighted Average” we may achieve more expressive effects. However in this case we may see some particles are being very fast and some of them may slide-off and water will lose shape of attractor model.

To solve this we may reduce velocities that are higher than some threshold and introduce “Stop-at-attractor” option in our setup so particles that are very close to attraction point are moving significally slower then others or even stop.

Velocity Cutting

Insert Particle-Nel-Channel op into graph after Force op. Name it “cut_high_velocities”.

Set channel to velocity and type to vector.

Say, we want all particles that are travelling faster then 100 meters per second to reduce their speed by half in each timestep.

Put the following into expression field:

(mag(.velocity) < 100) ? .velocity : .velocity*.5

This is the conditional expression. We check some condition and if it’s true we do one thing, if it’s not do another.

First, we are checking how fast are our particles: mag(.velocity) < 100 if they are slower then 100 then leave velocity as is, otherwise multiply it by 0.5.

Which is the same as divide by two, thus making velocity significally slower.

This is for reducing velocities that are too big.


To make liquid particles stop at attractor we will use distance field of our model and a NEL expression.

Add Field-Export op and connect it to Mesh-Volume op that converts our bunny into volume. In ‘Field channel’ field write “distance”.

Insert Particle-Nel-Channel op after cut-high-velocities op. Name it “stop_at_attactor”. Plug exported distance field from bunny to ‘f’ input of Particle-Nel-Channel op.

Set channel to velocity and type to vector.

Let’s take a look at channel expression:

:’f’<0.02 ? (.velocity[0]*.97) : .velocity[0]

This reads:

If value of connected field is less then 0.02 then multiply the X component of velocity of particle by 0.97, otherwise do not change it.

Same stuff for Y and Z components of velocity vector.

So, what does this mean: “value of connected field is less then 0.02”?

Since we are using distance field, it means: “if we are closer than 0.02 meters (2 cm) to surface of our bunny”.

Distance fields encode the distance to the surface. We have connected a distance field through the 'f' input, so its values corresponds to the distance to the closest point on the surface.

  • Values of 0 represent points that lie directly on the surface.
  • Values > 0 are outside the surface (along the surface normal)
  • Values < 0 (negative) are inside the surface.

Please note, distance field is scalar field, not vector as velocity field.

Now our operator will reduce velocities of those particles who are close to the surface of model.

To make velocities decay faster make multiplier lower. For example using 0.1 instead of 0.97 will make them stop almost immediately.

Download NI file here:

Tile-Refine op

A good alternative to initial velocity is Tile-Refine op. It is useful to be sure that attraction field is defined over a whole

attaction body instead of only some region in space where liquid particles currently are.

Insert Tile-Refine op right before particle_nel_compute_field-p_value op so all parts of our model are considered in

computation of custom_acceleraton vector.

Let’s take a look at first frame of our simulation:

On the left picture water body does not have tiles around bunny’s head and ears so they are not considered in attraction

field at start of our simulation.

On the right picture whole bunny including head and ears is attracting water.

If we look at attraction field with Streamline-Scope this is clearly seen:

On the left picture we can see that only part of our model is considered in attraction field.

On the right picture we see that attraction field is defined over a whole attaction body from the very beginning.

This may be important when we have model with relatively thin jut out parts like Utah teapot with nose and handle.

Take a look at teapot video:

Download Video: MP4, HTML5 Video Player by VideoJS

Notice very clean and organic waterflow.


Do your own experiment with your model!

Try to use field as velocity field, not acceleration or force. There will be no physical correctness but you may get interesting results.

Try to switch different attractor bodies in one sim.

Like here:

Last Updated on Sunday, 18 March 2012 13:06