Skip to content

Add whole-scene USD export and preview - #589

Merged
yuecideng merged 10 commits into
mainfrom
muzi/add_simple_usd
Sep 27, 2026
Merged

yuecideng merged 10 commits into
mainfrom
muzi/add_simple_usd

Conversation

@MuziWong

@MuziWong MuziWong commented Sep 5, 2026

Copy link
Copy Markdown
Collaborator

Description

This PR adds a portable whole-scene USD package alongside the existing editable
Scene Export output.

  • Generate scene_usd/scene.usda, a manifest, externally textured GLTF
    payloads, and articulated USDC payloads after both scene generation and scene
    editing.
  • Preserve final object poses, textures, GLB internal transforms, and
    articulated-object behavior through the package manifest.
  • Add embodichain preview-scene --output_root <path> --usd to preview the
    packaged scene; this also works with --viser and supported articulation
    joint controls.
  • Keep scene_export/ as the editable GLB/USDC source form, while
    scene_usd/ is the portable preview/delivery package.
  • Document the package layout and preview commands.

The native DexSim adapter deliberately loads packaged GLTF/USDC payloads
through the manifest because flattened USD mesh import does not currently
preserve GLB internal node transforms faithfully.

scene_usd.py is an internal Scene Engine adapter, not a public API module.

Dependencies: no new runtime dependencies.

No linked issue.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • Enhancement (non-breaking change which improves an existing functionality)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (existing functionality will not work without user modification)
  • Documentation update

Screenshots

N/A — CLI and simulation-preview change.

Validation

  • black --check --diff --color ./
  • Black formatting run; no formatting changes produced.
  • python docs/scripts/check_api_docs.py
    — 1680/1680 public exports documented.
  • python -m pytest tests/gen_sim/scene_engine/test_scene_core_and_export.py
    — 18 passed.

Checklist

  • I have run Black formatting for the code base.
  • I have made corresponding Scene Engine documentation changes.
  • Public API documentation coverage is aligned.
  • I have added and run focused tests for the Scene USD package and preview adapter.
  • No dependency updates are required.

@greptile-apps

greptile-apps Bot commented Sep 5, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 1/5

[Medium risk] Adds whole-scene USD export and preview loading.

The PR does not appear safe to merge while direct previews can misplace meshes, failed edits can retain an outdated delivery file, and logical USD entity IDs cannot reliably resolve runtime objects.

Fix All in CodexFindings

  1. P1 Direct USD preview misplaces meshes ▶
  2. P1 Failed rebuild leaves stale USDZ ▶
  3. P1 Logical UIDs do not resolve ▶
  4. P1 Security UID paths escape package roots ▶
Fix with agent prompt
### Issue 1
embodichain/gen_sim/scene_engine/pipeline/utils/scene_usd.py:355-360
For newly generated schema-v2 scenes, `--usd` and `--usd-file` now import the USD stage directly instead of loading the packaged GLTF/USDC assets. The existing compatibility path avoids direct import because DexSim cannot faithfully restore GLB internal node transforms from the flattened stage. Scenes with those transforms can therefore show misplaced meshes even though the package contains native assets that preserve their layout.

### Issue 2
embodichain/gen_sim/scene_engine/pipeline/utils/scene_usd.py:171-180
When an edit rewrites `scene_export/`, the rebuild does not remove the previous `scene.usdz`. If building the USD stage or packaging the new USDZ fails, the pipeline can warn that the optional export was skipped while leaving the old standalone file in place. Delivering or previewing that file then shows the scene from before the edit.

### Issue 3
embodichain/gen_sim/scene_engine/pipeline/utils/usd_scene.py:266-271
`scene_entity_cfg(uid)` returns the authored scene UID, but `add_usd()` registers imported objects under DexSim descriptor names without registering that UID as an alias. When an object's runtime name differs from its scene UID, the returned `SceneEntityCfg` cannot resolve the object through the simulation manager, breaking the promised stable-UID binding.

### Issue 4
embodichain/gen_sim/scene_engine/pipeline/utils/scene_usd.py:697-700
When editing or rebuilding a scene export whose accepted `uid` is absolute or contains parent-directory components, this code appends that value directly to the runtime-assets root and later the packaged-assets root, causing generated GLTF or USDC payloads to be written outside `scene_usd` and potentially overwrite another writable location. Validate or safely encode UIDs before using them as path components. **How this was verified:** The importer accepts any nonempty string as a UID, and the package builder uses that string directly as the destination path without a containment check.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

The PR adds whole-scene USDA/USDZ output, entity metadata and indexing, direct USD preview, and supporting documentation and tests.

  • Generated schema-v2 previews take a direct-import path that conflicts with the package's existing GLB-transform compatibility approach.
  • Rebuild failures can leave an outdated standalone USDZ, and logical UID bindings are not registered as runtime identities.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  E[Editable scene_export] --> B[Build scene.usda and metadata]
  B --> Z[Package scene.usdz]
  B --> M[Manifest and native assets]
  B --> D[Schema-v2 direct USD preview]
  M --> L[Legacy native-asset preview]
  Z --> F[Standalone --usd-file preview]
Loading

Reviews (4) · Last reviewed commit: "feat(gen-sim): preserve USD articulation..."

Comment on lines +515 to +518
runtime_assets[uid] = _externalize_glb_textures(
source_glb=source_glb,
destination_root=runtime_assets_root / uid,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 security UID paths escape package roots

When editing or rebuilding a scene export whose accepted uid is absolute or contains parent-directory components, this code appends that value directly to the runtime-assets root and later the packaged-assets root, causing generated GLTF or USDC payloads to be written outside scene_usd and potentially overwrite another writable location. Validate or safely encode UIDs before using them as path components. How this was verified: The importer accepts any nonempty string as a UID, and the package builder uses that string directly as the destination path without a containment check.

Knowledge Base Used:

Prompt To Fix With AI
This is a comment left during a code review.
Path: embodichain/gen_sim/scene_engine/pipeline/utils/scene_usd.py
Line: 515-518

Comment:
**UID paths escape package roots**

When editing or rebuilding a scene export whose accepted `uid` is absolute or contains parent-directory components, this code appends that value directly to the runtime-assets root and later the packaged-assets root, causing generated GLTF or USDC payloads to be written outside `scene_usd` and potentially overwrite another writable location. Validate or safely encode UIDs before using them as path components. **How this was verified:** The importer accepts any nonempty string as a UID, and the package builder uses that string directly as the destination path without a containment check.

**Knowledge Base Used:**
- [Generative simulation pipelines](https://app.greptile.com/dexforce/-/custom-context/knowledge-base/dexforce/embodichain/-/docs/generative-simulation.md)
- [Scene generation engine](https://app.greptile.com/dexforce/-/custom-context/knowledge-base/dexforce/embodichain/-/docs/scene-generation-engine.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex Fix in Claude Code

for managed_file in (scene_usd_path, manifest_path):
if managed_file.is_symlink():
managed_file.unlink()
_remove_path(scene_usd_root / "textures")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Rebuild can break existing package

When rebuilding an existing package, this removes its textures before the simulator is constructed. If construction fails, the old scene.usda and manifest remain, but their referenced textures are gone, so a previously usable package can no longer be previewed.

Prompt To Fix With AI
This is a comment left during a code review.
Path: embodichain/gen_sim/scene_engine/pipeline/utils/scene_usd.py
Line: 175

Comment:
**Rebuild can break existing package**

When rebuilding an existing package, this removes its textures before the simulator is constructed. If construction fails, the old `scene.usda` and manifest remain, but their referenced textures are gone, so a previously usable package can no longer be previewed.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex Fix in Claude Code

@greptile-apps

greptile-apps Bot commented Sep 26, 2026

Copy link
Copy Markdown

Want your agent to iterate on Greptile's feedback? Start a greploop in Codex and it will work through the open comments and keep going until this PR reviews clean.

Comment on lines +355 to +360
if usd_index.schema_version == USD_SCENE_SCHEMA:
return _load_embodichain_usd_stage(
sim=sim,
scene_usd_path=scene_usd_path,
index=usd_index,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Direct USD preview misplaces meshes

For newly generated schema-v2 scenes, --usd and --usd-file now import the USD stage directly instead of loading the packaged GLTF/USDC assets. The existing compatibility path avoids direct import because DexSim cannot faithfully restore GLB internal node transforms from the flattened stage. Scenes with those transforms can therefore show misplaced meshes even though the package contains native assets that preserve their layout.

Knowledge Base Used: Scene generation engine

Prompt To Fix With AI
This is a comment left during a code review.
Path: embodichain/gen_sim/scene_engine/pipeline/utils/scene_usd.py
Line: 355-360

Comment:
**Direct USD preview misplaces meshes**

For newly generated schema-v2 scenes, `--usd` and `--usd-file` now import the USD stage directly instead of loading the packaged GLTF/USDC assets. The existing compatibility path avoids direct import because DexSim cannot faithfully restore GLB internal node transforms from the flattened stage. Scenes with those transforms can therefore show misplaced meshes even though the package contains native assets that preserve their layout.

**Knowledge Base Used:** [Scene generation engine](https://app.greptile.com/dexforce/-/custom-context/knowledge-base/dexforce/embodichain/-/docs/scene-generation-engine.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex Fix in Claude Code

Comment on lines +171 to +180
scene_usd_path = scene_usd_root / "scene.usda"
temporary_scene_usd_path = scene_usd_root / "scene.in_progress.usda"
manifest_path = scene_usd_root / "scene_usd_manifest.json"
runtime_assets_root = scene_usd_root / ".export_runtime_assets"
packaged_assets_root = scene_usd_root / "assets"
temporary_scene_usd_path.unlink(missing_ok=True)
for managed_file in (scene_usd_path, manifest_path):
if managed_file.is_symlink():
managed_file.unlink()
_remove_path(scene_usd_root / "textures")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Failed rebuild leaves stale USDZ

When an edit rewrites scene_export/, the rebuild does not remove the previous scene.usdz. If building the USD stage or packaging the new USDZ fails, the pipeline can warn that the optional export was skipped while leaving the old standalone file in place. Delivering or previewing that file then shows the scene from before the edit.

Knowledge Base Used: Scene generation engine

Prompt To Fix With AI
This is a comment left during a code review.
Path: embodichain/gen_sim/scene_engine/pipeline/utils/scene_usd.py
Line: 171-180

Comment:
**Failed rebuild leaves stale USDZ**

When an edit rewrites `scene_export/`, the rebuild does not remove the previous `scene.usdz`. If building the USD stage or packaging the new USDZ fails, the pipeline can warn that the optional export was skipped while leaving the old standalone file in place. Delivering or previewing that file then shows the scene from before the edit.

**Knowledge Base Used:** [Scene generation engine](https://app.greptile.com/dexforce/-/custom-context/knowledge-base/dexforce/embodichain/-/docs/scene-generation-engine.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex Fix in Claude Code

Comment on lines +266 to +271
def scene_entity_cfg(self, uid: str) -> object:
"""Create the Gym ``SceneEntityCfg`` corresponding to ``uid``."""
self.get(uid)
from embodichain.lab.gym.envs.managers.cfg import SceneEntityCfg

return SceneEntityCfg(uid=uid)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Logical UIDs do not resolve

scene_entity_cfg(uid) returns the authored scene UID, but add_usd() registers imported objects under DexSim descriptor names without registering that UID as an alias. When an object's runtime name differs from its scene UID, the returned SceneEntityCfg cannot resolve the object through the simulation manager, breaking the promised stable-UID binding.

Knowledge Base Used: Simulation lab

Prompt To Fix With AI
This is a comment left during a code review.
Path: embodichain/gen_sim/scene_engine/pipeline/utils/usd_scene.py
Line: 266-271

Comment:
**Logical UIDs do not resolve**

`scene_entity_cfg(uid)` returns the authored scene UID, but `add_usd()` registers imported objects under DexSim descriptor names without registering that UID as an alias. When an object's runtime name differs from its scene UID, the returned `SceneEntityCfg` cannot resolve the object through the simulation manager, breaking the promised stable-UID binding.

**Knowledge Base Used:** [Simulation lab](https://app.greptile.com/dexforce/-/custom-context/knowledge-base/dexforce/embodichain/-/docs/simulation-lab.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex Fix in Claude Code

@yuecideng
yuecideng merged commit 79ae93a into main Sep 27, 2026
9 checks passed
@yuecideng
yuecideng deleted the muzi/add_simple_usd branch September 27, 2026 03:48
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