# Usd Authoring

> Author USD content via OpenUSD Exchange helpers (usdex.core, usdex.rtx, usdex.test). Use when writing or converting USD; do NOT use for install tasks.

- Skill: `nvidia-omniverse/usd-authoring` (Agent Skill, multi-file: 11 files)
- Install (CLI): `npx skillmds@latest add nvidia-omniverse/usd-authoring`
- Raw SKILL.md: https://api.skillmd.com/api/skills/nvidia-omniverse/usd-authoring/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: Apache-2.0
- Author: NVIDIA-Omniverse (https://skillmd.com/u/nvidia-omniverse)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/nvidia-omniverse/usd-authoring

---

<!-- SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -->
<!-- SPDX-License-Identifier: Apache-2.0 -->

# USD Authoring with the OpenUSD Exchange SDK

## When to apply

Apply when a task imports `usdex.core` / `usdex.rtx` / `usdex.test` in Python, or includes `<usdex/core/...>` / `<usdex/rtx/...>` / `<usdex/test/...>` in C++, or authors / converts / exports / validates OpenUSD data of any kind (`Usd.Stage`, `Sdf.Layer`, `UsdPrim`, `UsdGeomMesh`, `UsdGeomXformable`, `UsdGeomCamera`, `UsdLuxLight`, `UsdShadeMaterial`, `UsdPhysics*`, `.usd*` files). Stop when the task moves to non-USD work.

The audience is Physical AI converter / pipeline authors: robotics, simulation, synthetic data, digital twins, reusable asset libraries.

## Non-negotiables

These rules apply to every snippet you write and every API you call. Do not relax them with "this example is illustrative" or "this is just for teaching" reasoning.

### Use the SDK helpers; do not call raw OpenUSD where a helper exists

| Domain | Use this | Not this |
| --- | --- | --- |
| Stage creation | `usdex.core.createStage` | `Usd.Stage.CreateNew`, `Usd.Stage.CreateInMemory` plus manual metadata |
| Stage configuration | `usdex.core.configureStage` | `UsdGeomSetStageUpAxis` + `UsdGeomSetStageMetersPerUnit` + manual `creator` write |
| Stage save | `usdex.core.saveStage` | `stage.Save()` / `stage.GetRootLayer().Save()` |
| Single-layer save / export | `usdex.core.saveLayer` / `usdex.core.exportLayer` | `layer.Save()` / `layer.Export()` |
| Transforms | `usdex.core.setLocalTransform` (or pass `transform` to `defineXform` / `defineCamera`) | `UsdGeomXformCommonAPI`, `AddTranslateOp` / `AddRotateOp` / `AddScaleOp` / `AddTransformOp` |
| Names (prims) | `usdex.core.NameCache.getPrimName(s)` or `getValidPrimName(s)` / `getValidChildName(s)` | string literals, `Tf.MakeValidIdentifier`, `TfMakeValidIdentifier` |
| Names (properties) | `getValidPropertyName(s)` or `NameCache.getPropertyName(s)` | string literals for property names |
| References | `usdex.core.defineReference` | `prim.GetReferences().AddReference(...)` |
| Payloads | `usdex.core.definePayload` | `prim.GetPayloads().AddPayload(...)` |
| Scopes | `usdex.core.defineScope` | `UsdGeomScope.Define` |
| Xforms / meshes / curves / points / gprims / cameras / lights / materials / physics joints / physics materials | the matching `usdex.core.define*` helper | `Usd<Schema>.Define` plus attribute writes |
| OpenPBR (MaterialX) + Preview Surface materials | `usdex.core.definePbrMaterial` / `defineGlassPbrMaterial` | canonical MaterialX shader graphs |
| RTX MDL materials | `usdex.rtx.definePbrMaterial` / `defineGlassMaterial` | hand-rolled MDL shader graphs |
| Primvars (normals, UVs, widths, displayColor, displayOpacity, ids, custom) | wrap in `usdex.core.PrimvarData` or typed aliases `Vec3fPrimvarData` / `Vec2fPrimvarData` / `FloatPrimvarData` / `Int64PrimvarData` / `IntPrimvarData` / `TokenPrimvarData` / `StringPrimvarData` | direct `CreatePrimvar` + raw `VtArray` writes |
| Constant primvars holding one scalar value | `usdex.core.createConstantPrimvar(prim, name, value, [valueTypeName])`, or `setConstantPrimvar` to write another time sample | a one-element typed alias with `constant` interpolation |
| Custom primvars no `define*` helper covers | `<alias>.createPrimvar(prim, name, [valueTypeName])` | `prim.CreatePrimvar(...)` + `Set(...)` |
| Values on schema-declared attributes | `usdex.core.setEffectiveAttributeValue` | `prim.GetAttribute(name).Set(value)`, or a generated `Create<Name>Attr(value)` / `Get<Name>Attr().Set(value)` accessor, for every value including schema fallbacks |

Both primvar creation calls take an optional `valueTypeName`, which must be an array type. It carries a role only for `Vec3f` data, which authors `float3[]` unless told to author `color3f[]`, `normal3f[]`, or `point3f[]` — so pass it there, and leave it defaulted elsewhere. Every other alias accepts just its own array type, and a scalar spelling is rejected: `createConstantPrimvar(prim, "myInt", 42, Sdf.ValueTypeNames.Int)` authors nothing, it needs `IntArray`.

Raw schema is allowed (and required) only for APIs without a helper — e.g. `UsdPhysicsRigidBodyAPI.Apply`, `UsdPhysicsCollisionAPI.Apply`, `UsdPhysics.Scene.Define`, `UsdLux.DistantLight.Define` — and only **after** the prim has been defined via a helper, where one applies. That exemption covers defining the prim and applying the schema, not writing its values: author those with `setEffectiveAttributeValue` rather than the schema's generated `Create<Name>Attr` / `Get<Name>Attr().Set` accessors, so schema fallbacks stay unauthored. The generated accessors are the right tool only for what `setEffectiveAttributeValue` cannot express — time samples, connections, and metadata. See `references/attributes.md`.

### Names

Every prim name you author — including names you "own" (asset names, scope names, default-prim names, throwaway example names) — flows through the name pipeline. Never pass a string literal to a `usdex.core.define*` / `usdex.rtx.define*` / `defineScope` / `createMaterial` `name=` argument. Never pass a string literal to `defaultPrimName=`. Use a variable populated from `NameCache.getPrimName(parent, source.name)`, `getValidChildName(parent, source.name)`, or `getValidPrimName(asset.name)`.

For property names, the same rule applies via `getValidPropertyName(s)` or `NameCache.getPropertyName(s)`. The pipeline is for names you derive from source data, so names a schema already declares (`physics:mass`, `primvars:displayColor`) are passed through as literals.

### Authoring metadata

Every call to `createStage` / `configureStage` / `saveStage` / `saveLayer` / `exportLayer` must take an `authoringMetadata` value, and that value must be a variable (e.g. `AUTHORING_METADATA`), not a string literal. The variable should describe the host application and version (for example, `"My Converter 2026.1, usdex_ver: <ver>"`).

### Validation

If `usdex.test` is available, regression tests should subclass `usdex.test.TestCase` and call `self.assertIsValidUsd(stage)` on every produced stage. Diagnostic-checking tests use `usdex.test.ScopedDiagnosticChecker`. Outside of tests, run [USD Validation](../../../docs/devtools.md#asset-validator) on output. See `references/diagnostics-and-testing.md`.

## Canonical authoring flow (prose, not code)

The flow below applies whether you are writing one stage or an asset library. The reference files expand each step.

1. Activate the diagnostics delegate so SDK status messages stop printing to stdout. See `references/diagnostics-and-testing.md`.
2. Allocate a single `NameCache` for the whole conversion. Use it for every prim and property name you author. See `references/names.md`.
3. Define a module-level `AUTHORING_METADATA` string from the host application's identity and version. Pass it to every stage / layer call.
4. Create the stage with `usdex.core.createStage`, supplying `defaultPrimName=getValidPrimName(asset.name)`, `upAxis`, `linearUnits` (and `massUnits` if physics is involved), and `authoringMetadata=AUTHORING_METADATA`. See `references/stages-and-layers.md`.
5. For placeable assets (the typical converter output), define the default prim as `Xform` via `usdex.core.defineXform` — never leave it as the `Scope` fallback that `createStage` creates. Classify reusable assets with `configureComponentHierarchy` / `configureAssemblyHierarchy` (or rely on `addAssetInterface` for the multi-layer flow). See `references/asset-structure.md`.
6. Author content under the default prim using `usdex.core.define*` / `usdex.rtx.define*` helpers. For each prim:
    - Allocate the name through the cache.
    - Call the matching `define*` helper, passing typed data and any `PrimvarData`.
    - Apply API schemas (e.g. `UsdPhysicsRigidBodyAPI.Apply`) only after the prim is defined.
    - Set the local transform via `usdex.core.setLocalTransform` or by passing a transform to the `define*` helper.
    - For mesh normals use the source-provided `Vec3fPrimvarData` when available, or compute it when the source data lacks normals. Asset Validator's `NormalsExistChecker` rejects non-subdiv meshes that have no `primvars:normals` authored. When computing, use `usdex.core.computeMeshNormals` unless a higher fidelity mesh operation library is being used as well.
7. For multi-layer asset structure (Atomic Component, Library + Content + Interface layers), use `createAssetPayload` / `addAssetLibrary` / `addAssetContent` / `addAssetInterface`. See `references/asset-structure.md`.
8. For materials, prefer `usdex.core.definePbrMaterial` — it drives an OpenPBR shader for the `mtlx` render context and a Preview Surface for the universal context from one Material Interface. Use `definePreviewMaterial` when only the universal context is wanted, and `usdex.rtx.definePbrMaterial` / `defineGlassMaterial` when targeting the RTX Renderer specifically. Bind with `bindMaterial` / `bindMaterialSubsets`. See `references/materials.md`.
9. For physics, define visual / collision geometry first, then apply `UsdPhysicsRigidBodyAPI` / `UsdPhysicsCollisionAPI`, define `UsdPhysics.Scene` (raw schema), and use `definePhysicsFixedJoint` / `definePhysicsRevoluteJoint` / `definePhysicsPrismaticJoint` / `definePhysicsSphericalJoint` for joints. See `references/physics.md`.
10. Save with `usdex.core.saveStage(stage, AUTHORING_METADATA)`. For single-layer flows, use `saveLayer` / `exportLayer` instead. See `references/stages-and-layers.md`.
11. Validate the result with `usd_validation_nvidia.ValidationEngine` or `usdex.test.TestCase.assertIsValidUsd`. See `references/diagnostics-and-testing.md`.

## Reference index

Load only the files needed for the current task; this `SKILL.md` already contains the rules that apply to every domain.

| File | Read when the task involves |
| --- | --- |
| `references/stages-and-layers.md` | Creating, configuring, saving, or exporting stages / layers; choosing USDA vs USDC; layer authoring metadata; `Usd` → `Sdf` API moves in USD 25.11. |
| `references/names.md` | Any prim or property name; `NameCache`; `displayName` metadata; transcoding; the `USDEX_ENABLE_TRANSCODING` env setting. |
| `references/geometry.md` | Meshes, curves, points, basic gprims (sphere/cube/cone/cylinder/capsule/plane), subsets, primvars, normals computation. |
| `references/attributes.md` | Authoring values on schema-declared attributes, sparse layers, codeless schemas. |
| `references/materials.md` | OpenPBR (MaterialX), UsdPreviewSurface, and RTX MDL materials, textures, material interfaces, bindings, color space, primvar shaders. |
| `references/asset-structure.md` | Atomic Component assets, Library / Content / Interface layers, `defineReference` / `definePayload`, scopes, kinds. |
| `references/physics.md` | UsdPhysics scenes, rigid bodies, colliders, joints, physics materials, friction / restitution / density. |
| `references/lights.md` | `UsdLuxDomeLight`, `UsdLuxRectLight`, generic `UsdLuxLightAPI` attributes, the `inputs:` rename, dome pole axis. |
| `references/cameras.md` | `UsdGeomCamera` via `GfCamera`. |
| `references/diagnostics-and-testing.md` | Diagnostics delegate, `TF_DEBUG`, `usdex.test.TestCase`, `ScopedDiagnosticChecker`, USD Validation. |

## External references

- [Authoring USD Data](../../../docs/authoring-usd.md) — the SDK's own authoring narrative.
- [OpenUSD Exchange Samples](https://github.com/NVIDIA-Omniverse/usd-exchange-samples) — full end-to-end converters in matched C++ and Python.
- [Principles of Scalable Asset Structure](https://docs.omniverse.nvidia.com/usd/latest/learn-openusd/independent/asset-structure-principles.html.md) — background for the Asset Structure module.

