Skip to content

Deformable shadow model sync to support ovphysx + ovrtx/newton_warp combinations - #6773

Merged
kellyguo11 merged 37 commits into
isaac-sim:developfrom
huidongc:shadow-model-for-deformable-scene-data
Aug 1, 2026
Merged

Deformable shadow model sync to support ovphysx + ovrtx/newton_warp combinations#6773
kellyguo11 merged 37 commits into
isaac-sim:developfrom
huidongc:shadow-model-for-deformable-scene-data

Conversation

@huidongc

@huidongc huidongc commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Description

Context

When PhysX / OVPhysX simulates and Newton Warp / OVRTX renders:

Role Who owns it What it looks like
Simulation PhysX / OVPhysX SceneData get_points Soft-body nodal positions (tet nodes for volumes; surface verts for cloth)
Visualization Newton shadow particle_q and/or USD visual Mesh.points Authored visual triangle mesh

Issues before this PR

  1. Warp “tet spaghetti” — shadow model built from sim tet topology + live sim nodes → renderer draws tet surfaces, not the visual cuboid/cloth. See Before vs. After section.
  2. OVRTX static rest pose — live sync broken → clean visual mesh but no motion/deformation. See Before vs. After section.

Design goal

Keep SceneData sim-true (nodal counts from physics), while consumers that render the authored mesh see vis-sized positions every frame — shared between Warp and OVRTX.

Architecture

Schema hierarchy on the USD stage

Spawners (define_deformable_body_properties) and pre-authored USD share the same OmniPhysics layout.
OmniPhysicsDeformableBodyAPI marks the body root; sim/vis meshes carry the sim and pose APIs.

Root Xform / Mesh
  OmniPhysicsDeformableBodyAPI          ← body identity (discovery key)
  │
  ├── SimulationMesh  (TetMesh volume | Mesh surface; purpose=guide)
  │     OmniPhysicsVolumeDeformableSimAPI  or  OmniPhysicsSurfaceDeformableSimAPI
  │     UsdPhysics.CollisionAPI             ← collider usually = sim mesh
  │     OmniPhysicsDeformablePoseAPI:default
  │       purposes = ["bindPose"]           ← register pose for embedding
  │
  └── VisualMesh  (UsdGeom.Mesh; often different vertex count)
        OmniPhysicsDeformablePoseAPI:default
          purposes = ["bindPose"]
          points   = authored vis rest verts  ← skin/embed to sim via bindPose
Schema Where Role
OmniPhysicsDeformableBodyAPI body root Marks the deformable; subtree deforms with it
OmniPhysics*DeformableSimAPI sim mesh FEA topology / rest shape (volume tet or surface tri)
UsdPhysics.CollisionAPI sim mesh (typical) Collision participation
OmniPhysicsDeformablePoseAPI sim and vis meshes Multiple-apply bind pose so vis/collision can differ from sim

Optional third child (collision ≠ sim) also gets CollisionAPI + DeformablePoseAPI:bindPose. Isaac Lab spawners usually collide on the sim mesh.

Pipeline (spawn → render)

┌──────────────────────────────────────────────────────────────────────────┐
│ Spawners (meshes / from_files) — asset authoring                         │
│  create visual Mesh, then define_deformable_body_properties()            │
│  → applies schema hierarchy above (Body / Sim / Pose / Collision)        │
│  → authors sim TetMesh/Mesh (+ keeps sibling vis Mesh)                   │
│  (pre-authored USD may already have this setup and skip spawners)        │
└───────────────────────────────┬──────────────────────────────────────────┘
                                |
                                |
                                |
                                ▼
┌──────────────────────────────────────────────────────────────────────────┐
│ USD stage (see schema hierarchy above)                                   │
│  BodyAPI root → sim TetMesh/Mesh + vis sibling Mesh (V counts may differ)│
└───────────────────────────────┬──────────────────────────────────────────┘
                                |
                                |
─────────────────────────────── │ ─ UNCHANGED above (authoring prerequisite) ─
                                |
                                │
                                │ discover_deformables_on_stage()
                                │ called by PhysxManager / OvPhysxManager /
                                │ NewtonManager
                                │
              ┌─────────────────┴─────────────────┐
              ▼                                   ▼
