Deformables¶
All deformable models operate on point sets, arrays of 3D positions and velocities managed by PointDynamics.
Register a point set to get a PointSetHandler, which you pass to each energy model:
auto ps = simulation.deformables->point_sets->add(vertices);
Transforms¶
You can reposition and reorient the point set, or give it an initial velocity:
ps.add_translation({0.0, 0.0, 1.0});
ps.add_rotation(90.0, {1.0, 0.0, 0.0}); // angle_deg, axis
ps.set_velocity({0.0, 0.0, -1.0}); // applied to all points
Potential energies¶
EnergyLumpedInertia¶
Mass and Rayleigh damping for a point set. Works with any topology (edges, triangles, tets); mass is lumped to vertices proportional to element volume.
auto inertia_h = simulation.deformables->lumped_inertia->add(
ps, triangles,
stark::EnergyLumpedInertia::Params()
.set_density(0.2) // [kg/m²] for surfaces, [kg/m³] for volumes, etc.
.set_damping(0.5)
);
Every dynamic point set needs at least one inertia registration.
The quasistatic flag disables the kinetic energy term; see Simulation Loop for quasistatic usage.
EnergyPrescribedPositions¶
Penalty-based kinematic boundary conditions. Selected vertices are attracted to a target configuration with a stiffness penalty.
auto bc = simulation.deformables->prescribed_positions->add_inside_aabb(
ps,
Eigen::Vector3d(0, 0, 0), // AABB centre
Eigen::Vector3d(0.001, 1, 1), // AABB half-extents
stark::EnergyPrescribedPositions::Params()
.set_stiffness(1e6)
);
You can also select by explicit vertex list (add) or invert the AABB selection (add_outside_aabb).
To animate the boundary condition, update its target transformation each time step:
simulation.add_time_event(0.0, duration, [&](double t) {
bc.set_transformation(
Eigen::Vector3d(0, 0, 0), // translation
t * 90.0, // rotation angle (deg)
Eigen::Vector3d(1, 0, 0) // rotation axis
);
});
EnergySegmentStrain¶
1D axial strain energy for rods and cables. Acts on pairs of connected vertices (segments).
auto strain_h = simulation.deformables->segment_strain->add(
ps, segments,
stark::EnergySegmentStrain::Params()
.set_section_radius(5e-3) // rod cross-section radius
.set_youngs_modulus(1e6)
.set_damping(0.0)
);
Optional strain limiting caps elongation to prevent explosive stretching.
elasticity_only = true disables strain limiting and damping for a cheaper solve.
EnergyTriangleStrain¶
2D membrane strain energy for cloth and thin shells. Acts on triangles and models in-plane stretching and compression using the Neo-Hookean constitutive model.
auto strain_h = simulation.deformables->triangle_strain->add(
ps, triangles,
stark::EnergyTriangleStrain::Params()
.set_thickness(0.001) // shell thickness (m)
.set_youngs_modulus(1e5)
.set_poissons_ratio(0.3)
.set_strain_limit(0.2) // optional; 0 = disabled
);
An inflation parameter adds an outward pressure force, useful for inflatables.
elasticity_only = true disables strain limiting and damping for a cheaper solve.
EnergyDiscreteShells¶
Bending energy for triangle meshes (Grinspun et al. discrete shells or Bergou et al. flat quadratic model), acting on hinge edges.
auto bending_h = simulation.deformables->discrete_shells->add(
ps, triangles,
stark::EnergyDiscreteShells::Params()
.set_stiffness(1e-3)
.set_flat_rest_angle(true) // true → Bergou quadratic; false → use mesh's rest angle
);
This is always paired with EnergyTriangleStrain on the same triangle mesh.
The Surface preset does this automatically.
EnergyTetStrain¶
3D volumetric FEM strain energy for soft bodies. Acts on linear tetrahedra using the Neo-Hookean constitutive model.
auto strain_h = simulation.deformables->tet_strain->add(
ps, tets,
stark::EnergyTetStrain::Params()
.set_youngs_modulus(1e5)
.set_poissons_ratio(0.4)
);
elasticity_only = true disables strain limiting and damping for a cheaper solve.
Manual Composition¶
Any combination of the above energies can be registered on the same PointSetHandler.
See examples/main.cpp for a mesh with volumetric interior, shell surface, and rod edges — each energy registers independently and all contribute to the same Newton solve.
Output¶
Mesh output is registered separately:
simulation.deformables->output->add_triangle_mesh("cloth", ps, triangles);
simulation.deformables->output->add_tet_mesh("body", ps, tets);
simulation.deformables->output->add_segment_mesh("rod", ps, segments);
simulation.deformables->output->add_point_set("pts", ps);
Presets handle this automatically.