Skip to main content

Soft Skinned Actors

A soft skinned actor is an articulated actor that combines the articulated skeleton with one or more soft (deformable FEM) volumes rigidly attached to the skeleton. The skeleton provides the overall pose while the soft volumes add deformation — surface-level dynamics, compression, and contact response.

This one actor type spans three flavors of articulation:

  1. Rigid links with soft leaf volumes — a mostly-rigid articulation with soft volumes attached to selected links (e.g. an articulated robot with soft sensors on its end-effectors).
  2. An elastic skin over the articulation — a deformable skin wrapping the skeleton that deforms under contact (e.g. a character with an articulated skeleton and a soft body).
  3. A blended skin — a single surface that is soft and deforming in some regions and rigidly skeleton-following in others (e.g. a hand with soft fingertips).

Architecture

A soft skinned actor is not an actor entity of its own, it couples two actor types:

  • The articulated body actor is the skeleton: rigid links connected by joints (see Articulated Actors).
  • Each soft FEM actor is a deformable volume: a tetrahedral mesh with a material model and elastic parameters (see Soft Actors).

Multiple soft actors are supported per soft skinned actor (DynamicArray<SoftActorParams>), so different regions can use distinct meshes or materials. Every step, the soft volumes are skinned to the current skeletal pose, then their deformation is solved on top of that posed configuration (see Energy Formulations).

Attaching Soft Volumes to the Skeleton

Each soft volume is attached to the skeleton through a two-step mechanism; both steps are always required. First, a subset of its nodes — the constrained nodes — are pinned to the articulation. Second, the soft volume is driven via linear blend skinning by a subset of skeleton links. There are two ways to specify skinning, and every soft uses one of them:

  • Attach to a link — name the target link in softAttachLinks (1-to-1 with softParams). The soft is skinned by a single link, hence skinning weights and indices are not explicitly provided. Contact between the soft and its attach link is disabled automatically.
  • Skinning data — leave softAttachLinks empty and embed skinning weights in the soft shape, mapping its nodes across multiple links.

Contact Surface

  • By default, contact is computed on the individual soft surfaces. Set enableCollidingLinks to also collide the rigid links.
  • With a blended skin (skeletonParams.skin), a single overarching mesh becomes the colliding surface, presenting one seamless surface — deforming where it is backed by a soft region and rigidly following the skeleton elsewhere. See Blended Skin.

The Three Flavors

The flavors listed above are combinations of these two choices:

FlavorSoft coverageAttachmentColliding surface
1. Rigid + soft leavessoft volumes on some linkssoftAttachLinkssoft surfaces + rigid links
2. Elastic skinskin spanning the bodyskinning datathe soft skin
3. Blended skinmixed soft / rigid-followattach or skinning datablended skin mesh

Energy Formulations

Simulating a soft skinned actor combines skinning — the geometric transform that carries a soft volume along with the skeleton — with the elastic deformation solved by the soft FEM. Three things determine the outcome: how the two compose, how the soft is pinned to the skeleton, and where each physical energy is evaluated.

Deformation and Skinning

Using the soft actor notation, let X\mathbf{X} be a node's rest (unposed) position and u\mathbf{u} its elastic displacement, so x=X+u\mathbf{x} = \mathbf{X} + \mathbf{u} is the deformed position in the rest frame. The skeleton contributes a skinning map Tq\mathbf{T}_q for its current configuration qQq\in\mathcal Q — linear blend skinning over the links that drive the node:

Tq(y)=wT(q)y ,\mathbf{T}_q(\mathbf{y}) = \sum_{\ell} w_{\ell}\,\mathbf{T}_{\ell}(q)\,\mathbf{y}~,

where T(q)\mathbf{T}_{\ell}(q) is link \ell's world transform and ww_{\ell} its skinning weight. The two compose into the posed configuration:

  • Pure skinning Tq(X)\mathbf{T}_q(\mathbf{X}) — the volume simply follows the skeleton.
  • Skinned deformation Tq(X+u)\mathbf{T}_q(\mathbf{X} + \mathbf{u}) — deform in the rest frame, then skin.
  • Blended skin bTq(X+u)+(1b)Tq(X)b\,\mathbf{T}_q(\mathbf{X} + \mathbf{u}) + (1 - b)\,\mathbf{T}_q(\mathbf{X}) — a per-node weight b[0,1]b \in [0, 1] mixes the deformed and purely-skinned positions (b=1b = 1 fully soft, b=0b = 0 rigidly following the skeleton). See Blended Skin.

Constrained Nodes

The rigid coupling to the skeleton is enforced by fixing u=0\mathbf{u} = 0 on a subset of nodes — the constrained nodes — as zero-displacement Dirichlet boundary conditions. Those nodes then sit exactly at Tq(X)\mathbf{T}_q(\mathbf{X}), following the skeleton rigidly. This gives perfect rigid attachment robustly and efficiently, with no additional coupling constraints between the two actor types, and is always required (see Attaching Soft Volumes to the Skeleton).

Posed vs. Unposed Energies

Each physical energy can be evaluated at the unposed positions X+u\mathbf{X} + \mathbf{u} or the posed positions Tq(X+u)\mathbf{T}_q(\mathbf{X} + \mathbf{u}). Evaluating everything posed is the most physically accurate. But since skinning is a geometric — not physical — deformation, some terms are cheaper (and sometimes exact) unposed. The choice is made per term: set a term's flag on the parent SoftSkinnedActorParams to evaluate it posed, or on the child SoftActorParams to evaluate it unposed.

EnergyPosed (SoftSkinnedActorParams)Unposed (SoftActorParams)
Elasticity (hasStress)physically accuratecheaper — and exact when the soft is rigidly attached to a single link via softAttachLinks, since a rigid skinning transform preserves elastic energy
Inertia (hasInertia)physically accuratecheaper, but a cruder approximation
Gravity (hasGravity)physically accuratenot available — keep gravity posed on the parent, or disable it

Contact is always posed: it acts on the world-space surface and is not a choice.

Energy Flag Rules

Creating Soft Skinned Actors

A soft skinned actor is created in a single call to CreateSoftSkinnedActor / create_soft_skinned_actor from a SoftSkinnedActorParams, which bundles:

Bind each soft region to a skeleton link with softAttachLinks (1-to-1 with softParams). Name any link you attach to so it can be referenced; contact between a soft actor and its attach link is disabled automatically.

ArticulatedActorParams skeletonParams;
skeletonParams.name = "SoftSkinnedDoublePendulum";
// ... joints and links built as in Articulated Actors; links named
// "UpperArm"/"LowerArm" on layer "Pendulum" ...

// A soft skin actor: a tet mesh with constrained nodes (softShape). hasGravity must be
// false; this uses unposed elasticity (hasStress on the soft), accurate when rigidly attached.
SoftActorParams softParams;
softParams.name = "SoftArm";
softParams.layer = "Soft";
softParams.shape = softShape;
softParams.material.type = SoftMaterialType::NeoHookean;
softParams.material.neoHookean.youngsModulus = 1e4_r;
softParams.material.density = 500.0_r;
softParams.hasGravity = false;
softParams.hasInertia = false;
softParams.hasStress = true;

// Wrap skeleton + soft into the top-level articulated actor; posed gravity + inertia there.
SoftSkinnedActorParams softSkinnedParams;
softSkinnedParams.skeletonParams = skeletonParams;
softSkinnedParams.softParams = {softParams};
softSkinnedParams.softAttachLinks = {"LowerArm"}; // attach the soft to the lower arm
softSkinnedParams.enableCollidingLinks = true;
softSkinnedParams.hasGravity = true;
softSkinnedParams.hasInertia = true;
softSkinnedParams.hasStress = false;

Actor* actor = scene->CreateSoftSkinnedActor(softSkinnedParams, error);
Mixed energy formulation

This example mixes the two energy formulations: gravity and inertia are posed (on the top-level articulated actor) while elasticity is unposed (hasStress on the soft). This is valid as long as no flag is true on both sides.

Declarative alternative

The same scene can be authored declaratively as a prefab (.mochi_scene JSON) and loaded with prefab::AddToScene / mochi.prefab.add_to_scene. The Soft Skinned Double Pendulum example ships both forms.

SoftSkinnedActorParams Reference

The top-level parameters use SoftSkinnedActorParams (C++, Python).

FieldC++ TypePython NameDefaultDescription
skeletonParamsArticulatedActorParamsskeleton_params--The articulated skeleton. See Skeleton Parameters.
softParamsDynamicArray<SoftActorParams>soft_params[]One entry per deformable skin region. See Soft Skin Parameters.
softAttachLinksDynamicArray<String>soft_attach_links[]Names of skeleton links where soft actors attach. If provided, must be 1-to-1 with softParams. If empty, soft shapes must include skinning data. Contact between a soft actor and its attach link is disabled automatically.
enableCollidingLinksboolenable_colliding_linksfalseEnable internal skeleton links as colliding surfaces. If false, only the soft actors (or the blended skin) act as colliding surfaces.
hasGravityboolhas_gravityfalseGravity for the whole actor. Each SoftActorParams entry must have hasGravity = false.
hasInertiaboolhas_inertiafalseInertia on posed (post-skinning) positions. If true, each SoftActorParams must have hasInertia = false. See Energy Formulations.
hasStressboolhas_stressfalseElasticity on posed (post-skinning) positions. If true, each SoftActorParams must have hasStress = false. See Energy Formulations.

Skeleton Parameters

skeletonParams is a full ArticulatedActorParams (C++, Python); see the parameter reference. Joints, links, cycles, initial velocities, and root placement all behave exactly as for a standalone articulated actor. Only two aspects are specific to soft skinned actors:

  • skin (ArticulatedSkinParams) is the one field with soft-skinned-specific meaning: it enables the blended skin coupling mode. See Blended Skin.
  • worldFromRoot places the whole actor. Because each soft actor's worldFromLocal is forced to identity, the skeleton root transform is the single source of global placement — author the soft rest mesh directly in the skeleton's rest frame.

To keep the rigid links from colliding with each other or the environment (leaving the soft skin as the contact surface), disable their contact layer. In this scene the links share the Pendulum layer:

scene->EnableLayerContactSymmetric("Pendulum", "Pendulum", false, error);
scene->EnableLayerContactSymmetric("Pendulum", "Environment", false, error);

Soft Skin Parameters

Each entry in softParams uses SoftActorParams (C++, Python); see Soft Actors for the full field list. The members that carry soft-skinned-specific requirements:

MemberRequirement inside a soft skinned actor
hasGravityMust be false. Gravity is driven by SoftSkinnedActorParams.hasGravity.
hasInertia / hasStressSelect the unposed side of the energy formulation. Must not both be true here and on the parent.
shapeTetrahedral mesh with constrained nodes baked in — the nodes pinned to the skeleton (always required; see Architecture).
worldFromLocalForced to identity on creation; author the mesh in the skeleton rest frame.
nameFor a blended skin, must match the soft actor's blending data in the skin mesh.
materialEach region may use its own model (e.g. Neo-Hookean) and parameters (density, Young's modulus).

Blended Skin

The third flavor uses a blended skin: a single overarching triangle mesh that presents one seamless surface for the whole actor — deforming where it is backed by a soft region and rigidly following the skeleton everywhere else. This blended mesh, not the individual soft surfaces, is the colliding surface, so contact faithfully represents the actor's outer shape.

Attach it by setting skin (an ArticulatedSkinParams) on skeletonParams; the skin mesh must include blending data linking each soft region by name. The underlying soft volumes still couple to the skeleton the usual way — via softAttachLinks or skinning data — and always carry constrained nodes.

skeletonParams.skin = ArticulatedSkinParams{
.shape = skinShape, // triangle mesh with per-soft-actor blending data
.layer = "Skin",
};

See ArticulatedSkinParams for the field reference.

Working with Soft Skinned Actors at Runtime

The creation of a soft skinned actor returns the articulated-skeleton actor, so the whole articulated runtime APIGetNumDofs, GetArticulatedShapeInfo, GetArticulatedPose, SetArticulatedJointVelocities, and so on — applies directly. Beyond that, a soft skinned actor exposes its nested sub-actors and splits query support between them.

Enumerate the nested rigid links and soft skins through the parent Actor and look them up with GetActor / get_actor.

auto links = actor->GetNestedLinkActors(error);
for (auto handle : links) {
Actor* link = scene->GetActor(handle); // link->GetType() == ActorType::Rigid
}
auto softs = actor->GetNestedSoftActors(error);
for (auto handle : softs) {
Actor* soft = scene->GetActor(handle); // soft->GetType() == ActorType::Soft
}

Queries and Contact

Deformation and contact queries (e.g. NodePositions, ContactPoints, TotalContactForce) are supported on the nested soft actor, not on the articulated actor — use is_query_supported to check. Register the query on the nested soft, call scene.step so the data is computed, then read it back. In the example scene, ball is a rigid actor placed within reach of the swinging soft:

soft_actor = scene.get_actor(actor.get_nested_soft_actors()[0])
force_query = soft_actor.register_query(mochi.QueryType.TOTAL_CONTACT_FORCE)
scene.step(1.0 / 60.0)
force = soft_actor.get_contact_force_from_actor_world(ball) # net force from the ball
soft_actor.cancel_query(force_query)

The C++ equivalents are RegisterQuery, GetContactForceFromActorWorld, and CancelQuery. When a blended skin is used, contact is reported on the skin surface instead of the individual soft actors.

Examples

Soft Skinned Double Pendulum: attaches a tetrahedral soft rod via constrained nodes and softAttachLinks, with unposed elasticity.

  • Python — uv run --no-project superdex_physics/examples/example_articulations_soft_skinned_double_pendulum.py
  • Prefab — superdex_physics/assets/samples/articulations_soft_skinned_double_pendulum.mochi_scene
  • Articulated Actors — The skeleton component of a soft skinned actor.
  • Soft Actors — The deformable skin component.
  • Contact Filtering — Layer-based contact configuration for isolating skeleton and skin.
  • Pose Controller — Implicit PD control for driving the articulated skeleton toward joint-space or Cartesian link targets.
  • Solvers — Newton solver configuration for tuning convergence.