┌─────────────────────────────┐   ┌──────────────────────────────────────────┐
│ PhysxManager /              │   │ NewtonManager                            │
│ OvPhysxManager              │   │  visualization_builder                   │
│  DeformableStageEntry →     │   │    → add_shadow_deformables_to_builder   │
│  SceneDataBackend points    │   │    • volume + count mismatch →           │
│  (sim-sized nodal export)   │──▶│      VolumeVisRemap + add_cloth_mesh     │
│                             │   │    • volume 1:1 → add_soft_mesh          │
│                             │   │    • surface → add_cloth_mesh            │
│                             │   │  ShadowDeformableEntity (sim+vis slots)  │
│                             │   │  _sim_particle_q ← SceneData (sim-sized) │
│                             │   │  particle_q ← remapped/copied (vis-sized)│
└─────────────────────────────┘   └───────────┬──────────────┬───────────────┘
                                              │              │
                                              ▼              ▼
                                   Newton Warp renderer   OVRTX (USD vis
                                   reads shadow           Mesh.points ←
                                   particle_q             particle_q slices)

One-sentence summary: managers discover sim/vis meshes; shadow build allocates dual particle layouts and (for volumes) a barycentric table; each frame PhysX/OVPhysX SceneData fills sim slots and a Warp kernel fills vis slots for renderers.

Type of change

  • New feature (non-breaking change which adds functionality)
  • Documentation update

Before vs. After

Rendering

Before After
“tet spaghetti” image ovphysx-newton_renderer-rgb
Rendering Sync franka_cloth-ovphysx-ovrtx_renderer-rgb-before franka_cloth-ovphysx-ovrtx_renderer-rgb-after

Total startup (s)

(128 envs, 100 steps)

Task Physics Renderer Before After Δ %
Isaac-Lift-Cloth-Franka-Camera ovphysx ovrtx 81.4 93.0 +14%
Isaac-Lift-Cloth-Franka-Camera ovphysx newton_renderer 75.0 90.6 +21%
Isaac-Lift-Soft-Franka-Camera ovphysx ovrtx 77.0 81.4 +6%
Isaac-Lift-Soft-Franka-Camera ovphysx newton_renderer 70.0 77.5 +11%

Mean Total FPS

(128 envs, 100 steps)

Task Physics Renderer Before After Δ %
Isaac-Lift-Cloth-Franka-Camera ovphysx ovrtx 1841 1574 −15%
Isaac-Lift-Cloth-Franka-Camera ovphysx newton_renderer 5072 4575 −10%
Isaac-Lift-Soft-Franka-Camera ovphysx ovrtx 1907 1601 −16%
Isaac-Lift-Soft-Franka-Camera ovphysx newton_renderer 5766 5729 −1%

Checklist

  • I have read and understood the contribution guidelines
  • I have run the pre-commit checks with ./isaaclab.sh --format
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • I have added a changelog fragment under source/<pkg>/changelog.d/ for every touched package (do not edit CHANGELOG.rst or bump extension.toml — CI handles that)
  • I have added my name to the CONTRIBUTORS.md or my name already exists there

@huidongc
huidongc requested a review from a team July 29, 2026 03:39
@github-actions github-actions Bot added documentation Improvements or additions to documentation isaac-lab Related to Isaac Lab team labels Jul 29, 2026
@huidongc
huidongc marked this pull request as draft July 29, 2026 03:39
Comment thread source/isaaclab_newton/isaaclab_newton/physics/visualization_builder.py Outdated
Comment thread source/isaaclab/isaaclab/scene_data/deformable_discovery.py Outdated
Comment thread source/isaaclab_tasks/test/rendering_test_utils.py Outdated
@greptile-apps

greptile-apps Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds deformable scene-data synchronization into shadow Newton models and addresses the previously reported discovery, registry, and rendering-validation gaps.

  • Adds PhysX and OVPhysX deformable point backends, geometry mapping, and per-frame shadow-particle synchronization.
  • Adds deformable USD discovery, visual-mesh selection, and barycentric simulation-to-visual remapping.
  • Populates OVRTX deformable registry metadata for cloned and standalone scenes.
  • Restores Franka cloth and soft-body golden-image validation and adds corresponding fixtures.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains in the reviewed fixes, and the previously reported standalone metadata, registry path, sibling discovery, visual selection, and golden-validation issues are addressed by the current code and focused tests.

Important Files Changed

Filename Overview
source/isaaclab/isaaclab/scene_data/deformable_discovery.py Discovers deformable simulation and visual meshes, including direct siblings, and deterministically ranks multiple visual candidates.
source/isaaclab/isaaclab/scene_data/deformable_vis_remap.py Builds and executes barycentric mappings from volume simulation nodes to visual-mesh vertices.
source/isaaclab/isaaclab/scene_data/scene_data_provider.py Adds geometry path mapping and bounded point-copy support to the central scene-data provider.
source/isaaclab_newton/isaaclab_newton/physics/visualization_builder.py Builds shadow visualization models with deformable metadata in cloned and standalone scenes.
source/isaaclab_newton/isaaclab_newton/physics/visualization_deformables.py Creates shadow deformable render slots and registry paths while preserving exact standalone paths.
source/isaaclab_newton/isaaclab_newton/physics/newton_manager.py Synchronizes backend nodal positions into shadow Newton particle state and applies volume visual remaps.
source/isaaclab_tasks/test/rendering_test_utils.py Restores direct golden-image validation for Franka cloth and soft-body rendering tests.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    USD[USD deformable geometry] --> Discovery[Deformable discovery]
    PhysX[PhysX / OVPhysX nodal tensors] --> Backend[SceneDataBackend points]
    Backend --> Provider[SceneDataProvider geometry mapping]
    Discovery --> Shadow[Shadow Newton model and registry]
    Provider --> SimBuffer[Simulation-sized particle buffer]
    SimBuffer -->|direct copy| RenderBuffer[Newton particle_q render slots]
    SimBuffer -->|barycentric remap| RenderBuffer
    Shadow --> RenderBuffer
    RenderBuffer --> Consumers[Newton Warp and OVRTX renderers]
Loading

Reviews (4): Last reviewed commit: "Document shadow deformable and SceneData..." | Re-trigger Greptile

@huidongc

Copy link
Copy Markdown
Collaborator Author

@greptile-apps

Comment thread source/isaaclab_newton/isaaclab_newton/physics/visualization_deformables.py Outdated
Comment thread source/isaaclab/isaaclab/scene_data/deformable_discovery.py Outdated
@huidongc

Copy link
Copy Markdown
Collaborator Author

@greptile-apps

@huidongc
huidongc force-pushed the shadow-model-for-deformable-scene-data branch from 4578d98 to 666a1ab Compare July 30, 2026 12:24
@huidongc

Copy link
Copy Markdown
Collaborator Author

@greptile-apps

@huidongc
huidongc requested a review from daniela-hase July 30, 2026 12:29
@huidongc
huidongc marked this pull request as ready for review July 30, 2026 12:29
@huidongc huidongc changed the title Shadow model for deformable scene data Deformable shadow model sync to support ovphysx + ovrtx/newton_warp combinations Jul 30, 2026

@isaaclab-review-bot isaaclab-review-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Isaac Lab Review Bot

The deformable SceneData and Newton shadow-model integration is well structured, but concrete correctness and lifecycle issues remain: shadow particle offsets can target the wrong slots when the builder already contains particles, deformable-only OVPhysX scenes skip binding setup, the changelog gives impossible migration guidance, and teardown retains the simulation particle buffer.

  • Design and architecture: The backend/provider/shadow-builder split is coherent. However, shadow deformables must account for particles already present in the Newton builder; using a separate zero-based render cursor breaks synchronization for builders containing pre-existing particle data.
  • API: The new SceneData properties and methods are additive with safe backend defaults. The Newton changelog incorrectly tells callers of update_visualization_state to pass allow_passthrough=True even though that method has no such parameter, so the migration guidance must be corrected.
  • Implementation: OVPhysX deformable setup is currently bypassed when no rigid-body patterns are found, preventing deformable-only scenes from exporting points. Shadow render offsets ignore existing builder particles, and NewtonManager.clear() does not release the newly added _sim_particle_q device buffer.

Significant concerns. Posted 4 actionable findings inline.

Conservative automated review; human maintainers own approval decisions.

Comment thread source/isaaclab_newton/isaaclab_newton/physics/visualization_deformables.py Outdated
Comment thread source/isaaclab_ovphysx/isaaclab_ovphysx/physics/ovphysx_manager.py
Comment thread source/isaaclab_newton/changelog.d/huidongc-shadow-deformable-sync.rst Outdated
Comment thread source/isaaclab_newton/isaaclab_newton/physics/newton_manager.py
@huidongc

Copy link
Copy Markdown
Collaborator Author

@isaaclab-review-bot review

@isaaclab-review-bot isaaclab-review-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Isaac Lab Review Bot

The dual sim/render particle layout is coherent, but two concrete issues remain: failed volume remaps can trigger an invalid direct copy, and new public Warp interfaces lack the required concrete dtype annotations.

  • Design and architecture: The shared discovery and dual-buffer design is sound. However, mismatched volume meshes need an explicit safe fallback when barycentric remap construction fails.
  • API: The additive SceneData geometry API is compatible, but VolumeVisRemap and launch_volume_vis_remap use generic wp.array annotations instead of the concrete Warp dtypes required for public interfaces.
  • Implementation: When a mismatched volume remap is unavailable, the render sync copies vis_particle_count values directly from the sim slice. This can cross entity or buffer bounds and does not provide a valid sim-to-visual mapping; the fallback must skip the copy or use compatible sim topology.

Minor fixes needed. Posted 2 actionable findings inline.

Conservative automated review; human maintainers own approval decisions.

Comment thread source/isaaclab_newton/isaaclab_newton/physics/newton_manager.py Outdated
Comment thread source/isaaclab/isaaclab/scene_data/deformable_vis_remap.py Outdated
@huidongc

Copy link
Copy Markdown
Collaborator Author

@isaaclab-review-bot review

@isaaclab-review-bot isaaclab-review-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Isaac Lab Review Bot

The sim-sized SceneData to vis-sized shadow-render design is reasonable, but three concrete correctness issues remain: unresolved geometry mappings collapse deformables to zero, non-environment deformables are imported twice in clone-plan scenes, and shadow mesh placement applies the deformable root transform twice.

  • Design and architecture: The clone-plan builder path imports deformables outside /World/envs through the top-level USD import and then adds them again through the shadow-deformable path, producing duplicate particle allocations and invalid offsets.
  • API: The additive SceneData point and geometry APIs are documented and retain safe backend defaults. However, geometry mapping uses exact path equality while backends may expose related child paths; unresolved mappings are not propagated to the subsequent render sync, causing skipped source slices to be treated as valid zero data.
  • Implementation: Unmapped deformables have zero-initialized sim slices copied into render slots, collapsing their meshes to the origin. In addition, discovered vertices are baked into the deformable root's parent frame but are instantiated using the root pose, double-applying non-identity root transforms.

Significant concerns. Posted 3 actionable findings inline.

Conservative automated review; human maintainers own approval decisions.

Comment thread source/isaaclab_newton/isaaclab_newton/physics/newton_manager.py Outdated
Comment thread source/isaaclab_newton/isaaclab_newton/physics/visualization_builder.py Outdated
Comment thread source/isaaclab_newton/isaaclab_newton/physics/visualization_deformables.py Outdated
@huidongc

Copy link
Copy Markdown
Collaborator Author

@isaaclab-review-bot review

@huidongc
huidongc force-pushed the shadow-model-for-deformable-scene-data branch from 35e6368 to 3058c8e Compare July 30, 2026 14:31
@huidongc

Copy link
Copy Markdown
Collaborator Author

@isaaclab-review-bot review

huidongc added 15 commits August 1, 2026 08:53
Avoid rebuilding the host-side offset set via mapping.numpy() on every
update_visualization_state call. Compute it when the geometry mapping is
created, and clear the offset cache whenever that mapping is rebuilt.
Share volume remaps across env clones, build barycentric tables on
GPU with Warp, cache stage discovery with numpy-baked verts, and
replace per-frame host scatter/copy loops with batched device
kernels (SceneData, PhysX/OVPhysX merge, Newton sync).
Usd.Stage is always weak-referenceable, so drop the TypeError guard
and write the discovery cache directly.
Drop redundant discovery/remap/builder cases and the destination-clamp
geometry test that no longer matches the device scatter path, and fold
the standalone registry-path check into the clone builder coverage.
These tests use SimpleNamespace stage stubs and only cover rigid-body
binding setup, so mock discover_deformables_on_stage to avoid the
weakref cache path meant for real USD stages.
Drop unused NewtonSceneDataBackend point/geometry overrides and
ShadowDeformableEntity compatibility aliases introduced in this PR.
Deduplicate visualization-state fixtures and keep only high-value
coverage of PhysX/OVPhysX shadow sync and builder paths.
Replace the RelativeJointPositionActionCfg workaround with a small absolute
EE pose nudge so motion_vectors goldens use the default DiffIK action path
again. Refresh the isaaclab_tasks skip changelog fragment for this PR.
Drop the test-only file materialization and env0 export wrappers from
OvPhysxManager. Point unit tests at the in-memory _serialize_selected_stage
path used by production warmup.
Treat create_geometry_mapping's None identity result as a valid cached
value via an explicit ready flag, so mapped-offset and batch metadata are
not rebuilt every frame for the common identity layout.
Require a separate visual Mesh prim before barycentric remapping instead
of comparing vertex counts, so equal-count but non-identical visuals still
drive cloth slots for Newton Warp and OVRTX.
Caching create_geometry_mapping's None identity result skipped the
per-frame mapped-offset and batch-sync refresh that soft-body viz
depends on, causing stretched or missing deformables in Franka soft
rendering tests.
Use USD row-vector convention when baking discovered verts, clamp
scatter copies to each destination slot so backend/shadow count
mismatches cannot overwrite the next env, and invalidate discovery
cache before PhysX/OVPhysX/shadow walks so cooked tet counts stay
aligned.
Drop the process-global WeakKeyDictionary memo and invalidate helpers.
Reuse discovery results via entries= instead; setup cost is unchanged.
@huidongc
huidongc force-pushed the shadow-model-for-deformable-scene-data branch from fb7a5f5 to b6c6918 Compare August 1, 2026 00:55
@huidongc

huidongc commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator Author

@isaaclab-review-bot review

@isaaclab-review-bot isaaclab-review-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Isaac Lab Review Bot

The SceneData geometry contract and dual sim/visual shadow-particle design provide a coherent path for PhysX/OVPhysX deformables to drive Newton Warp and OVRTX. Before merge, the per-frame sync metadata churn should be removed, and wildcard-grouped deformables must not share barycentric remaps unless their topology is verified compatible.

  • Design and architecture: Keeping SceneData simulation-true while the Newton shadow model owns visualization-sized render slots is a sound separation. However, grouping deformables solely by environment-wildcard paths assumes matching simulation and visual topology across environments; heterogeneous entries can consequently reuse incompatible remap tables and particle counts. Grouping must include topology characteristics or retain per-entry remaps.
  • API: The additive SceneData points, geometry-path, and geometry-count interfaces have safe backend defaults and corresponding documentation and changelog coverage. The accepted concerns are internal implementation and grouping behavior rather than the public SceneData contract.
  • Implementation: The discovery-to-render path correctly separates simulation and visualization buffers, but its hot path has avoidable costs: geometry scatter performs host synchronization, repeated metadata uploads, and a quadratic destination scan each frame, while identity mappings invalidate and rebuild batched remap/copy metadata every frame. Additionally, sharing a template remap across wildcard-grouped entries can produce invalid barycentric and tet indexing when their topologies differ.

Significant concerns. Posted 3 actionable findings inline.

Automated review; human maintainers own approval decisions.

continue
# Space until the next destination slot (or end of buffer), not merely dest_size.
next_dest = dest_size
for offset in positive_dests:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Warning · Implementation — Per-frame host scan in points scatter

get_points calls this on every render frame, and each call performs mapping.numpy() (a device sync), a linear scan of positive_dests per entity (quadratic in deformable body count, i.e. envs × assets), and three fresh Warp uploads. Precompute the source/destination offset and count device arrays once and rebuild only when entity_counts or the mapping change; use bisect over the sorted offsets.


# Invalidate the mapped-offset cache so that it can be rebuilt immediately after.
cls._mapped_sim_particle_offsets = None
cls._invalidate_shadow_deformable_batch_sync()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Warning · Implementation — Batch sync cache invalidated on identity mappings

Identity layouts make create_geometry_mapping return None, so _scene_data_geometry_mapping stays None and this block re-runs every render frame, calling _invalidate_shadow_deformable_batch_sync(). _ensure_shadow_deformable_batch_sync then rebuilds per-particle Python id lists and several Warp arrays every frame, defeating the sync_key cache it was added for. The sync_key comparison already detects real layout changes, so drop the unconditional invalidation here.

register_usd_vis_point_bindings=uses_remap or template.sim_mesh_path == template.vis_mesh_path,
)

group_volume_vis_remap = _build_volume_vis_remap(template, device) if uses_remap else None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Warning · Implementation — Shared remap assumes identical group topology

Wildcard groups are keyed only on env-rewritten root/sim/vis paths, then every member reuses the template's remap and entities[0].vis_particle_count. If two environments share prim names but differ in tet or visual vertex counts (heterogeneous multi-asset spawning), the batch kernel indexes bary_weights[local_vis] beyond the template rows and applies template tet indices to a different sim slice. Include per-entry vertex counts in the grouping key, or build a remap per entry.

@daniela-hase daniela-hase left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The Newton and Scene Data Provider changes seem good to me :)

