usd-gltf 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +59 -2
- package/bin/usd-gltf.js +53 -0
- package/package.json +53 -4
- package/src/convert/gltf-to-usd.js +1807 -0
- package/src/convert/usd-material.js +1063 -0
- package/src/convert/usd-mesh.js +329 -0
- package/src/convert/usd-shapes.js +202 -0
- package/src/convert/usd-to-gltf.js +1325 -0
- package/src/detect.js +28 -0
- package/src/gltf/document.js +353 -0
- package/src/gltf/glb.js +105 -0
- package/src/gltf/meshopt.js +537 -0
- package/src/image/deflate.js +705 -0
- package/src/image/index.js +173 -0
- package/src/image/inflate.js +520 -0
- package/src/image/jpeg.js +1025 -0
- package/src/image/png.js +560 -0
- package/src/image/webp-tables.js +119 -0
- package/src/image/webp.js +1634 -0
- package/src/index.d.ts +71 -0
- package/src/index.js +67 -0
- package/src/usd/model.js +237 -0
- package/src/usd/stage.js +880 -0
- package/src/usd/usda/reader.js +869 -0
- package/src/usd/usda/writer.js +381 -0
- package/src/usd/usdc/intcompression.js +220 -0
- package/src/usd/usdc/lz4.js +295 -0
- package/src/usd/usdc/reader.js +1079 -0
- package/src/usd/usdc/types.js +162 -0
- package/src/usd/usdc/writer.js +1108 -0
- package/src/usd/usdz.js +141 -0
- package/src/usd/xform.js +99 -0
- package/src/util/crc32.js +18 -0
- package/src/util/math.js +235 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Richard Monette
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,60 @@
|
|
|
1
|
-
#
|
|
1
|
+
# usd-gltf
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Convert between [OpenUSD](https://openusd.org/) and [glTF](https://www.khronos.org/gltf/) in both directions, in pure JavaScript with no dependencies. Runs in Node and the browser, [live demo](https://richardmonette.github.io/usd-gltf/examples/). Reads and writes all three USD encodings: text `.usda`, binary crate `.usdc`, and the `.usdz` package.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
npm install usd-gltf
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
import { usdToGLB, glbToUSD } from 'usd-gltf';
|
|
11
|
+
|
|
12
|
+
const glb = await usdToGLB( usdzBytes );
|
|
13
|
+
const usdz = await glbToUSD( glbBytes ); // or { format: 'usda' } / { format: 'usdc' }
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
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:
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
const usdz = await glbToUSD( gltfBytes, { resolver: ( uri ) => readFile( join( dir, uri ) ) } );
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
npx usd-gltf model.usdz model.glb
|
|
24
|
+
npx usd-gltf model.glb model.usdz
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## What converts
|
|
28
|
+
|
|
29
|
+
USD to glTF composes the stage first (sublayers, references, payloads, inherits, specializes, variant sets) and then converts:
|
|
30
|
+
|
|
31
|
+
- Xform hierarchies, every xformOp type, animated transforms, up axis and `metersPerUnit`
|
|
32
|
+
- Meshes with any primvar interpolation, indexed primvars, GeomSubsets, holes and left handed orientation; Points, BasisCurves and the intrinsic shapes
|
|
33
|
+
- `UsdPreviewSurface` 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 layout
|
|
34
|
+
- UsdSkel skeletons, skinning and blend shapes
|
|
35
|
+
- Material variant sets as `KHR_materials_variants`, animation variant sets as separate glTF animations
|
|
36
|
+
- Cameras, UsdLux lights as `KHR_lights_punctual`, PointInstancers
|
|
37
|
+
|
|
38
|
+
glTF 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.
|
|
39
|
+
|
|
40
|
+
## Conformance
|
|
41
|
+
|
|
42
|
+
Current status:
|
|
43
|
+
|
|
44
|
+
- All 18 USD files in Apple's AR Quick Look gallery convert to GLB. Per mesh triangle counts and world space bounds at the start, middle and end of each animation match OpenUSD with skinning baked, and the Khronos glTF Validator reports no errors. (The gallery's three `.reality` files are RealityKit's format, not USD.)
|
|
45
|
+
- All 150 Khronos glTF sample models convert to USDZ that OpenUSD's validators accept with no errors or warnings, with geometry matching the source at several animation times, and convert back to glTF with identical materials, material variants and animations.
|
|
46
|
+
|
|
47
|
+
The acceptance corpora are every model in [Apple's AR Quick Look gallery](https://developer.apple.com/augmented-reality/quick-look/) and every model in the [Khronos glTF Sample Assets](https://github.com/KhronosGroup/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.
|
|
48
|
+
|
|
49
|
+
To run it locally (needs Python with `pip install usd-core`, in a `.venv` here or on `PATH`):
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
npm run fetch-corpus
|
|
53
|
+
npm run conformance
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The [Conformance workflow](.github/workflows/conformance.yml) runs the same check in CI.
|
|
57
|
+
|
|
58
|
+
## License
|
|
59
|
+
|
|
60
|
+
MIT
|
package/bin/usd-gltf.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { basename, dirname, extname, resolve } from 'node:path';
|
|
5
|
+
import { detectFormat, usdToGLB, glbToUSD } from '../src/index.js';
|
|
6
|
+
|
|
7
|
+
const [ input, output ] = process.argv.slice( 2 );
|
|
8
|
+
|
|
9
|
+
if ( ! input || ! output ) {
|
|
10
|
+
|
|
11
|
+
console.error( 'usage: usd-gltf <input.usd[a|c|z]|input.glb|input.gltf> <output.glb|output.usd[a|c|z]>' );
|
|
12
|
+
process.exit( 1 );
|
|
13
|
+
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const data = await readFile( input );
|
|
17
|
+
const from = detectFormat( data );
|
|
18
|
+
const to = extname( output ).slice( 1 ).toLowerCase();
|
|
19
|
+
|
|
20
|
+
// files referenced by relative paths (gltf buffers and textures, usd sublayers and references)
|
|
21
|
+
const dir = dirname( resolve( input ) );
|
|
22
|
+
const resolver = ( path ) => readFile( resolve( dir, path ) );
|
|
23
|
+
const log = ( message ) => console.warn( `warning: ${ message }` );
|
|
24
|
+
|
|
25
|
+
let result;
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
|
|
29
|
+
if ( from === 'usda' || from === 'usdc' || from === 'usdz' ) {
|
|
30
|
+
|
|
31
|
+
if ( to !== 'glb' ) throw new Error( `cannot write .${ to } from USD, use .glb` );
|
|
32
|
+
result = await usdToGLB( data, { identifier: resolve( input ).replace( /\\/g, '/' ), resolver, log } );
|
|
33
|
+
|
|
34
|
+
} else if ( from === 'glb' || from === 'gltf' ) {
|
|
35
|
+
|
|
36
|
+
const format = to === 'usd' ? 'usdc' : to;
|
|
37
|
+
if ( format !== 'usda' && format !== 'usdc' && format !== 'usdz' ) throw new Error( `cannot write .${ to } from glTF, use .usda, .usdc or .usdz` );
|
|
38
|
+
result = await glbToUSD( data, { format, resolver, log } );
|
|
39
|
+
|
|
40
|
+
} else {
|
|
41
|
+
|
|
42
|
+
throw new Error( `${ basename( input ) } is not a USD or glTF file` );
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
} catch ( e ) {
|
|
47
|
+
|
|
48
|
+
console.error( `usd-gltf: ${ e.message.replace( /^usd-gltf: /, '' ) }` );
|
|
49
|
+
process.exit( 1 );
|
|
50
|
+
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
await writeFile( output, result );
|
package/package.json
CHANGED
|
@@ -1,6 +1,55 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "usd-gltf",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Convert between USD (usda, usdc, usdz) and glTF / GLB, pure JavaScript with no dependencies",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"module": "src/index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./src/index.d.ts",
|
|
11
|
+
"default": "./src/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"bin": {
|
|
15
|
+
"usd-gltf": "bin/usd-gltf.js"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"src",
|
|
19
|
+
"bin"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"test": "node --test test/*.test.js",
|
|
23
|
+
"conformance": "node scripts/conformance.js",
|
|
24
|
+
"fetch-corpus": "node scripts/fetch-corpus.js"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=18"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"usd",
|
|
31
|
+
"usda",
|
|
32
|
+
"usdc",
|
|
33
|
+
"usdz",
|
|
34
|
+
"openusd",
|
|
35
|
+
"gltf",
|
|
36
|
+
"glb",
|
|
37
|
+
"converter",
|
|
38
|
+
"3d"
|
|
39
|
+
],
|
|
40
|
+
"author": "Richard Monette",
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "git+https://github.com/richardmonette/usd-gltf.git"
|
|
45
|
+
},
|
|
46
|
+
"bugs": {
|
|
47
|
+
"url": "https://github.com/richardmonette/usd-gltf/issues"
|
|
48
|
+
},
|
|
49
|
+
"homepage": "https://github.com/richardmonette/usd-gltf#readme",
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"gltf-validator": "^2.0.0-dev.3.10",
|
|
52
|
+
"meshoptimizer": "^1.3.0"
|
|
53
|
+
},
|
|
54
|
+
"types": "src/index.d.ts"
|
|
55
|
+
}
|