Skip to content

[FEATURE] Decouple visual from physics geometry for FEM entities.#2904

Merged
duburcqa merged 30 commits into
Genesis-Embodied-AI:mainfrom
ACMLCZH:pr/fem-render-meshes
Jul 20, 2026
Merged

[FEATURE] Decouple visual from physics geometry for FEM entities.#2904
duburcqa merged 30 commits into
Genesis-Embodied-AI:mainfrom
ACMLCZH:pr/fem-render-meshes

Conversation

@ACMLCZH

@ACMLCZH ACMLCZH commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

Description

FEM entities now expose their morph sub-meshes as visual geoms (fem_entity.vgeoms, mirroring the rigid entity API): each FEMVisGeom pairs a render mesh carrying its own surface and UVs with the map from its vertices to the simulated vertices. The rasterizer and raytracer draw the authored input surface per visual geom and update its vertices from the simulation state through that map, while the FEM solver drops its render-only topology and UV fields. Sub-meshes are welded into a single simulation mesh before tetrahedralization, which now runs before the morph position is applied so the tetrahedralization and its on-disk cache are shared across placements of the same geometry. The normal render pass supports double-sided primitives in both offscreen and interactive viewer renders through a shared shader cache keyed on the primitive defines.

Motivation and Context

Multi-material assets lost their appearance when simulated as FEM entities: rendering used the tetrahedral boundary with a single entity-wide surface and zero-padded UVs. Decoupling render geometry from simulation geometry preserves the authored look (per-sub-mesh materials, textures, UVs) and enables sub-mesh level segmentation for FEM entities.

How Has This Been / Can This Be Tested?

  • tests/deformable/test_fem.py: the new test_multi_submesh_render_decoupling asserts exact per-vertex tracking between visual geoms and simulated vertices on a two-material GLB; test_interior_tetrahedralized_vertex checks the same invariant on a tetrahedralized box. The full file passes, including the implicit falling sphere/box rest-state checks.
  • tests/rendering/test_offscreen.py: the new test_multi_submesh_fem_render snapshot test covers rgb/depth/segmentation/normal on the rasterizer and rgb on the raytracer; test_segmentation_map covers the per-sub-mesh segmentation keys at "geom" level.
  • Genesis-Intelligence/snapshots updated to revision 11a81c48367a18aedf0a3bed460b69c7ba7ccd4e (5 new PNGs), pinned in tests/utils.py.

Screenshots (if appropriate):

Pair 1 - Ducks (Left Rigid, Right FEM)

Before After (This PR)
sbs_upstream sbs_ours

Pair 2 - Multi-sub-mesh FEM rendering (trashbag_rope.glb)

Before (uniform single surface) After (per-sub-mesh GLB materials)
trashbag_before trashbag_after

Checklist:

  • I read the CONTRIBUTING document.
  • I followed the Submitting Code Changes section of CONTRIBUTING document.
  • I tagged the title correctly (including BUG FIX/FEATURE/MISC/BREAKING)
  • I updated the documentation accordingly or no change is needed.
  • I tested my changes and added instructions on how to test it for reviewers.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

ACMLCZH added 5 commits June 5, 2026 11:11
Introduce a `render_meshes` + `sim_vert_maps` model on FEMEntity so the
visualizer can draw the user's original input surface (multi-sub-mesh
GLBs supported) while the FEM solver retains its own tet-boundary
topology for physics.

Changes:
- FEMEntity.sample() builds `_render_meshes` (list[gs.Mesh]) and
  `_sim_vert_maps` (list[np.ndarray]) via `gs.Mesh.from_morph_surface`
  and a new `_merge_elements` helper that dedupes vertices across
  sub-meshes and remaps element indices.
- FEM solver drops the `surface_render_f` (triangle-indices) and
  `surface_render_uvs` (per-vertex UV) fields; rendering topology /
  UVs now live on FEMEntity's per-sub-mesh `Mesh` objects.
- `get_state_render(f)` returns sim vertex positions only.
- Rasterizer + raytracer iterate per-sub-mesh and key static nodes by
  `(env_idx, entity.uid, sub_idx)`.
- `mesh_to_elements` signature change: accepts a trimesh directly,
  returns (verts, elems) only (UVs come from the input render mesh).
- `gs.Mesh.from_morph_surface` returns a list for primitive morphs
  too — uniform return type makes consumers simpler.
- `test_interior_tetrahedralized_vertex` updated to assert the new
  invariant: viz vertices = sim_verts[sim_vert_maps[0]].
Comment thread genesis/ext/pyrender/shaders/mesh_normal.vert
Comment thread genesis/utils/element.py
Comment thread tests/test_fem.py Outdated
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown

⚠️ Abnormal Benchmark Result Detected ➡️ Report