@kellyguo11
kellyguo11 merged commit 9f28e8e into isaac-sim:develop Aug 1, 2026
46 of 48 checks passed
@huidongc
huidongc deleted the shadow-model-for-deformable-scene-data branch August 1, 2026 04:14
matthewtrepte pushed a commit to matthewtrepte/IsaacLab that referenced this pull request Aug 4, 2026
…ombinations (isaac-sim#6773)

# Description

## Context

When **PhysX / OVPhysX** simulates and **Newton Warp / OVRTX** renders:

| Role | Who owns it | What it looks like |
|------|-------------|--------------------|
| Simulation | PhysX / OVPhysX SceneData `get_points` | Soft-body
**nodal** positions (tet nodes for volumes; surface verts for cloth) |
| Visualization | Newton shadow `particle_q` and/or USD visual
`Mesh.points` | Authored **visual** triangle mesh |

### Issues before this PR

1. **Warp “tet spaghetti”** — shadow model built from sim tet topology +
live sim nodes → renderer draws tet surfaces, not the visual
cuboid/cloth. See Before vs. After section.
2. **OVRTX static rest pose** — live sync broken → clean visual mesh but
no motion/deformation. See Before vs. After section.

## Design goal

Keep SceneData **sim-true** (nodal counts from physics), while consumers
that render the authored mesh see **vis-sized** positions every frame —
shared between Warp and OVRTX.

## Architecture

### Schema hierarchy on the USD stage

Spawners (`define_deformable_body_properties`) and pre-authored USD
share the same OmniPhysics layout.
`OmniPhysicsDeformableBodyAPI` marks the **body root**; sim/vis meshes
carry the **sim** and **pose** APIs.

```
Root Xform / Mesh
  OmniPhysicsDeformableBodyAPI          ← body identity (discovery key)
  │
  ├── SimulationMesh  (TetMesh volume | Mesh surface; purpose=guide)
  │     OmniPhysicsVolumeDeformableSimAPI  or  OmniPhysicsSurfaceDeformableSimAPI
  │     UsdPhysics.CollisionAPI             ← collider usually = sim mesh
  │     OmniPhysicsDeformablePoseAPI:default
  │       purposes = ["bindPose"]           ← register pose for embedding
  │
  └── VisualMesh  (UsdGeom.Mesh; often different vertex count)
        OmniPhysicsDeformablePoseAPI:default
          purposes = ["bindPose"]
          points   = authored vis rest verts  ← skin/embed to sim via bindPose
```

| Schema | Where | Role |
|--------|-------|------|
| `OmniPhysicsDeformableBodyAPI` | body root | Marks the deformable;
subtree deforms with it |
| `OmniPhysics*DeformableSimAPI` | sim mesh | FEA topology / rest shape
(volume tet or surface tri) |
| `UsdPhysics.CollisionAPI` | sim mesh (typical) | Collision
participation |
| `OmniPhysicsDeformablePoseAPI` | sim **and** vis meshes |
Multiple-apply bind pose so vis/collision can differ from sim |

Optional third child (collision ≠ sim) also gets `CollisionAPI` +
`DeformablePoseAPI:bindPose`. Isaac Lab spawners usually collide on the
sim mesh.

### Pipeline (spawn → render)

```
┌──────────────────────────────────────────────────────────────────────────┐
│ Spawners (meshes / from_files) — asset authoring                         │
│  create visual Mesh, then define_deformable_body_properties()            │
│  → applies schema hierarchy above (Body / Sim / Pose / Collision)        │
│  → authors sim TetMesh/Mesh (+ keeps sibling vis Mesh)                   │
│  (pre-authored USD may already have this setup and skip spawners)        │
└───────────────────────────────┬──────────────────────────────────────────┘
                                |
                                |
                                |
                                ▼
┌──────────────────────────────────────────────────────────────────────────┐
│ USD stage (see schema hierarchy above)                                   │
│  BodyAPI root → sim TetMesh/Mesh + vis sibling Mesh (V counts may differ)│
└───────────────────────────────┬──────────────────────────────────────────┘
                                |
                                |
─────────────────────────────── │ ─ UNCHANGED above (authoring prerequisite) ─
                                |
                                │
                                │ discover_deformables_on_stage()
                                │ called by PhysxManager / OvPhysxManager /
                                │ NewtonManager
                                │
              ┌─────────────────┴─────────────────┐
              ▼                                   ▼
┌─────────────────────────────┐   ┌──────────────────────────────────────────┐
│ PhysxManager /              │   │ NewtonManager                            │
│ OvPhysxManager              │   │  visualization_builder                   │
│  DeformableStageEntry →     │   │    → add_shadow_deformables_to_builder   │
│  SceneDataBackend points    │   │    • volume + count mismatch →           │
│  (sim-sized nodal export)   │──▶│      VolumeVisRemap + add_cloth_mesh     │
│                             │   │    • volume 1:1 → add_soft_mesh          │
│                             │   │    • surface → add_cloth_mesh            │
│                             │   │  ShadowDeformableEntity (sim+vis slots)  │
│                             │   │  _sim_particle_q ← SceneData (sim-sized) │
│                             │   │  particle_q ← remapped/copied (vis-sized)│
└─────────────────────────────┘   └───────────┬──────────────┬───────────────┘
                                              │              │
                                              ▼              ▼
                                   Newton Warp renderer   OVRTX (USD vis
                                   reads shadow           Mesh.points ←
                                   particle_q             particle_q slices)
```

**One-sentence summary:** managers discover sim/vis meshes; shadow build
allocates dual particle layouts and (for volumes) a barycentric table;
each frame PhysX/OVPhysX SceneData fills sim slots and a Warp kernel
fills vis slots for renderers.

## Type of change

- New feature (non-breaking change which adds functionality)
- Documentation update

## Before vs. After

### Rendering

| | Before | After |
| -- | ------ | ----- |
| “tet spaghetti” | <img width="262" height="262" alt="image"
src="https://github.com/user-attachments/assets/3fcb22f2-076f-42ae-b3a4-3c2926ff41f8"
/> | <img width="262" height="262" alt="ovphysx-newton_renderer-rgb"
src="https://github.com/user-attachments/assets/82c6a44e-6a04-4a99-8f42-e42d3a7125da"
/> |
| Rendering Sync | <img width="262" height="262"
alt="franka_cloth-ovphysx-ovrtx_renderer-rgb-before"
src="https://github.com/user-attachments/assets/2148b565-66b7-4ba2-a1ed-4ce1d65a216b"
/> | <img width="262" height="262"
alt="franka_cloth-ovphysx-ovrtx_renderer-rgb-after"
src="https://github.com/user-attachments/assets/f00ba2b5-9bb8-4333-92d5-cc44ffb395e4"
/> |

### Total startup (s)

(128 envs, 100 steps)

| Task | Physics | Renderer | Before | After | Δ % |
| :----------------------------- | :------ | :-------------- | -----: |
----: | ---: |
| Isaac-Lift-Cloth-Franka-Camera | ovphysx | ovrtx | 81.4 | 93.0 | +14%
|
| Isaac-Lift-Cloth-Franka-Camera | ovphysx | newton_renderer | 75.0 |
90.6 | +21% |
| Isaac-Lift-Soft-Franka-Camera | ovphysx | ovrtx | 77.0 | 81.4 | +6% |
| Isaac-Lift-Soft-Franka-Camera | ovphysx | newton_renderer | 70.0 |
77.5 | +11% |

### Mean Total FPS

(128 envs, 100 steps)

| Task | Physics | Renderer | Before | After | Δ % |
| :----------------------------- | :------ | :-------------- | -----: |
----: | ---: |
| Isaac-Lift-Cloth-Franka-Camera | ovphysx | ovrtx | 1841 | 1574 | −15%
|
| Isaac-Lift-Cloth-Franka-Camera | ovphysx | newton_renderer | 5072 |
4575 | −10% |
| Isaac-Lift-Soft-Franka-Camera | ovphysx | ovrtx | 1907 | 1601 | −16% |
| Isaac-Lift-Soft-Franka-Camera | ovphysx | newton_renderer | 5766 |
5729 | −1% |


## Checklist

- [x] I have read and understood the [contribution
guidelines](https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html)
- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`./isaaclab.sh --format`
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] I have added a changelog fragment under
`source/<pkg>/changelog.d/` for every touched package (do **not** edit
`CHANGELOG.rst` or bump `extension.toml` — CI handles that)
- [x] I have added my name to the `CONTRIBUTORS.md` or my name already
exists there
kellyguo11 pushed a commit that referenced this pull request Sep 4, 2026
# Description

Revives #6308 on current `develop` and supersedes #3728 with a single
backend-neutral contract for kinematic rigid-object rendering.

## Architecture

`source/isaaclab/test/renderers/rigid_object_rendering_contract.py` is
the composition root. It owns the cloned scene, kinematic pose sequence,
depth measurements, and assertions. Package-local adapters own only
availability checks, simulation/renderer selection, and backend cleanup:

- Isaac RTX + PhysX on CPU and CUDA, with and without a coexisting
articulation;
- Newton Warp + PhysX on CUDA;
- OVRTX + OVPhysX on CUDA through both legacy and OVStage scene
ownership (OVStage runs when installed).

The dependency direction is adapter -> shared test contract -> public
Isaac Lab APIs. An AST architecture gate rejects backend imports in the
shared contract and rejects scene, asset, sensor, or class ownership in
adapters.

The contract creates two cloned instanceable DexCubes with root-level
nonuniform scale, verifies their depth silhouettes, moves both kinematic
bodies through the public rigid-object tensor API, verifies the physics
poses, and requires opposite rendered centroid displacement.

## Current-develop audit

Most production changes in the old PR have since landed through newer
ownership boundaries: Isaac RTX render-product lifetime in #6729, Newton
shadow-state copying in #6773, OVRTX scale-aware transform writes in
#7010, and Newton Fabric scale preservation in #7481. This revival
removes those stale patches rather than carrying duplicate
implementations.

