FEM and plasticity

In this post I will show how I achieved plastic deformations with Houdini’s FEM solver. Here is video with results.


At first I recommend watching masterclass about FEM and checking example files they provided. Also I’d like to thank guys on odforce forum who suggested these ideas. If you found some mistakes or know better way please let me know and I will update this post ūüôā

Fem solver supports two ways of controlling tets shape. Throught target and rest geometry. When target geometry is specified solver computes force¬†which is assigned to tets to match their position with target position. When rest geometry is specified it tells what shape tets should return to when they are deformed. If you stretch a tetrahedron it will try to regain it’s original shape. But when tetrahedron is stretched we can tell fem solver that this¬†is his new rest shape and it can stay as it is. To determine when tetrahedron changed it’s shape we can for example compare tets current volume with volume from previous simulation step. Information about current tets volume¬†is present in primitive¬†inrinsics, along with¬†area and perimeter. Then we just blend vertex restP attribute with its current position based on amount of volume change.

So choose a model you would like to deform. Nice thing is that it isn’t necessary to have clean topology. It is thanks to embedding workflow where simulated is tetrahedralized representation of geometry. Original geometry is then deformed by simulated tets. Conversion to tets is done with Solid Embed node which internally converts input geo to SDF and then back to polygons which will assure that geometry is waterproof.


Original geometry and it’s tetrahedrons representation

It is also recommended not to simulate thin tets. So dive into Solid Embed asset and icrease offset value in Peak node.

Then create basic FEM setup with shelf tools. Create SOP Solver and attach it with FEM Solver into Multi Solver.

DOP node network

Inside SOP Solver create Object Merge which will fetch the same tets. It is only for initializing restP attribute.

Then create¬†Attribute Wrangle¬†in which we will blend P and restP attributes. On Attribute Wrangle create necessary parameters like Volume change multiplier (float) and Continous (int, 0-1). Continous parameter is basically swithcer which chooses two ways of comparing volume values. It set to 1, old volume’s value is averaged over two simulation steps which has smoother results. Play with both options and choose whichever suits you more ūüôā

int vtxprim = vertexprim(0,@vtxnum); // prim num of current vtx
float init_vol = primintrinsic(1,"measuredvolume",vtxprim); // volume of init state
float my_vol = primintrinsic(0,"measuredvolume",vtxprim); // current volume

if (chi("continous"))
    f@my_vol_old = (f@my_vol_old + f@my_vol) / 2; // assign averaged vel from prev frame
    f@my_vol_old = f@my_vol;
float old_vol = f@my_vol_old; // store in local var
f@my_vol = my_vol; // assign current vel

float vol_change = my_vol / old_vol; // compute ratio
vol_change = abs(1 - vol_change); // compute abs difference
vol_change *= chf("vol_change_mult"); // scale
vol_change = clamp(vol_change,0,1); // clamp

if(@Frame < 3) v@restP = vertex(1,"P",@vtxnum); // take restP from init state

else v@restP = lerp(v@restP,v@P,vol_change); // mix restP with P by change in volume

//v@Cd = set(vol_change,0,0);
f@vol_change = vol_change;
//f@init_vol = init_vol;


Nodes inside SOP Solver
FEM and plasticity