@dotdotdash/stunner-usd
v0.4.2
Published
USD/USDC/USDZ loader addon for @stunner/core
Readme
@dotdotdash/stunner-usd
Optional Universal Scene Description (USD/USDC/USDZ) loader for the
Stunner renderer. Translates a
composed USD stage into a RenderScene consumable by @dotdotdash/stunner-core — same
shape produced by the built-in glTF loader.
This package is a sibling addon to @dotdotdash/stunner-draco: it never imports
@dotdotdash/stunner-core's renderer internals or any 3D library, and @dotdotdash/stunner-core
itself does not depend on it. Add it only when you need USD assets.
Install
npm install @dotdotdash/stunner-usd fflatefflate is a peer dependency (used to unzip USDZ archives and to gunzip
compressed USDC layers).
Basic Usage
import { loadUsdSceneFromUrl } from '@dotdotdash/stunner-usd';
const { scene, cameras, warnings } = await loadUsdSceneFromUrl(
'/models/usd/Train.usdz',
);
for (const w of warnings) console.warn('[usd]', w);
engine.setScene(scene);
if (cameras[0]) engine.setCamera(cameras[0].camera);For raw bytes:
import { loadUsdSceneFromArrayBuffer } from '@dotdotdash/stunner-usd';
const result = await loadUsdSceneFromArrayBuffer(
bytes,
'memory://scene.usdz',
);Options
LoadUsdSceneOptions extends StageOpenOptions and BuildSceneOptions:
| Option | Type | Notes |
| ----------------- | --------------------------------- | ---------------------------------------------------------------- |
| resolver | AssetResolver | Custom asset resolver. Defaults to one backed by globalThis.fetch. |
| fetcher | (uri) => Promise<Uint8Array> | Used to construct the default resolver in non-browser contexts. |
| time | number | USD time code for value resolution. Defaults to defaultTime. |
| variantSelections | Record<string, string> | Forced variant choices ({ "/Asset.shadingVariant": "high" }). |
| purpose | ('render'\|'proxy'\|'guide')[] | Which purpose prims to include. Defaults to ['render']. |
| coordinateSystem | 'preserve' \| 'rh-y-up' | Convert from authored axis to right-handed Y-up if needed. |
What Is Returned
type UsdLoadResult = {
scene: RenderScene; // meshes, lights, textureLibrary, environment
cameras: Array<{ name: string; primPath: string; camera: Camera }>;
skeletons: SkelData[]; // UsdSkel rest pose + joint topology
stage: Stage; // composed stage for further introspection
warnings: string[]; // soft failures (unsupported prim types, etc.)
};USDZ-internal texture references appear in scene.textureLibrary with the
usd: prefix and the authored asset path. Resolve them to blob URLs (or your
own URLs) before handing the scene to the renderer — see
stunner-demo/src/examples/usd.ts for a concrete pattern.
Supported Subset
See stunner-core/documentation/usd-package.md
for the full schema-by-schema table. Highlights:
UsdGeomMesh,UsdGeomXform,UsdGeomCamera,UsdGeomPointInstancer.UsdLux*lights includingDomeLight→RenderScene.environmentIBL.UsdShadeMaterial+UsdPreviewSurface+UsdUVTexture(sampler config andsttransforms respected).UsdSkelSkeleton+UsdSkelBlendShape(rest pose + per-vertex morphs).- Time-sampled attributes with stepped + linear interpolation.
Limitations
Subdivision surfaces are rendered as their base mesh; volumes (OpenVDB) and displacement are unsupported. Morph targets run via WebGPU compute.
Hard exclusions: NURBS patches, USD physics schemas, Hydra render delegates,
MaterialX nodes outside the UsdPreviewSurface subset.
Architecture
URL / ArrayBuffer
→ AssetResolver fetch + USDZ unzip + gunzip
→ loadLayer USDA / USDC / USDZ auto-detect
→ compose LayerStack: sublayers, references, payloads, variants
→ ValueResolver time-sampled attribute resolution
→ schema/* converters Xform, Mesh, Material, Light, Camera, Skel, …
→ buildRenderScene → RenderScene, cameras, skeletons, warningsLower-level helpers (openStage, Stage, AssetResolver) are exported for
consumers that need to inspect the composed stage directly.
License
Same as the parent Stunner project (private).