@ACMLCZH
ACMLCZH marked this pull request as ready for review June 9, 2026 00:48
@ACMLCZH
ACMLCZH requested a review from YilingQiao as a code owner June 9, 2026 00:48

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 063d6bc580

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread genesis/ext/pyrender/renderer.py
ACMLCZH added 3 commits June 8, 2026 18:48
- FEM `morph.pos` now applied as float64 in `instantiate`; gs.np_float (float32)
  quantizes 0.4/-0.1/0.1 etc. and perturbs downstream coords enough to push
  the macOS `linear_corotated` falling-sphere rest-state assertion over its
  tolerance.
- `_merge_elements` no longer downcasts merged verts to gs.np_float; tetgen
  is sensitive to vertex coord precision and the downcast-then-upcast loses
  ULPs vs the upstream float64 path.
- `split_all_surface_tets` is now applied only to file-loaded `Mesh` morphs
  (matching upstream); calling it for `Sphere`/`Box`/`Cylinder` primitives
  changed tet topology vs upstream.
- Viewer's normal-pass `CustomShaderCache` strips the `DOUBLE_SIDED` define
  before compiling. Without the matching geometry shader, `mesh_normal.vert`
  emits `v_frag_*` while `mesh_normal.frag` expects `frag_*`, breaking shader
  linking on GUI normal captures of double-sided primitives.
The previous fix (commit 14e6d7c) only changed the float32→float64 dtype
of `p` in `instantiate`, but left tetgen seeing the centered (un-translated)
mesh. Tetgen's Steiner-point insertion is sensitive to absolute coords:

- Centered sphere → 960 verts / 3726 elems
- Sphere translated to (0.4, -0.1, 0.1) → 968 verts / 3784 elems  ← upstream

The mesh-count delta cascaded through the implicit FEM integrator on macOS
and pushed `test_implicit_falling_sphere_box[SAP-linear_corotated-64]`'s
0.025 rest-state tolerance over by ~12% (90/2973 vertices violating).

Apply pos to the merged surface verts in `sample` (before tetgen runs), and
remove the duplicate translation from `instantiate`. The tet mesh now matches
upstream's `sphere_to_elements` / `box_to_elements` output byte-for-byte.
@ACMLCZH
ACMLCZH requested a review from duburcqa June 9, 2026 06:50
# Conflicts:
#	genesis/engine/entities/fem_entity.py
#	genesis/vis/rasterizer_context.py
#	tests/rendering/test_offscreen.py
#	tests/utils.py
@duburcqa duburcqa changed the title [FEATURE] Decouple FEM render geometry from sim geometry (multi-sub-mesh + double-sided normal pass) [FEATURE] Decouple FEM render geometry from simulation geometry Jul 20, 2026
@duburcqa

duburcqa commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Superseded by #3079. Successive review and CI rounds (per-visual-geom API aligned with the rigid entity, vertex welding pipeline, solver-side render state, normal-pass shader cache, snapshot and test rework) rewrote more than half of the original diff - less than half of the final added lines remain from this branch - so the consolidated version moves to a new PR with authorship reflecting that split. The original commits are preserved on this branch and the new commit credits you via Co-authored-by.

@duburcqa duburcqa closed this Jul 20, 2026
@duburcqa

Copy link
Copy Markdown
Collaborator

Reopening: reassessed against the design rather than the diff line count. The consolidated version keeps this PR's architecture, welding algorithm, shaders and validation approach unchanged; the rewrites are repo conventions and API surface. Authorship stays here, and #3079 is closed.

@duburcqa duburcqa reopened this Jul 20, 2026
@duburcqa

Copy link
Copy Markdown
Collaborator

@codex review

@duburcqa
duburcqa force-pushed the pr/fem-render-meshes branch from b733601 to ea076ed Compare July 20, 2026 12:01

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b733601c24

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread genesis/engine/materials/FEM/base.py Outdated
@duburcqa duburcqa changed the title [FEATURE] Decouple FEM render geometry from simulation geometry [FEATURE] Decouple FEM render geometry from simulation geometry. Jul 20, 2026
duburcqa
duburcqa previously approved these changes Jul 20, 2026
@duburcqa

Copy link
Copy Markdown
Collaborator

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: 45dfcc1b52

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@duburcqa duburcqa changed the title [FEATURE] Decouple FEM render geometry from simulation geometry. [FEATURE] Decouple FEM render geometry from physics geometry. Jul 20, 2026
@duburcqa duburcqa changed the title [FEATURE] Decouple FEM render geometry from physics geometry. [FEATURE] Decouple FEM visual geometry from physics geometry. Jul 20, 2026
@duburcqa duburcqa changed the title [FEATURE] Decouple FEM visual geometry from physics geometry. [FEATURE] Decouple visual from physics geometry for FEM entities. Jul 20, 2026
@duburcqa
duburcqa merged commit ecf7ce4 into Genesis-Embodied-AI:main Jul 20, 2026
21 of 22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants