Page MenuHome

Cloth: implement support for a hydrostatic pressure gradient.
ClosedPublic

Authored by Alexander Gavrilov (angavrilov) on Dec 18 2019, 4:25 PM.

Details

Summary

When a fluid is put under influence of gravity or acceleration, it
forms an internal pressure gradient, which causes observable effects
like buoyancy. Since now cloth has support for simulating pressure
changes caused by fluid compression or expansion, it makes sense to
also support the effects of gravity.

This is intended for better simulation of objects filled or
surrounded by fluids, especially when constrained by collisions
or pinned vertices, and should result in more realistic shapes.

Obviously, this doesn't actually simulate fluid dynamics; instead
it is assumed that the fluid immediately adapts to changes in the
shape or acceleration of the object without friction or turbulence,
and instantly reaches a new static equilibrium.

Diff Detail

Repository
rB Blender

Event Timeline

This demonstrates the difference between tripling vertex mass and adding a roughly equivalent amount of negative buoyancy (emulating heavy fluid inside the object). Note how the object on the right bulges in at the top, and resists folding at the bottom, because the imaginary fluid realistically wants to be as low as possible. Other than mass vs buoyancy the objects otherwise the same stiffness and pressure settings.

This code looks good to me.

My previous attempt enables user to set an explicit water level, and for each triangle in the mesh, if its barycenter is below the water level, then additional pressure is added to this face which is proportional to the distance of the barycenter to the water level plane.

Looks like that your code is similar, except that the water level is dynamic (and implicit) such that the total added pressure is zero and the triangles above the water level are also considered.

My previous attempt enables user to set an explicit water level, and for each triangle in the mesh, if its barycenter is below the water level, then additional pressure is added to this face which is proportional to the distance of the barycenter to the water level plane.
Looks like that your code is similar, except that the water level is dynamic (and implicit) such that the total added pressure is zero and the triangles above the water level are also considered.

I'm actually more interested in simulating the effects of having heavy fluid inside the object to tell the truth, like in that picture. Given that, and the fact that there are already separate controls for overall pressure, I decided to eliminate the 'water level' completely by targeting zero average pressure instead, so overall compression of the object is isolated from the fluid gravity effects.

One issue this implementation has however is that currently forces don't cancel out correctly, so the object may start to spin or move sideways due to topology and triangulation quirks (especially if it's low poly). I probably need a proper solution for converting a linear pressure field over a triangle to three forces at the vertices - do you happen to know of it, or do I have to try to do the integrals and solve the equations?

This also doesn't account for changes in the pressure gradient of the fluid inside the object due to object acceleration; I wonder if there is a clear way to make this more realistic.

To do this properly, you would have to convert the mesh into a tetrahedral volume mesh. We do not have any remesher that does this currently.

After that, you will know how much volume loss you have in each part of the mesh (how much each tetrahedron has shrunk) and you can apply pressure accordingly to each part of the mesh and not uniformly.
This is also needed to have actual softbody volume preservation.

With this setup you can even simulate liquid inside the volume as you can "fill" each tetrahedron with liquid and they could simulate the liquid flowing through the volume and apply pressure to the surface of the volume.
This way you can for example fill a sphere half full and have the liquid flow around inside it as it moves.

I don't think the current approach will be able to simulate this in a satisfying way. But I'm always happy to be proven wrong.

Use a better formula for converting a linear pressure field to per-vertex forces.

This seems to fix the spinning and sideways movement problem.

Take object acceleration into account for inner fluid buoyancy, in order
to somewhat emulate inertia of the fluid inside the object. For instance,
in free fall the pressure gradient should basically disappear, as the
fluid inside it is effectively weightless. Accelerating the cloth by
an external force should now also cause the 'fluid' to push back via
shifts in the pressure gradient.

Video (new on the bottom): https://gfycat.com/unequaledremorsefulhumpbackwhale

Also take the change in the volume into account to preserve the total
mass of the fluid inside the object.

Since the fluid inside the object is different from the infinite surrounding
fluid, and reacts to the acceleration and size of the object, I wonder if
it would be better to split this into two separate density fields, instead
of using the same one with different signs. Currently it can't simulate that
motion interaction in the case when both inside and outside have fluid.

Renamed buoyancy to hydrostatic pressure gradient to reflect the actual behavior better.

