Melting Objects by Varying Viscosity in Houdini FLIP

Converting a mesh into a highly viscous FLIP fluid in Houdini, then selectively lowering the viscosity of certain areas by raising their temperature, is a fairly simple way to simulate a melting object, with reasonable art-directability by means of noising and animating an invisible heat source.

It’d be lovely if this technique was covered by Entagma or Steven Knipping, but it ain’t. The best tutorial we could find is Ben Watt’s Fallen Angel from 2015. Tobias’s 2017 Face Melt Tutorial is also fun. There are a bunch of very helpful forum threads though YMMV.

Below are a ragbag of tips and hints that we commit to screen, lest we forget them next time.

How Houdini thinks about viscosity

Some places say that a viscosity value of 100,000 will result in solid-like behaviour in Houdini. It won’t. It’ll result in ketchup-like behavior. Houdini respects real world viscosity properties and measurement units. So if you want a viscous liquid to behave like a solid, that is, if you want it to actually stand up before you melt it, viscosity needs to be set very high. At least 100 billion (1e+11) mPa·s (millipascal seconds) / cP (centrepoise), and maybe an order of magnitude larger than that if the material is dense.

MaterialViscosity (mPa·s)
Water1
Milk2
Olive oil50
Honey10,000
Peanut butter100,000
Pitch2.3*10^11
Viscosity of some common materials

FLIP resolution is always lossy

No matter how low you set your particle separation, the mesh of the simulated fluid surface is likely to lose the fine detail present in your original geometry. If you want to melt a finely detailed object, this is a problem. Even if your fluid mesh has the same number of polygons as your original geometry, surface details will tend to be smoothed away. We cheated by crossfading from the high resolution geometry of the model to the smushed FLIP version.

Mapping temperature to viscosity

We tried using the Gas Temperature Update node to map temperature to viscosity. We found it confusing and under-explained. So we coded our own mapping function in VEX along with some crude diffusion algorithms.

//temperature to viscosity
int exponent = ch('exponent');

f@normalizedviscosity = 1 - f@temperature;
f@viscosity = pow((1e+1 * f@normalizedviscosity), exponent); 
//heat diffusion
float t;
float delta;
float diffusionrate = ch('diffusion_rate');
float searchradius = ch('search_radius');
int maxpoints = ch('max_points');

int pts[] = nearpoints (0, @P, searchradius, maxpoints);
int pt;

foreach (pt; pts)
    {
    t = point(0, 'temperature', pt);
    delta = abs(f@temperature - t);
        if (t > f@temperature)
        {
        f@temperature = clamp(f@temperature + (delta * diffusionrate), 0, 1);
        return;
        }
    }
//uniform cooling
float decrease;
float coolingrate = ch('cooling_rate');

decrease = f@temperature * coolingrate;
f@temperature = clamp(f@temperature - decrease, 0, 1);

This nearly worked, except addition of the cooling rule kept making the simulation explode chaotically near the end of its runtime.

Maybe we should have switched from the Splashy Kernel to the Swirly Kernel in the solver (recommended for highly viscous simulations, and we did do this later anyway) but at this point we gave up and reverted to the previously abandoned Gas Temperature Update node, albeit this time with a little more understanding and humility. Here are two things we wish we’d figured out earlier.

Viscosity is an inverse exponential function of temperature

First, the default mapping of temperature to viscosity in the Gas Temperature Update node is highly exponential. Viscosity is roughly the complement of temperature multiplied by the twelfth exponent of 10, i.e.

v = (1 - t)*10^12

The Ramp Remap option might make it look like the relationship between temperature and viscosity is linear, but don’t be fooled, it most definitely is not. That said, the relationship should be highly exponential: it is physically accurate and yields credible simulations.

Fine tuning the temperature to viscosity relationship

Second, and relatedly, the Solidify Threshold has an interesting and useful effect on the exponential relationship between temperature and viscosity, just not as advertised. The descriptor for this parameter says it gives a boost to viscosity for areas below the specified temperature threshold. This is quite misleading. Now hold tight. Lower values of the threshold (i.e. below the default value of 0.15) in fact make viscosity values lower in relation to all temperature values, not just those temperature values above the threshold. Conversely, higher values make viscosity values higher in relation to all temperature values, not just those temperature values above the threshold. More subtly, lower threshold values seem to have the effect of making the temperature to viscosity relationship more exponential, so lowering low viscosity values more than it lowers high viscosity values.

Fun, huh? But this is actually really useful! Lowering the value of the Solidify Threshold parameter by an increment of 0.01 appears to reduce the value of the lowest viscosity value by roughly an order of magnitude. When working with very high viscosity values for quasi-solid liquids, we had to reduce the Solidify Threshold value to 0.09 to see melted, liquid-like behavior at high temperatures. (Also note that setting the solidify threshold to zero does not turn this parameter off but rather breaks the solver, with the effect that viscosity will not reduce at all as temperature increases).

In short, you should lower the value of the Solidify Threshold to make the fluid runnier at high temperatures, and raise it to make it gloopier at low temperatures. Of course, we need both: we need the fluid to be solid-like (really viscous) at low temperatures, and really runny (extremely un-viscous) at high temperatures. So the best balance seemed to be a very high initial viscosity (1e+12) and a pretty low Solidify Threshold (0.09).

Mesh flickering

There’s lots of other really tricky stuff about FLIP, especially flickering of the surface because of small changes to the mesh from frame to frame, especially with thin sheets of liquid. Zero adaptivity helps. Dilation and erosion help. Additional smoothing of the mesh, including another round trip to volumes and back to polygons, helps. Helps, but doesn’t completely fix 🙁

Leave a comment

Your email address will not be published. Required fields are marked *