Splashes and Tendrils
Splashes and Tendrils
RealFlow Tutorials
by Thomas Schlick
Annotations 6
Paint Tendrils 18
Paint Simulations 18
Object Settings 18
Fluid Settings 19
Simulation Settings 20
Variations 21
Meshing the Paint Tendrils 21
Paint Strings 24
A Fast Approach 24
Daemons 25
Simulation Settings 25
Paint Strings Extended 26
Paint Blobs 29
Fibres, Strings, Blobs 29
Scene Setup 29
Concept and Idea 31
The SimulationPre Script 32
Selecting Particles 32
Paint Ribbons 38
Drawing with Particles 38
Domain and Emitter Settings 39
Daemons 40
Butterfly Splashes 44
Fluid Wings 44
The RealFlow Setup 45
Noise 45
Basic Splash 45
Domain Settings 46
Daemons 46
Discussion 48
Collision Splashes 48
First Impressions 49
Enhancing the Butterfly Effect 51
Last Settings 52
Improvements and Suggestions 53
Rain Splashes 55
Emitter Management 55
Standard Particles or Dyverso? 55
The Idea 55
Batch Script 56
SimulationPre Script "Initialize" 58
FramesPre Script "Rain" 59
FramesPost Script "Clear" 60
The Scene 61
High-Viscosity Strings 65
Viscosity and Substeps 65
Scene Setup 65
Animating the Emitter 66
Initial Tests and Adjustments 67
Substeps and Speed 68
Meshing 69
Spline Splashes 81
And Another Script 81
Scene Setup 81
Point Attractors 82
Finding Positions and Particles 83
Accelerating the Particles 85
Discussion 87
DSpline Splashes 90
Splines in RealFlow 90
The Daemon 90
The Fluid 92
Helper Daemons 93
The Can 94
The work on this edition also gave me new insights and sometimes RealFlow refused to do what
I wanted it to do, but that's how most simulation packages work. Despite all problems it is simply
a fact that the quality of RealFlow's fluids is unparalleled.
Annotations
All tutorials and scripts in this issue have been created with the latest version of RealFlow 2015.
Some of the scripts and simulations can also be used with previous versions, but there is no guar-
antee that they will really work.
RealFlow provides the possibility of defining which axis should be the scene’s vertical axis. For
some 3D programs it is Y, for others it is Z. In this magazine, a Y setup is used by default, and for
Z-based setups you have to swap Y and Z values.
An example:
• Let's say there is a scale value with three elements, e.g. (1.0,5.0,1.0) – a so-called vector.
• This means that the object's length and width are 1 m each, while height is 5 m.
• With a Z-based setup, the vector must be changed to (1.0,1.0,5.0).
This notation is also interesting for scripts, because the magazine's programs are not axes-aware.
You have to convert all XYZ vectors like position, velocity, force, or scale.
There are just three golden rules – please be fair and repsect them:
Thank you!
Several years ago RealFlow simulations appeared with interesting, filament-like structures and
thin sheets of fluid without holes or torn areas. The main technology behind these kinds of simu-
lations is a hole-filling algorithm. In RealFlow, this tool is known as the “Sheeter” daemon.
One of the main problems with small scale fluid solvers is that particles tend to break apart and
the result is a completely torn fluid with lots of drops.
A comparison between RealFlow fluids with and without the "Sheeter" daemon.
When you look at stills from real fluids you will observe coherent and closed areas. This behaviour
is the result of forces between the water molecules. In the world of VFX we have to find other,
much faster solutions, and physically accurate simulations are not really an option. Therefore,
developers always look for alternatives and one of these methods is a hole-filling process. We will
go through this technique a little later.
Another, very important, element with tendril simulations is chaos. The more collisions, differently
accelerated particles, and random effects, the higher the probability for tendrils. There is also a
way to pull out tendrils with the help of scripting, and one approach can be found in the water-
line magazine “Scripting with RealFlow” edition: crown splashes. It is possible to modify this script
and do really fancy things. A basic approach can also be found in this issue (“Paint Fibres”).
Recently, some exciting new technologies emerged, and some of these methods do not even
require hole-filling tricks or other detours. But, here we will stick with the “old-fashioned” tools,
but don't worry, because our results will also have production quality, and they do not require
external plugins. This does not mean that 3rd party plugins are not worth their price, or that
they are a waste of money. No, it is exactly the opposite: I am very happy that these tools exist,
because they give you so many new possibilities and extend RealFlow's feature set with really
cool solvers.
Before we dive into more advanced methods we should try what we can get with RealFlow's
standard daemons and solvers. Board means like “Sheeter”, “Noise Field”, and “Drag Force”
daemons have so much potential, and you will be amazed what is possible with them.
This daemon will be the main element in many of our simulations and therefore it is necessary to
know exactly what it does and how its parameters work. As mentioned before, the daemons pur-
pose is to create thin fluid layers without holes or gaps. To do this, the “Sheeter” provides a wide
variety of parameters, but the most important one is certainly “Min cavity size”:
Cavity Size
“Min cavity size” is a typical example for a parameter that works exactly the opposite way as we
all might think. The value is
• a limit and holes, bigger than the given threshold, will not be filled
• not measured in metres, but it is dimensionless.
The consequence of these two statements is that there still can be holes in your fluid and that the
parameter is not easy to adjust, because “Min cavity size” is an abstract value without any refer-
ence. This circumstance makes it difficult to provide a global rule that is valid for most cases. Your
final value depends on the situation, but there are few things you should know:
Velocity Alignment
When “Use velocity alignment” is enabled RealFlow compares the motion directions of particles.
If the angle between these directions is smaller than “@ alignment threshold”, the “Sheeter”
creates particles to fill the occurring gap.
With thin sheets of fluid, for example in conjunction with a “Linear” emitter, velocity alignment
helps to get better results, because more particles will be taken into account. In simulations where
we want to create strings or tendrils it is normally better to turn off this feature.
Another problematic situation are simulations where particles collide with objects. The daemon
is not aware of these objects and places its particles where ever it is necessary. This often leads to
unwanted accumulations, and here, velocity alignment can be an option, as well.
The most effective method to delete additional particles from the inside of objects is the
"k Object" graph from the waterline magazine "Fields and Graphs" edition.
“Use speed” restricts the hole-filling process to particles with velocities between “@ min relative
speed” and “@ max relative speed”. The results may look more natural, because it is possible to
apply the daemon to slower particles only, while faster particles break apart.
The mode of operation of “Use age” is similar: only particles with an age, smaller than “@ max
age”, will be considered.
Tendrils
RealFlow's “Sheeter” daemon also provides the possibility of pulling out tendrils, but in many cas-
es this feature does not give any results at all. And if it works, the actual number of tendrils rarely
matches the “@ count” parameter. We cannot specify where the fibres will finally occur and the
process is triggered at one fixed point in time only. The daemon reveals exactly the problems with
tendril creation: it is difficult to identify adequate tendril seed particles.
The daemon's internal criteria for tendrils is velocity, and this is exactly the reason, why it fails so
often. In many cases, particles with an appropriate velocity are located inside the main body of
particles, not at the borders. And you need very high forces to release these inner particles. As a
result you sometimes see a short flicker or a small bulge, indicating that something is happening,
but nothing more.
“Create tendrils” works best with thin sheets of fluids, for example with a drop falling onto a
ground object and spreading out:
Conclusion
RealFlow's “Sheeter” is certainly not an all-purpose weapon and has its weak points. Some of
you might also ask why the daemon is not as versatile as other proprietary or commercial tools? In
fact there is hardly any difference. Maybe it is easier with some plugins to achieve a certain effect,
but speaking for myself I could never see these differences and was always happy with RealFlow's
built-in daemon. The “Sheeter” daemon has strong advantages, because it
Scripted Approaches
Hole-filling scripts are nornally really slow, because they make use of three computationally ex-
pensive Python commands:
• getNeighborsis used to find and store neighbours within a certain radius around the currently
observed particle. The bigger the radius, the slower the entire process.
• createVoxelization creates an internal data structure and keeps the fluid stable when new par-
ticles are being added.
• testPositionForParticleInsertion checks, if it is safe to place a new particle at a certain posi-
tion. This function is the slowest part – especially with high particle counts.
So, the main question is, if it does make sense at all to write a custom application with Python?
In my opinion it is definitely not necessary, unless you have certain demands, need a proprietary
solution, or if you want to extend your Python knowledge about the development of efficient
data structures.
Let's Start
Now, that we know the “Sheeter” daemon's parameters and elements it is time for some practical
exercises. The following examples have been created to give you ideas and a collection of basic
scenes. You can extend and adjust the setups to your needs. The examples follow completely dif-
ferent approaches, some of them include scripts, while others have really simple setups. But, they
all have three things in common: splashes and tendrils.
As with every simulation software, testing is an important part of the creation process. I often
hear complaints about the time needed for a fluid or body dynamics shot, but that's how simula-
tions work. Some users also claim that other software packages are more user-friendly, but this is
nothing more than a myth. It is no problem to produce scary results with Houdini, Naiad, Bifröst...
For shots in production quality you have to master the software and its settings, understand how
things work together, and gather experience. This is what all simulation and 3D tools have in
common.
Off-the-shelf solutions with globally valid settings are very rare and every scene is different. Even
small changes influence the particles and may lead to different results.
You might be lucky and get what you want after a few minutes, but in most cases you have to
adjust parameters carefully, simulate, readjust, simulate...
The entire situation is comparable to render engines, where you normally do not get the final
lighting just by adding a single light source.
Anyway, I have to admit that some packages are more “complete”. RealFlow has its flaws and esp.
RealWave and Caronte, the body dynamics solver, are totally outdated. Smoke and fire are also
absent, although they are must-haves in today's VFX world. In my personal opinion, a software
like RealFlow, specialized in fluids, is incomplete without these standard solvers.
Although the following description is not absolutely necessary for our splash toolbox, I want to
show you how to work with multiple emitters and domains anyway. It is simply a very interesting
feature, but requires at least RealFlow 2015 (9.1.1.0186).
Dyverso domains are able to interact, and this way it is possible to simulate fluids with different
densities or viscosities, for example water and oil, or cream and chocolate. You are also free to at-
tach multiple emitters to one domain and create more than one fluid source. A domain's attached
emitters have exactly the same physical properties, but speed, randomness, position, and emitter
type can be different of course. In the example below you see one domain with three emitters:
For a setup with one emitter per domain follow these instructions:
Each domain can be affected by different daemons, interact with individual objects, and be
meshed separately. All you have to do is to delete and redraw the appropriate connections in
RealFlow's “Relationship Editor”.
Paint Simulations
The simulation of paint splashes and paint tendrils is definitely one of my personal favourites.
I love the motion of these slightly viscous fluids, the way how tendrils are formed, and how the
fluid borders contract due to high surface tension. In slow-motion these fluids are even more
appealing and exciting. So it is obvious to explore some possibilities.
In the first scene, RealFlow 2015's Dyverso solver will be used. Unfortunately, the presented set-
up does not work with RealFlow's standard particle solver. Well it works, at least sort of, but the
results are completely different. Feel free to try and get better results than me.
Object Settings
This setup is really super fast and it takes just a few minutes to complete it – including the simu-
lation. Start with a simple cube and don't make it too small, something like 15 m x 15 m is good.
Thickness can be around 0.5 m.
The cube's “Dyverso - Particles Interaction” panel is of particular importance and responsible for
the final look. Here are my settings:
• “Bounce” is set to its maximum – we want the ground to behave like an elastic material.
• “Sticky” mimics an adhesive force and some particles will stick to the ground object.
• “DY Interaction Factor” gives the bouncing particles an extra push. This parameter is not
available for standard particle fluids, and therefore the results turn out different.
Fluid Settings
For the fluid, a “Linear” Dyverso emitter is required. It is rotated by -90° around the X axis – the
emission is horizontal. Shift the emitter 2 m in Z (Y) direction, and 3.3 m in Y (Z) direction.
When you start a simulation you will see that the particles hit the ground object around frame 16
or 17. This is an important point in time, because we need it for the animation of our daemons.
We are almost done and all we need are a few basic daemons. “Gravity” and “Noise Field” will be
animated:
Of course, a “Sheeter” daemon is mandatory, and there is just one parameter – the rest is disa-
bled: Min cavity size = 1.0
Simulation Settings
When I work with higher “Viscosity” and “Surface Tension” in Dyverso I often increase the solver's
substeps, because the results will be much better. Fortunately, this increase can be moderate in
most cases. Go to the “Simulation Options” dialogue:
That's it and now we can start our simulation. Depending on your computer, the entire process
should not take longer than 1 minute. Considering that we have more than 160,000 particles in
the end, this is really, really fast.
What we get is a fluid with super nice, super fast, and long tendrils. Some of these strings are
even connected and interwoven. If you want to see the influence of the increased “MAX sub-
steps” then fire off another simulation with the default value of 2.
Variations
There are several ways to modify this scene. Just try out a few things to see what is happening:
• Play with the parameters from “Dyverso - Particles Interaction”. You can, for example, apply
texture to control these settings.
• Change “Viscosity” and “Surface Tension”.
• Create a slow-motion simulation with 75 or 100 fps.
• Activate “Gravity” again after 50 or 60 frames.
• Reapply the “Noise Field” daemon.
If you want a clean simulation you should create an initial state from the frame where the first
particles hit the ground. In this case do not forget to remove the animation keys from the “Gravi-
ty” and “Noise Field” daemons!
Since we are using a simulation with a “Sheeter” daemon, RealFlow 2015's OpenVDB particle
mesh engine is the only choice. Only with this tool we will get a flicker-free mesh. The OpenVDB
engine's mode of operation is almost exactly the same as with the RK meshing tool. This means
that the parameters are split into a mesh and a field part:
Polygon size
0.02 is my favourite default and I often get very good results with this value.
Volume Filter
For these meshes I have applied a “Smooth” filter with 4 iterations to iron out small bumps and
irregularities.
@ Thinning
Thinning and eroding plays an important role with the OpenVDB engine to remove the thick and
blobby look. In most cases, OpenVDB meshes are thicker than RK meshes due to the higher “Radi-
us”, but with filters it is possible to get a nicely shaped result. Try a value of 0.5.
Radius
The default value of 0.08 works fine in many cases. Instead of decreasing “Radius” it can be bet-
ter to work with “Smooth”, “Erode”, and “Dilate” filters to shape the mesh. A good alternative
to “Erode” is the “@ Thinning” filter.
A Fast Approach
This is another project that can be completed within minutes, but it has great potential for chang-
es and experiments, and the results are also very nice. Everything starts with a few white lines on
a black canvas in Photoshop, e.g. like in the example below:
The image will be used as an emission mask for a Dyverso (or standard particles) “Bitmap” emit-
ter. Here are the hard facts:
“Volume” creates a thin layer of particles along the image's white lines. And these strings will be
disturbed. Before we add the necessary emitters we will take a look at the “DY_Domain01” node:
“Viscosity” and “Surface tension” have a contracting effect on the fluid and prevent the particles
from drifting apart. The high "Resolution" value is needed to get any particles at all.
Daemons
• “Attractor”. We simply leave the default settings and set “Enable falloff” to “Yes”.
• “Noise Field”. A “Strength” value of 3.0 disturbs the fluid.
• “k Isolation”. We delete stray particles after 0.01 seconds.
• “Sheeter”. The only used parameter is “Min cavity size” with a value of 2.5.
Simulation Settings
It is always interesting to see how things evolve and therefore we are going to create a slow-
motion simulation this time:
Since we have a high number of frames per second it is not necessary to increase “MAX substeps”
this time. The simulation range is 100 frames.
That's it! Start the simulation and watch how the fluid is contracting, moving, and forming out
strings. Of course you can keep this simulation and mesh it right away, but it is also possible to
create an initial state from an interesting frame, deactivate the daemons, and let the simulation
run again.
The effect of these slight changes is that the fluid is now more or less self-driven, because the
particles have kept their velocity from the previous simulation. This is the good thing with initial
states. The decreased noise strength adds some moderate turbulence and the particles are free to
move. If you think that there is still too much or not enough noise just change “Strength”.
A weak “Drag Force” daemon can also help to control the fluid's motion.
It is also safe to disable the “DY_Emitter01” node, because in Dyverso the domain holds the parti-
cles, not the emitter.
What we get is a paint simulation with thicker drops and super thin strings, colliding tendrils, and
drops forming and vanishing. The meshing part will be a little challenging, because we can see
some jittering particles already. But with RealFlow 2015's OpenVDB mesh engine it is possible to
get flicker-free results. Of course, this requires some tweaking and a few OpenGL previews, but it
is possible. Below you can see the values I have found for the final mesh:
The following approach uses a short a script at the beginning of a simulation, while the actual
process of forming out tendrils is done with animated daemons. The advantage with this meth-
od is that we have more control over the number of fibres than with completely daemon-based
scenes: the script will randomly choose a certain number of particles, and only these seed particles
will be accelerated.
Here, RealFlow's standard particle solver will be used, because it gives much better and more
natural results. Dyverso is a great solver, no question, but the old SPH system still has its relevance
and we can only hope that this solver will not be removed. Simulation speed is not always the
Holy Grail, but sometimes it is simply about quality and possibilities.
Anyway, I will provide a script for Dyverso as well, becasue it requires a different syntax to find
neighbour particles. And you will also be able to run your own tests and compare them.
Scene Setup
The main element is a fluid inside an open container – here it is a vase object. Open a “Batch
Script” editor with F10. Then, enter scene.addVase(50,1,1.0)
The high-res vase can be treated like any other native RealFlow object (values are for Y-based
setups, flip Y and Z for other setups):
Now, a “Circle” emitter is placed inside the vase with the following settings:
We transfer the values from the "Cirle01" emitter's “Particles” panel to a "Container" node, be-
cause both nodes must share exactly the same “Resolution”. Otherwise, the particles will explode.
The final scene elements are:
The “Cube” node will serve as a ground object and catch the falling particles. Make it big
enough!
The idea is to select particles with a script from an existing fluid volume and shift them to a con-
tainer:
• This separation allows us to uplift the seeds through a negative “Gravity” daemon, while the
remaining original particles will follow a standard “Gravity” daemon.
• Furthermore, the seeds will also be affected by a “Noise Field” and a “Sheeter” daemon.
• The mesh, on the other hand, is then created from both emitters.
Here is a screenshot from the “Relationship Editor”, showing which elements are able to interact.
The “Container01” is linked to “Gravity02” and the “Hub”, and this means that the container is
under the influence of “Gravity01” as well. But, how can we lift the particles with such a setup?
Currently, they are just attracted by two daemons of equal strength. The answer is “animation”:
As long as “Strength” (from "Gravity02") is smaller than 9.81 we will see an acceleration in posi-
tive vertical direction. Then, the standard “Gravity01” daemon takes over and attracts the parti-
cles towards the ground. The result is a natural motion and we do not need any additional scripts,
slowing down the simulation. Of course it is possible to play with the “Gravity02” daemon's
“Strength” to control the length of the strings. Please take a look at the next page as well, be-
cause the best results can be achieved when the animation curve has a certain shape.
A “k Speed” daemon limits the speed of very fast particles. It is also possible to animate “Max
speed”, because in most cases, the highly accelerated particles appear during the first 3-5 frames.
The daemon will also help us to avoid very long strings.
The script itself is a simple particle-swapping (see waterline magazine “Scripting with RealFlow”)
script with a few extensions. We have to find a method for selecting particles. Once we got these
seeds, the script should look for neighbours within a small area to get thicker tendrils.
Selecting Particles
There are several methods for finding and selecting particles, e.g. with random numbers. This
approach has the advantage that we will be able to define an exact number of strings – at least
more or less: it might happen that some particles are nearby and act as a single string.
Another way is to pick out every 10th, or 40th particles, for example. This is a typical application
for the modulo (%) operator. Modulo performs a division and tells us if there is a remainder:
seedNum = 50
And here is the complete script. As always, mind the indents, because otherwise you will get syn-
tax errors:
< py | simulationpre>
if (scene.getCurrentFrame() == 0):
emitter = scene.get_PB_Emitter("Circle01")
container = scene.get_PB_Emitter("Container01")
particleList = emitter.getParticles()
seedNum = 40
searchRadius = 0.01
neighborList = particle.getNeighbors(searchRadius)
The first line prevents the script from being executed after resuming the simulation.
Simulation
In simulations with high “Viscosity” settings it is often necessary to increase the solver's precision
to avoid instabilities like exploding particles. Of course, this will also result in longer simulation
times, but here changes will be moderate. Open the “Simulation Options” and change “MIN
substeps” and “MAX substeps” to 10 and 100. It might happen that you have to try out different
substeps settings, e.g. when there are lots of misbehaving particles. Another idea is to change the
number of seed particles with seedNum.
Now, select “Circle01” and “Container01” and hit “Simulate”. It will take some time until the par-
ticles are transferred between the emitters, but the viewport information keeps you updated how
many particles are affected:
If you cannot see anything or if you get a syntax error in the “Messages” window I recommend
checking the script's indenting, because this is the most common source of errors. After a few mo-
ments the particles start moving:
Meshing
Again we have to deal with very thin structures and particles, added through the “Sheeter” dae-
mon. And again, the OpenVDB engine is the best choice, because it will give us a clean and flick-
er-free mesh. Especially in those areas, where fibres and tendrils intersect, accumulate, and finally
divide, we can often observe flickering.
In this scene things will be better, because we do not have a slow-motion shot here. But with 75
fps or 100 fps, the flicker effect can be very present in conjunction with RK and legacy particle
meshes.
The mesh node contains both emitters and we can leave the standard “Radius” of 0.08. OpenVDB
meshes always turn out thicker than their particle mesh counterparts, but we have (volume) filters
to work on the mesh and make it thinner. Here are my settings – you can use them as a starting
point:
On the following page you will see the code for Dyverso domains. As mentioned before, the
mechanism of finding neighbour particles is different with Dyverso. It might happen that you
observe exploding particles and strange patterns with particle swapping methods in Dyverso.
The reason for this misbehavbiour is a bug, but we will not see a fix for RealFlow 2015.
Instead of an emitter and a container two domains with equal "Resolution" will be needed.
Please also read the "Multiple Dyverso Emitter and Domains" chapter on page 15 for more infor-
mation.
Just copy and paste the script, but again, mind the indents, because otherwise you will get errors:
< py | simulationpre>
if (scene.getCurrentFrame() == 0):
source = scene.get_DY_Domain("DY_Domain01")
target = scene.get_DY_Domain("DY_Domain02")
particleList = source.getParticles()
seedNum = 40
searchRadius = 0.01
source.createVoxelization()
Our next project “draws” ribbons of paint, chocolate, or milk in the air. A handful of daemons
will help us to keep the particles together and even stop their expansion.
Start with a square emitter. Horizontal scale is around 1.5, but height is just 0.1. Here I will be
using a Dyverso emitter again, but standard particles are Ok as well. In the next step, the emitter
will be attached to custom spline and follow this path. The spline's shape is not relevant, but you
should avoid intersections, unless you really want the particles to collide.
Of course it is possible to animate the emitter manually and align it to a spline. Or we simply add
animation keys randomly at different points in time. This way we are able to create twists, or
faster and slower sections. But, it can be a difficult and time-consuming task to make the emitter
follow a spline. Another idea is to create a dummy animation with a simple object, e.g. a cube,
inside your 3D program. Then, we export the object and load it to RealFlow, where the emitter is
just parented to the imported helper object. All we have to do is correct the emitter's emission
direction: the emitter's viewport arrow should point in opposite direction to its motion:
The red arrows indicate the emitter's motion direction, blue stands for emission direction.
Here, we will be using a nice little script, written by my colleague Alex Ribao, to make the emit-
ter follow the path and align it automatically as shown above. This script will also be the starting
point for the "Spline Splashes". The basic idea is to evaluate a spline's curve, create animation
keys from the position values, and transfer them to an emitter.
Before we take a look at the listing, here are the parameters you can change:
• Enter the exact names of the spline and the emitter you want to use for the simulation.
• steps defines the resolution of the transfer process – you can keep this value in most cases.
• maxDistance is the distance in which the position keys will be added.
• maxFrames is the last frame of the animation range.
• reorient triggers the alignment function when set to “True”.
In the first step, the animation curves for position and rotation will be created. Then, the script
removes the already existing animation keys, because otherwise old keys will be mixed with new
ones. The loop goes through the spline's control points and evaluates the intermediate positions,
based on steps and maxDistance. When a point is within the given maxDistance, a new key is being
created.
If reorient is active (“True”) the script calculates the Euler angels between two point positions and
a reference angle. The result is the emitter's orientation in the form of a rotation vector consist-
ing of X, Y, and Z values. Finally, the keys will be adjusted to the scene's FPS rate and maxFrames.
On page 41 you will find the script. All you have to do is to copy/paste it to a “Batch Script” editor
(F10), make your settings, and execute it with Batch Script > Script > Run. Of course you cannot
only align emitters to a spline with this script, but any other node as well.
The fluid properties are pretty straight forward and more or less what has been used in the pre-
vious simulations. As always, the shown values are nothing more than suggestions. "Resolution"
can be moderate, because we will also use a "Sheeter" daemon. Eventually occuring holes can
also be closed with adequate mesh settings.
Our first tests do not look very promising. After a few frames everything ends up in a complete
chaos and it is definitely a good idea to change the emitter's "V | H random" settings to 0.1. We
have to slow down the fluid and this can be done with a "Drag Force" daemon. In order to get a
smooth emission I have chosen a "Speed" value of 6.0 here.
Daemons
We need two bounded daemons – “Noise Field” and “Drag Force”. Scale the bounding spheres to
make them fit around the emitter:
With "Drag strength" values of 20 or more I had constant crashes, due to the rather high forces
acting on the fluid. The only way to fix this was to increase "MAX substeps" set to 10. Maybe you
have to use even higher substeps settings. The final value depends on the strength of the "Drag
Force" daemon. In this scene I have used a strength value of 50 to get a continous ribbon without
holes or gaps, but also to maintain a slight expansion. If you want to stop the particles complete-
ly just use higher settings or add another "Drag Force" daemon, but this time not parented and
unbounded.
Noise plays an important role to get the disturbed and wavy look. Below you see the settings for
the "Drag Force" and "Noise Field" daemons.
Finally, we need a “Sheeter” daemon and again, the only relevant parameter is “Min Cavity Size”.
Start with values around 1.7, but the actual value depends on the number of particles, emitter's
motion speed, and "Drag Strength".
Below you will find the script. All you have to do is to copy/paste it to a “Batch Script” editor
(F10), make your settings, and execute it with Batch Script > Script > Run. Of course you cannot
only align emitters to a spline with this script, but any other node as well.
splineNode = Spline01
emitter = DY_Emitter01
steps = 3000
maxDistance = 0.2
maxFrame = 125
reorient = True
# Do not make changes below this line unless you know what you're doing
noControlPoints = splineNode.getNumberOfControlPoints()
curStep = 0
lastPos = Vector.new(0,1,0)
posCurveX = emitter.getParameterCurve("Position.X")
posCurveY = emitter.getParameterCurve("Position.Y")
posCurveZ = emitter.getParameterCurve("Position.Z")
posCurves = [posCurveX, posCurveY, posCurveZ]
rotCurveX = emitter.getParameterCurve("Rotation.X")
rotCurveY = emitter.getParameterCurve("Rotation.Y")
rotCurveZ = emitter.getParameterCurve("Rotation.Z")
rotCurves = []
if reorient:
rotCurves = [rotCurveX, rotCurveY, rotCurveZ]
for c in posCurves:
c.removeAllKeys()
if reorient:
for c in rotCurves:
c.removeAllKeys()
lastPos = pos
curStep += 1
# Re-scale time
scale = float(maxFrame) / scene.getFps() / curStep
for c in allCurves:
for k in c.getKeys():
k.setTime(k.time * scale)
Fluid Wings
Maybe you have seen some of these appealing simulations of highly distorted fluid streams with
tendrils shooting out all the time, droplets, and wing-like structures. This is exactly what we will
be recreating here. And I am 100% sure that most of you will be very happy to read that we will
not need a single line of Python code.
You will see that this approach has potential for your own experiments and ideas. Even small pa-
rameter changes have huge influence on a simulation. This makes it easy to get lots of different
results quickly. But it is also the main difficulty, because it might take many tests until you really
get what you want.
Important:
Please note that all translations (position, rotation, scale) are based on a YXZ setup for Cinema 4D
and Lightwave. If you have a setup with Z as the height axis you have to swap the Y and Z values
given here. In order to change the setup go to:
Our starting point is a simple scene and the results will be refined over time. Of course, this in-
cludes changes in the setup, but every scene will be unique and can be used for further testing
and new arrangements. Here I am going to present two different types of simulations, whereas
the second project can be seen as a further development of the first scene.
Noise
Noise is an essential concept, because it will help us to displace the particles and this is the most
important requirement for vivid splashes and tendrils. The idea is to create gaps and holes, al-
though this is something we want to avoid normally, by filling them with RealFlow's “Sheeter”
daemon.
The most obvious tool for noise generation is the “Noise Field” daemon. Another method is to
increase an emitter's “V random” and “H random” parameters. Differences in emission speed or
direction, e.g. moving or rotating emitters are also good ways to create chaos.
Basic Splash
We start with a Dyverso “Circle” emitter. Emission direction will be along one of the horizontal
axis, e.g. Z (Y), and here are the position and rotation settings:
The emitter's “Speed” is 7.0 m/s and this value is the result of some testing and tweaking. Feel
free to try other settings. Another important action is to set “V random” and “H random” to 1.0.
Unlike RealFlow's legacy SPH solver, many Dyverso emitters only accept random values between 0
and 1, but this limitation prevents the creation of really chaotic structures.
Domain Settings
When the first emitter in a scene is being created, RealFlow will always add a domain. If you are
familiar with RealFlow's Hybrido technology you might expect something like a “Cell size” value
for adjusting the domain's resolution and number of particles. With Dyverso it is different, and
here, cell size only plays a role in terms of fluid-object interaction. The number of Dyverso parti-
cles is controlled with the domain's “Resolution” and the emitter's “Speed” parameters.
Maybe you have recognized that “Type” is set to “Liquid - SPH”? This fluid type uses the same
core technology as RealFlow's standard particles, but with lots of speed improvements. I decided
to do some tests with DySPH, because the results with “Liquid - PBD” were a little disappointing –
at least in this special case. In the end I kept DySPH for all of my butterfly splash simulations.
Daemons
In most cases the first daemon is “Gravity”, but in this scene we do not want the particles to fall
down immediately. We want a nicely bowed shape instead:
The final “Strength” value mainly depends on the emitter's “Speed” and the faster the particles,
the higher the daemon's force. With slowly moving particles, values smaller than 1.0 might be
necessary.
The next daemon is “Noise Field” and it will help us to add more chaos to the simulation. An-
other side effect is that daemons like “Noise Field” have a decelerating effect. The particles get
jammed and start to spread, but we will also see strong deformations with increasing “Strength”.
After several initial tests I decided to continue with a bounded daemon (Scale = 1.75 | 1.75 | 1.75)
around the emitter and the following settings:
• Strength = 22.0
• Space scale = 2.0
With smaller “Space scale”, we will get more repetitions of the noise pattern. If we increase
“Time scale” the pattern will be repeated in shorter intervals.
In my first simulations the particles have been too fast and so I set “FPS output” to 50 fps. What I
got was not bad and I have achieved a high amount of noise already. The main stream of particle
splits, there are droplets, holes and twists. But unfortunately, the fluid is also totally torn, distort-
ed and coiled. Anyway, the final evaluation can only be made with a “Sheeter” daemon. Only the
“Min cavity size” parameter has been used with a value of 1.4.
There are thicker and thinner zones, a “backbone” and these wing-like structures, but hardly any
tendrils. A simulation like that has some potential and we can get many different looks just by
playing with the “Noise Field” daemon's “Strength”, different emitter types and shapes, or the
“Sheeter” daemon's “@ min relative speed” and “@ max relative speed”.
So, the scene is definitely nothing that should be dumped, just because it does not meet our cur-
rent expectations.
Discussion
Despite the nice results we are still far away from what is shown in the introduction images.
One of the main problems is that the particles do not spread out horizontally. Instead we get this
almost conical fluid structure. And there are hardly any tendrils, but this could also be a matter
of our “Sheeter” settings.
Another thing that should be changed is the current frame rate of 50 fps, because simulations
should work at standard frame rates like 25 or 30. Change" FPS output" accordingly.
It also seems as if there is not enough turbulence and noise. Yes, it is true that we are using a
bounded “Noise Field” here, but a global, unrestricted noise will disturb everything completely.
Believe me, I have tested that ;-)
Collision Splashes
We have seen that our approach goes into the right direction, but there are several problems.
The main issue is certainly the fluid stream's shape. The particles should spread out more horizon-
tally. Randomness is another point we have to address.
A collision object is the best method to influence the fluid's shape. This supporting object has
some more advantages:
Since we want to get this neat butterfly effect a cube appears to be the ideal object. The idea is
simply to let the particles collide with the cube's surface and this interaction forces the fluid to
spread out. Noise, and the aforementioned “DY” parameters, help us to get the tendrils.
Add a "Cube" object and make the following settings under its "Dyverso - Particles Interaction"
panel.
If you want to recreate the scene 1:1 just take a look at the position and rotation settings below.
Users with a Z-based setup have to swap Y and Z values again:
First Impressions
The rest of the settings will remain untouched. A test simulation gives us an idea whether we
have a working approach or not. It only takes a few frames to recognize that the method is obvi-
ously very promising.
The fluid spreads out and we observe the first beginnings of tendrils and these butterfly struc-
tures. But, there are also jammed particles, influenced by the “Noise Field” daemon, and highly
disturbed. The angle between emitter and collision object plays a very important role, and getting
the right angles might take some time.
If the angle is
• too small, the “wings” turn out very small and there are hardly any tendrils.
• too big, we might see jammed particles and a totally chaotic fluid.
This is what we get with the settings from the screenshots on the previous pages:
So, we need a balance between the parameters and I have made a few more changes:
The higher friction will decelerate the particles. You might suggest to decrease the emitter's
”Speed” instead of using a higher friction. Basically, this is true, but we need a certain particle
speed to make the fluid spread out. Furthermore, the “Noise Field” daemon's “Space scale” has
been set to 8.0, because I wanted to create really strong displacement in small areas.
One the following page you can see a screenshot from a simulation with the new settings.
Perhaps you have noticed another thing in the image above? There is something like a spiky
“backbone” in the middle of the fluid. This is a very interesting structure and makes the fluid
much more vivid.
When you change your point of view you will see that this type of simulation only looks good un-
der certain perspectives. The best view – at least in my opinion – is similar to the one in the image.
Side views are also suited, especially when you focus on the details or fluid borders. Top views, on
the other hand, often look strange.
Of course, it reads if all the changes I am describing here are the result of a few minutes of trial
and error. In fact, it took me countless simulations to find out how velocity, emission direction,
angles, and friction are connected. But, thanks to the incredible simulation speed of DySPH I was
able to finish a single test within 1 or 2 minutes. With RealFlow's standard particles I would have
spent much more time on watching the progress bar.
For the next simulation cycle I have increased the following parameters, because I wanted to cre-
ate wider “wings”:
Last Settings
What we have now is very close to the reference images and there is only one thing left to do: the
tendrils are too long, because the “Sheeter” constantly creates new particles between the fibres.
Fortunately, this is easy to fix. All we need is a condition for the tendrils to break:
As we can see it is possible to achieve fantastic tendrils with RealFlow's “Sheeter” daemon and
the results are absolutely stunning. Another advantage is the daemon's unparalleled speed. The
trick is simply to turn off the node's own “Create tendrils” option, because it will not help us
here. Instead it is better rely on noise, bouncing effects, and collisions, because they are the ingre-
dients for successful simulations.
There is also one more way of introducing more turbulence and randomness. Just add an expres-
sion to the collision object's “DY Friction” parameter:
=0.002*sin(t*15)+0.01
With this formula, friction oscillates between 0.008 and 0.012 (0.01 - 0.002 and 0.01 + 0.002).
Avoid high friction settings, because some particles might get jammed! Another idea is to work
with different emitter types (“Square”, or “Triangle”) and other collision objects, e.g. a cylinder,
a hemisphere, etc. Just try and play with the parameters.
Emitter Management
The main problem with rain simulations is how to create and handle a sufficient amount of emit-
ters. A nice approach is to draw emission masks and apply them to a “Bitmap” emitter. These
masks are just white spots on a black canvas and the "Bitmap" node even has a loop function for
reloading the image sequence. Despite these advantages we face a few issues here: when the
loop is being repeated from the beginning we often observe artifacts. This means that a larger
number of maps is required to avoid "seams". Another problem is that all drops emit from exactly
the same height and this creates unwanted layers. It can also happen that several drops from two
consecutive frames gather and form elongated "super drops".
A different approach is the usage of “Sphere” emitters, but it is a tedious task to add 50, 100, or
more emitters, and adjust their parameters. There has to be another solution. If you are a regular
reader of waterline magazine you will probably know what I am talking about: scripting. Only
scripting allows us to keep track of a large number of emitters and manipulate their parameters
at simulation time automatically.
If you are a proud owner of RealFlow 2015 (9.1.1.0186 or higher) then Dyverso is the perfect solu-
tion, because it has several advantages. Dyverso is very fast, and it is possible to group multiple
emitters under a single domain. These domains are also able to interact. Another advantage is the
small number of export resources, becasue only the domain(s) will be exported, not the emitters.
With standard particles I recommend using the bitmap emitter method. Of course, you can test
out bitmaps with Dyverso as well, but here I want to present a completely different method.
The Idea
The idea is to write a batch script to create, distribute, and adjust a customizable number of
“Sphere” emitters. During simulation, the emitters will be controlled through three scripts:
1. The first script cleans the scene and removes existing particles.
2. Another script will be executed at the beginning of every new frame. All it does is to select a
random number of emitters, activate them, and enable their “Fill sphere” option.
3. Script number three will be executed at the end of a frame. In this program, the emitters will
be disabled again and repositioned.
You might ask why it is necessary to change the emitters' positions again in step 3? Without this
step it might happen that one emitter is selected twice within two frames. As a result we will get
one big drop or other unwanted effects. The refreshed positions and scales guarantee enough
randomness, esp. with a small number of emitters.
Batch Script
I do not want to go into the script's details here, because everything you need can be found in
waterline magazine “Scripting with RealFlow”. Only the most important parts and sections will
be explained. As always, the script is for Y-based setups. Swap Y and Z if necessary.
In the first part a batch script has to be executed, but only once. This script will create our emit-
ters, spread them randomly over a given area, applies a random radius, and sets the emitters'
“Simulation” mode to “Inactive”. Furthermore, the nodes will be added to a group, named
“Emitters”. If this group does not exist it will be added automatically.
Here is the explanation of the variables – these values can be changed to get different starting
conditions:
The script's core creates the emitters based on your settings in the variables section. A loop adds
one emitter (numDrops) per cycle, scales and positions it, and sets the initial speed:
import random
scene.enablePaint(False)
maxX = 10.0
maxZ = 10.0
vOffset = 2.0
vRndOffset = 0.5
dropSize = 0.1
dropVar = 0.05
numDrops = 30
maxSpeed = 3.0
speedVar = 1.0
groupFlag = False
scene.setGlobalVariableValue("maxX", maxX)
scene.setGlobalVariableValue("maxZ", maxZ)
groups = scene.getGroups()
for group in groups:
if (group.getName() == "Emitters"): groupFlag = True
if (groupFlag == False):
curGroup = scene.addGroup()
curGroup.setName("Emitters")
emitter.setParameter("Scale",scaleVec)
emitter.setParameter("Speed", maxSpeed - speedRndVar)
emitter.setParameter("Randomness", 0.0)
emitter.setParameter("Simulation", "Inactive")
curGroup.add(emitter.getName())
scene.enablePaint(True)
Adding, grouping, and linking the emitter's takes a little time. In order to speed up this process,
RealFlow's viewport is disabled with enablePaint(False) and reactivated later.
Before the simulation starts we have to initialize the scene. This should only be done at frame 0,
and not when the simulation is resumed:
Open RealFlow's "Simulation Flow" window, right-click on "SimulationPre" and choose "Add
Script". Then copy or type the following lines of code to the new editor, but mind the indents:
group = scene.getGroup("Emitters")
domains = scene.get_DY_Domains()
emitters = group.getNodes()
if (scene.getCurrentFrame() == 0):
for emitter in emitters:
emitter.setParameter("Simulation", "Inactive")
The actual number of active emitters can be smaller though, because it might happen that the
random generator spills out the same number several times.
Our script reads out the emitters from the group, and determines the final number of active emit-
ters for this frame. As in the script before it is not necessary to do any axis adaption (YZ-swap) this
time.
In the script's main section, a loop is started, going from 0 to the number of active emitters.
A random emitter will be selected and stored in a list. Now, the script goes through this list again
and enables the included emitters. Finally, the list is stored globally to make sure that the next
script under “FramesPost” has access to the emitters as well.
import random
maxActive = 20
minActive = 10
group = scene.getGroup("Emitters")
emitters = group.getNodes()
numNodes = len(emitters)
active = []
rndActive = random.randint(minActive, maxActive)
scene.setGlobalVariableValue("active", active)
In this script, large parts of the batch script can be reused, because the process of setting a new
position and scale is exactly the same. Disabling an emitter is also nothing new and just the oppo-
site of enabling it. Here you have to mind the axis setup and swap Y and Z values if necessary.
Important:
This part has one speciality. As you can see below there are some of the initial parameters from
the batch script (maxX, maxZ, vOffset, etc.). These varaibles are required, because the emitters
will be repositioned to avoid unwanted effects like jammed particles. It is possible to transfer the
values from the "Batch" script to the "FramesPost" script, but if you close and open the scene at
a later point time – without executing the "Batch" script – you will get syntax errors. Therefore
I decided that you have to synchronize the green parameters manually.
maxX = 10.0
maxZ = 10.0
vOffset = 2.0
vRndOffset = 0.5
active = scene.getGlobalVariableValue("active")
The Scene
It is time for a first test: we execute the batch script and watch how the emitters are added to the
group and spread over the given area. We need a “Gravity” daemon and a container to catch the
particles:
• Add a cube and scale it. The object should be larger than the area of emission (maxX, maxZ).
• Set the cube's “Volume mode” to “Solid outside”
• A good idea is to increase “DY Friction” (~ 0.1) and “DY Bounce” (~ 0.4)
• “Surface Tension” helps to maintain the drops' spherical shape - a value around 100 is good.
• Please also make sure that all nodes are properly connected in the “Relationship Editor”.
• Maybe you will get better results with "Liquid - SPH" particles.
When we start the simulation we will reach a heavy disappointment, because the particles vanish
immediately. The reason is that the script disables an emitter at the end of a frame and its parti-
cles will be deleted as well. This is a serious problem, but can be solved without scripting or other
fancy stuff. All we need is a “Filter” daemon and a second Dyverso domain. Both domains should
share the same "Particles" settings. "Resultion" is of particular importance, and these values must
be equal. "Resolution" depends on the drops' size, but values around 200.0 should be working.
What we are doing is to shift the particles from “DY_Domain01” to “DY_Domain02” as soon as
they enter the stage (age = 0.0). The “Filter” daemon is executed with every simulation step and
this guarantees that the particles will be shifted within a frame. Ain't that cool?
Our rain scene can be used everywhere, e.g. for drops falling
Final tip: Attach a “Sheeter” daemon with a small "Min cavity size" value to “DY_Domain02”.
On the following page you will see a few screenshots with 50 emitters, DySPH particles, and a
"Sheeter" daemon (Min cavity size = 0.35). When the drops hit the ground they burst, some parti-
cles are reflected due to a "DY Bounce" value of 0.6, and create the impression of spray.
But, the high "DY Bounce" value may lead to some unwanted jitter effects. If you observe second-
ary bounces decrease the parameter.
In a narrow sense, this project is not about splashes, but we have been working with viscosity sev-
eral times so far, and now it is time for a closer look. The idea for this scene is not mine, but has
been developed by Yuval Kolton, also known as “pixelpro”. You can see his results here:
https://vimeo.com/134007021
Yuval's approach is really clever. He uses a Dyverso “Bitmap” emitter to wrap fibres around
a thicker string in the middle. Then, he animates the emitter's rotation to get this twisted look.
When we talk about high viscosity in conjunction with particle solvers we always have to think
about substeps. High substeps. And these high settings will slow down our simulation significant-
ly, but they prevent us from exploding particles and instabilities. The biggest advantage is that
Dyverso is really fast, but despite this huge improvements in simulation speed we have to look
for the smallest possible “MIN substeps” and “MAX substeps” settings.
From my own experience I suggest to use fixed substeps for this kind of simulations. For the
“Liquid – PBD” type, the default values are 2 | 2. When we compare these setting with the default
values for RealFlow's standard solver of 1 | 300 we begin to understand why Dyverso is so fast.
The substeps issue will be addressed a little later.
Scene Setup
Before we dig deeper into substeps we have to talk about the scene itself and the basic parame-
ters. The best way to start is with a ground object, e.g. a cube, and the Dyverso “Bitmap” emitter.
The emission mask is a black and white bitmap.
Load the image to the emitter's “Emission mask” field and scale the node to 0.7 | 0.7 | 0.7. This
is a really small area and therefore it is necessary to increase the domain's “Resolution” to get
enough particles. A value of 100.0 should be working:
In this scene we do not want to simulate a particular type of fluid. All we want to create here is a
nice looking “something”. For this reason I was just playing with “Viscosity” and came up with a
value of 250.0 in the end. Since Dyverso is a pretty new solver type I recommend testing out how
high-viscosity fluids behave and how to scale the parameter.
We start with the emitter's animation. Instead of keyframing a circular animation path we can use
two simple expressions for the horizontal position axes. For a Y-based axis setup enter:
• Position.X =sin(t)*1.2
• Position.Z =cos(t)*1.2
These formulas create a circular motion with a radius of 1.2 m. One revolution requires approx-
imately 157 frames. In order to change the number revolutions multiply the t variable with a
factor:
The height axis (Y or Z) will be animated as well, but this time with keys:
The emitter has to be rotated around its height axis as well and this calls for another expression –
again for a Y setup:
• Rotation.Y =t*180
Our simple formula creates a spinning emitter. For changes we do not have to set animation keys,
but we enter a new factor (greater or smaller than 180) instead.
Time for a first simulation! The domain uses a really high “Viscosity”, but the results are disap-
pointing and some particle even pass through the ground object:
This has absolutely nothing to do with what is shown on pixelpro's Vimeo page. The emission is
chopped and the particles flow apart immediately. The entire simulation appears watery and ob-
viously there is something going wrong completely.
One method to fix this is to increase the domain's “Viscosity”. Let's start another test with 2500.
To get a better view of the simulation go to
Now we start another simulation. Despite the fact that we have just simulated molten glass, the
results are still very poor. The only difference is that the particles do not spread out so fast any-
more. So, we can switch back to Viscosity = 250 and look for other solutions.
A very efficient way to prevent particles from flowing apart is the ground object's friction:
Furthermore, the “DY Bounce” parameter should be set to 0.0, because we want to avoid elastic
effects. Now we can start another try:
What we get here can be seen as a first small victory, because the particles stick together, al-
though there is still no real structure.
In the introduction to this project I was talking about substeps and their importance for high-vis-
cosity simulations. We start with a moderate change. Open RealFlow's “Simulation Options” and
enter 10 for both “MIN substeps” and “MAX substeps”. Then, simulate again:
With minimum and maximum substeps of 50 we get a pretty stable simulation, but it might hap-
pen that the simulation still lacks particles. Increasing “Resolution” will not help too much, be-
cause this trick will not fill the gaps between the particles. It seems as if the emitter's position and
rotation animation is the source of the problem. The only way to compensate for this is a higher
emission speed. Currently, “Speed” is set to 2.0, but with 3.0 or 4.0 we should get a satisfying sim-
ulation.
We are really close to Yuval's simulation now. In order to slow down everything a little more, and
get an even better particle stream, I normally add a weak “Drag Force” daemon. “Strength” val-
ues between 0.1 and 0.3 are enough in most cases.
We also want to take a quick look at simulation times. The same scene with standard particles and
a “Viscosity” value of 250 requires more than 50 substeps. In fact, something between 400 and
500 fixed steps is realistic. With Dyverso 50 steps are enough already and here on my dual Xeon
E2630 v2 (2 x 6 cores @ 2.6 GHz) the entire simulation took only 36 minutes.
Meshing
In simulations with highly viscous fluids we often observe how particles slowly interact, esp. in
areas where the fluid layers are touching. Structures like these are very challenging for mesh
engines, because they cause an unwanted flicker. RealFlow 2015's OpenVDB particle mesh is the
perfect choice again.
In the previous projects I have used a rather high “Radius” value of 0.08 – the default value.
Filters helped me to carve out the fluid's details. For this simulation I want to work with a much
smaller “Radius” of 0.021, because the particles are densely packed. The fluid also has very subtle
structures and to get them I have decreased “Polygon size” to 0.01.
Of course, filters play an important role here as well and these are my settings:
Scene Description
In this project we will be simulating splashes, triggered through a bouncing ball. This scene is one
of the first projects I did during my tests on RealFlow's 2015 “Crown” daemon in conjunction with
Dyverso fluids. The idea is simple:
The execution of the scene's “recipe” is bit more complex and requires some preparation, as well
as several animation curves and expressions.
Before we start with the fluid simulation we have to create the sphere and analyse its motion.
There are some events we have to know, because they will play an important role for the simula-
tion. Proceed as follows:
The statement scene.addSphere(4) creates a high-resolution sphere. Scale it to 3.0 | 3.0 | 3.0, and
place it 5.25 m above a ground object. The ground object is a simple cube with a horizontal scale
of 30 m x 30 m. Its height should be around 0.5 m to avoid leaking particles. Make the cube a pas-
sive rigid body. Our sphere, on the other hand, is going to be a soft body. Here are the rigid and
soft body settings for both nodes:
Now, add a “Gravity” daemon, change “FPS Output” to 75, and simulate. The first moment, when
the ball hits the ground is around frame 64, the second touch is at frame 173. Write down these
values – we will need them again. By the way, a bounding “k Volume” daemon won't hurt.
It might happen that the sphere experiences strong deformations at the beginning of a simula-
tion. This is because of a bug in RealFlow's dynamics engine, but there are a few ways to fix this:
• Change one soft body parameter, hit enter, and reapply its original value.
• Reload the scene.
• If all this does not help, recreate the sphere.
We have to do a few more adjustments on the sphere later, but for now make it inactive.
The Puddle
We need a fluid volume for the sphere to interact with, e.g. a puddle. You can either fill a con-
tainer or create a puddle – in this case it will be the latter option. Create a Dyverso “Sphere” emit-
ter with “Scale” set to 1.5 | 1.5 | 1.5 and enter 2.5 m for its vertical position. To get a nice splash, a
sufficient amount of particles is required - something around 130,000 - 150,000 particles is a good
value. With RealFlow's Dyverso "Liquid - PBD" solver this amount is absolutely no problem.
Now open the cube's “Dyverso - Particles Interaction” panel and make the following settings:
“DY Friction” has been set to a high value to prevent the particles from flowing apart. We do not
want to end up with an ultra thin fluid layer, but a convex, lens-like puddle. Finally, add a drag
force daemon, set “Drag strength” to 50.0, and make it inactive.
• Start the simulation and let it run until the puddle's diameter reaches approx. 9.5 m.
• Stop the simulation, set “Drag_Force01” to “Active”.
• Resume and simulate for another 75 - 100 frames.
The “Drag Force” daemon will slow down the particles, but it is not necessary to stop them com-
pletely. Once the puddle has reached its final dimension delete the “Drag Force” daemon or deac-
tivate it again – it will not be used anymore. And disable the emitter's “Fill sphere” option!
On the next page there are images of how the fluid should look now.
If the puddle looks similar to the image below you can create an initial state, and “Reset to Initial
State”.
In the next step, we want to create a nice crown-shaped splash when the sphere is hitting the
fluid. Add a “Crown” daemon, open its “Daemon” settings under “Node Params”, and look for
“Creation time”. This value is given in seconds and specifies the point in time when the daemon
starts to attract the particles. “Acting time” tells us how long the attraction will last.
The moment when the sphere touches the ground is frame 64. To convert this value to seconds
just calculate:
64 f / 75 fps = 0.85 s
Here are the complete settings for the “Crown” daemon. They are the result of some testing, but
of course you can use other values as well:
RealFlow's “Crown” daemon has an internal hole-filling procedure, so it is actually not necessary
to add a separate “Sheeter”. But the main problem is that “Crown” does not provide any param-
eters to control the effect, and this is the reason why some simulations lack particles. Another
thing is that new particles will be created even when the daemon's forces are not active anymore
and this fact creates unwanted effects sometimes. Fortunately, both issues can be fixed easily:
• Right-click on Crown > Node > Simulation and choose “Edit Curve...”
• In the expression field enter if(f>115,0,1)
• At frame 116 the daemon's “Simulation” mode will be set from “Active” to “Inactive”.
Of course, the crown has to be shaped, because in its default form we will not get the expected
results. What we need is a relatively flat, but wide crown. RealFlow's “Crown” daemon can be
scaled like another object and its base diameter should roughly match the sphere's lower third.
To work on the daemon's viewport gizmo click on Crown > Daemon > Edit. A yellow frame appears
around the viewport, indicating that you are in edit mode. A big plus is that it is possible to select
several control points at once and move, scale or rotate them together:
1. Select the four upper points and scale them until you get a wide crown – approximately 3x the
size of the lower base.
2. Keep the points selected and move (W) the points downwards.
3. Go to top view (1) and drag the tangent handles until you get a circular crown again.
4. Select the spike points and move them vertically – they should all have different lengths.
5. Click on “Edit” again.
Adding Turbulence
What we get is not really exciting and the entire simulation has a clean, almost sterile look. It
lacks turbulence, drops, and chaos. There is also hardly any interaction with the sphere, it does
not get wet and particles do not stick on its surface. Change the following parameters:
Note:
If you try to recreate this scene with standard particles then bear in mind that Standard – Particles
Interaction > Sticky does not work with animated and dynamically driven objects!
With these new values the result is much better! But now the splash is way too exaggerated and
we have to fine tune the “Sheeter” daemon's “Min cavity size” – something around 0.45 works
well. Despite the progress we have made, there are still a few things to fix. One of the most an-
noying effects can be seen near frame 135, where the fluid is pushed back from the sphere. This
“explosion” is related to the high “DY Interaction Factor”, and we should animate the parameter:
DY Interaction Factor 120 F -> 128 F 3.0 -> 1.0 Bezier keys
We're getting there, but it is not exactly what I had in mind, although the rising water column
between ground and sphere rewards us with a neat secondary crown splash. To get even more
turbulence let's add a bounded and animated “Noise Field” daemon. This is the “Strength” pa-
rameter's animation curve:
Strength 75 F -> 98 F -> 120 F 0.0 -> 20.0 -> 0.0 Bezier keys
Enable the daemon's “Bounded” option, scale it to 1.6 | 1.6 | 1.6 and place it above the puddle.
Make sure that the bounding sphere does not touch the fluid:
Then simulate again and you will see that we have turned an unspectacular and unexciting splash
into something really vivid. Maybe you have to do some final adjustments on the “Sheeter” dae-
mon's “Min cavity size”.
Ok, this part uses scripting again and maybe you are asking if it is really necessary to do so much
with Python? Aren't there easier ways to achieve certain things? The plain truth is that most of
the really neat simulations, you see on video platforms, have been done through customization.
Yes, it is true, RealFlow provides a lot of features, but why should I look for complex solutions
with the software's integrated tools when there is an easier way through scripting? Python is
nothing more than another feature and its main purpose is to extend RealFlow's possibilities.
And this is exactly what we are doing here.
Of course there is always a certain chance that a script is buggy, but this is something that can
be fixed. And once you are used to Python scripts you will use them like any other function with
parameters and values.
Scene Setup
Our scene is super simple: it consists of a closed cube, a “Gravity” and a “Sheeter” daemon, as
well as a Dyverso domain and a “Fill Object” emitter.
When the Dyverso “Fill Object” emitter is used you have to be careful with the cube's “Volume
mode” settings, because is does not work as you might expect. Normally, the object's “Solid out-
side” mode should be the correct choice, but you will get an offset around the object's bounda-
ries instead. One solution is:
This solution works, but is very cumbersome and not exactly user-friendly. A much better method
is to work with a copy of the cube. Create a new cube ("Cube02"):
With this trick, “Cube02” will be used to create the particles, but the interaction between fluid
and particles happens with “Cube01” only.
Point Attractors
The script from the “Paint Ribbons” chapter contains a very nice routine to subdivide a spline into
points of equal distance. And if you have read the “Scripting with RealFlow” issue you have also
gone through the crown splash part. At the end of this section you find a suggestion for an im-
provement: “Use spline control point positions or object vertices as tendril seeds.”
This, not really remarkable, idea gives us the possibility of turning a spline into an attractor,
where individual points on the spline act like force centres. Our “Paint Ribbons” script makes this
possible. Below is the output of a modified and simplified version of the script where the points
have been made visible through particles. On the right you see the original SVG spline:
Getting the attractor positions is just the first step, but the real magic has to be done inside a
“Simulation Flow” or daemon script. For the sake of simplicity and simulation speed we will pro-
ceed with a simulation script.
Important:
As always, all scripts are only valid for RealFlow scenes with a Y-based axis setup. If Z is your hight
axis you have to swap all Y and Z values in lines with three individual values.
import random
splineNode = Spline01
domain = DY_Domain01
sheeter = Sheeter01
steps = 3000
maxDistance = 0.1
splashDiameter = 0.25
startFrame = 10
stopFrame = 40
tendrilSpeed = 2.0
maxRndSpeed = 4.0
disableSheeter = True
offsetFrame = 10
noControlPoints = splineNode.getNumberOfControlPoints()
curStep = 0
lastPos = Vector.new(0,1,0)
tendrilSeedList = []
attractors = []
idList = []
if (scene.getCurrentFrame() == 0):
sheeter.setParameter("Simulation", "Active")
if (pId in idList):
pass
else:
rndSpeed = random.uniform(0.0, maxRndSpeed)
tendrilSeedList.append([pId,tendrilSpeed + rndSpeed])
scene.setGlobalVariableValue("tendrilSeedList", tendrilSeedList)
scene.setGlobalVariableValue("startFrame", startFrame)
scene.setGlobalVariableValue("stopFrame", stopFrame)
scene.setGlobalVariableValue("tendrilSpeed", tendrilSpeed)
scene.setGlobalVariableValue("domain", domain)
scene.setGlobalVariableValue("sheeter", sheeter)
scene.setGlobalVariableValue("disableSheeter", disableSheeter)
scene.setGlobalVariableValue("offsetFrame", offsetFrame)
The script prints out the number of attractor points. Please also check if the names of the nodes
involved match the names in the script (here: “Spline01”, “DY_Domain01”, “Sheeter01”). Change
them if necessary.
What we do here is to go loop through the spline points and compare their positions with the
position values of every particle. This is a brute force method, and it will take some time until the
splash particles have been found, because Python is single-threaded. There is also a routine to
check if a particle has been selected already. And, of course, the entire process of finding appro-
priate particles should only be executed once at the beginning of the simulation.
If you want to wrap the above parameters into a nice GUI download waterline magazine's
“Scripting with RealFlow” edition. Starting on page page 53 you will learn how to add user inter-
faces to custom scripts.
If a particle is within a certain radius around a spline's control point it will be saved and tagged
as a candidate. In a second script the candidates will be accelerated, but only in the time between
startFrame and stopFrame.
tendrilSeedList = scene.getGlobalVariableValue("tendrilSeedList")
domain = scene.getGlobalVariableValue("domain")
startFrame = scene.getGlobalVariableValue("startFrame")
stopFrame = scene.getGlobalVariableValue("stopFrame")
tendrilSpeed = scene.getGlobalVariableValue("tendrilSpeed")
sheeter = scene.getGlobalVariableValue("sheeter")
disableSheeter = scene.getGlobalVariableValue("disableSheeter")
offsetFrame = scene.getGlobalVariableValue("offsetFrame")
curFrame = scene.getCurrentFrame()
All the script does is to go through the candidates and set a velocity. The entire process of finding
particles has to be done once only.
You might have noticed that there is a function to disable the “Sheeter” daemon. The reason is
that the numbers of particles can increase drastically in some cases and this will slow down the
simulation. If you want the “Sheeter” to work permanently, set disableSheeter to False.
One the following page you will see a few frames from an "I Like" spline, converted into attrac-
tor points, and simulated with RealFlow's Dyverso solver.
Discussion
Now we are able to turn virtually any spline into a splash, but please be aware that a spline's
vertical position is not considered. You can, for example, use the control points' height values to
modify the particles' velocities. Sometimes the splashes also very look clean and smooth. A “Noise
Field” daemon helps to add some randomness – as done in the simulation above.
When the “Sheeter” is disabled you will recognize that the break-up process starts immediately.
There might be situations where this sudden break looks weird or artificial. In such a case the only
possibilities are to
Another problem is what can be done when you just want to change a daemon value, e.g. “Min
cavity size”, but the spline itself remains the same? Is it really necessary to go through the process
of finding the candidates again? No, fortunately this is not necessary, because the list with the
seed particles will be kept and all you have to do is to disable the “SimulationPre” script tempo-
rarily. Maybe it is also required to activate the “Sheeter” again.
Splines in RealFlow
Our last project deals with Dyverso fluids and the “DSpline” daemon. There are many tutorials
available on relevant video platform, but I want to discuss at least one scene for the sake of com-
pleteness. Here, we want to simulate a stream of particles that crawls around a soda can.
RealFlow 2015 supports splines and it is possible to import splines via the SVG format, but you
have to be careful, because the import of paths without Bezier tangents fails. A good example is
a path made of straight lines. The splines below cannot be imported, for example:
Another drawback is that there is hardly any support for 3D splines, because many programs do
not provide SVG exporters. Therefore it can be difficult to create really complex shapes in Real-
Flow. The best way to start with splines is to use a template. This way I was able to draw a helical
spline in RealFlow within a couple of minutes:
I normally start with a spline in my 3D program and place small objects at the most significant
points. The objects are then exported as an Alembic or SD file, and loaded into RealFlow as a ref-
erence for the new spline. The fine-tuning of the spline's control points is done in RealFlow's
2D views front and side. You can, of course, draw the daemon without taking a detour via a sep-
arate spline node or helper objects, but maybe you feel more comfortable without the daemon's
circles, esp. with very complex splines and lots of control points.
The Daemon
Once the spline is finished it can be transferred to a “DSpline” daemon with its “Copy spline...”
option. Sometimes it is also necessary to reverse the spline. If you are not sure about the control
points' enumeration press “EDIT”, go to “Display Spline”, and enable “Show CP indexes”.
A “DSpline” daemon's parameter set can be confusing when you work with this node type for
the first time, but in fact the principle is easy to understand. As you see in the image above, the
“DSpline” section is subdivided:
The purple area contains global values for vortex, axial, and radial forces. These parameters
act like multipliers for the control points' individual settings from the blue part. The associated
“@ CP ...” parameters are only accessible when the daemon is in edit mode, but both global and
individual parameters do exactly the same:
• Vortex creates a twist and makes the fluid more turbulent. With high settings it often happens
that particles leave the daemon. Use positive and negative settings to change direction.
• Axial attracts the particles towards the actual spline. The fluid becomes faster and thinner. Use
negative values for a repulsion.
• Radial moves the particles between the spline's control points.
Then there is also “@ CP radius” to influence the size of the circles around the control points.
Such a circle represents a control point's scope. When particles are outside these circles they are
no longer influenced by forces and might get stuck or fly away. Fortunately, it is possible to select
more than one control point and change their parameters/radii together.
In many cases it is enough to change the global vortex, axial, and radial values, and this is what
we will be doing here. The art is to find a good balance between the three forces and make the
particles follow the given path. My standard workflow is to start with the “Radial” forces and
a "Drag Force" daemon. Then I work on "Axial" and later on "Vortex". Corrections on all three
values are always required until I get the final look. It might be necessary to use rather high force
settings, as shown below (the "EDIT" section for individual points is not displayed):
The Fluid
As mentioned, this project uses a Dyverso “Circle” emitter, but you can also use a standard parti-
cle emitter instead. The “Circle” emitter's viewport gizmo shows an arrow, indicating the node's
emission direction. Move the emitter to the spline's first control point and rotate it until the ar-
row is roughly aligned with the spline. Scale the emitter if necessary, e.g. to 0.75 | 0.75 | 0.75.
For the domain I have used a “Resolution” of 50. When we consider the available emission area,
this is not very much, but it was good for my simulation. Don't hesitate to change this value to
your own needs. “Surface tension” is 20.
The emitter (green) is placed inside the first control point's circle and roughly aligned.
Here are some screenshots of how the particle stream evolved with different settings for "Radial",
"Axial", "Vortex", and a "Drag Force" daemon:
Radial = 15.0, Axial = 5.0, Drag = 0.3 | Radial = 15.0, Axial = 5.0, Vortex = 9.0, Drag = 0.3
Helper Daemons
In many cases, the particles refuse to follow a certain path, no matter what you do. Then it is time
for a “Drag Force” daemon – just as I already did. I recommend starting with the default “Drag
strength” of 0.1 and increase the value carefully if necessary.
A “k Age” daemon should not be missing, because when the particles are passing the last control
point they gather or fly away. The daemon's “Life” and “Variation” are measured in frames.
Another thing you will observe is that the fluid becomes less turbulent over time and in the end
it often has the look of a tube or a hose. To avoid this just scatter a few bounded “Noise Field”
daemon's along the spline's control points. It might happen that you need strong noise forces to
get any effect.
RealFlow's “Sheeter” daemon helps to fill unwanted gaps and holes – use a moderate “Min cavity
size”.
The Can
We also want some interaction with an object – in this scene it is a soda can. Ideally, the fluid
crawls along the can's surface. To achieve this it is necessary that parts of the spline pass through
the can's inside. Since the daemon can be scaled like any other node it is easy to adjust the path,
but you can also scale the can instead.
I have also made a few adjustments on the can itself and how it reacts with the fluid. The follow-
ing settings are just a starting point, not really a reference:
“Sticky” is of particular importance, because it will help to flatten the fluid and avoid a thin tube,
but higher values will also slow down the fluid. In my scenes, values around 20.0 worked best.