Alexander Gavrilov (angavrilov) retitled this revision from Cloth: implement support for buoyancy pressure gradient. to Cloth: implement support for a hydrostatic pressure gradient..Dec 29 2019, 12:02 PM
Alexander Gavrilov (angavrilov) edited the summary of this revision. (Show Details)
Alexander Gavrilov (angavrilov) edited the summary of this revision. (Show Details)

Compute the per-vertex pressure once and store it in an array.

The main remaining suspect thing here is the average_acceleration field - it is a part of dynamic state, so technically probably should be cached if you want to be able to continue simulation from the last cached frame after jumping. Otherwise the weight force from the fluid inside the object would be wrong for one frame.

This state is necessary because acceleration can only be found at the end of a step (so forces need the value from the previous step), and averaging avoids instability due to increasing 'fluid inertia' forces opposing acceleration from the previous step.

Store the average acceleration in the point cache.

This patch doesn't apply to the current master.

Code wise I think this looks fine I just have a 3 nitpick comments.

Could you update the patch to master?

source/blender/physics/intern/BPH_mass_spring.cpp
127

Add braces here.

152

Add braces here too.

697

Add braces here also.

During my testing I couldn't reproduce the any huge differences in how the objects reacted when comparing to just increasing the vertex weight, using force fields, or tweaking the gravity to emulate buoyancy.
Noted that there were observable differences, but to me they were too minor or too hard to control.

