Skip to content

Repository files navigation

openusd logo

openusd

CI codecov dependency status

openusd is a Rust implementation of Pixar's Universal Scene Description (USD) format with no C++ dependencies.

This repository contains the following crates:

Crate Description
openusd Core USD library — file formats, composition engine, and the composed Stage API. Crates.io Version
docs.rs
openusd‑schemas Typed views for USD's standard schemas — UsdGeom, UsdShade, UsdSkel, and more. Crates.io Version
docs.rs

For a detailed comparison with the C++ reference implementation and current progress, see the Roadmap.

Features

  • File formats — reads and writes .usda (text), .usdc (binary), and .usdz (archive).
  • A fully featured composition engineLIVRPS strength ordering over a per-prim node graph, with list editing, scene-graph instancing, non-destructive relocates, and variable expressions.
  • A composed Stage — lazy cached per-prim composition with typed value resolution, predicate-based traversal, and full prim/property query API over the composed scene.
  • An authoring API — build scenes through layer- and stage-tier APIs, with typed spec views, composed prim/attribute/relationship handles with chained fluent edits, EditTarget routing to a specific layer, in-memory anonymous-root stages, and applied API schema authoring.
  • Live sync friendly — listen to Stage edit events and capture each edit as a transferable, replayable Diff for live mirroring across processes.
  • Domain schema readers (opt-in per family, layered on the composed stage) — UsdGeom, UsdLux, UsdPhysics, UsdRender, UsdSkel, and UsdShade.

If you encounter a file that can't be read, please open an issue and attach the USD file for investigation.

Compliance

The AOUSD Core Specification 1.0 has been officially ratified. As part of the specification, sample implementations for compliance testing are provided as Python scripts with JSON baselines. Where JSON baselines are available, the crate parses them and verifies that its output matches.

Area Status Notes
Text format parsing ✅ Passes 10 tests against JSON baselines
Binary format parsing ✅ Passes 42 tests manually backported from the reference suite's test_binary.py in tests/binary_format.rs
Composition ✅ Passes tests/composition.rs runs the full vendor suite (138 assets) through both the text and binary parsers, regenerating each pcp.txt dump to validate strength ordering, prim/property stacks, and time offsets
Value resolution ☑️ Partial 8 tests in tests/value_resolution.rs (defaults, time samples, value clips). Excludes attribute fallbacks and splines
Combine chains ✅ Passes ListOp::combined_with and ListOp::reduced against JSON baselines

Getting started

Warning

These crates are under active development. No API stability is guaranteed until version 1.0.

Make sure you have Rust installed on your system, rustup will do the rest.

Add the crates you need — openusd-schemas is optional, with one feature per schema family:

[dependencies]
openusd = "0.7"
openusd-schemas = { version = "0.7", features = ["geom", "shade"] }

Open a stage, walk its composed prims, and read a resolved attribute value:

use openusd::usd;

let stage = usd::Stage::open("scene.usda")?;

// `DEFAULT` prunes inactive, unloaded, and abstract subtrees.
stage.traverse(usd::PrimPredicate::DEFAULT, |prim_path| {
    println!("{prim_path}");
})?;

let sphere = stage.prim("/World/Sphere")?;
println!("type: {:?}", sphere.type_name()?);

// Resolved across every layer, reference, and payload that composes the prim.
let radius = stage.attribute("/World/Sphere.radius")?;
if let Some(r) = radius.get::<f64>()? {
    println!("radius = {r}");
}

Authoring works the same way round:

use openusd::usd;

let stage = usd::Stage::builder().in_memory("root.usda")?;

stage.define_prim("/World")?.set_type_name("Xform")?;
stage.define_prim("/World/Sphere")?.set_type_name("Sphere")?;
stage.set_default_prim("World")?;

stage.create_attribute("/World/Sphere.radius", "double")?.set(2.5_f64)?;

Typed schema views layer on top of that stage — here a mesh's points and the shader driving a material's surface:

use openusd::{gf, usd};
use openusd_schemas::geom::{self, PointBased};
use openusd_schemas::shade;

let stage = usd::Stage::open("scene.usda")?;

// `PointBased` is in scope so `Mesh` inherits its accessors.
if let Some(mesh) = geom::Mesh::get(&stage, "/World/Mesh")? {
    if let Some(points) = mesh.points_attr().get::<Vec<gf::Vec3f>>()? {
        println!("{} points", points.len());
    }
}

// Follow the material's surface terminal to the shader driving it.
if let Some(material) = shade::Material::get(&stage, "/World/Material")? {
    if let Some(terminal) = material.compute_surface_source(&[])? {
        for source in terminal.sources() {
            if let Some(shader) = source.shader() {
                println!("surface shader: {:?}", shader.id()?);
            }
        }
    }
}

Minimum supported Rust version (MSRV)

The project targets stable Rust and aims for the latest Rust editions. The MSRV is bumped on an as-needed basis, whenever it makes sense for the project. Please refer to rust-toolchain.toml for the exact version currently used by our CIs.

License

Licensed under the MIT License.

About

Native Rust USD library

Topics

Resources

Contributing

Stars

126 stars

Watchers

3 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages