Skip to content

Flexcomp: deformable body support (grid, mesh, direct)#18

Draft
jonathanembleyriches wants to merge 3 commits intomainfrom
feature/flexcomp-support
Draft

Flexcomp: deformable body support (grid, mesh, direct)#18
jonathanembleyriches wants to merge 3 commits intomainfrom
feature/flexcomp-support

Conversation

@jonathanembleyriches
Copy link
Copy Markdown
Contributor

Summary

Adds support for MuJoCo's <flexcomp> macro — deformable ropes (1D), cloth (2D), and volumetric bodies (3D).

Three commits:

  1. Import + spec registrationUMjFlexcomp component wraps MuJoCo's flexcomp. Rather than reimplementing MuJoCo's macro expansion, the component serialises itself back to an MJCF fragment, parses it via mj_parseXMLString, and attaches the sub-spec with mjs_attach. This means every DOF mode (full/radial/trilinear/quadratic) and geometry type (grid/box/cylinder/ellipsoid/square/disc/circle/mesh/direct) works without plugin-side reimplementation. Mesh type sources geometry from a child UStaticMeshComponent — welded vertices are exported to an OBJ in the VFS on registration.
  2. Runtime visualizationBind creates a UDynamicMeshComponent mirroring the source static mesh (geometry, UVs, normals copied from LOD 0). Each tick, deformed vertex positions are read from mjData.flexvert_xpos under CallbackMutex and pushed via FastNotifyPositionsUpdated. Source static mesh is hidden.
  3. Documentation — user-facing guide and MJCF schema coverage update.

Known limitation

TAA ghosting on fast deformation. FLocalVertexFactory has no previous-position vertex stream and there is no public API to provide one, so CPU-deformed meshes produce zero motion vectors — TAA accumulates stale samples. Workaround: set r.AntiAliasingMethod=1 (FXAA). Proper fix would require a custom vertex factory + forked shader (~1000+ LoC). Documented in docs/guides/flexcomp.md.

UMjFlexcomp component parses MuJoCo <flexcomp> XML into UE properties
(type, dim, count, spacing, mass, elasticity, contact, pin, etc).
RegisterToSpec serializes the attributes back to a standalone MJCF
fragment, parses it via mj_parseXMLString, and attaches the resulting
expanded sub-spec (flex + generated bodies + slider joints) into the
parent body via mjs_addFrame + mjs_attach. MuJoCo's own parser handles
the macro expansion, so all geometry types (grid, box, mesh, direct)
and DOF modes (full, radial, trilinear, quadratic) work correctly.

Mesh-type flexcomps: welds per-face-split UE render verts, writes an
OBJ to the wrapper's VFS, references it by filename in the generated
XML. Python preprocessor (clean_meshes.py) extended to convert
flexcomp-referenced meshes to GLB during import.

XML parser creates a child UStaticMeshComponent for mesh-type
flexcomps by resolving the file attribute relative to the XML
directory, preferring GLB over raw OBJ.

7 automated tests covering grid (1D/2D/3D) compilation, flex vertex
count, pinning, import attribute parsing, and elasticity propagation.
Each UMjFlexcomp creates a UDynamicMeshComponent on Bind that mirrors
the source static mesh (positions, UVs, normals from the LOD render
data) and hides the original static mesh. Every tick, the deformed
vertex positions are pulled from mjData.flexvert_xpos, converted to
UE local space, and pushed via FastNotifyPositionsUpdated.

Raw UE vertex attributes (UVs, normals, material) are preserved via
a RawToWelded remap table, so the source mesh's UV seams and smooth
shading carry over to the deforming display. The source material is
copied directly onto the dynamic mesh. Tangents are auto-calculated
by GeometryFramework via MikkTSpace to avoid crashes from manually
populated tangent overlays.

Reads of flexvert_xpos are guarded by the physics engine's callback
mutex to prevent torn reads while the async physics thread steps.

Known limitation: TAA ghosts slightly on fast deformation because
FLocalVertexFactory (used by UDynamicMeshComponent) has no previous-
position vertex stream. For flex-heavy scenes, set FXAA via
r.AntiAliasingMethod=1.
Add user-facing guide covering authoring, import, visualization, DOF
modes, and the TAA ghosting limitation with FXAA workaround. Update
MJCF schema coverage with all supported flexcomp attributes and
sub-elements, noting pingrid/pinrange as the remaining gaps.
@jonathanembleyriches jonathanembleyriches linked an issue Apr 18, 2026 that may be closed by this pull request
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

[Enhancement] MuJoCo Flex Support

1 participant