One thing is clear to me though, this does not (at least in it's current state) emulate fluid inside the object in a satisfying manner.
If you have fluid in the name, I think that most people will expect that it will at least simulate it moving around inside the object.
(Or at least try to simulate the incompressible nature of fluids)
Now, we simple get a very minor tweak to how pressure forces are distributed.

We could simply drop the fluid naming, but even then, I'm not really convinced that this is really useful.
Even when I cranked up the density difference to 100 (both positive and negative) it didn't behave much differently to just tweaking the weight or the gravity.

I'm sorry for being so negative, but I can't really see the use cases for this in the current state.

Alexander Gavrilov (angavrilov) marked 2 inline comments as done.EditedFeb 13 2020, 4:20 PM

During my testing I couldn't reproduce the any huge differences in how the objects reacted when comparing to just increasing the vertex weight, using force fields, or tweaking the gravity to emulate buoyancy.
Noted that there were observable differences, but to me they were too minor or too hard to control.

I don't know how you were testing, but the differences are major and obvious.

Maybe you didn't have any colliders or pinned vertices for the object to interact with, or something? In free fall adding weighted fluid inside the object has no effect by definition, as everything accelerates uniformly under gravity.

One thing is clear to me though, this does not (at least in it's current state) emulate fluid inside the object in a satisfying manner.

This statement is wrong. It does not emulate fluid dynamics, but in a static state this is all that is required. I.e. in a state when everything has stopped moving, the simulation is complete.

Also, cloth can't simulate an incompressible fluid, only a gas; to emulate strong resistance to compression you need to use Factor to boost the neutral ambient pressure.

I did multiple experiments with the same sort of setup you showed. Different objects that starts in the air and then collides with a ground plane.
I'll re-test with your file tomorrow.

Aha, I see now.

I've done some more testing after looking at your test file and it seems like the effects are only major when you have the simulation settings in a "sweet spot".

I think this will have to be tweaked to have more obvious influences on the simulation without having to know where these sweet spots are settings wise.
Otherwise, this feature will be very confusing and probably not used at all in the end.

For example, just the simple fact that without tweaking the blending springs settings, the result of the feature is not obvious:

This is even with the cranked density setting and the pressure factor set to a high number

For example, just the simple fact that without tweaking the blending springs settings, the result of the feature is not obvious:

Well, obviously, if the object devolves into a sphere at the slightest sign of any pressure, it is hard to distinguish two slighly differently squashed spheres. For this reason, using a sphere object is also a bad idea.

My test is based on just two guidelines: there should be some stiffness so the object can retain its shape, and the pressure Factor should be increased together with density to represent the physical fact that putting more gas inside an object increases pressure. The main inspiration for the test were plastic bags they sell car washer fluid in: they certainly expand due to the pressure of the liquid inside, but there are stiff folds that give the bag some shape and allow it to stand on its bottom - hence using a cube with stiffness.

I would like to see better examples of use cases to motivate why we need this, and a more user-friendly parameter behavior and/or name description.

I'm not sure what the bags with car washer fluid are, but there has to be a more important example? And can we see an example on a mesh other than a simple primitive like a cube or sphere? Even in the video, it's hard to see the difference.

A negative density value is strange, having two values or a ratio may be better. If this isn't really physically accurate at all since we are not simulating fluids, it may be better to try to rescale values to something user-friendly rather than based in physics, and not use "fluid" in the name. Like remapping 0..1 to 0..inf or scaling it with the pressure. I don't know the specifics, but maybe there is some way to get a simple slider that has a clear influence.

Rebased, increased the averaging factor to handle high density better.

Even in the video, it's hard to see the difference.

A negative density value is strange, having two values or a ratio may be better. If this isn't really physically accurate at all since we are not simulating fluids, it may be better to try to rescale values to something user-friendly rather than based in physics, and not use "fluid" in the name. Like remapping 0..1 to 0..inf or scaling it with the pressure. I don't know the specifics, but maybe there is some way to get a simple slider that has a clear influence.

Really, I have no idea what are you talking about. The difference in behavior is obvious, and there is nothing more 'user friendly' than a realistic physical density parameter; the most unrealistic thing here is that it's not connected to pressure so you have to adjust them both - in a real gas the values would be linearly proportional with the ratio determined by the chemical composition and temperature of the gas. Also, as I already said before, this model is quite realistic once things stop moving - detailed fluid simulation only matters in motion; this simplified method basically assumes that the fluid is always static, instantly adapting to changes in shape with no internal flows/turbulence or viscous friction, and damping being abstracted to a simple running average of acceleration.

Btw, note that the density of water is 1000 kg/m3, so don't expect to see a difference with small density values. I actually tweaked the averaging factor just now to support bigger density values easier.

Here's one more test with a half-pinned half-sphere and density of 1000 vs high vertex mass:

P.S. Rather than focusing on bags or such, the idea behind this is trying to simulate a solid soft-body better without actually simulating the internals - as you can see, the behavior of an empty heavy shell is quite different from a light shell filled with something that has mass. Simulating a fluid-filled object seems to be the easiest way to do that, combined with pressure and optionally internal springs to simulate other aspects of internal structure.

Really, I have no idea what are you talking about. The difference in behavior is obvious, and there is nothing more 'user friendly' than a realistic physical density parameter; the most unrealistic thing here is that it's not connected to pressure so you have to adjust them both - in a real gas the values would be linearly proportional with the ratio determined by the chemical composition and temperature of the gas.

If we were making an application for physicists that might be true, but it's really not the case for our target userbase. User-friendly means parameters have a simple range with perceptually linear corresponding effect, and orthogonal to other parameters. This isn't always practical and there are cases where physical units are preferred, but it is something to keep in mind when designing parameters.

If the values are linearly proportional, can't we make the ratio the parameter?

Here's one more test with a half-pinned half-sphere and density of 1000 vs high vertex mass:

That's a good example of why this is useful.

Rebased and fixed conflicts. So what are the plans for this?

I firmly believe that any input fields that map to real world values should
use specific physically valid units, rather than some weird "user friendly"
nonsense, because for one, that would allow using values measured for real
materials. If you really don't like that to get a big effect you have to
crank the value up to 1000, maybe it can use kg/liter instead of kg/m3 so
it's 1 for water, but I believe that it should be some real unit mentioned
in the documentation.

Density and pressure are linked linearly for a real gas, but I don't think
that using that here is a good idea, because one, you'd need fields for
temperature and molar mass instead, which are even more confusing; and two,
due to the limitations of the simulation you have to emulate incompressible
fluids by cranking up pressure until it 'looks right', which makes the
physical connection irrelevant.

Switched the density field to use kg/liter so that water is 1, and improved tooltips.

Other than my very small nitpick, this looks good to me now!

source/blender/makesrna/intern/rna_cloth.c
1021

Just a small nitpick. Add (kg/m^3)*10^3 as well? So:
(kg/l or (kg/m^-3)*10^3)

As kg/l is not the usual unit for density. So if people look up liquid density, they will hopefully realize that they can use the kg/m^3 values without any fancy conversions.

source/blender/makesrna/intern/rna_cloth.c
1021

Isn't this kind of redundant explanation better suited for the docs?

source/blender/makesrna/intern/rna_cloth.c
1021

I guess you are right. This clarification should be in the docs.

This revision is now accepted and ready to land.Jun 12 2020, 5:02 PM