Page MenuHome

Cloth: implement support for a hydrostatic pressure gradient.
Needs ReviewPublic

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
Branch
temp-angavrilov-cloth-buoyancy (branched from master)
Build Status
Buildable 6221
Build 6221: arc lint + arc unit

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..Sun, Dec 29, 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.