Skip to content

Add USD to Simularium converter#206

Open
dillonl wants to merge 3 commits intosimularium:mainfrom
dillonl:main
Open

Add USD to Simularium converter#206
dillonl wants to merge 3 commits intosimularium:mainfrom
dillonl:main

Conversation

@dillonl
Copy link
Copy Markdown

@dillonl dillonl commented Mar 31, 2026

Time estimate or Size
Small: ~1 hour to review. New self-contained module with no changes to existing code paths.

Problem
There is no way to convert USD (Universal Scene Description) files into the .simularium format. USD is a widely used interchange format exported by tools like Blender, Maya, and Houdini, and is a natural input for biological simulation visualization workflows.

Solution
Added a UsdConverter and UsdData class following the same patterns as existing converters (e.g. CellPackConverter). The converter:

Opens a USD stage and discovers all mesh geometry prims
Deduplicates meshes by geometry hash and normalizes them relative to their local origin (preserving pivot points set in DCC tools)
Extracts per-frame local transforms using Gf.Transform, decomposing rotation into intrinsic XYZ Euler angles compatible with the THREE.js viewer
Applies np.unwrap per-axis to remove Euler discontinuities
Supports optional animation trimming (trim_to_animation=True by default) to crop to the actual animated frame range
Supports display data overrides by name
Writes mesh geometry as .obj files alongside the .simularium output

Type of change
New feature (non-breaking change which adds functionality)
This change requires updated or new tests

Change summary:
Add USD converter for importing Universal Scene Description files
Fix USD rotation convention to match THREE.js Euler('XYZ') intrinsic order
Clean up USD converter: remove stale comments, unused imports, and improve error handling

Steps to Verify:
Install with USD support: pip install ".[usd]"
Run the test suite: pytest simulariumio/tests/converters/test_usd_converter.py
Convert a USD file manually:

from simulariumio.usd import UsdConverter, UsdData
converter = UsdConverter(UsdData(usd_file_path="my_file.usd"))
converter.save("output")
Open output.simularium in the Simularium viewer at simularium.allencell.org
Verify agents appear with correct positions, rotations, and mesh shapes across frames

Keyfiles:
simulariumio/usd/usd_converter.py -> main converter logic
simulariumio/usd/usd_data.py -> input data container
simulariumio/tests/converters/test_usd_converter.py -> test suite

dillonl added 3 commits March 30, 2026 10:55
Reads .usd/.usda/.usdc files and converts them to .simularium format
with OBJ mesh geometry output. Supports animated transforms (position
and rotation), mesh deduplication via geometry hashing, material color
extraction, and centering/scaling.

Key details:
- Rotations are converted from USD degrees to radians for the viewer
- OBJ meshes are normalized to unit sphere so viewer radius scaling works
- Mesh deduplication avoids writing redundant OBJ files
- Optional dependency: pip install simulariumio[usd]
Decompose(Z, Y, X) produced intrinsic ZYX angles which, when passed to
the viewer's THREE.js Euler('XYZ'), generated incorrect rotations (up to
1.24 quaternion error). Switched to Decompose(X, Y, Z) which uses the
same intrinsic XYZ convention as the viewer, eliminating barrel-roll
artifacts on animated meshes.

Also wrap Usd.Stage.Open in try/except for a clearer error on bad paths,
remove stale comments and unused imports from iteration.
…prove error handling

Remove class-level type annotations not used by other converters, unused
Tuple/MetaData/UnitData imports, redundant rotation comment, and replace
verbose/inaccurate convention comments with concise versions. Wrap
Usd.Stage.Open in try/except for a clearer error on invalid file paths.
@dillonl dillonl requested a review from a team as a code owner March 31, 2026 23:15
@dillonl dillonl requested review from ascibisz and toloudis and removed request for a team March 31, 2026 23:15
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.

1 participant