# Converting Newton Simulations to USD Format for Visualization

> Convert Newton simulations to USD format for visualization. Easily import USD stages into Newton using ModelBuilder.add_usd() and control visual shapes and sites with simple flags.

- Repository: [Newton Physics/newton](https://github.com/newton-physics/newton)
- Tags: how-to-guide
- Published: 2026-03-19

---

**Use `ModelBuilder.add_usd()` to import any USD stage into Newton, leveraging built-in schema resolvers to automatically map physics attributes from Newton, PhysX, or MuJoCo schemas while controlling visualization through flags like `load_visual_shapes` and `load_sites`.**

Converting Newton simulations to USD format for visualization is handled through the high-level import pipeline provided by the `newton-physics/newton` repository. The framework's `ModelBuilder.add_usd` API parses a USD stage—or a path/URL to a USD file—and automatically creates the corresponding Newton bodies, shapes, joints, sites, and visual geometry. This enables seamless integration of external USD assets into Newton's physics simulation environment for immediate visualization and analysis.

## Understanding the USD Import Pipeline

The conversion process operates in three distinct stages that transform USD prims into Newton simulation entities.

### The Three-Stage Conversion Process

1. **USD Loading**: The system opens a `Usd.Stage` from a file path, URL, or existing stage object. The helper `resolve_usd_from_url` in [`newton/_src/utils/import_usd.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/utils/import_usd.py) handles path resolution and optional conversion to USDA format.

2. **Schema Resolution**: Low-level helpers in `newton.usd` utilize `SchemaResolver` classes to read physics-specific attributes. The resolvers extract Newton-specific (`newton:*`), PhysX-specific (`physx*`), and MuJoCo-specific (`mjc:*`) attributes from USD prims.

3. **Builder Population**: The parsed data feeds into `ModelBuilder` to create simulation entities. This stage respects optional flags such as `load_sites`, `collapse_fixed_joints`, `apply_up_axis_from_stage`, and `enable_self_collisions`.

### Key Source Files and Architecture

The core implementation resides in two primary locations:

- **[`newton/_src/sim/builder.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/builder.py)** (lines 2199-2265): Contains the `ModelBuilder.add_usd` method implementation, handling stage acquisition, transform composition, and entity creation loops.

- **[`newton/usd.py`](https://github.com/newton-physics/newton/blob/main/newton/usd.py)** (lines 25-84): Public API exposing utility functions and the three built-in schema resolvers: `SchemaResolverNewton`, `SchemaResolverPhysx`, and `SchemaResolverMjc`.

Additional utility functions for mesh conversion and attribute extraction reside in [`newton/_src/usd/schema_resolver.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/usd/schema_resolver.py) and [`newton/_src/utils/import_usd.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/utils/import_usd.py).

## Using ModelBuilder.add_usd for USD Conversion

The primary entry point for converting USD to Newton simulations is the `add_usd` method of `ModelBuilder`.

### Method Signature and Parameters

```python
def add_usd(
    self,
    source: str | UsdStage,
    *,
    xform: Transform | None = None,
    floating: bool | None = None,
    base_joint: dict | None = None,
    parent_body: int = -1,
    only_load_enabled_rigid_bodies: bool = False,
    only_load_enabled_joints: bool = True,
    joint_drive_gains_scaling: float = 1.0,
    verbose: bool = False,
    ignore_paths: list[str] | None = None,
    collapse_fixed_joints: bool = False,
    enable_self_collisions: bool = True,
    apply_up_axis_from_stage: bool = False,
    root_path: str = "/",
    joint_ordering: Literal["bfs", "dfs"] | None = "dfs",
    bodies_follow_joint_ordering: bool = True,
    skip_mesh_approximation: bool = False,
    load_sites: bool = True,
    load_visual_shapes: bool = True,
    hide_collision_shapes: bool = False,
    force_show_colliders: bool = False,
    parse_mujoco_options: bool = True,
    mesh_maxhullvert: int | None = None,
    schema_resolvers: list[SchemaResolver] | None = None,
    force_position_velocity_actuation: bool = False,
    override_root_xform: bool = False,
) -> dict[str, Any]:
    ...

```

Key parameters for visualization control include:

- **`load_visual_shapes`**: Imports visual-only meshes for rendering.
- **`load_sites`**: Imports MuJoCo site primitives as Newton sites.
- **`hide_collision_shapes`** / **`force_show_colliders`**: Controls visibility of collision geometry.
- **`apply_up_axis_from_stage`**: Automatically respects the USD stage's up-axis (Y or Z).
- **`xform`**: Applies a global transform to the imported stage.

### Return Value Structure

The method returns a dictionary containing rich metadata about the imported scene:

| Key | Description |
|-----|-------------|
| `fps` | Frames-per-second of the USD stage |
| `duration` | Time span of the stage |
| `up_axis` | Detected up-axis (`X`, `Y`, or `Z`) |
| `path_body_map` / `path_joint_map` / `path_shape_map` | Mappings from USD prim paths to Newton indices |
| `mass_unit` / `linear_unit` | Unit scaling from USD metadata |
| `scene_attributes` | Attributes applied to the PhysicsScene prim |
| `collapse_results` | Information about fixed-joint collapsing |
| `schema_attrs` | Collected schema-specific attributes |

## Schema Resolvers and Attribute Mapping

Newton supports multiple physics schemas through a pluggable resolver system defined in [`newton/usd.py`](https://github.com/newton-physics/newton/blob/main/newton/usd.py).

### Built-in Schema Resolvers

The three built-in resolvers handle different physics dialects:

- **`SchemaResolverNewton`**: Extracts `newton:*` attributes (e.g., `newton:selfCollisionEnabled`).
- **`SchemaResolverPhysx`**: Extracts PhysX-specific attributes (`physx*`).
- **`SchemaResolverMjc`**: Extracts MuJoCo-specific fields (`mjc:*`).

```python
from newton.usd import SchemaResolverNewton, SchemaResolverPhysx, SchemaResolverMjc

# Use specific resolvers to import PhysX-specific data

builder.add_usd(
    source="robot.usd",
    schema_resolvers=[SchemaResolverPhysx()]
)

```

### Utility Functions

`newton.usd` also exports low-level helpers for direct USD manipulation:

- `get_mesh()`: Extracts mesh geometry as Warp-compatible numpy arrays.
- `get_attribute()`: Safely retrieves USD attributes.
- `type_to_warp()`: Converts USD types to Warp types.

These utilities reside in [`newton/usd.py`](https://github.com/newton-physics/newton/blob/main/newton/usd.py) (lines 44-61) and support the internal conversion pipeline.

## Practical Example: Loading and Visualizing a USD Scene

Below is a complete workflow that loads a USD pendulum model, configures the import for visualization, and renders it using Newton's viewer.

```python
import newton
from newton import ModelBuilder
from newton.viewer import Viewer
from pathlib import Path

# Path to a USD file (could also be a URL)

usd_path = Path(__file__).parent / "assets" / "pendulum.usda"

# Create a builder and import the USD stage

builder = ModelBuilder()

# Optional: apply a global transform (rotate 90° about X to match Y-up)

builder.add_usd(
    source=str(usd_path),
    xform=newton.Transform.from_euler_xyz((90.0, 0.0, 0.0), deg=True),
    load_sites=True,               # import MjcSiteAPI primitives as Newton sites

    load_visual_shapes=True,       # bring in visual-only meshes

    collapse_fixed_joints=False,   # keep fixed joints (useful for debugging)

    apply_up_axis_from_stage=True, # respect any up-axis encoded in the file

)

# Finalise the model

model = builder.finalize()

# Run a short simulation and visualise

viewer = Viewer(model)
viewer.run(duration=3.0, fps=60)

```

**What the script accomplishes:**

1. **Loads** the `pendulum.usda` file via `ModelBuilder.add_usd` using the `resolve_usd_from_url` helper.
2. **Applies** an optional transform (`xform`) to align the USD stage's coordinate system with Newton's expectations.
3. **Preserves** all sites and visual shapes so they appear correctly in the Newton viewer.
4. **Finalises** the model into a simulation-ready state.
5. **Visualizes** the result using the built-in viewer at 60 FPS.

You can customize the import by toggling flags such as `collapse_fixed_joints=True` to merge fixed bodies into single rigid bodies, or by specifying `schema_resolvers=[newton.SchemaResolverPhysx()]` to prioritize PhysX-specific attributes over Newton's defaults.

## Summary

- **`ModelBuilder.add_usd`** is the primary entry point for converting USD stages into Newton simulations, located in [`newton/_src/sim/builder.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/builder.py).
- The conversion pipeline uses **three stages**: USD loading, schema resolution via `SchemaResolver` classes, and builder population to create bodies, joints, and shapes.
- **Schema resolvers** (`SchemaResolverNewton`, `SchemaResolverPhysx`, `SchemaResolverMjc`) handle physics-specific attributes from different dialects, defined in [`newton/usd.py`](https://github.com/newton-physics/newton/blob/main/newton/usd.py).
- **Visualization flags** like `load_visual_shapes`, `load_sites`, and `apply_up_axis_from_stage` control how geometry and coordinate systems are handled during import.
- The method returns a **metadata dictionary** containing mappings between USD prim paths and Newton indices, scene attributes, and unit scaling information.

## Frequently Asked Questions

### What is the primary entry point for converting USD files in Newton?

The primary entry point is `ModelBuilder.add_usd()`, implemented in [`newton/_src/sim/builder.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/builder.py) (lines 2199-2265). This method accepts a USD file path, URL, or `Usd.Stage` object and automatically populates the `ModelBuilder` with corresponding rigid bodies, joints, shapes, and visual geometry.

### How does Newton handle different physics schemas like PhysX or MuJoCo?

Newton handles multiple physics schemas through a pluggable resolver system defined in [`newton/usd.py`](https://github.com/newton-physics/newton/blob/main/newton/usd.py). The three built-in `SchemaResolver` classes—`SchemaResolverNewton`, `SchemaResolverPhysx`, and `SchemaResolverMjc`—extract attributes prefixed with `newton:*`, `physx*`, and `mjc:*` respectively. You can specify which resolvers to use via the `schema_resolvers` parameter in `add_usd()`.

### Can I apply custom transforms when importing USD files?

Yes, the `add_usd()` method accepts an `xform` parameter of type `Transform` that applies a global transformation to the entire USD stage during import. Additionally, setting `apply_up_axis_from_stage=True` automatically adjusts the coordinate system to match the USD file's up-axis (Y-up or Z-up), ensuring correct orientation in Newton's viewer.

### What information does the add_usd method return?

The `add_usd()` method returns a comprehensive dictionary containing metadata about the imported scene. Key entries include `path_body_map`, `path_joint_map`, and `path_shape_map` (mapping USD prim paths to Newton indices), `up_axis` and `scene_attributes` (coordinate system and physics scene settings), `schema_attrs` (captured physics attributes from various schemas), and unit scaling information (`mass_unit`, `linear_unit`).