The revived contract exposed one remaining OVRTX bug: composed scale was
captured only for clone-plan source paths, while OVRTX creates
non-source destinations after exporting the host USD stage. Those
destinations therefore defaulted to unit scale. As a deliberately
temporary bridge, this PR projects only captured non-unit scales through
the existing `isaaclab.cloner.query.path_env_ids` and `path_to_clone`
boundary using the already-validated `ClonePlan`; real destination
scales take precedence. It adds no plan fields, query APIs, renderer
configuration, or per-body fallback, and the bridge can be deleted as
one unit when SDP supplies composed scale aligned with canonical
rigid-body paths.

Historical context: [Isaac Sim forum
report](https://forums.developer.nvidia.com/t/rigidbody-prim-is-not-updated-in-rendering-pipeline-if-set-to-kinematic/346608).

## Type of change

- Bug fix
- Shared regression coverage

## Testing

- Isaac RTX contract: 4 passed (CUDA/CPU x articulation absent/present).
- Newton Warp contract: 1 passed.
- OVRTX contract: 2 passed (legacy and OVStage).
- OVRTX renderer unit surface: 167 passed.
- Core architecture and Newton visualization suites: 25 passed.
- OVRTX clone-plan suite: 17 passed.
- Cloner query and rendering-contract architecture suites: 87 passed.
- Controlled OVRTX regression: failed before the production fix with
clone silhouettes of 264 vs. 36 pixels; passed after the fix.
- Incoming #7462 NumPy-backed `ClonePlan` query-boundary smoke check:
passed unchanged, including non-dense environment ids.
- `uv run isaaclab -f`: all hooks passed against the exact upstream
`develop` base, including changelog validation.

## Checklist

- [x] I have read and understood the contribution guidelines
- [x] I have run the pre-commit checks
- [x] Documentation changes are not applicable
- [x] I have added unit and integration regression coverage
- [x] I have added changelog fragments for every touched package
- [x] My name is already present in `CONTRIBUTORS.md`
kellyguo11 added a commit that referenced this pull request Sep 5, 2026
#7587)

# Description

Backports #6308 to `release/3.0.0`.

The canonical merged commit `ab34e8c5e3ee7a2c5f260d1511714e5be3bed3eb`
was cherry-picked with `-x` provenance. Eleven of its twelve source
paths replay exactly.
`source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py` required a
localized release-compatible conflict resolution, so this PR is
intentionally a draft for release-maintainer review.

| Field | Commit |
|---|---|
| Original merged change | `ab34e8c5e3ee7a2c5f260d1511714e5be3bed3eb` |
| Release base used | `1c754876008f0806fdcfda8e3a6b2f593b34d6fc` |
| Proposed backport | `740e3d7b2efe15c5a25f671583d29c034602e36f` |

## Conflict resolution

The release renderer already contains the prerequisite work from #6729,
#6773, #7010, and #7481, but differs from the source parent around
clone-plan handling and method documentation.

The resolution preserves the release branch's tensor-backed `ClonePlan`
validation and existing renderer structure, then adds only #6308's
semantic change:

- imports the existing `isaaclab.cloner.query` API;
- passes the validated release clone plan into `_capture_object_scales`;
- projects captured non-unit source scales to active clone destinations
with `path_env_ids` and `path_to_clone`;
- retains real destination scales via `setdefault`.

No paths outside the original PR are changed.

## Type of change

- Bug fix
- Shared regression coverage

## Validation

- Repository backport candidate validation passed across all 12 original
source paths.
- Per-file stable patch IDs match on 11 paths; only the
conflict-resolved renderer path differs.
- Shared rendering-contract architecture tests — 2 passed.
- Focused clone-query tests for `path_env_ids` and `path_to_clone` — 4
passed.
- Python compilation passed for all changed Python files.
- All changed-file pre-commit hooks passed, including changelog and Git
LFS checks.
- `git diff --check upstream/release/3.0.0...HEAD` passed.
- The focused OVRTX runtime test was retried with the documented `ov`
extra, but the release lock has no macOS/arm64 environment. Backend
rendering tests and the canonical `uv run isaaclab -f` remain pending
Linux CI.

## Checklist

- [x] I have read and understood the contribution guidelines
- [x] I have run the available pre-commit checks
- [x] Documentation changes are not applicable
- [x] The original unit and integration regression coverage is preserved
- [x] Changelog fragments are preserved for every touched package
- [x] The original contributor is already listed in `CONTRIBUTORS.md`

Co-authored-by: ooctipus <zhengyuz@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation isaac-lab Related to Isaac Lab team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants