# Loading OpenUSD Scenes and Performing Format Conversions in Newton: A Complete Guide

> Learn to load OpenUSD scenes and convert physics data in Newton. The ModelBuilder.add_usd function simplifies imports, converting attributes and metadata for Warp simulation.

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

---

**Newton's `ModelBuilder.add_usd` function imports OpenUSD scenes and automatically converts physics attributes, geometry, and solver-specific metadata into Warp-compatible simulation data.**

Newton, an open-source physics simulation framework developed by newton-physics, provides a robust pipeline for loading OpenUSD scenes and performing format conversions. The `ModelBuilder.add_usd` method in [`newton/_src/sim/builder.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/builder.py) serves as the primary entry point, handling everything from stage acquisition to rigid-body creation while preserving solver-specific attributes from PhysX, MuJoCo, or custom schemas.

## How Newton Imports OpenUSD Scenes via ModelBuilder.add_usd

The core import logic resides in `ModelBuilder.add_usd` (lines 2199–2265 of [`newton/_src/sim/builder.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/builder.py)). This method treats a USD file or an already-opened `Usd.Stage` as a complete description of one or more rigid-body articulations.

### Stage Acquisition and Root Transform Handling

When `add_usd` is called, Newton first acquires the USD stage. If the *source* argument is a string, Newton opens the file via `Usd.Stage.Open` (or a URL). If it is already a `UsdStage` object, the stage is reused.

An optional `xform` (a `newton.Transform`) is either composed with the articulation’s root transform or, when `override_root_xform=True`, replaces it entirely. This lets you clone an articulation at a specific pose without moving any of its internal geometry.

### Schema Resolution for Solver-Specific Attributes

Newton ships with three built-in resolvers that know how to read solver-specific attributes from USD prims:

- `SchemaResolverNewton`
- `SchemaResolverPhysx`
- `SchemaResolverMjc`

These classes are defined in [`newton/_src/usd/schema_resolver.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/usd/schema_resolver.py) and registered in [`newton/_src/usd/schemas.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/usd/schemas.py). Users can pass a custom list via the `schema_resolvers` argument to collect additional namespaced attributes; the result is returned in the `"schema_attrs"` entry of the mapping returned by `add_usd`.

### Attribute Conversion to Warp Types

Low-level helpers in [`newton/_src/usd/utils.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/usd/utils.py) translate USD scalar, vector, and quaternion attributes into Warp-compatible values (`float`, `wp.vec3`, `wp.quat`). For example, `get_quat` reads a quaternion attribute and returns a `wp.quat` in Newton’s internal `x, y, z, w` ordering.

## Converting USD Physics Data to Newton Simulation Elements

Once attributes are resolved and converted, `add_usd` iterates over the stage prims to instantiate simulation objects.

### Rigid Bodies and Inertia Tensors

Rigid bodies are added for each prim that implements the `PhysicsRigidBodyAPI`. Their mass and inertia are read from `physics:mass` and `physics:inertiaTensor`, with the latter converted to a `wp.mat33`. The `newton:selfCollisionEnabled` flag is applied if present.

### Joints and Articulation Hierarchies

Joints are created from `PhysicsJointAPI` prims. The `floating`, `base_joint`, and `parent_body` arguments control how the root body attaches to the world or to an existing body. This enables complex articulation hierarchies where a USD scene is grafted onto an existing simulation.

### Collision Geometry and Mesh Approximation

Collision and visual geometry is extracted from `UsdGeom` prims. Meshes can be approximated to convex hulls using the `mesh_maxhullvert` parameter, skipped entirely with `skip_mesh_approximation`, or forced to be visible with `force_show_colliders`.

## Post-Processing and Scene Optimization

After instantiation, Newton applies several optimization passes:

- **Fixed-joint collapse**: When `collapse_fixed_joints=True`, bodies connected by fixed joints are merged, and a `"collapse_results"` dictionary is returned detailing the merges.
- **Up-axis handling**: The `apply_up_axis_from_stage` option respects the stage’s authored up-axis.
- **MuJoCo option parsing**: The `parse_mujoco_options` flag processes MuJoCo-specific compiler and option attributes.

The method returns a dictionary containing meta-information (FPS, duration, up-axis, unit scaling) and mapping tables from USD prim paths to Newton body/joint/shape indices. These mappings enable downstream inspection or custom processing of the imported scene.

## Practical Code Examples for OpenUSD Integration

The following examples demonstrate common workflows for loading OpenUSD scenes and performing format conversions in Newton.

```python
import newton as nx

# 1. Simple USD import – load the built‑in bunny asset.

builder = nx.ModelBuilder()
usd_path = nx.examples.get_asset("bunny.usd")   # helper that returns a local path

result = builder.add_usd(usd_path, floating=True)   # FREE joint at world root

print("Imported bodies:", result["path_body_map"].keys())

```

```python

# 2. Apply a transform and override the root pose.

builder = nx.ModelBuilder()
stage = nx.usd.Usd.Stage.Open(usd_path)   # low‑level USD API

builder.add_usd(
    stage,
    xform=nx.transform(wp.vec3(1.0, 0.0, 0.5), wp.quat_identity()),
    override_root_xform=True,
    collapse_fixed_joints=True,
)

```

```python

# 3. Custom schema resolver to capture PhysX‑specific attributes.

from newton._src.usd.schema_resolver import SchemaResolverPhysx

builder = nx.ModelBuilder()
result = builder.add_usd(
    usd_path,
    schema_resolvers=[nx.usd.SchemaResolverNewton(),
                      SchemaResolverPhysx()],   # include PhysX attrs

)
print("PhysX attrs found:", result["schema_attrs"])

```

```python

# 4. Skipping mesh approximation and disabling collision‑shape visibility.

builder = nx.ModelBuilder()
builder.add_usd(
    usd_path,
    skip_mesh_approximation=True,
    force_show_colliders=False,
    hide_collision_shapes=True,
)

```

## Key Source Files and Architecture

Understanding the source layout helps when extending or debugging the OpenUSD import pipeline.

| File | Role | Link |
|------|------|------|
| [`newton/usd.py`](https://github.com/newton-physics/newton/blob/main/newton/usd.py) | Public façade exposing utility functions and schema resolver types used by `ModelBuilder.add_usd`. | https://github.com/newton-physics/newton/blob/main/newton/usd.py |
| [`newton/_src/sim/builder.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/builder.py) | Core implementation of `ModelBuilder.add_usd` and all related import logic. | https://github.com/newton-physics/newton/blob/main/newton/_src/sim/builder.py |
| [`newton/_src/usd/utils.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/usd/utils.py) | Low‑level helpers for reading USD attributes and converting them to Warp types. | https://github.com/newton-physics/newton/blob/main/newton/_src/usd/utils.py |
| [`newton/_src/usd/schema_resolver.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/usd/schema_resolver.py) | Abstract base and concrete resolver classes that map USD attribute namespaces to Newton data structures. | https://github.com/newton-physics/newton/blob/main/newton/_src/usd/schema_resolver.py |
| [`newton/_src/usd/schemas.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/usd/schemas.py) | Registers the built‑in resolvers (`Newton`, `Physx`, `Mjc`) and defines the priority order. | https://github.com/newton-physics/newton/blob/main/newton/_src/usd/schemas.py |

## Summary

- **Primary entry point**: The `ModelBuilder.add_usd` method in [`newton/_src/sim/builder.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/builder.py) (lines 2199–2265) handles the complete OpenUSD import pipeline.
- **Flexible stage input**: Accepts either a file path string or an existing `Usd.Stage` object, automatically handling URL resolution and stage reuse.
- **Solver-agnostic schemas**: Built-in resolvers for Newton, PhysX, and MuJoCo attributes preserve domain-specific metadata in the `"schema_attrs"` dictionary.
- **Automatic conversion**: Low-level utilities in [`newton/_src/usd/utils.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/usd/utils.py) translate USD scalars, vectors, and quaternions into Warp-native types (`wp.vec3`, `wp.quat`, `wp.mat33`).
- **Optimization options**: Fixed-joint collapse, mesh convex-hull approximation, and up-axis correction are applied as post-processing steps.

## Frequently Asked Questions

### What USD schemas does Newton support out of the box?

Newton natively supports `PhysicsRigidBodyAPI`, `PhysicsJointAPI`, and `UsdGeom` prims. Through the built-in schema resolvers—`SchemaResolverNewton`, `SchemaResolverPhysx`, and `SchemaResolverMjc`—it also captures solver-specific attributes from PhysX, MuJoCo, and custom `newton:*` namespaces.

### How do I preserve PhysX-specific attributes when loading a USD scene?

Pass a custom list of schema resolvers to `add_usd` that includes `SchemaResolverPhysx` from `newton._src.usd.schema_resolver`. The function returns a dictionary containing `"schema_attrs"`, which maps prim paths to the captured PhysX metadata.

### Can I override the root transform of an imported articulation without modifying internal geometry?

Yes. Use the `xform` argument to provide a `newton.Transform`, and set `override_root_xform=True`. This replaces the articulation’s root pose entirely, allowing you to instantiate the same USD asset at different locations without altering the relative transforms of its internal bodies or joints.

### How does Newton handle mesh geometry from USD for collision detection?

Newton extracts vertices and indices from `UsdGeom.Mesh` prims and converts them to Warp-compatible `wp.vec3` arrays. By default, it can approximate meshes to convex hulls using the `mesh_maxhullvert` parameter. You can disable approximation with `skip_mesh_approximation=True` or control visibility with `force_show_colliders` and `hide_collision_shapes`.