Convert between OpenUSD and glTF in both directions, in pure JavaScript with no dependencies. Runs in Node and the browser, live demo. Reads and writes all three USD encodings: text .usda, binary crate .usdc, and the .usdz package.
Work in progress, not yet published to npm.
npm install usd-gltf
import { usdToGLB, glbToUSD } from 'usd-gltf';
const glb = await usdToGLB( usdzBytes );
const usdz = await glbToUSD( glbBytes ); // or { format: 'usda' } / { format: 'usdc' }
Files that reference other files (a .gltf with .bin and textures, or a .usda with sublayers and references) need a resolver that returns the bytes for a relative path:
const usdz = await glbToUSD( gltfBytes, { resolver: ( uri ) => readFile( join( dir, uri ) ) } );
npx usd-gltf model.usdz model.glb
npx usd-gltf model.glb model.usdz
USD to glTF composes the stage first (sublayers, references, payloads, inherits, specializes, variant sets) and then converts:
metersPerUnitUsdPreviewSurface networks and MaterialX graphs built from ND_UsdPreviewSurface, ND_standard_surface and ND_open_pbr_surface, with textures repacked when glTF needs a different channel layoutKHR_materials_variants, animation variant sets as separate glTF animationsKHR_lights_punctual, PointInstancersglTF to USD writes UsdPreviewSurface materials, UsdSkel skins and blend shapes, time sampled animation, variant sets for material variants and multiple animations, cameras and lights. glTF features that UsdPreviewSurface can’t express (transmission, sheen, iridescence, …) are kept in the material’s customData, so converting back to glTF is lossless.
The acceptance corpora are every model in Apple’s AR Quick Look gallery and every model in the Khronos glTF Sample Assets. Conversions are checked against Pixar’s OpenUSD (usd-core) and the Khronos glTF Validator: per mesh triangle counts and world space bounds at several animation times, with skinning baked by OpenUSD, must match.
node scripts/fetch-corpus.js
MIT