@loaders.gl/scene 5.0.0-beta.1 → 5.0.0-beta.10
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/DRACO-README.md +15 -0
- package/GLTF-README.md +1 -1
- package/OBJ-README.md +1 -1
- package/README.md +13 -2
- package/THIRD-PARTY-NOTICES.md +10 -1
- package/dist/dist.dev.js +21207 -14204
- package/dist/dist.min.js +32 -24
- package/dist/draco/bundled.cjs +34 -0
- package/dist/draco/bundled.cjs.map +7 -0
- package/dist/draco/bundled.d.ts +5 -0
- package/dist/draco/bundled.d.ts.map +1 -0
- package/dist/draco/bundled.js +6 -0
- package/dist/draco/bundled.js.map +1 -0
- package/dist/draco/draco-format.cjs +41 -0
- package/dist/draco/draco-format.cjs.map +7 -0
- package/dist/draco/draco-format.d.ts +15 -0
- package/dist/draco/draco-format.d.ts.map +1 -0
- package/dist/draco/draco-format.js +18 -0
- package/dist/draco/draco-format.js.map +1 -0
- package/dist/draco/draco-javascript-loader-with-parser.cjs +47 -0
- package/dist/draco/draco-javascript-loader-with-parser.cjs.map +7 -0
- package/dist/draco/draco-javascript-loader-with-parser.d.ts +36 -0
- package/dist/draco/draco-javascript-loader-with-parser.d.ts.map +1 -0
- package/dist/draco/draco-javascript-loader-with-parser.js +14 -0
- package/dist/draco/draco-javascript-loader-with-parser.js.map +1 -0
- package/dist/draco/draco-libraries.cjs +61 -0
- package/dist/draco/draco-libraries.cjs.map +7 -0
- package/dist/draco/draco-libraries.d.ts +28 -0
- package/dist/draco/draco-libraries.d.ts.map +1 -0
- package/dist/draco/draco-libraries.js +33 -0
- package/dist/draco/draco-libraries.js.map +1 -0
- package/dist/draco/draco-library-options.cjs +80 -0
- package/dist/draco/draco-library-options.cjs.map +7 -0
- package/dist/draco/draco-library-options.d.ts +16 -0
- package/dist/draco/draco-library-options.d.ts.map +1 -0
- package/dist/draco/draco-library-options.js +52 -0
- package/dist/draco/draco-library-options.js.map +1 -0
- package/dist/draco/draco-loader-options.cjs +37 -0
- package/dist/draco/draco-loader-options.cjs.map +7 -0
- package/dist/draco/draco-loader-options.d.ts +27 -0
- package/dist/draco/draco-loader-options.d.ts.map +1 -0
- package/dist/draco/draco-loader-options.js +12 -0
- package/dist/draco/draco-loader-options.js.map +1 -0
- package/dist/draco/draco-loader-types.cjs +87 -0
- package/dist/draco/draco-loader-types.cjs.map +7 -0
- package/dist/draco/draco-loader-types.d.ts +41 -0
- package/dist/draco/draco-loader-types.d.ts.map +1 -0
- package/dist/draco/draco-loader-types.js +54 -0
- package/dist/draco/draco-loader-types.js.map +1 -0
- package/dist/draco/draco-loader.cjs +51 -0
- package/dist/draco/draco-loader.cjs.map +7 -0
- package/dist/draco/draco-loader.d.ts +41 -0
- package/dist/draco/draco-loader.d.ts.map +1 -0
- package/dist/draco/draco-loader.js +22 -0
- package/dist/draco/draco-loader.js.map +1 -0
- package/dist/draco/draco-wasm-loader-with-parser.cjs +48 -0
- package/dist/draco/draco-wasm-loader-with-parser.cjs.map +7 -0
- package/dist/draco/draco-wasm-loader-with-parser.d.ts +36 -0
- package/dist/draco/draco-wasm-loader-with-parser.d.ts.map +1 -0
- package/dist/draco/draco-wasm-loader-with-parser.js +14 -0
- package/dist/draco/draco-wasm-loader-with-parser.js.map +1 -0
- package/dist/draco/draco-writer.cjs +183 -0
- package/dist/draco/draco-writer.cjs.map +7 -0
- package/dist/draco/draco-writer.d.ts +98 -0
- package/dist/draco/draco-writer.d.ts.map +1 -0
- package/dist/draco/draco-writer.js +166 -0
- package/dist/draco/draco-writer.js.map +1 -0
- package/dist/draco/draco3d/draco3d-types.cjs +76 -0
- package/dist/draco/draco3d/draco3d-types.cjs.map +7 -0
- package/dist/draco/draco3d/draco3d-types.d.ts +303 -0
- package/dist/draco/draco3d/draco3d-types.d.ts.map +1 -0
- package/dist/draco/draco3d/draco3d-types.js +47 -0
- package/dist/draco/draco3d/draco3d-types.js.map +1 -0
- package/dist/draco/draco3d-loader-with-parser.cjs +50 -0
- package/dist/draco/draco3d-loader-with-parser.cjs.map +7 -0
- package/dist/draco/draco3d-loader-with-parser.d.ts +36 -0
- package/dist/draco/draco3d-loader-with-parser.d.ts.map +1 -0
- package/dist/draco/draco3d-loader-with-parser.js +21 -0
- package/dist/draco/draco3d-loader-with-parser.js.map +1 -0
- package/dist/draco/index.cjs +51 -0
- package/dist/draco/index.cjs.map +7 -0
- package/dist/draco/index.d.ts +11 -0
- package/dist/draco/index.d.ts.map +1 -0
- package/dist/draco/index.js +10 -0
- package/dist/draco/index.js.map +1 -0
- package/dist/draco/lib/draco-builder.cjs +660 -0
- package/dist/draco/lib/draco-builder.cjs.map +7 -0
- package/dist/draco/lib/draco-builder.d.ts +175 -0
- package/dist/draco/lib/draco-builder.d.ts.map +1 -0
- package/dist/draco/lib/draco-builder.js +612 -0
- package/dist/draco/lib/draco-builder.js.map +1 -0
- package/dist/draco/lib/draco-library-loader.cjs +47 -0
- package/dist/draco/lib/draco-library-loader.cjs.map +7 -0
- package/dist/draco/lib/draco-library-loader.d.ts +5 -0
- package/dist/draco/lib/draco-library-loader.d.ts.map +1 -0
- package/dist/draco/lib/draco-library-loader.js +23 -0
- package/dist/draco/lib/draco-library-loader.js.map +1 -0
- package/dist/draco/lib/draco-module-loader.cjs +281 -0
- package/dist/draco/lib/draco-module-loader.cjs.map +7 -0
- package/dist/draco/lib/draco-module-loader.d.ts +25 -0
- package/dist/draco/lib/draco-module-loader.d.ts.map +1 -0
- package/dist/draco/lib/draco-module-loader.js +220 -0
- package/dist/draco/lib/draco-module-loader.js.map +1 -0
- package/dist/draco/lib/draco-parser.cjs +601 -0
- package/dist/draco/lib/draco-parser.cjs.map +7 -0
- package/dist/draco/lib/draco-parser.d.ts +143 -0
- package/dist/draco/lib/draco-parser.d.ts.map +1 -0
- package/dist/draco/lib/draco-parser.js +598 -0
- package/dist/draco/lib/draco-parser.js.map +1 -0
- package/dist/draco/lib/draco-types.cjs +19 -0
- package/dist/draco/lib/draco-types.cjs.map +7 -0
- package/dist/draco/lib/draco-types.d.ts +59 -0
- package/dist/draco/lib/draco-types.d.ts.map +1 -0
- package/dist/draco/lib/draco-types.js +5 -0
- package/dist/draco/lib/draco-types.js.map +1 -0
- package/dist/draco/lib/parse-draco.cjs +60 -0
- package/dist/draco/lib/parse-draco.cjs.map +7 -0
- package/dist/draco/lib/parse-draco.d.ts +22 -0
- package/dist/draco/lib/parse-draco.d.ts.map +1 -0
- package/dist/draco/lib/parse-draco.js +33 -0
- package/dist/draco/lib/parse-draco.js.map +1 -0
- package/dist/draco/lib/utils/get-draco-schema.cjs +74 -0
- package/dist/draco/lib/utils/get-draco-schema.cjs.map +7 -0
- package/dist/draco/lib/utils/get-draco-schema.d.ts +7 -0
- package/dist/draco/lib/utils/get-draco-schema.d.ts.map +1 -0
- package/dist/draco/lib/utils/get-draco-schema.js +45 -0
- package/dist/draco/lib/utils/get-draco-schema.js.map +1 -0
- package/dist/draco/lib/utils/version.cjs +31 -0
- package/dist/draco/lib/utils/version.cjs.map +7 -0
- package/dist/draco/lib/utils/version.d.ts +2 -0
- package/dist/draco/lib/utils/version.d.ts.map +1 -0
- package/dist/draco/lib/utils/version.js +8 -0
- package/dist/draco/lib/utils/version.js.map +1 -0
- package/dist/draco/unbundled.cjs +31 -0
- package/dist/draco/unbundled.cjs.map +7 -0
- package/dist/draco/unbundled.d.ts +3 -0
- package/dist/draco/unbundled.d.ts.map +1 -0
- package/dist/draco/unbundled.js +5 -0
- package/dist/draco/unbundled.js.map +1 -0
- package/dist/draco/workers/draco-worker-node.cjs +8 -0
- package/dist/draco/workers/draco-worker-node.cjs.map +7 -0
- package/dist/draco/workers/draco-worker-node.d.ts +2 -0
- package/dist/draco/workers/draco-worker-node.d.ts.map +1 -0
- package/dist/draco/workers/draco-worker-node.js +9 -0
- package/dist/draco/workers/draco-worker-node.js.map +1 -0
- package/dist/draco/workers/draco-worker.cjs +7 -0
- package/dist/draco/workers/draco-worker.cjs.map +7 -0
- package/dist/draco/workers/draco-worker.d.ts +2 -0
- package/dist/draco/workers/draco-worker.d.ts.map +1 -0
- package/dist/draco/workers/draco-worker.js +7 -0
- package/dist/draco/workers/draco-worker.js.map +1 -0
- package/dist/draco/workers/draco-writer-worker-node.cjs +11 -0
- package/dist/draco/workers/draco-writer-worker-node.cjs.map +7 -0
- package/dist/draco/workers/draco-writer-worker-node.d.cts +2 -0
- package/dist/draco/workers/draco-writer-worker-node.d.cts.map +1 -0
- package/dist/draco/workers/draco-writer-worker-node.d.ts +2 -0
- package/dist/draco/workers/draco-writer-worker-node.d.ts.map +1 -0
- package/dist/draco/workers/draco-writer-worker-node.js +9 -0
- package/dist/draco/workers/draco-writer-worker-node.js.map +1 -0
- package/dist/draco/workers/draco-writer-worker.cjs +10 -0
- package/dist/draco/workers/draco-writer-worker.cjs.map +7 -0
- package/dist/draco/workers/draco-writer-worker.d.ts +2 -0
- package/dist/draco/workers/draco-writer-worker.d.ts.map +1 -0
- package/dist/draco/workers/draco-writer-worker.js +7 -0
- package/dist/draco/workers/draco-writer-worker.js.map +1 -0
- package/dist/draco-javascript-loader.cjs +25 -0
- package/dist/draco-javascript-loader.cjs.map +7 -0
- package/dist/draco-javascript-loader.d.ts +2 -0
- package/dist/draco-javascript-loader.d.ts.map +1 -0
- package/dist/draco-javascript-loader.js +3 -0
- package/dist/draco-javascript-loader.js.map +1 -0
- package/dist/draco-library-options.cjs +36 -0
- package/dist/draco-library-options.cjs.map +7 -0
- package/dist/draco-library-options.d.ts +3 -0
- package/dist/draco-library-options.d.ts.map +1 -0
- package/dist/draco-library-options.js +4 -0
- package/dist/draco-library-options.js.map +1 -0
- package/dist/draco-loader-types.cjs +25 -0
- package/dist/draco-loader-types.cjs.map +7 -0
- package/dist/draco-loader-types.d.ts +2 -0
- package/dist/draco-loader-types.d.ts.map +1 -0
- package/dist/draco-loader-types.js +3 -0
- package/dist/draco-loader-types.js.map +1 -0
- package/dist/draco-loader.cjs +25 -0
- package/dist/draco-loader.cjs.map +7 -0
- package/dist/draco-loader.d.ts +2 -0
- package/dist/draco-loader.d.ts.map +1 -0
- package/dist/draco-loader.js +3 -0
- package/dist/draco-loader.js.map +1 -0
- package/dist/draco-wasm-loader.cjs +25 -0
- package/dist/draco-wasm-loader.cjs.map +7 -0
- package/dist/draco-wasm-loader.d.ts +2 -0
- package/dist/draco-wasm-loader.d.ts.map +1 -0
- package/dist/draco-wasm-loader.js +3 -0
- package/dist/draco-wasm-loader.js.map +1 -0
- package/dist/draco-worker-node.js +29842 -0
- package/dist/draco-worker-node.js.map +7 -0
- package/dist/draco-worker.js +19668 -0
- package/dist/draco-worker.js.map +7 -0
- package/dist/draco-writer-worker-node.cjs +30022 -0
- package/dist/draco-writer-worker-node.cjs.map +7 -0
- package/dist/draco-writer-worker.js +19767 -0
- package/dist/draco-writer-worker.js.map +7 -0
- package/dist/draco-writer.cjs +25 -0
- package/dist/draco-writer.cjs.map +7 -0
- package/dist/draco-writer.d.ts +2 -0
- package/dist/draco-writer.d.ts.map +1 -0
- package/dist/draco-writer.js +3 -0
- package/dist/draco-writer.js.map +1 -0
- package/dist/draco3d-loader.cjs +25 -0
- package/dist/draco3d-loader.cjs.map +7 -0
- package/dist/draco3d-loader.d.ts +2 -0
- package/dist/draco3d-loader.d.ts.map +1 -0
- package/dist/draco3d-loader.js +3 -0
- package/dist/draco3d-loader.js.map +1 -0
- package/dist/glb-loader-types.cjs +61 -0
- package/dist/glb-loader-types.cjs.map +7 -0
- package/dist/glb-loader-types.d.ts +2 -0
- package/dist/glb-loader-types.d.ts.map +1 -0
- package/dist/glb-loader-types.js +2 -0
- package/dist/glb-loader-types.js.map +1 -0
- package/dist/glb-loader.cjs +48 -0
- package/dist/glb-loader.cjs.map +7 -0
- package/dist/glb-loader.d.ts +2 -0
- package/dist/glb-loader.d.ts.map +1 -0
- package/dist/glb-loader.js +2 -0
- package/dist/glb-loader.js.map +1 -0
- package/dist/glb-writer.cjs +53 -0
- package/dist/glb-writer.cjs.map +7 -0
- package/dist/glb-writer.d.ts +2 -0
- package/dist/glb-writer.d.ts.map +1 -0
- package/dist/glb-writer.js +2 -0
- package/dist/glb-writer.js.map +1 -0
- package/dist/gltf/glb-loader-types.cjs +1 -1
- package/dist/gltf/glb-loader-types.cjs.map +2 -2
- package/dist/gltf/glb-loader-types.d.ts +2 -2
- package/dist/gltf/glb-loader-types.js +1 -1
- package/dist/gltf/glb-loader-types.js.map +1 -1
- package/dist/gltf/gltf-loader-types.cjs +1 -1
- package/dist/gltf/gltf-loader-types.cjs.map +2 -2
- package/dist/gltf/gltf-loader-types.d.ts +11 -5
- package/dist/gltf/gltf-loader-types.d.ts.map +1 -1
- package/dist/gltf/gltf-loader-types.js +1 -1
- package/dist/gltf/gltf-loader-types.js.map +1 -1
- package/dist/gltf/gltf-loader.cjs.map +1 -1
- package/dist/gltf/gltf-loader.d.ts +4 -4
- package/dist/gltf/gltf-loader.d.ts.map +1 -1
- package/dist/gltf/index.cjs +2 -0
- package/dist/gltf/index.cjs.map +2 -2
- package/dist/gltf/index.d.ts +2 -2
- package/dist/gltf/index.d.ts.map +1 -1
- package/dist/gltf/index.js +1 -1
- package/dist/gltf/index.js.map +1 -1
- package/dist/gltf/lib/api/gltf-extensions.cjs +7 -2
- package/dist/gltf/lib/api/gltf-extensions.cjs.map +2 -2
- package/dist/gltf/lib/api/gltf-extensions.d.ts.map +1 -1
- package/dist/gltf/lib/api/gltf-extensions.js +7 -5
- package/dist/gltf/lib/api/gltf-extensions.js.map +1 -1
- package/dist/gltf/lib/encoders/encode-gltf-draco.cjs +12 -2
- package/dist/gltf/lib/encoders/encode-gltf-draco.cjs.map +2 -2
- package/dist/gltf/lib/encoders/encode-gltf-draco.d.ts +1 -1
- package/dist/gltf/lib/encoders/encode-gltf-draco.d.ts.map +1 -1
- package/dist/gltf/lib/encoders/encode-gltf-draco.js +1 -1
- package/dist/gltf/lib/encoders/encode-gltf-draco.js.map +1 -1
- package/dist/gltf/lib/extensions/EXT_texture_webp.cjs +1 -0
- package/dist/gltf/lib/extensions/EXT_texture_webp.cjs.map +2 -2
- package/dist/gltf/lib/extensions/EXT_texture_webp.d.ts.map +1 -1
- package/dist/gltf/lib/extensions/EXT_texture_webp.js +3 -0
- package/dist/gltf/lib/extensions/EXT_texture_webp.js.map +1 -1
- package/dist/gltf/lib/extensions/KHR_accessor_float64.cjs +45 -0
- package/dist/gltf/lib/extensions/KHR_accessor_float64.cjs.map +7 -0
- package/dist/gltf/lib/extensions/KHR_accessor_float64.d.ts +6 -0
- package/dist/gltf/lib/extensions/KHR_accessor_float64.d.ts.map +1 -0
- package/dist/gltf/lib/extensions/KHR_accessor_float64.js +20 -0
- package/dist/gltf/lib/extensions/KHR_accessor_float64.js.map +1 -0
- package/dist/gltf/lib/extensions/KHR_draco_mesh_compression.cjs +2 -2
- package/dist/gltf/lib/extensions/KHR_draco_mesh_compression.cjs.map +2 -2
- package/dist/gltf/lib/extensions/KHR_draco_mesh_compression.d.ts.map +1 -1
- package/dist/gltf/lib/extensions/KHR_draco_mesh_compression.js +1 -1
- package/dist/gltf/lib/extensions/KHR_draco_mesh_compression.js.map +1 -1
- package/dist/gltf/lib/extensions/KHR_gaussian_splatting.cjs +23 -7
- package/dist/gltf/lib/extensions/KHR_gaussian_splatting.cjs.map +2 -2
- package/dist/gltf/lib/extensions/KHR_gaussian_splatting.d.ts +2 -1
- package/dist/gltf/lib/extensions/KHR_gaussian_splatting.d.ts.map +1 -1
- package/dist/gltf/lib/extensions/KHR_gaussian_splatting.js +21 -5
- package/dist/gltf/lib/extensions/KHR_gaussian_splatting.js.map +1 -1
- package/dist/gltf/lib/extensions/MSFT_texture_dds.cjs +64 -0
- package/dist/gltf/lib/extensions/MSFT_texture_dds.cjs.map +7 -0
- package/dist/gltf/lib/extensions/MSFT_texture_dds.d.ts +12 -0
- package/dist/gltf/lib/extensions/MSFT_texture_dds.d.ts.map +1 -0
- package/dist/gltf/lib/extensions/MSFT_texture_dds.js +39 -0
- package/dist/gltf/lib/extensions/MSFT_texture_dds.js.map +1 -0
- package/dist/gltf/lib/extensions/utils/3d-tiles-utils.cjs +1 -1
- package/dist/gltf/lib/extensions/utils/3d-tiles-utils.cjs.map +2 -2
- package/dist/gltf/lib/extensions/utils/3d-tiles-utils.d.ts.map +1 -1
- package/dist/gltf/lib/extensions/utils/3d-tiles-utils.js +3 -1
- package/dist/gltf/lib/extensions/utils/3d-tiles-utils.js.map +1 -1
- package/dist/gltf/lib/parsers/parse-gltf.cjs +34 -8
- package/dist/gltf/lib/parsers/parse-gltf.cjs.map +3 -3
- package/dist/gltf/lib/parsers/parse-gltf.d.ts +2 -0
- package/dist/gltf/lib/parsers/parse-gltf.d.ts.map +1 -1
- package/dist/gltf/lib/parsers/parse-gltf.js +26 -6
- package/dist/gltf/lib/parsers/parse-gltf.js.map +1 -1
- package/dist/gltf/lib/types/gltf-additional-extension-schemas.cjs +22 -0
- package/dist/gltf/lib/types/gltf-additional-extension-schemas.cjs.map +2 -2
- package/dist/gltf/lib/types/gltf-additional-extension-schemas.d.ts +23 -0
- package/dist/gltf/lib/types/gltf-additional-extension-schemas.d.ts.map +1 -1
- package/dist/gltf/lib/types/gltf-additional-extension-schemas.js +22 -0
- package/dist/gltf/lib/types/gltf-additional-extension-schemas.js.map +1 -1
- package/dist/gltf/lib/types/gltf-ext-gaussian-splatting-schema.cjs.map +1 -1
- package/dist/gltf/lib/types/gltf-ext-gaussian-splatting-schema.d.ts +1 -1
- package/dist/gltf/lib/types/gltf-ext-gaussian-splatting-schema.d.ts.map +1 -1
- package/dist/gltf/lib/types/gltf-extension-schemas.cjs +8 -0
- package/dist/gltf/lib/types/gltf-extension-schemas.cjs.map +2 -2
- package/dist/gltf/lib/types/gltf-extension-schemas.d.ts +27 -0
- package/dist/gltf/lib/types/gltf-extension-schemas.d.ts.map +1 -1
- package/dist/gltf/lib/types/gltf-extension-schemas.js +8 -1
- package/dist/gltf/lib/types/gltf-extension-schemas.js.map +1 -1
- package/dist/gltf/lib/types/gltf-json-schema.cjs.map +1 -1
- package/dist/gltf/lib/types/gltf-json-schema.d.ts +2 -2
- package/dist/gltf/lib/types/gltf-json-schema.d.ts.map +1 -1
- package/dist/gltf/lib/types/gltf-texture-procedurals.cjs +19 -0
- package/dist/gltf/lib/types/gltf-texture-procedurals.cjs.map +7 -0
- package/dist/gltf/lib/types/gltf-texture-procedurals.d.ts +45 -0
- package/dist/gltf/lib/types/gltf-texture-procedurals.d.ts.map +1 -0
- package/dist/gltf/lib/types/gltf-texture-procedurals.js +5 -0
- package/dist/gltf/lib/types/gltf-texture-procedurals.js.map +1 -0
- package/dist/gltf/lib/types/gltf-types.cjs.map +1 -1
- package/dist/gltf/lib/types/gltf-types.d.ts +7 -0
- package/dist/gltf/lib/types/gltf-types.d.ts.map +1 -1
- package/dist/gltf/lib/types/gltf-version-zod-schemas.d.ts +34 -0
- package/dist/gltf/lib/types/gltf-version-zod-schemas.d.ts.map +1 -1
- package/dist/gltf/lib/types/gltf-zod-schema.cjs +4 -1
- package/dist/gltf/lib/types/gltf-zod-schema.cjs.map +2 -2
- package/dist/gltf/lib/types/gltf-zod-schema.d.ts +57 -1
- package/dist/gltf/lib/types/gltf-zod-schema.d.ts.map +1 -1
- package/dist/gltf/lib/types/gltf-zod-schema.js +6 -2
- package/dist/gltf/lib/types/gltf-zod-schema.js.map +1 -1
- package/dist/gltf/lib/utils/version.cjs +1 -1
- package/dist/gltf/lib/utils/version.cjs.map +1 -1
- package/dist/gltf/lib/utils/version.js +1 -1
- package/dist/gltf/lib/utils/version.js.map +1 -1
- package/dist/gltf/schema.cjs +3 -0
- package/dist/gltf/schema.cjs.map +2 -2
- package/dist/gltf/schema.d.ts +1 -0
- package/dist/gltf/schema.d.ts.map +1 -1
- package/dist/gltf/schema.js +1 -0
- package/dist/gltf/schema.js.map +1 -1
- package/dist/gltf-loader-types.cjs +73 -0
- package/dist/gltf-loader-types.cjs.map +7 -0
- package/dist/gltf-loader-types.d.ts +2 -0
- package/dist/gltf-loader-types.d.ts.map +1 -0
- package/dist/gltf-loader-types.js +2 -0
- package/dist/gltf-loader-types.js.map +1 -0
- package/dist/gltf-loader.cjs +48 -0
- package/dist/gltf-loader.cjs.map +7 -0
- package/dist/gltf-loader.d.ts +2 -0
- package/dist/gltf-loader.d.ts.map +1 -0
- package/dist/gltf-loader.js +2 -0
- package/dist/gltf-loader.js.map +1 -0
- package/dist/gltf-source.cjs +238 -0
- package/dist/gltf-source.cjs.map +7 -0
- package/dist/gltf-source.d.ts +2 -0
- package/dist/gltf-source.d.ts.map +1 -0
- package/dist/gltf-source.js +2 -0
- package/dist/gltf-source.js.map +1 -0
- package/dist/gltf-writer.cjs +69 -0
- package/dist/gltf-writer.cjs.map +7 -0
- package/dist/gltf-writer.d.ts +2 -0
- package/dist/gltf-writer.d.ts.map +1 -0
- package/dist/gltf-writer.js +2 -0
- package/dist/gltf-writer.js.map +1 -0
- package/dist/index.cjs +18 -5
- package/dist/index.cjs.map +2 -2
- package/dist/index.d.ts +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -3
- package/dist/index.js.map +1 -1
- package/dist/libs/DRACO-LICENSE +252 -0
- package/dist/libs/README.md +20 -0
- package/dist/libs/draco_decoder.js +34 -0
- package/dist/libs/draco_decoder.mjs +37 -0
- package/dist/libs/draco_decoder.wasm +0 -0
- package/dist/libs/draco_decoder_gltf.wasm +0 -0
- package/dist/libs/draco_encoder.js +98 -0
- package/dist/libs/draco_encoder.mjs +101 -0
- package/dist/libs/draco_encoder.wasm +0 -0
- package/dist/libs/draco_wasm_wrapper.js +117 -0
- package/dist/libs/draco_wasm_wrapper.mjs +120 -0
- package/dist/libs/draco_wasm_wrapper_gltf.js +116 -0
- package/dist/libs/draco_wasm_wrapper_gltf.mjs +119 -0
- package/dist/materialx/parse-materialx.cjs +61 -0
- package/dist/materialx/parse-materialx.cjs.map +7 -0
- package/dist/materialx/parse-materialx.d.ts +23 -0
- package/dist/materialx/parse-materialx.d.ts.map +1 -0
- package/dist/materialx/parse-materialx.js +39 -0
- package/dist/materialx/parse-materialx.js.map +1 -0
- package/dist/materialx/procedural-graph.cjs +77 -0
- package/dist/materialx/procedural-graph.cjs.map +7 -0
- package/dist/materialx/procedural-graph.d.ts +40 -0
- package/dist/materialx/procedural-graph.d.ts.map +1 -0
- package/dist/materialx/procedural-graph.js +59 -0
- package/dist/materialx/procedural-graph.js.map +1 -0
- package/dist/materialx-loader-types.cjs +57 -0
- package/dist/materialx-loader-types.cjs.map +7 -0
- package/dist/materialx-loader-types.d.ts +34 -0
- package/dist/materialx-loader-types.d.ts.map +1 -0
- package/dist/materialx-loader-types.js +20 -0
- package/dist/materialx-loader-types.js.map +1 -0
- package/dist/materialx-loader.cjs +40 -0
- package/dist/materialx-loader.cjs.map +7 -0
- package/dist/materialx-loader.d.ts +19 -0
- package/dist/materialx-loader.d.ts.map +1 -0
- package/dist/materialx-loader.js +14 -0
- package/dist/materialx-loader.js.map +1 -0
- package/dist/mtl-loader-types.cjs +61 -0
- package/dist/mtl-loader-types.cjs.map +7 -0
- package/dist/mtl-loader-types.d.ts +2 -0
- package/dist/mtl-loader-types.d.ts.map +1 -0
- package/dist/mtl-loader-types.js +2 -0
- package/dist/mtl-loader-types.js.map +1 -0
- package/dist/mtl-loader.cjs +47 -0
- package/dist/mtl-loader.cjs.map +7 -0
- package/dist/mtl-loader.d.ts +2 -0
- package/dist/mtl-loader.d.ts.map +1 -0
- package/dist/mtl-loader.js +2 -0
- package/dist/mtl-loader.js.map +1 -0
- package/dist/obj/bundled.cjs +2 -4
- package/dist/obj/bundled.cjs.map +2 -2
- package/dist/obj/bundled.d.ts +1 -1
- package/dist/obj/bundled.d.ts.map +1 -1
- package/dist/obj/bundled.js +1 -1
- package/dist/obj/bundled.js.map +1 -1
- package/dist/obj/index.cjs +0 -6
- package/dist/obj/index.cjs.map +3 -3
- package/dist/obj/index.d.ts +0 -4
- package/dist/obj/index.d.ts.map +1 -1
- package/dist/obj/index.js +0 -5
- package/dist/obj/index.js.map +1 -1
- package/dist/obj/mtl-loader-types.cjs +4 -7
- package/dist/obj/mtl-loader-types.cjs.map +2 -2
- package/dist/obj/mtl-loader-types.d.ts +2 -22
- package/dist/obj/mtl-loader-types.d.ts.map +1 -1
- package/dist/obj/mtl-loader-types.js +2 -4
- package/dist/obj/mtl-loader-types.js.map +1 -1
- package/dist/obj/mtl-loader.cjs +1 -1
- package/dist/obj/mtl-loader.cjs.map +2 -2
- package/dist/obj/mtl-loader.js +1 -1
- package/dist/obj/mtl-loader.js.map +1 -1
- package/dist/obj/obj-loader-types.cjs +9 -10
- package/dist/obj/obj-loader-types.cjs.map +2 -2
- package/dist/obj/obj-loader-types.d.ts +19 -39
- package/dist/obj/obj-loader-types.d.ts.map +1 -1
- package/dist/obj/obj-loader-types.js +6 -6
- package/dist/obj/obj-loader-types.js.map +1 -1
- package/dist/obj/obj-loader.cjs +63 -31
- package/dist/obj/obj-loader.cjs.map +3 -3
- package/dist/obj/obj-loader.d.ts +43 -9
- package/dist/obj/obj-loader.d.ts.map +1 -1
- package/dist/obj/obj-loader.js +61 -22
- package/dist/obj/obj-loader.js.map +1 -1
- package/dist/obj/obj-writer.cjs +3 -3
- package/dist/obj/obj-writer.cjs.map +2 -2
- package/dist/obj/obj-writer.d.ts +5 -4
- package/dist/obj/obj-writer.d.ts.map +1 -1
- package/dist/obj/obj-writer.js +4 -4
- package/dist/obj/obj-writer.js.map +1 -1
- package/dist/obj/unbundled.cjs +2 -6
- package/dist/obj/unbundled.cjs.map +2 -2
- package/dist/obj/unbundled.d.ts +2 -2
- package/dist/obj/unbundled.d.ts.map +1 -1
- package/dist/obj/unbundled.js +2 -2
- package/dist/obj/unbundled.js.map +1 -1
- package/dist/obj/workers/obj-worker.cjs +5 -5
- package/dist/obj/workers/obj-worker.cjs.map +2 -2
- package/dist/obj/workers/obj-worker.js +6 -6
- package/dist/obj/workers/obj-worker.js.map +1 -1
- package/dist/obj-loader-types.cjs +70 -0
- package/dist/obj-loader-types.cjs.map +7 -0
- package/dist/obj-loader-types.d.ts +2 -0
- package/dist/obj-loader-types.d.ts.map +1 -0
- package/dist/obj-loader-types.js +2 -0
- package/dist/obj-loader-types.js.map +1 -0
- package/dist/obj-loader.cjs +195 -0
- package/dist/obj-loader.cjs.map +7 -0
- package/dist/obj-loader.d.ts +2 -0
- package/dist/obj-loader.d.ts.map +1 -0
- package/dist/obj-loader.js +2 -0
- package/dist/obj-loader.js.map +1 -0
- package/dist/obj-worker.js +1420 -406
- package/dist/obj-writer.cjs +167 -0
- package/dist/obj-writer.cjs.map +7 -0
- package/dist/obj-writer.d.ts +2 -0
- package/dist/obj-writer.d.ts.map +1 -0
- package/dist/obj-writer.js +2 -0
- package/dist/obj-writer.js.map +1 -0
- package/dist/stl/parse-stl.cjs +100 -0
- package/dist/stl/parse-stl.cjs.map +7 -0
- package/dist/stl/parse-stl.d.ts +4 -0
- package/dist/stl/parse-stl.d.ts.map +1 -0
- package/dist/stl/parse-stl.js +84 -0
- package/dist/stl/parse-stl.js.map +1 -0
- package/dist/stl-loader-types.cjs +58 -0
- package/dist/stl-loader-types.cjs.map +7 -0
- package/dist/stl-loader-types.d.ts +32 -0
- package/dist/stl-loader-types.d.ts.map +1 -0
- package/dist/stl-loader-types.js +25 -0
- package/dist/stl-loader-types.js.map +1 -0
- package/dist/stl-loader.cjs +38 -0
- package/dist/stl-loader.cjs.map +7 -0
- package/dist/stl-loader.d.ts +17 -0
- package/dist/stl-loader.d.ts.map +1 -0
- package/dist/stl-loader.js +13 -0
- package/dist/stl-loader.js.map +1 -0
- package/dist/usd/index.cjs.map +1 -1
- package/dist/usd/index.d.ts +1 -1
- package/dist/usd/index.d.ts.map +1 -1
- package/dist/usd/lib/parse-usd.cjs +42 -5
- package/dist/usd/lib/parse-usd.cjs.map +2 -2
- package/dist/usd/lib/parse-usd.d.ts.map +1 -1
- package/dist/usd/lib/parse-usd.js +53 -6
- package/dist/usd/lib/parse-usd.js.map +1 -1
- package/dist/usd/lib/parse-usdc.cjs +187 -0
- package/dist/usd/lib/parse-usdc.cjs.map +7 -0
- package/dist/usd/lib/parse-usdc.d.ts +4 -0
- package/dist/usd/lib/parse-usdc.d.ts.map +1 -0
- package/dist/usd/lib/parse-usdc.js +176 -0
- package/dist/usd/lib/parse-usdc.js.map +1 -0
- package/dist/usd/lib/parse-usdz.cjs +22 -0
- package/dist/usd/lib/parse-usdz.cjs.map +2 -2
- package/dist/usd/lib/parse-usdz.d.ts.map +1 -1
- package/dist/usd/lib/parse-usdz.js +26 -0
- package/dist/usd/lib/parse-usdz.js.map +1 -1
- package/dist/usd/lib/usd-types.cjs.map +1 -1
- package/dist/usd/lib/usd-types.d.ts +14 -1
- package/dist/usd/lib/usd-types.d.ts.map +1 -1
- package/dist/usd/lib/usd-types.js +1 -1
- package/dist/usd/lib/usd-types.js.map +1 -1
- package/dist/usd/libs/README.md +27 -0
- package/dist/usd/libs/THREE-LICENSE +21 -0
- package/dist/usd/libs/usdc-parser.d.ts +78 -0
- package/dist/usd/libs/usdc-parser.d.ts.map +1 -0
- package/dist/usd/libs/usdc-parser.js +1669 -0
- package/dist/usd/libs/usdc-parser.js.map +1 -0
- package/dist/usd/usd-loader-types.cjs +5 -5
- package/dist/usd/usd-loader-types.cjs.map +2 -2
- package/dist/usd/usd-loader-types.d.ts +7 -7
- package/dist/usd/usd-loader-types.d.ts.map +1 -1
- package/dist/usd/usd-loader-types.js +7 -7
- package/dist/usd/usd-loader-types.js.map +1 -1
- package/dist/usd/usd-loader.cjs.map +1 -1
- package/dist/usd/usd-loader.d.ts +4 -4
- package/dist/usd/usd-loader.d.ts.map +1 -1
- package/dist/usd/usd-loader.js +2 -2
- package/dist/usd/usd-loader.js.map +1 -1
- package/dist/usd-loader-types.cjs +69 -0
- package/dist/usd-loader-types.cjs.map +7 -0
- package/dist/usd-loader-types.d.ts +2 -0
- package/dist/usd-loader-types.d.ts.map +1 -0
- package/dist/usd-loader-types.js +2 -0
- package/dist/usd-loader-types.js.map +1 -0
- package/dist/usd-loader.cjs +43 -0
- package/dist/usd-loader.cjs.map +7 -0
- package/dist/usd-loader.d.ts +2 -0
- package/dist/usd-loader.d.ts.map +1 -0
- package/dist/usd-loader.js +2 -0
- package/dist/usd-loader.js.map +1 -0
- package/package.json +144 -72
- package/src/draco/bundled.ts +9 -0
- package/src/draco/draco-format.ts +20 -0
- package/src/draco/draco-javascript-loader-with-parser.ts +30 -0
- package/src/draco/draco-libraries.ts +35 -0
- package/src/draco/draco-library-options.ts +76 -0
- package/src/draco/draco-loader-options.ts +33 -0
- package/src/draco/draco-loader-types.ts +77 -0
- package/src/draco/draco-loader.ts +45 -0
- package/src/draco/draco-wasm-loader-with-parser.ts +31 -0
- package/src/draco/draco-writer.ts +254 -0
- package/src/draco/draco3d/draco3d-types.ts +498 -0
- package/src/draco/draco3d-loader-with-parser.ts +34 -0
- package/src/draco/index.ts +42 -0
- package/src/draco/lib/draco-builder.ts +935 -0
- package/src/draco/lib/draco-library-loader.ts +38 -0
- package/src/draco/lib/draco-module-loader.ts +370 -0
- package/src/draco/lib/draco-parser.ts +779 -0
- package/src/draco/lib/draco-types.ts +72 -0
- package/src/draco/lib/parse-draco.ts +52 -0
- package/src/draco/lib/utils/get-draco-schema.ts +65 -0
- package/src/draco/lib/utils/version.ts +8 -0
- package/src/draco/libs/DRACO-LICENSE +252 -0
- package/src/draco/libs/README.md +20 -0
- package/src/draco/libs/draco_decoder.js +34 -0
- package/src/draco/libs/draco_decoder.wasm +0 -0
- package/src/draco/libs/draco_decoder_gltf.wasm +0 -0
- package/src/draco/libs/draco_encoder.js +98 -0
- package/src/draco/libs/draco_encoder.wasm +0 -0
- package/src/draco/libs/draco_wasm_wrapper.js +117 -0
- package/src/draco/libs/draco_wasm_wrapper_gltf.js +116 -0
- package/src/draco/unbundled.ts +6 -0
- package/src/draco/workers/draco-worker-node.ts +10 -0
- package/src/draco/workers/draco-worker.ts +8 -0
- package/src/draco/workers/draco-writer-worker-node.cjs +21 -0
- package/src/draco/workers/draco-writer-worker-node.ts +13 -0
- package/src/draco/workers/draco-writer-worker.ts +11 -0
- package/src/draco-javascript-loader.ts +2 -0
- package/src/draco-library-options.ts +6 -0
- package/src/draco-loader-types.ts +2 -0
- package/src/draco-loader.ts +2 -0
- package/src/draco-wasm-loader.ts +2 -0
- package/src/draco-writer.ts +2 -0
- package/src/draco3d-loader.ts +2 -0
- package/src/glb-loader-types.ts +1 -0
- package/src/glb-loader.ts +1 -0
- package/src/glb-writer.ts +1 -0
- package/src/gltf/glb-loader-types.ts +1 -1
- package/src/gltf/gltf-loader-types.ts +11 -5
- package/src/gltf/gltf-loader.ts +4 -4
- package/src/gltf/index.ts +4 -1
- package/src/gltf/lib/api/gltf-extensions.ts +7 -2
- package/src/gltf/lib/encoders/encode-gltf-draco.ts +2 -2
- package/src/gltf/lib/extensions/EXT_texture_webp.ts +3 -0
- package/src/gltf/lib/extensions/KHR_accessor_float64.ts +22 -0
- package/src/gltf/lib/extensions/KHR_draco_mesh_compression.ts +2 -1
- package/src/gltf/lib/extensions/KHR_gaussian_splatting.ts +31 -7
- package/src/gltf/lib/extensions/MSFT_texture_dds.ts +52 -0
- package/src/gltf/lib/extensions/utils/3d-tiles-utils.ts +5 -1
- package/src/gltf/lib/parsers/parse-gltf.ts +38 -6
- package/src/gltf/lib/types/gltf-additional-extension-schemas.ts +32 -0
- package/src/gltf/lib/types/gltf-ext-gaussian-splatting-schema.ts +1 -1
- package/src/gltf/lib/types/gltf-extension-schemas.ts +12 -0
- package/src/gltf/lib/types/gltf-json-schema.ts +2 -1
- package/src/gltf/lib/types/gltf-texture-procedurals.ts +67 -0
- package/src/gltf/lib/types/gltf-types.ts +8 -0
- package/src/gltf/lib/types/gltf-zod-schema.ts +7 -1
- package/src/gltf/schema.ts +1 -0
- package/src/gltf-loader-types.ts +1 -0
- package/src/gltf-loader.ts +1 -0
- package/src/gltf-source.ts +1 -0
- package/src/gltf-writer.ts +1 -0
- package/src/index.ts +13 -3
- package/src/materialx/README.md +5 -0
- package/src/materialx/parse-materialx.ts +70 -0
- package/src/materialx/procedural-graph.ts +94 -0
- package/src/materialx-loader-types.ts +24 -0
- package/src/materialx-loader.ts +15 -0
- package/src/mtl-loader-types.ts +1 -0
- package/src/mtl-loader.ts +1 -0
- package/src/obj/bundled.ts +1 -4
- package/src/obj/index.ts +0 -6
- package/src/obj/mtl-loader-types.ts +1 -4
- package/src/obj/mtl-loader.ts +1 -1
- package/src/obj/obj-loader-types.ts +11 -11
- package/src/obj/obj-loader.ts +87 -37
- package/src/obj/obj-writer.ts +12 -8
- package/src/obj/unbundled.ts +2 -2
- package/src/obj/workers/obj-worker.ts +6 -6
- package/src/obj-loader-types.ts +1 -0
- package/src/obj-loader.ts +1 -0
- package/src/obj-writer.ts +1 -0
- package/src/stl/parse-stl.ts +90 -0
- package/src/stl-loader-types.ts +28 -0
- package/src/stl-loader.ts +12 -0
- package/src/usd/index.ts +1 -0
- package/src/usd/lib/parse-usd.ts +68 -7
- package/src/usd/lib/parse-usdc.ts +188 -0
- package/src/usd/lib/parse-usdz.ts +28 -0
- package/src/usd/lib/usd-types.ts +16 -2
- package/src/usd/libs/README.md +27 -0
- package/src/usd/libs/THREE-LICENSE +21 -0
- package/src/usd/libs/usdc-parser.d.ts +18 -0
- package/src/usd/libs/usdc-parser.js +1669 -0
- package/src/usd/usd-loader-types.ts +6 -6
- package/src/usd/usd-loader.ts +2 -2
- package/src/usd-loader-types.ts +1 -0
- package/src/usd-loader.ts +1 -0
|
@@ -0,0 +1,1669 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Copyright (c) vis.gl contributors
|
|
3
|
+
// @ts-nocheck -- Vendored r187 decoder; the handwritten adapter provides the checked public boundary.
|
|
4
|
+
// Copyright © 2010-2026 three.js authors. See THREE-LICENSE and README.md.
|
|
5
|
+
// Adapted to fail on unsupported encodings and enforce bounded allocations/offsets.
|
|
6
|
+
let allocationBytes = 0;
|
|
7
|
+
/** Budgets decoded storage without confusing byte/component lengths with logical counts. */
|
|
8
|
+
function checkedLength(length, bytesPerElement = 8) {
|
|
9
|
+
const byteLength = length * bytesPerElement;
|
|
10
|
+
if (
|
|
11
|
+
!Number.isSafeInteger(length) ||
|
|
12
|
+
length < 0 ||
|
|
13
|
+
!Number.isSafeInteger(byteLength) ||
|
|
14
|
+
byteLength > 256 * 1024 * 1024 - allocationBytes
|
|
15
|
+
)
|
|
16
|
+
throw new Error('USDC: decoded allocation limit exceeded');
|
|
17
|
+
allocationBytes += byteLength;
|
|
18
|
+
return length;
|
|
19
|
+
}
|
|
20
|
+
/** Bounds logical collection entries independently of their storage representation. */
|
|
21
|
+
function checkedCount(count) {
|
|
22
|
+
if (!Number.isSafeInteger(count) || count < 0 || count > 4_000_000)
|
|
23
|
+
throw new Error('USDC: decoded allocation limit exceeded');
|
|
24
|
+
return checkedLength(count);
|
|
25
|
+
}
|
|
26
|
+
const textDecoder = new TextDecoder();
|
|
27
|
+
|
|
28
|
+
// Pre-computed half-float exponent lookup table for fast conversion
|
|
29
|
+
// Math.pow(2, exp - 15) for exp = 0..31
|
|
30
|
+
const HALF_EXPONENT_TABLE = new Float32Array(32);
|
|
31
|
+
for (let i = 0; i < 32; i++) {
|
|
32
|
+
HALF_EXPONENT_TABLE[i] = Math.pow(2, i - 15);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Pre-computed constant for denormalized half-floats: 2^-14
|
|
36
|
+
const HALF_DENORM_SCALE = Math.pow(2, -14);
|
|
37
|
+
|
|
38
|
+
// Type enum values from crateDataTypes.h
|
|
39
|
+
const TypeEnum = {
|
|
40
|
+
Invalid: 0,
|
|
41
|
+
Bool: 1,
|
|
42
|
+
UChar: 2,
|
|
43
|
+
Int: 3,
|
|
44
|
+
UInt: 4,
|
|
45
|
+
Int64: 5,
|
|
46
|
+
UInt64: 6,
|
|
47
|
+
Half: 7,
|
|
48
|
+
Float: 8,
|
|
49
|
+
Double: 9,
|
|
50
|
+
String: 10,
|
|
51
|
+
Token: 11,
|
|
52
|
+
AssetPath: 12,
|
|
53
|
+
Matrix2d: 13,
|
|
54
|
+
Matrix3d: 14,
|
|
55
|
+
Matrix4d: 15,
|
|
56
|
+
Quatd: 16,
|
|
57
|
+
Quatf: 17,
|
|
58
|
+
Quath: 18,
|
|
59
|
+
Vec2d: 19,
|
|
60
|
+
Vec2f: 20,
|
|
61
|
+
Vec2h: 21,
|
|
62
|
+
Vec2i: 22,
|
|
63
|
+
Vec3d: 23,
|
|
64
|
+
Vec3f: 24,
|
|
65
|
+
Vec3h: 25,
|
|
66
|
+
Vec3i: 26,
|
|
67
|
+
Vec4d: 27,
|
|
68
|
+
Vec4f: 28,
|
|
69
|
+
Vec4h: 29,
|
|
70
|
+
Vec4i: 30,
|
|
71
|
+
Dictionary: 31,
|
|
72
|
+
TokenListOp: 32,
|
|
73
|
+
StringListOp: 33,
|
|
74
|
+
PathListOp: 34,
|
|
75
|
+
ReferenceListOp: 35,
|
|
76
|
+
IntListOp: 36,
|
|
77
|
+
Int64ListOp: 37,
|
|
78
|
+
UIntListOp: 38,
|
|
79
|
+
UInt64ListOp: 39,
|
|
80
|
+
PathVector: 40,
|
|
81
|
+
TokenVector: 41,
|
|
82
|
+
Specifier: 42,
|
|
83
|
+
Permission: 43,
|
|
84
|
+
Variability: 44,
|
|
85
|
+
VariantSelectionMap: 45,
|
|
86
|
+
TimeSamples: 46,
|
|
87
|
+
Payload: 47,
|
|
88
|
+
DoubleVector: 48,
|
|
89
|
+
LayerOffsetVector: 49,
|
|
90
|
+
StringVector: 50,
|
|
91
|
+
ValueBlock: 51,
|
|
92
|
+
Value: 52,
|
|
93
|
+
UnregisteredValue: 53,
|
|
94
|
+
UnregisteredValueListOp: 54,
|
|
95
|
+
PayloadListOp: 55,
|
|
96
|
+
TimeCode: 56,
|
|
97
|
+
PathExpression: 57,
|
|
98
|
+
Relocates: 58,
|
|
99
|
+
Spline: 59,
|
|
100
|
+
AnimationBlock: 60
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/** Scalar arrays with an implemented dictionary value representation. */
|
|
104
|
+
const DICTIONARY_ARRAY_TYPES = new Set([
|
|
105
|
+
TypeEnum.Int,
|
|
106
|
+
TypeEnum.UInt,
|
|
107
|
+
TypeEnum.Float,
|
|
108
|
+
TypeEnum.Double,
|
|
109
|
+
TypeEnum.Half,
|
|
110
|
+
TypeEnum.String,
|
|
111
|
+
TypeEnum.Token
|
|
112
|
+
]);
|
|
113
|
+
|
|
114
|
+
// Field set terminator marker
|
|
115
|
+
const FIELD_SET_TERMINATOR = 0xffffffff;
|
|
116
|
+
|
|
117
|
+
// Float compression type codes
|
|
118
|
+
const FLOAT_COMPRESSION_INT = 0x69; // 'i' - compressed as integers
|
|
119
|
+
const FLOAT_COMPRESSION_LUT = 0x74; // 't' - lookup table
|
|
120
|
+
|
|
121
|
+
// ============================================================================
|
|
122
|
+
// LZ4 Decompression (minimal implementation for USD)
|
|
123
|
+
// Based on LZ4 block format specification
|
|
124
|
+
// ============================================================================
|
|
125
|
+
|
|
126
|
+
function lz4DecompressBlock(input, inputOffset, inputEnd, output, outputOffset, outputEnd) {
|
|
127
|
+
while (inputOffset < inputEnd) {
|
|
128
|
+
// Read token
|
|
129
|
+
const token = input[inputOffset++];
|
|
130
|
+
if (inputOffset > inputEnd) throw new Error('USDC: truncated LZ4 token');
|
|
131
|
+
|
|
132
|
+
// Literal length
|
|
133
|
+
let literalLength = token >> 4;
|
|
134
|
+
if (literalLength === 15) {
|
|
135
|
+
let b;
|
|
136
|
+
do {
|
|
137
|
+
if (inputOffset >= inputEnd) throw new Error('USDC: truncated LZ4 length');
|
|
138
|
+
b = input[inputOffset++];
|
|
139
|
+
literalLength += b;
|
|
140
|
+
} while (b === 255);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Copy literals
|
|
144
|
+
if (literalLength > 0) {
|
|
145
|
+
if (inputOffset + literalLength > inputEnd) {
|
|
146
|
+
throw new Error('USDC: truncated LZ4 literal');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
for (let i = 0; i < literalLength; i++) {
|
|
150
|
+
if (outputOffset >= outputEnd) throw new Error('USDC: LZ4 output overflow');
|
|
151
|
+
output[outputOffset++] = input[inputOffset++];
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Check if we're at the end (last sequence has no match)
|
|
156
|
+
if (inputOffset >= inputEnd) break;
|
|
157
|
+
|
|
158
|
+
// Read match offset (little-endian 16-bit)
|
|
159
|
+
if (inputOffset + 2 > inputEnd) throw new Error('USDC: truncated LZ4 offset');
|
|
160
|
+
const matchOffset = input[inputOffset++] | (input[inputOffset++] << 8);
|
|
161
|
+
|
|
162
|
+
if (matchOffset === 0) {
|
|
163
|
+
throw new Error('USDC: invalid LZ4 match offset');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Match length
|
|
167
|
+
let matchLength = (token & 0x0f) + 4;
|
|
168
|
+
if (matchLength === 19) {
|
|
169
|
+
let b;
|
|
170
|
+
do {
|
|
171
|
+
if (inputOffset >= inputEnd) throw new Error('USDC: truncated LZ4 length');
|
|
172
|
+
b = input[inputOffset++];
|
|
173
|
+
matchLength += b;
|
|
174
|
+
} while (b === 255);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Copy match (byte-by-byte to handle overlapping)
|
|
178
|
+
const matchPos = outputOffset - matchOffset;
|
|
179
|
+
if (matchPos < 0) {
|
|
180
|
+
throw new Error('USDC: invalid LZ4 match position');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
for (let i = 0; i < matchLength; i++) {
|
|
184
|
+
if (outputOffset >= outputEnd) throw new Error('USDC: LZ4 output overflow');
|
|
185
|
+
output[outputOffset++] = output[matchPos + i];
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return outputOffset;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// USD uses TfFastCompression which wraps LZ4 with chunk headers
|
|
193
|
+
function decompressLZ4(input, uncompressedSize, allowShortOutput = false) {
|
|
194
|
+
// TfFastCompression format (used by OpenUSD):
|
|
195
|
+
// Single chunk (byte 0 == 0): [0] + LZ4 data
|
|
196
|
+
// Multi chunk (byte 0 > 0): [numChunks] + [compressedSizes...] + [chunkData...]
|
|
197
|
+
|
|
198
|
+
const output = new Uint8Array(checkedLength(uncompressedSize, 1));
|
|
199
|
+
if (!input.length) throw new Error('USDC: missing LZ4 chunk header');
|
|
200
|
+
const numChunks = input[0];
|
|
201
|
+
|
|
202
|
+
if (numChunks === 0) {
|
|
203
|
+
// Single chunk - all remaining bytes are LZ4 compressed
|
|
204
|
+
const written = lz4DecompressBlock(input, 1, input.length, output, 0, uncompressedSize);
|
|
205
|
+
if (!allowShortOutput && written !== uncompressedSize)
|
|
206
|
+
throw new Error('USDC: incomplete LZ4 output');
|
|
207
|
+
return output.subarray(0, written);
|
|
208
|
+
} else {
|
|
209
|
+
// Multiple chunks - each chunk decompresses to max 65536 bytes
|
|
210
|
+
const CHUNK_SIZE = 65536;
|
|
211
|
+
|
|
212
|
+
// First, read all chunk sizes
|
|
213
|
+
if (1 + numChunks * 4 > input.length) throw new Error('USDC: truncated LZ4 chunk sizes');
|
|
214
|
+
let headerOffset = 1;
|
|
215
|
+
const compressedSizes = [];
|
|
216
|
+
|
|
217
|
+
for (let i = 0; i < numChunks; i++) {
|
|
218
|
+
const size =
|
|
219
|
+
(input[headerOffset] |
|
|
220
|
+
(input[headerOffset + 1] << 8) |
|
|
221
|
+
(input[headerOffset + 2] << 16) |
|
|
222
|
+
(input[headerOffset + 3] << 24)) >>>
|
|
223
|
+
0;
|
|
224
|
+
compressedSizes.push(size);
|
|
225
|
+
headerOffset += 4;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Decompress each chunk
|
|
229
|
+
let inputOffset = headerOffset;
|
|
230
|
+
let outputOffset = 0;
|
|
231
|
+
|
|
232
|
+
for (let i = 0; i < numChunks; i++) {
|
|
233
|
+
const chunkCompressedSize = compressedSizes[i];
|
|
234
|
+
const chunkOutputSize = Math.min(CHUNK_SIZE, uncompressedSize - outputOffset);
|
|
235
|
+
|
|
236
|
+
if (chunkCompressedSize > input.length - inputOffset)
|
|
237
|
+
throw new Error('USDC: truncated LZ4 chunk');
|
|
238
|
+
const written = lz4DecompressBlock(
|
|
239
|
+
input,
|
|
240
|
+
inputOffset,
|
|
241
|
+
inputOffset + chunkCompressedSize,
|
|
242
|
+
output,
|
|
243
|
+
outputOffset,
|
|
244
|
+
outputOffset + chunkOutputSize
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
inputOffset += chunkCompressedSize;
|
|
248
|
+
if (i < numChunks - 1 && written !== outputOffset + chunkOutputSize)
|
|
249
|
+
throw new Error('USDC: incomplete LZ4 chunk');
|
|
250
|
+
outputOffset = written;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (inputOffset !== input.length || (!allowShortOutput && outputOffset !== uncompressedSize))
|
|
254
|
+
throw new Error('USDC: incomplete LZ4 output');
|
|
255
|
+
return output.subarray(0, outputOffset);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// ============================================================================
|
|
260
|
+
// Integer Decompression (USD-specific delta + variable-width encoding)
|
|
261
|
+
// ============================================================================
|
|
262
|
+
|
|
263
|
+
function decompressIntegers32(compressedData, numInts) {
|
|
264
|
+
// First decompress with LZ4
|
|
265
|
+
const encodedSize = numInts * 4 + ((numInts * 2 + 7) >> 3) + 4;
|
|
266
|
+
const encoded = decompressLZ4(new Uint8Array(compressedData), encodedSize, true);
|
|
267
|
+
|
|
268
|
+
// Then decode
|
|
269
|
+
return decodeIntegers32(encoded, numInts);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function decodeIntegers32(data, numInts) {
|
|
273
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
274
|
+
let offset = 0;
|
|
275
|
+
|
|
276
|
+
// Read common value (signed 32-bit)
|
|
277
|
+
const commonValue = view.getInt32(offset, true);
|
|
278
|
+
offset += 4;
|
|
279
|
+
|
|
280
|
+
const numCodesBytes = (numInts * 2 + 7) >> 3;
|
|
281
|
+
if (data.length < offset + numCodesBytes) throw new Error('USDC: truncated integer codes');
|
|
282
|
+
const codesStart = offset;
|
|
283
|
+
const vintsStart = offset + numCodesBytes;
|
|
284
|
+
|
|
285
|
+
const result = new Int32Array(checkedLength(numInts));
|
|
286
|
+
let prevVal = 0;
|
|
287
|
+
let codesOffset = codesStart;
|
|
288
|
+
let vintsOffset = vintsStart;
|
|
289
|
+
|
|
290
|
+
for (let i = 0; i < numInts; ) {
|
|
291
|
+
const codeByte = data[codesOffset++];
|
|
292
|
+
|
|
293
|
+
for (let j = 0; j < 4 && i < numInts; j++, i++) {
|
|
294
|
+
const code = (codeByte >> (j * 2)) & 3;
|
|
295
|
+
let delta = 0;
|
|
296
|
+
|
|
297
|
+
switch (code) {
|
|
298
|
+
case 0: // Common value
|
|
299
|
+
delta = commonValue;
|
|
300
|
+
break;
|
|
301
|
+
case 1: // 8-bit signed
|
|
302
|
+
delta = view.getInt8(vintsOffset);
|
|
303
|
+
vintsOffset += 1;
|
|
304
|
+
break;
|
|
305
|
+
case 2: // 16-bit signed
|
|
306
|
+
delta = view.getInt16(vintsOffset, true);
|
|
307
|
+
vintsOffset += 2;
|
|
308
|
+
break;
|
|
309
|
+
case 3: // 32-bit signed
|
|
310
|
+
delta = view.getInt32(vintsOffset, true);
|
|
311
|
+
vintsOffset += 4;
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
prevVal += delta;
|
|
316
|
+
result[i] = prevVal;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return result;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// ============================================================================
|
|
324
|
+
// Binary Reader Helper
|
|
325
|
+
// ============================================================================
|
|
326
|
+
|
|
327
|
+
class BinaryReader {
|
|
328
|
+
constructor(buffer) {
|
|
329
|
+
this.buffer = buffer;
|
|
330
|
+
this.view = new DataView(buffer);
|
|
331
|
+
this.offset = 0;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
seek(offset) {
|
|
335
|
+
if (!Number.isSafeInteger(offset) || offset < 0 || offset > this.buffer.byteLength)
|
|
336
|
+
throw new Error('USDC: invalid seek');
|
|
337
|
+
this.offset = offset;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
tell() {
|
|
341
|
+
return this.offset;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
readUint8() {
|
|
345
|
+
const value = this.view.getUint8(this.offset);
|
|
346
|
+
this.offset += 1;
|
|
347
|
+
return value;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
readInt8() {
|
|
351
|
+
const value = this.view.getInt8(this.offset);
|
|
352
|
+
this.offset += 1;
|
|
353
|
+
return value;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
readUint16() {
|
|
357
|
+
const value = this.view.getUint16(this.offset, true);
|
|
358
|
+
this.offset += 2;
|
|
359
|
+
return value;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
readInt16() {
|
|
363
|
+
const value = this.view.getInt16(this.offset, true);
|
|
364
|
+
this.offset += 2;
|
|
365
|
+
return value;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
readUint32() {
|
|
369
|
+
const value = this.view.getUint32(this.offset, true);
|
|
370
|
+
this.offset += 4;
|
|
371
|
+
return value;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
readInt32() {
|
|
375
|
+
const value = this.view.getInt32(this.offset, true);
|
|
376
|
+
this.offset += 4;
|
|
377
|
+
return value;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
readUint64() {
|
|
381
|
+
const lo = this.view.getUint32(this.offset, true);
|
|
382
|
+
const hi = this.view.getUint32(this.offset + 4, true);
|
|
383
|
+
this.offset += 8;
|
|
384
|
+
// For values that fit in Number, this is safe
|
|
385
|
+
const result = hi * 0x100000000 + lo;
|
|
386
|
+
if (!Number.isSafeInteger(result)) throw new Error('USDC: integer exceeds safe precision');
|
|
387
|
+
return result;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
readInt64() {
|
|
391
|
+
const lo = this.view.getUint32(this.offset, true);
|
|
392
|
+
const hi = this.view.getInt32(this.offset + 4, true);
|
|
393
|
+
this.offset += 8;
|
|
394
|
+
const result = hi * 0x100000000 + lo;
|
|
395
|
+
if (!Number.isSafeInteger(result)) throw new Error('USDC: integer exceeds safe precision');
|
|
396
|
+
return result;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
readFloat32() {
|
|
400
|
+
const value = this.view.getFloat32(this.offset, true);
|
|
401
|
+
this.offset += 4;
|
|
402
|
+
return value;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
readFloat64() {
|
|
406
|
+
const value = this.view.getFloat64(this.offset, true);
|
|
407
|
+
this.offset += 8;
|
|
408
|
+
return value;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
readBytes(length) {
|
|
412
|
+
const bytes = new Uint8Array(this.buffer, this.offset, length);
|
|
413
|
+
this.offset += length;
|
|
414
|
+
return bytes;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
readString(length) {
|
|
418
|
+
const bytes = this.readBytes(length);
|
|
419
|
+
let end = 0;
|
|
420
|
+
while (end < length && bytes[end] !== 0) end++;
|
|
421
|
+
return textDecoder.decode(bytes.subarray(0, end));
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// ============================================================================
|
|
426
|
+
// ValueRep - 64-bit packed value representation
|
|
427
|
+
// ============================================================================
|
|
428
|
+
|
|
429
|
+
class ValueRep {
|
|
430
|
+
constructor(lo, hi) {
|
|
431
|
+
this.lo = lo; // Lower 32 bits
|
|
432
|
+
this.hi = hi; // Upper 32 bits
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
get isArray() {
|
|
436
|
+
return (this.hi & 0x80000000) !== 0;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
get isInlined() {
|
|
440
|
+
return (this.hi & 0x40000000) !== 0;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
get isCompressed() {
|
|
444
|
+
return (this.hi & 0x20000000) !== 0;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
get typeEnum() {
|
|
448
|
+
return (this.hi >> 16) & 0xff;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
get payload() {
|
|
452
|
+
// 48-bit payload: lo (32 bits) + hi lower 16 bits
|
|
453
|
+
// Note: JavaScript numbers are IEEE 754 doubles with 53 bits of integer precision,
|
|
454
|
+
// so 48-bit values are represented exactly without loss of precision.
|
|
455
|
+
return this.lo + (this.hi & 0xffff) * 0x100000000;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
getInlinedValue() {
|
|
459
|
+
// For inlined scalars, the value is in the lower 32 bits
|
|
460
|
+
return this.lo;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// ============================================================================
|
|
465
|
+
// USDC Parser
|
|
466
|
+
// ============================================================================
|
|
467
|
+
|
|
468
|
+
class USDCParser {
|
|
469
|
+
/**
|
|
470
|
+
* Parse USDC file and return raw spec data without building Three.js scene.
|
|
471
|
+
* Used by USDComposer for unified scene composition.
|
|
472
|
+
*/
|
|
473
|
+
parseData(buffer) {
|
|
474
|
+
allocationBytes = 0;
|
|
475
|
+
this._valueReadCount = 0;
|
|
476
|
+
this._activeDictionaries = new Set();
|
|
477
|
+
|
|
478
|
+
this.buffer = buffer instanceof ArrayBuffer ? buffer : buffer.buffer;
|
|
479
|
+
this.reader = new BinaryReader(this.buffer);
|
|
480
|
+
this.version = {major: 0, minor: 0, patch: 0};
|
|
481
|
+
|
|
482
|
+
this._conversionBuffer = new ArrayBuffer(4);
|
|
483
|
+
this._conversionView = new DataView(this._conversionBuffer);
|
|
484
|
+
|
|
485
|
+
this._readBootstrap();
|
|
486
|
+
this._readTOC();
|
|
487
|
+
this._readTokens();
|
|
488
|
+
this._readStrings();
|
|
489
|
+
this._readFields();
|
|
490
|
+
this._readFieldSets();
|
|
491
|
+
this._readPaths();
|
|
492
|
+
this._readSpecs();
|
|
493
|
+
|
|
494
|
+
// Build specsByPath without building scene
|
|
495
|
+
this.specsByPath = Object.create(null);
|
|
496
|
+
|
|
497
|
+
for (const spec of this.specs) {
|
|
498
|
+
const path = this.paths[spec.pathIndex];
|
|
499
|
+
if (!path) continue;
|
|
500
|
+
|
|
501
|
+
const fields = this._getFieldsForSpec(spec);
|
|
502
|
+
this.specsByPath[path] = {specType: spec.specType, fields};
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
return {specsByPath: this.specsByPath};
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
_readBootstrap() {
|
|
509
|
+
const reader = this.reader;
|
|
510
|
+
reader.seek(0);
|
|
511
|
+
|
|
512
|
+
// Read magic "PXR-USDC"
|
|
513
|
+
const magic = reader.readString(8);
|
|
514
|
+
if (magic !== 'PXR-USDC') {
|
|
515
|
+
throw new Error('THREE.USDCParser: Not a valid USDC file.');
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// Read version
|
|
519
|
+
this.version.major = reader.readUint8();
|
|
520
|
+
this.version.minor = reader.readUint8();
|
|
521
|
+
this.version.patch = reader.readUint8();
|
|
522
|
+
reader.readBytes(5); // Skip remaining version bytes
|
|
523
|
+
|
|
524
|
+
// Read TOC offset
|
|
525
|
+
this.tocOffset = reader.readUint64();
|
|
526
|
+
|
|
527
|
+
// Skip reserved bytes (rest of 128-byte header)
|
|
528
|
+
// Already at offset 24, skip to end of bootstrap (88 bytes total for bootstrap struct)
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
_readTOC() {
|
|
532
|
+
const reader = this.reader;
|
|
533
|
+
reader.seek(this.tocOffset);
|
|
534
|
+
|
|
535
|
+
// Read number of sections
|
|
536
|
+
const numSections = reader.readUint64();
|
|
537
|
+
if (numSections > 16) throw new Error('USDC: invalid section count');
|
|
538
|
+
this.sections = Object.create(null);
|
|
539
|
+
|
|
540
|
+
for (let i = 0; i < numSections; i++) {
|
|
541
|
+
const name = reader.readString(16);
|
|
542
|
+
const start = reader.readUint64();
|
|
543
|
+
const size = reader.readUint64();
|
|
544
|
+
|
|
545
|
+
this.sections[name] = {start, size};
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
_readTokens() {
|
|
550
|
+
const section = this.sections['TOKENS'];
|
|
551
|
+
if (!section) return;
|
|
552
|
+
|
|
553
|
+
const reader = this.reader;
|
|
554
|
+
reader.seek(section.start);
|
|
555
|
+
|
|
556
|
+
const numTokens = checkedCount(reader.readUint64());
|
|
557
|
+
this.tokens = [];
|
|
558
|
+
|
|
559
|
+
if (this.version.major === 0 && this.version.minor < 4) {
|
|
560
|
+
// Uncompressed tokens (version < 0.4.0)
|
|
561
|
+
const tokensNumBytes = reader.readUint64();
|
|
562
|
+
const tokensData = reader.readBytes(tokensNumBytes);
|
|
563
|
+
|
|
564
|
+
let strStart = 0;
|
|
565
|
+
for (let i = 0; i < numTokens; i++) {
|
|
566
|
+
let strEnd = strStart;
|
|
567
|
+
while (strEnd < tokensData.length && tokensData[strEnd] !== 0) strEnd++;
|
|
568
|
+
|
|
569
|
+
if (strEnd >= tokensData.length) throw new Error('USDC: unterminated token data');
|
|
570
|
+
this.tokens.push(textDecoder.decode(tokensData.subarray(strStart, strEnd)));
|
|
571
|
+
strStart = strEnd + 1;
|
|
572
|
+
}
|
|
573
|
+
} else {
|
|
574
|
+
// Compressed tokens (version >= 0.4.0)
|
|
575
|
+
const uncompressedSize = reader.readUint64();
|
|
576
|
+
const compressedSize = reader.readUint64();
|
|
577
|
+
const compressedData = reader.readBytes(compressedSize);
|
|
578
|
+
|
|
579
|
+
const tokensData = decompressLZ4(compressedData, uncompressedSize);
|
|
580
|
+
checkedLength(tokensData.length, 2);
|
|
581
|
+
|
|
582
|
+
let strStart = 0;
|
|
583
|
+
for (let i = 0; i < numTokens; i++) {
|
|
584
|
+
let strEnd = strStart;
|
|
585
|
+
while (strEnd < tokensData.length && tokensData[strEnd] !== 0) strEnd++;
|
|
586
|
+
|
|
587
|
+
if (strEnd >= tokensData.length) throw new Error('USDC: unterminated token data');
|
|
588
|
+
this.tokens.push(textDecoder.decode(tokensData.subarray(strStart, strEnd)));
|
|
589
|
+
strStart = strEnd + 1;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
_readStrings() {
|
|
595
|
+
const section = this.sections['STRINGS'];
|
|
596
|
+
if (!section) {
|
|
597
|
+
this.strings = [];
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
const reader = this.reader;
|
|
602
|
+
reader.seek(section.start);
|
|
603
|
+
|
|
604
|
+
const numStrings = checkedCount(reader.readUint64());
|
|
605
|
+
this.strings = [];
|
|
606
|
+
|
|
607
|
+
for (let i = 0; i < numStrings; i++) {
|
|
608
|
+
this.strings.push(reader.readUint32());
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
_readFields() {
|
|
613
|
+
const section = this.sections['FIELDS'];
|
|
614
|
+
if (!section) return;
|
|
615
|
+
|
|
616
|
+
const reader = this.reader;
|
|
617
|
+
reader.seek(section.start);
|
|
618
|
+
|
|
619
|
+
this.fields = [];
|
|
620
|
+
|
|
621
|
+
if (this.version.major === 0 && this.version.minor < 4) {
|
|
622
|
+
// Uncompressed fields
|
|
623
|
+
const numFields = Math.floor(section.size / 12); // 4 bytes token index + 8 bytes value rep
|
|
624
|
+
|
|
625
|
+
for (let i = 0; i < numFields; i++) {
|
|
626
|
+
const tokenIndex = reader.readUint32();
|
|
627
|
+
const repLo = reader.readUint32();
|
|
628
|
+
const repHi = reader.readUint32();
|
|
629
|
+
|
|
630
|
+
this.fields.push({
|
|
631
|
+
tokenIndex,
|
|
632
|
+
valueRep: new ValueRep(repLo, repHi)
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
} else {
|
|
636
|
+
// Compressed fields (version >= 0.4.0)
|
|
637
|
+
const numFields = checkedCount(reader.readUint64());
|
|
638
|
+
|
|
639
|
+
// Read compressed token indices
|
|
640
|
+
const tokenIndicesCompressedSize = reader.readUint64();
|
|
641
|
+
const tokenIndicesCompressed = reader.readBytes(tokenIndicesCompressedSize);
|
|
642
|
+
const tokenIndices = decompressIntegers32(
|
|
643
|
+
tokenIndicesCompressed.buffer.slice(
|
|
644
|
+
tokenIndicesCompressed.byteOffset,
|
|
645
|
+
tokenIndicesCompressed.byteOffset + tokenIndicesCompressedSize
|
|
646
|
+
),
|
|
647
|
+
numFields
|
|
648
|
+
);
|
|
649
|
+
|
|
650
|
+
// Read compressed value reps (LZ4 only, no integer encoding)
|
|
651
|
+
const repsCompressedSize = reader.readUint64();
|
|
652
|
+
const repsCompressed = reader.readBytes(repsCompressedSize);
|
|
653
|
+
const repsData = decompressLZ4(repsCompressed, numFields * 8);
|
|
654
|
+
const repsView = new DataView(repsData.buffer, repsData.byteOffset, repsData.byteLength);
|
|
655
|
+
|
|
656
|
+
for (let i = 0; i < numFields; i++) {
|
|
657
|
+
const repLo = repsView.getUint32(i * 8, true);
|
|
658
|
+
const repHi = repsView.getUint32(i * 8 + 4, true);
|
|
659
|
+
|
|
660
|
+
this.fields.push({
|
|
661
|
+
tokenIndex: tokenIndices[i],
|
|
662
|
+
valueRep: new ValueRep(repLo, repHi)
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
_readFieldSets() {
|
|
669
|
+
const section = this.sections['FIELDSETS'];
|
|
670
|
+
if (!section) return;
|
|
671
|
+
|
|
672
|
+
const reader = this.reader;
|
|
673
|
+
reader.seek(section.start);
|
|
674
|
+
|
|
675
|
+
this.fieldSets = [];
|
|
676
|
+
|
|
677
|
+
if (this.version.major === 0 && this.version.minor < 4) {
|
|
678
|
+
// Uncompressed field sets
|
|
679
|
+
const numFieldSets = Math.floor(section.size / 4);
|
|
680
|
+
|
|
681
|
+
for (let i = 0; i < numFieldSets; i++) {
|
|
682
|
+
this.fieldSets.push(reader.readUint32());
|
|
683
|
+
}
|
|
684
|
+
} else {
|
|
685
|
+
// Compressed field sets
|
|
686
|
+
const numFieldSets = checkedCount(reader.readUint64());
|
|
687
|
+
const compressedSize = reader.readUint64();
|
|
688
|
+
const compressed = reader.readBytes(compressedSize);
|
|
689
|
+
|
|
690
|
+
const indices = decompressIntegers32(
|
|
691
|
+
compressed.buffer.slice(compressed.byteOffset, compressed.byteOffset + compressedSize),
|
|
692
|
+
numFieldSets
|
|
693
|
+
);
|
|
694
|
+
|
|
695
|
+
for (let i = 0; i < numFieldSets; i++) {
|
|
696
|
+
this.fieldSets.push(indices[i]);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
_readPaths() {
|
|
702
|
+
const section = this.sections['PATHS'];
|
|
703
|
+
if (!section) return;
|
|
704
|
+
|
|
705
|
+
const reader = this.reader;
|
|
706
|
+
reader.seek(section.start);
|
|
707
|
+
|
|
708
|
+
const numPaths = checkedCount(reader.readUint64());
|
|
709
|
+
this.paths = new Array(checkedLength(numPaths)).fill('');
|
|
710
|
+
|
|
711
|
+
if (this.version.major === 0 && this.version.minor < 4) {
|
|
712
|
+
// Uncompressed paths - recursive tree structure
|
|
713
|
+
this._readPathsRecursive('');
|
|
714
|
+
} else {
|
|
715
|
+
// Compressed paths (version >= 0.4.0)
|
|
716
|
+
// Note: numPaths is stored twice - once for array sizing, once in compressed paths section
|
|
717
|
+
reader.readUint64(); // Read duplicate numPaths value (matches numPaths above)
|
|
718
|
+
|
|
719
|
+
const compressedSize1 = reader.readUint64();
|
|
720
|
+
const pathIndicesCompressed = reader.readBytes(compressedSize1);
|
|
721
|
+
const pathIndices = decompressIntegers32(
|
|
722
|
+
pathIndicesCompressed.buffer.slice(
|
|
723
|
+
pathIndicesCompressed.byteOffset,
|
|
724
|
+
pathIndicesCompressed.byteOffset + compressedSize1
|
|
725
|
+
),
|
|
726
|
+
numPaths
|
|
727
|
+
);
|
|
728
|
+
|
|
729
|
+
const compressedSize2 = reader.readUint64();
|
|
730
|
+
const elementTokenIndicesCompressed = reader.readBytes(compressedSize2);
|
|
731
|
+
const elementTokenIndices = decompressIntegers32(
|
|
732
|
+
elementTokenIndicesCompressed.buffer.slice(
|
|
733
|
+
elementTokenIndicesCompressed.byteOffset,
|
|
734
|
+
elementTokenIndicesCompressed.byteOffset + compressedSize2
|
|
735
|
+
),
|
|
736
|
+
numPaths
|
|
737
|
+
);
|
|
738
|
+
|
|
739
|
+
const compressedSize3 = reader.readUint64();
|
|
740
|
+
const jumpsCompressed = reader.readBytes(compressedSize3);
|
|
741
|
+
const jumps = decompressIntegers32(
|
|
742
|
+
jumpsCompressed.buffer.slice(
|
|
743
|
+
jumpsCompressed.byteOffset,
|
|
744
|
+
jumpsCompressed.byteOffset + compressedSize3
|
|
745
|
+
),
|
|
746
|
+
numPaths
|
|
747
|
+
);
|
|
748
|
+
|
|
749
|
+
// Build paths from compressed data
|
|
750
|
+
this._buildPathsFromCompressed(pathIndices, elementTokenIndices, jumps);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
_readPathsRecursive(parentPath, depth = 0) {
|
|
755
|
+
const reader = this.reader;
|
|
756
|
+
|
|
757
|
+
// Prevent infinite recursion
|
|
758
|
+
if (depth > 1000) return;
|
|
759
|
+
|
|
760
|
+
// Read path item header
|
|
761
|
+
const index = reader.readUint32();
|
|
762
|
+
const elementTokenIndex = reader.readUint32();
|
|
763
|
+
const bits = reader.readUint8();
|
|
764
|
+
|
|
765
|
+
const hasChild = (bits & 1) !== 0;
|
|
766
|
+
const hasSibling = (bits & 2) !== 0;
|
|
767
|
+
const isPrimProperty = (bits & 4) !== 0;
|
|
768
|
+
|
|
769
|
+
// Build path
|
|
770
|
+
let path;
|
|
771
|
+
if (parentPath === '') {
|
|
772
|
+
path = '/';
|
|
773
|
+
} else {
|
|
774
|
+
const elemToken = this.tokens[elementTokenIndex] || '';
|
|
775
|
+
if (isPrimProperty) {
|
|
776
|
+
path = parentPath + '.' + elemToken;
|
|
777
|
+
} else {
|
|
778
|
+
path = parentPath === '/' ? '/' + elemToken : parentPath + '/' + elemToken;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
checkedLength(path.length, 2);
|
|
783
|
+
this.paths[index] = path;
|
|
784
|
+
|
|
785
|
+
// Process children and siblings
|
|
786
|
+
if (hasChild && hasSibling) {
|
|
787
|
+
// Read sibling offset
|
|
788
|
+
const siblingOffset = reader.readUint64();
|
|
789
|
+
|
|
790
|
+
// Read child
|
|
791
|
+
this._readPathsRecursive(path, depth + 1);
|
|
792
|
+
|
|
793
|
+
// Read sibling
|
|
794
|
+
reader.seek(siblingOffset);
|
|
795
|
+
this._readPathsRecursive(parentPath, depth + 1);
|
|
796
|
+
} else if (hasChild) {
|
|
797
|
+
this._readPathsRecursive(path, depth + 1);
|
|
798
|
+
} else if (hasSibling) {
|
|
799
|
+
this._readPathsRecursive(parentPath, depth + 1);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
/** Rebuilds compressed paths with an explicit stack instead of sibling recursion. */
|
|
804
|
+
_buildPathsFromCompressed(pathIndices, elementTokenIndices, jumps) {
|
|
805
|
+
let traversalCount = 0;
|
|
806
|
+
const pendingPaths = [{startIndex: 0, parentPath: ''}];
|
|
807
|
+
while (pendingPaths.length) {
|
|
808
|
+
const pendingPath = pendingPaths.pop();
|
|
809
|
+
let currentIndex = pendingPath.startIndex;
|
|
810
|
+
let parentPath = pendingPath.parentPath;
|
|
811
|
+
while (currentIndex < pathIndices.length) {
|
|
812
|
+
if (++traversalCount > pathIndices.length * 2)
|
|
813
|
+
throw new Error('USDC: path traversal limit exceeded');
|
|
814
|
+
const nodeIndex = currentIndex++;
|
|
815
|
+
const pathIndex = pathIndices[nodeIndex];
|
|
816
|
+
const elementTokenIndex = elementTokenIndices[nodeIndex];
|
|
817
|
+
const jump = jumps[nodeIndex];
|
|
818
|
+
if (
|
|
819
|
+
pathIndex < 0 ||
|
|
820
|
+
pathIndex >= this.paths.length ||
|
|
821
|
+
Math.abs(elementTokenIndex) >= this.tokens.length ||
|
|
822
|
+
jump < -2
|
|
823
|
+
)
|
|
824
|
+
throw new Error('USDC: invalid compressed path index');
|
|
825
|
+
let path;
|
|
826
|
+
if (parentPath === '') {
|
|
827
|
+
path = '/';
|
|
828
|
+
parentPath = path;
|
|
829
|
+
} else {
|
|
830
|
+
const elementToken = this.tokens[Math.abs(elementTokenIndex)];
|
|
831
|
+
path =
|
|
832
|
+
elementTokenIndex < 0
|
|
833
|
+
? parentPath + '.' + elementToken
|
|
834
|
+
: parentPath === '/'
|
|
835
|
+
? '/' + elementToken
|
|
836
|
+
: parentPath + '/' + elementToken;
|
|
837
|
+
}
|
|
838
|
+
checkedLength(path.length, 2);
|
|
839
|
+
this.paths[pathIndex] = path;
|
|
840
|
+
const hasChild = jump > 0 || jump === -1;
|
|
841
|
+
const hasSibling = jump >= 0;
|
|
842
|
+
if ((hasChild || hasSibling) && currentIndex >= pathIndices.length)
|
|
843
|
+
throw new Error('USDC: missing compressed path entry');
|
|
844
|
+
if (hasChild && hasSibling) {
|
|
845
|
+
const siblingIndex = nodeIndex + jump;
|
|
846
|
+
if (siblingIndex <= currentIndex || siblingIndex >= pathIndices.length)
|
|
847
|
+
throw new Error('USDC: invalid compressed path jump');
|
|
848
|
+
pendingPaths.push({startIndex: siblingIndex, parentPath});
|
|
849
|
+
}
|
|
850
|
+
if (hasChild) parentPath = path;
|
|
851
|
+
else if (!hasSibling) break;
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
_readSpecs() {
|
|
857
|
+
const section = this.sections['SPECS'];
|
|
858
|
+
if (!section) return;
|
|
859
|
+
|
|
860
|
+
const reader = this.reader;
|
|
861
|
+
reader.seek(section.start);
|
|
862
|
+
|
|
863
|
+
this.specs = [];
|
|
864
|
+
|
|
865
|
+
if (this.version.major === 0 && this.version.minor < 4) {
|
|
866
|
+
// Uncompressed specs
|
|
867
|
+
// Each spec: pathIndex (4), fieldSetIndex (4), specType (4) = 12 bytes
|
|
868
|
+
// For version 0.0.1 there may be different padding
|
|
869
|
+
const specSize = this.version.minor === 0 && this.version.patch === 1 ? 16 : 12;
|
|
870
|
+
const numSpecs = Math.floor(section.size / specSize);
|
|
871
|
+
|
|
872
|
+
for (let i = 0; i < numSpecs; i++) {
|
|
873
|
+
const pathIndex = reader.readUint32();
|
|
874
|
+
const fieldSetIndex = reader.readUint32();
|
|
875
|
+
const specType = reader.readUint32();
|
|
876
|
+
|
|
877
|
+
if (specSize === 16) reader.readUint32(); // padding
|
|
878
|
+
|
|
879
|
+
this.specs.push({pathIndex, fieldSetIndex, specType});
|
|
880
|
+
}
|
|
881
|
+
} else {
|
|
882
|
+
// Compressed specs
|
|
883
|
+
const numSpecs = checkedCount(reader.readUint64());
|
|
884
|
+
|
|
885
|
+
const compressedSize1 = reader.readUint64();
|
|
886
|
+
const pathIndicesCompressed = reader.readBytes(compressedSize1);
|
|
887
|
+
const pathIndices = decompressIntegers32(
|
|
888
|
+
pathIndicesCompressed.buffer.slice(
|
|
889
|
+
pathIndicesCompressed.byteOffset,
|
|
890
|
+
pathIndicesCompressed.byteOffset + compressedSize1
|
|
891
|
+
),
|
|
892
|
+
numSpecs
|
|
893
|
+
);
|
|
894
|
+
|
|
895
|
+
const compressedSize2 = reader.readUint64();
|
|
896
|
+
const fieldSetIndicesCompressed = reader.readBytes(compressedSize2);
|
|
897
|
+
const fieldSetIndices = decompressIntegers32(
|
|
898
|
+
fieldSetIndicesCompressed.buffer.slice(
|
|
899
|
+
fieldSetIndicesCompressed.byteOffset,
|
|
900
|
+
fieldSetIndicesCompressed.byteOffset + compressedSize2
|
|
901
|
+
),
|
|
902
|
+
numSpecs
|
|
903
|
+
);
|
|
904
|
+
|
|
905
|
+
const compressedSize3 = reader.readUint64();
|
|
906
|
+
const specTypesCompressed = reader.readBytes(compressedSize3);
|
|
907
|
+
const specTypes = decompressIntegers32(
|
|
908
|
+
specTypesCompressed.buffer.slice(
|
|
909
|
+
specTypesCompressed.byteOffset,
|
|
910
|
+
specTypesCompressed.byteOffset + compressedSize3
|
|
911
|
+
),
|
|
912
|
+
numSpecs
|
|
913
|
+
);
|
|
914
|
+
|
|
915
|
+
for (let i = 0; i < numSpecs; i++) {
|
|
916
|
+
this.specs.push({
|
|
917
|
+
pathIndex: pathIndices[i],
|
|
918
|
+
fieldSetIndex: fieldSetIndices[i],
|
|
919
|
+
specType: specTypes[i]
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
// ========================================================================
|
|
926
|
+
// Value Reading
|
|
927
|
+
// ========================================================================
|
|
928
|
+
|
|
929
|
+
_readValue(valueRep) {
|
|
930
|
+
this._valueReadCount = (this._valueReadCount || 0) + 1;
|
|
931
|
+
if (this._valueReadCount > 1_000_000) throw new Error('USDC: value traversal limit exceeded');
|
|
932
|
+
|
|
933
|
+
const type = valueRep.typeEnum;
|
|
934
|
+
const isArray = valueRep.isArray;
|
|
935
|
+
const isInlined = valueRep.isInlined;
|
|
936
|
+
|
|
937
|
+
// Handle TimeSamples specially - they have their own format
|
|
938
|
+
if (type === TypeEnum.TimeSamples) {
|
|
939
|
+
return this._readTimeSamples(valueRep);
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
if (isInlined) {
|
|
943
|
+
return this._readInlinedValue(valueRep);
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
// Seek to payload offset and read value
|
|
947
|
+
const offset = valueRep.payload;
|
|
948
|
+
if (offset === 0 && isArray) {
|
|
949
|
+
// Spec 16.3.9.3: Array payload 0 is an explicit empty-array sentinel.
|
|
950
|
+
return [];
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
if (offset < 0 || offset >= this.buffer.byteLength) {
|
|
954
|
+
throw new RangeError(
|
|
955
|
+
'USDCParser: Invalid payload offset ' + offset + ' for type ' + type + '.'
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
const savedOffset = this.reader.tell();
|
|
960
|
+
this.reader.seek(offset);
|
|
961
|
+
|
|
962
|
+
let value;
|
|
963
|
+
|
|
964
|
+
if (isArray) {
|
|
965
|
+
value = this._readArrayValue(valueRep);
|
|
966
|
+
} else {
|
|
967
|
+
value = this._readScalarValue(type);
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
this.reader.seek(savedOffset);
|
|
971
|
+
return value;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
_readInlinedValue(valueRep) {
|
|
975
|
+
const type = valueRep.typeEnum;
|
|
976
|
+
const payload = valueRep.getInlinedValue();
|
|
977
|
+
const view = this._conversionView;
|
|
978
|
+
|
|
979
|
+
switch (type) {
|
|
980
|
+
case TypeEnum.Dictionary:
|
|
981
|
+
if (payload !== 0) throw new Error('USDC: invalid inline dictionary');
|
|
982
|
+
return Object.create(null);
|
|
983
|
+
case TypeEnum.Bool:
|
|
984
|
+
return payload !== 0;
|
|
985
|
+
case TypeEnum.UChar:
|
|
986
|
+
return payload & 0xff;
|
|
987
|
+
case TypeEnum.Int:
|
|
988
|
+
case TypeEnum.Int64:
|
|
989
|
+
return payload | 0;
|
|
990
|
+
case TypeEnum.UInt:
|
|
991
|
+
case TypeEnum.UInt64:
|
|
992
|
+
return payload >>> 0;
|
|
993
|
+
case TypeEnum.Half:
|
|
994
|
+
return this._halfToFloat(payload & 0xffff);
|
|
995
|
+
case TypeEnum.Float: {
|
|
996
|
+
view.setUint32(0, payload, true);
|
|
997
|
+
return view.getFloat32(0, true);
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
case TypeEnum.Double: {
|
|
1001
|
+
// When a double is inlined, it's stored as float32 bits in the payload
|
|
1002
|
+
view.setUint32(0, payload, true);
|
|
1003
|
+
return view.getFloat32(0, true);
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
case TypeEnum.Token:
|
|
1007
|
+
return this.tokens[payload] || '';
|
|
1008
|
+
case TypeEnum.String:
|
|
1009
|
+
return this.tokens[this.strings[payload]] || '';
|
|
1010
|
+
case TypeEnum.AssetPath:
|
|
1011
|
+
return this.tokens[payload] || '';
|
|
1012
|
+
case TypeEnum.Specifier:
|
|
1013
|
+
return payload; // 0=def, 1=over, 2=class
|
|
1014
|
+
case TypeEnum.Permission:
|
|
1015
|
+
case TypeEnum.Variability:
|
|
1016
|
+
return payload;
|
|
1017
|
+
|
|
1018
|
+
// Vec2h: Two half-floats fit in 4 bytes, stored directly
|
|
1019
|
+
case TypeEnum.Vec2h: {
|
|
1020
|
+
view.setUint32(0, payload, true);
|
|
1021
|
+
return [
|
|
1022
|
+
this._halfToFloat(view.getUint16(0, true)),
|
|
1023
|
+
this._halfToFloat(view.getUint16(2, true))
|
|
1024
|
+
];
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
// Inlined vectors that don't fit in 4 bytes are encoded as signed 8-bit integers
|
|
1028
|
+
// Vec2f = 8 bytes (2x float32), Vec3f = 12 bytes, Vec4f = 16 bytes, etc.
|
|
1029
|
+
case TypeEnum.Vec2f:
|
|
1030
|
+
case TypeEnum.Vec2i: {
|
|
1031
|
+
view.setUint32(0, payload, true);
|
|
1032
|
+
return [view.getInt8(0), view.getInt8(1)];
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
case TypeEnum.Vec3f:
|
|
1036
|
+
case TypeEnum.Vec3i: {
|
|
1037
|
+
view.setUint32(0, payload, true);
|
|
1038
|
+
return [view.getInt8(0), view.getInt8(1), view.getInt8(2)];
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
case TypeEnum.Vec4f:
|
|
1042
|
+
case TypeEnum.Vec4i: {
|
|
1043
|
+
view.setUint32(0, payload, true);
|
|
1044
|
+
return [view.getInt8(0), view.getInt8(1), view.getInt8(2), view.getInt8(3)];
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
case TypeEnum.Matrix2d: {
|
|
1048
|
+
// Inlined Matrix2d stores diagonal values as 2 signed int8 values
|
|
1049
|
+
view.setUint32(0, payload, true);
|
|
1050
|
+
const d0 = view.getInt8(0),
|
|
1051
|
+
d1 = view.getInt8(1);
|
|
1052
|
+
return [d0, 0, 0, d1];
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
case TypeEnum.Matrix3d: {
|
|
1056
|
+
// Inlined Matrix3d stores diagonal values as 3 signed int8 values
|
|
1057
|
+
view.setUint32(0, payload, true);
|
|
1058
|
+
const d0 = view.getInt8(0),
|
|
1059
|
+
d1 = view.getInt8(1),
|
|
1060
|
+
d2 = view.getInt8(2);
|
|
1061
|
+
return [d0, 0, 0, 0, d1, 0, 0, 0, d2];
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
case TypeEnum.Matrix4d: {
|
|
1065
|
+
// Inlined Matrix4d stores diagonal values as 4 signed int8 values
|
|
1066
|
+
view.setUint32(0, payload, true);
|
|
1067
|
+
const d0 = view.getInt8(0),
|
|
1068
|
+
d1 = view.getInt8(1),
|
|
1069
|
+
d2 = view.getInt8(2),
|
|
1070
|
+
d3 = view.getInt8(3);
|
|
1071
|
+
return [d0, 0, 0, 0, 0, d1, 0, 0, 0, 0, d2, 0, 0, 0, 0, d3];
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
default:
|
|
1075
|
+
throw new Error('USDC: unsupported inline value type ' + type);
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
_readTimeSamples(valueRep) {
|
|
1080
|
+
const reader = this.reader;
|
|
1081
|
+
const offset = valueRep.payload;
|
|
1082
|
+
const savedOffset = reader.tell();
|
|
1083
|
+
reader.seek(offset);
|
|
1084
|
+
|
|
1085
|
+
// TimeSamples format uses RELATIVE offsets (from OpenUSD _RecursiveRead):
|
|
1086
|
+
// _RecursiveRead: read int64 relativeOffset at current position, then seek to start + relativeOffset
|
|
1087
|
+
// After reading timesRep, continue reading from current position (after timesRep)
|
|
1088
|
+
// Layout at TimeSamples location:
|
|
1089
|
+
// - int64 timesOffset (relative from start of this int64)
|
|
1090
|
+
// At (start + timesOffset): timesRep ValueRep, then int64 valuesOffset, then numValues + ValueReps
|
|
1091
|
+
|
|
1092
|
+
// Read times relative offset and resolve
|
|
1093
|
+
const timesStart = reader.tell();
|
|
1094
|
+
const timesRelOffset = reader.readInt64();
|
|
1095
|
+
reader.seek(timesStart + timesRelOffset);
|
|
1096
|
+
|
|
1097
|
+
const timesRepLo = reader.readUint32();
|
|
1098
|
+
const timesRepHi = reader.readUint32();
|
|
1099
|
+
const timesRep = new ValueRep(timesRepLo, timesRepHi);
|
|
1100
|
+
|
|
1101
|
+
// Resolve times array
|
|
1102
|
+
const times = this._readValue(timesRep);
|
|
1103
|
+
|
|
1104
|
+
// Continue reading from current position (after timesRep)
|
|
1105
|
+
// The second _RecursiveRead reads from CURRENT position, not from the beginning
|
|
1106
|
+
const afterTimesRep = timesStart + timesRelOffset + 8;
|
|
1107
|
+
reader.seek(afterTimesRep);
|
|
1108
|
+
|
|
1109
|
+
// Read values relative offset
|
|
1110
|
+
const valuesStart = reader.tell();
|
|
1111
|
+
const valuesRelOffset = reader.readInt64();
|
|
1112
|
+
reader.seek(valuesStart + valuesRelOffset);
|
|
1113
|
+
|
|
1114
|
+
// Read number of values
|
|
1115
|
+
const numValues = checkedCount(reader.readUint64());
|
|
1116
|
+
|
|
1117
|
+
// Read all ValueReps
|
|
1118
|
+
const valueReps = [];
|
|
1119
|
+
for (let i = 0; i < numValues; i++) {
|
|
1120
|
+
const repLo = reader.readUint32();
|
|
1121
|
+
const repHi = reader.readUint32();
|
|
1122
|
+
valueReps.push(new ValueRep(repLo, repHi));
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
// Resolve each value
|
|
1126
|
+
const values = [];
|
|
1127
|
+
for (let i = 0; i < numValues; i++) {
|
|
1128
|
+
values.push(this._readValue(valueReps[i]));
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
reader.seek(savedOffset);
|
|
1132
|
+
|
|
1133
|
+
// Convert times to array if needed
|
|
1134
|
+
const timesArray =
|
|
1135
|
+
times instanceof Float64Array ? Array.from(times) : Array.isArray(times) ? times : [times];
|
|
1136
|
+
|
|
1137
|
+
return {times: timesArray, values};
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
_readScalarValue(type) {
|
|
1141
|
+
const reader = this.reader;
|
|
1142
|
+
|
|
1143
|
+
switch (type) {
|
|
1144
|
+
case TypeEnum.Invalid:
|
|
1145
|
+
return null;
|
|
1146
|
+
case TypeEnum.Bool:
|
|
1147
|
+
return reader.readUint8() !== 0;
|
|
1148
|
+
case TypeEnum.UChar:
|
|
1149
|
+
return reader.readUint8();
|
|
1150
|
+
case TypeEnum.Int:
|
|
1151
|
+
return reader.readInt32();
|
|
1152
|
+
case TypeEnum.UInt:
|
|
1153
|
+
return reader.readUint32();
|
|
1154
|
+
case TypeEnum.Int64:
|
|
1155
|
+
return reader.readInt64();
|
|
1156
|
+
case TypeEnum.UInt64:
|
|
1157
|
+
return reader.readUint64();
|
|
1158
|
+
case TypeEnum.Half:
|
|
1159
|
+
return this._readHalf();
|
|
1160
|
+
case TypeEnum.Float:
|
|
1161
|
+
return reader.readFloat32();
|
|
1162
|
+
case TypeEnum.Double:
|
|
1163
|
+
return reader.readFloat64();
|
|
1164
|
+
case TypeEnum.String:
|
|
1165
|
+
case TypeEnum.Token: {
|
|
1166
|
+
const index = reader.readUint32();
|
|
1167
|
+
return this.tokens[index] || '';
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
case TypeEnum.AssetPath: {
|
|
1171
|
+
const index = reader.readUint32();
|
|
1172
|
+
return this.tokens[index] || '';
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
case TypeEnum.Vec2f:
|
|
1176
|
+
return [reader.readFloat32(), reader.readFloat32()];
|
|
1177
|
+
case TypeEnum.Vec2d:
|
|
1178
|
+
return [reader.readFloat64(), reader.readFloat64()];
|
|
1179
|
+
case TypeEnum.Vec2i:
|
|
1180
|
+
return [reader.readInt32(), reader.readInt32()];
|
|
1181
|
+
case TypeEnum.Vec3f:
|
|
1182
|
+
return [reader.readFloat32(), reader.readFloat32(), reader.readFloat32()];
|
|
1183
|
+
case TypeEnum.Vec3d:
|
|
1184
|
+
return [reader.readFloat64(), reader.readFloat64(), reader.readFloat64()];
|
|
1185
|
+
case TypeEnum.Vec3i:
|
|
1186
|
+
return [reader.readInt32(), reader.readInt32(), reader.readInt32()];
|
|
1187
|
+
case TypeEnum.Vec4f:
|
|
1188
|
+
return [
|
|
1189
|
+
reader.readFloat32(),
|
|
1190
|
+
reader.readFloat32(),
|
|
1191
|
+
reader.readFloat32(),
|
|
1192
|
+
reader.readFloat32()
|
|
1193
|
+
];
|
|
1194
|
+
case TypeEnum.Vec4d:
|
|
1195
|
+
return [
|
|
1196
|
+
reader.readFloat64(),
|
|
1197
|
+
reader.readFloat64(),
|
|
1198
|
+
reader.readFloat64(),
|
|
1199
|
+
reader.readFloat64()
|
|
1200
|
+
];
|
|
1201
|
+
case TypeEnum.Quatf:
|
|
1202
|
+
return [
|
|
1203
|
+
reader.readFloat32(),
|
|
1204
|
+
reader.readFloat32(),
|
|
1205
|
+
reader.readFloat32(),
|
|
1206
|
+
reader.readFloat32()
|
|
1207
|
+
];
|
|
1208
|
+
case TypeEnum.Quatd:
|
|
1209
|
+
return [
|
|
1210
|
+
reader.readFloat64(),
|
|
1211
|
+
reader.readFloat64(),
|
|
1212
|
+
reader.readFloat64(),
|
|
1213
|
+
reader.readFloat64()
|
|
1214
|
+
];
|
|
1215
|
+
case TypeEnum.Matrix4d: {
|
|
1216
|
+
const m = [];
|
|
1217
|
+
for (let i = 0; i < 16; i++) m.push(reader.readFloat64());
|
|
1218
|
+
return m;
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
case TypeEnum.TokenVector: {
|
|
1222
|
+
const count = checkedCount(reader.readUint64());
|
|
1223
|
+
const tokens = [];
|
|
1224
|
+
for (let i = 0; i < count; i++) {
|
|
1225
|
+
const index = reader.readUint32();
|
|
1226
|
+
tokens.push(this.tokens[index] || '');
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
return tokens;
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
case TypeEnum.PathVector: {
|
|
1233
|
+
const count = checkedCount(reader.readUint64());
|
|
1234
|
+
const paths = [];
|
|
1235
|
+
for (let i = 0; i < count; i++) {
|
|
1236
|
+
const index = reader.readUint32();
|
|
1237
|
+
paths.push(this.paths[index] || '');
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
return paths;
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
case TypeEnum.DoubleVector: {
|
|
1244
|
+
// DoubleVector is a count-prefixed array of doubles
|
|
1245
|
+
const count = checkedCount(reader.readUint64());
|
|
1246
|
+
const arr = new Float64Array(checkedLength(count));
|
|
1247
|
+
for (let i = 0; i < count; i++) arr[i] = reader.readFloat64();
|
|
1248
|
+
return arr;
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
case TypeEnum.Dictionary:
|
|
1252
|
+
return this._readDictionary();
|
|
1253
|
+
case TypeEnum.TokenListOp:
|
|
1254
|
+
case TypeEnum.StringListOp:
|
|
1255
|
+
case TypeEnum.IntListOp:
|
|
1256
|
+
case TypeEnum.Int64ListOp:
|
|
1257
|
+
case TypeEnum.UIntListOp:
|
|
1258
|
+
case TypeEnum.UInt64ListOp:
|
|
1259
|
+
// These complex types are not needed for geometry loading
|
|
1260
|
+
// Composition semantics must not be silently discarded.
|
|
1261
|
+
throw new Error('USDC: value list operations are unsupported');
|
|
1262
|
+
|
|
1263
|
+
case TypeEnum.PathListOp: {
|
|
1264
|
+
// PathListOp format (from AOUSD Core Spec 16.3.10.25):
|
|
1265
|
+
// Header byte bitmask:
|
|
1266
|
+
// - bit 0 (0x01): Make Explicit (clears list)
|
|
1267
|
+
// - bit 1 (0x02): Add Explicit Items
|
|
1268
|
+
// - bit 2 (0x04): Add Items
|
|
1269
|
+
// - bit 3 (0x08): Delete Items
|
|
1270
|
+
// - bit 4 (0x10): Reorder Items
|
|
1271
|
+
// - bit 5 (0x20): Prepend Items
|
|
1272
|
+
// - bit 6 (0x40): Append Items
|
|
1273
|
+
// Arrays follow in order: Explicit, Add, Prepend, Append, Delete, Reorder
|
|
1274
|
+
// Each array: uint64 count + count * uint32 path indices
|
|
1275
|
+
const flags = reader.readUint8();
|
|
1276
|
+
if (flags & 0x18 || (flags & 0x66).toString(2).replaceAll('0', '').length > 1)
|
|
1277
|
+
throw new Error('USDC: compound path list operations are unsupported');
|
|
1278
|
+
const hasExplicitItems = (flags & 0x02) !== 0;
|
|
1279
|
+
const hasAddItems = (flags & 0x04) !== 0;
|
|
1280
|
+
const hasDeleteItems = (flags & 0x08) !== 0;
|
|
1281
|
+
const hasReorderItems = (flags & 0x10) !== 0;
|
|
1282
|
+
const hasPrependItems = (flags & 0x20) !== 0;
|
|
1283
|
+
const hasAppendItems = (flags & 0x40) !== 0;
|
|
1284
|
+
|
|
1285
|
+
const readPathList = () => {
|
|
1286
|
+
const itemCount = checkedCount(reader.readUint64());
|
|
1287
|
+
const paths = [];
|
|
1288
|
+
for (let i = 0; i < itemCount; i++) {
|
|
1289
|
+
const pathIdx = reader.readUint32();
|
|
1290
|
+
paths.push(this.paths[pathIdx]);
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
return paths;
|
|
1294
|
+
};
|
|
1295
|
+
|
|
1296
|
+
// Read arrays in spec order: Explicit, Add, Prepend, Append, Delete, Reorder
|
|
1297
|
+
let explicitPaths = null;
|
|
1298
|
+
let addPaths = null;
|
|
1299
|
+
let prependPaths = null;
|
|
1300
|
+
let appendPaths = null;
|
|
1301
|
+
|
|
1302
|
+
if (hasExplicitItems) explicitPaths = readPathList();
|
|
1303
|
+
if (hasAddItems) addPaths = readPathList();
|
|
1304
|
+
if (hasPrependItems) prependPaths = readPathList();
|
|
1305
|
+
if (hasAppendItems) appendPaths = readPathList();
|
|
1306
|
+
if (hasDeleteItems) readPathList(); // Skip delete items
|
|
1307
|
+
if (hasReorderItems) readPathList(); // Skip reorder items
|
|
1308
|
+
|
|
1309
|
+
// Return the first non-empty list (connections are typically prepended)
|
|
1310
|
+
if (prependPaths && prependPaths.length > 0) return prependPaths;
|
|
1311
|
+
if (explicitPaths && explicitPaths.length > 0) return explicitPaths;
|
|
1312
|
+
if (appendPaths && appendPaths.length > 0) return appendPaths;
|
|
1313
|
+
if (addPaths && addPaths.length > 0) return addPaths;
|
|
1314
|
+
|
|
1315
|
+
return null;
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
case TypeEnum.VariantSelectionMap: {
|
|
1319
|
+
const elementCount = checkedCount(reader.readUint64());
|
|
1320
|
+
const map = Object.create(null);
|
|
1321
|
+
|
|
1322
|
+
for (let i = 0; i < elementCount; i++) {
|
|
1323
|
+
const keyIdx = reader.readUint32();
|
|
1324
|
+
const valueIdx = reader.readUint32();
|
|
1325
|
+
const key = this.tokens[this.strings[keyIdx]];
|
|
1326
|
+
const value = this.tokens[this.strings[valueIdx]];
|
|
1327
|
+
if (key && value) map[key] = value;
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
return map;
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
default:
|
|
1334
|
+
throw new Error(
|
|
1335
|
+
'USDC: unsupported encoding: ' + ['USDCParser: Unsupported scalar type', type].join(' ')
|
|
1336
|
+
);
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
/** Reads bounded string-keyed dictionary entries and their recursive value representations. */
|
|
1341
|
+
_readDictionary() {
|
|
1342
|
+
const reader = this.reader;
|
|
1343
|
+
const dictionaryOffset = reader.tell();
|
|
1344
|
+
this._activeDictionaries ||= new Set();
|
|
1345
|
+
if (this._activeDictionaries.has(dictionaryOffset))
|
|
1346
|
+
throw new Error('USDC: cyclic dictionary value');
|
|
1347
|
+
if (this._activeDictionaries.size >= 64)
|
|
1348
|
+
throw new Error('USDC: dictionary depth limit exceeded');
|
|
1349
|
+
this._activeDictionaries.add(dictionaryOffset);
|
|
1350
|
+
try {
|
|
1351
|
+
const count = checkedCount(reader.readUint64());
|
|
1352
|
+
if (count > Math.floor((this.buffer.byteLength - reader.tell()) / 20))
|
|
1353
|
+
throw new Error('USDC: truncated dictionary entries');
|
|
1354
|
+
const dictionary = Object.create(null);
|
|
1355
|
+
for (let index = 0; index < count; index++) {
|
|
1356
|
+
const stringIndex = reader.readUint32();
|
|
1357
|
+
const key = this.tokens[this.strings[stringIndex]];
|
|
1358
|
+
if (typeof key !== 'string' || Object.hasOwn(dictionary, key))
|
|
1359
|
+
throw new Error('USDC: invalid dictionary key');
|
|
1360
|
+
const offsetLocation = reader.tell();
|
|
1361
|
+
const relativeOffset = reader.readInt64();
|
|
1362
|
+
if (relativeOffset < 8) throw new Error('USDC: invalid dictionary value offset');
|
|
1363
|
+
reader.seek(offsetLocation + relativeOffset);
|
|
1364
|
+
const representation = new ValueRep(reader.readUint32(), reader.readUint32());
|
|
1365
|
+
if (
|
|
1366
|
+
representation.typeEnum < TypeEnum.Bool ||
|
|
1367
|
+
(representation.typeEnum > TypeEnum.AssetPath &&
|
|
1368
|
+
representation.typeEnum !== TypeEnum.Dictionary) ||
|
|
1369
|
+
(representation.isArray && !DICTIONARY_ARRAY_TYPES.has(representation.typeEnum))
|
|
1370
|
+
)
|
|
1371
|
+
throw new Error('USDC: unsupported dictionary value type');
|
|
1372
|
+
const nextEntry = reader.tell();
|
|
1373
|
+
const value = this._readValue(representation);
|
|
1374
|
+
dictionary[key] =
|
|
1375
|
+
representation.typeEnum === TypeEnum.AssetPath ? {assetPath: value} : value;
|
|
1376
|
+
reader.seek(nextEntry);
|
|
1377
|
+
}
|
|
1378
|
+
return dictionary;
|
|
1379
|
+
} finally {
|
|
1380
|
+
this._activeDictionaries.delete(dictionaryOffset);
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
_readArrayValue(valueRep) {
|
|
1385
|
+
const reader = this.reader;
|
|
1386
|
+
const type = valueRep.typeEnum;
|
|
1387
|
+
const isCompressed = valueRep.isCompressed;
|
|
1388
|
+
|
|
1389
|
+
// Read array size
|
|
1390
|
+
let size;
|
|
1391
|
+
if (this.version.major === 0 && this.version.minor < 7) {
|
|
1392
|
+
size = reader.readUint32();
|
|
1393
|
+
} else {
|
|
1394
|
+
size = reader.readUint64();
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
if (!Number.isSafeInteger(size) || size < 0) {
|
|
1398
|
+
throw new RangeError('USDCParser: Invalid array size ' + size + ' for type ' + type + '.');
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
if (size > 0x7fffffff) {
|
|
1402
|
+
// Crate stores counts as uint64, but JS typed arrays cannot represent all such sizes.
|
|
1403
|
+
throw new RangeError('USDCParser: Array size ' + size + ' exceeds implementation limits.');
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
size = checkedCount(size);
|
|
1407
|
+
if (size === 0) return [];
|
|
1408
|
+
|
|
1409
|
+
// Handle compressed arrays
|
|
1410
|
+
if (isCompressed) {
|
|
1411
|
+
return this._readCompressedArray(type, size);
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
// Read uncompressed array
|
|
1415
|
+
switch (type) {
|
|
1416
|
+
case TypeEnum.Int: {
|
|
1417
|
+
const arr = new Int32Array(checkedLength(size));
|
|
1418
|
+
for (let i = 0; i < size; i++) arr[i] = reader.readInt32();
|
|
1419
|
+
return arr;
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
case TypeEnum.UInt: {
|
|
1423
|
+
const arr = new Uint32Array(checkedLength(size));
|
|
1424
|
+
for (let i = 0; i < size; i++) arr[i] = reader.readUint32();
|
|
1425
|
+
return arr;
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
case TypeEnum.Float: {
|
|
1429
|
+
const arr = new Float32Array(checkedLength(size));
|
|
1430
|
+
for (let i = 0; i < size; i++) arr[i] = reader.readFloat32();
|
|
1431
|
+
return arr;
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
case TypeEnum.Double: {
|
|
1435
|
+
const arr = new Float64Array(checkedLength(size));
|
|
1436
|
+
for (let i = 0; i < size; i++) arr[i] = reader.readFloat64();
|
|
1437
|
+
return arr;
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
case TypeEnum.Vec2f: {
|
|
1441
|
+
const arr = new Float32Array(checkedLength(size * 2));
|
|
1442
|
+
for (let i = 0; i < size * 2; i++) arr[i] = reader.readFloat32();
|
|
1443
|
+
return arr;
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
case TypeEnum.Vec3f: {
|
|
1447
|
+
const arr = new Float32Array(checkedLength(size * 3));
|
|
1448
|
+
for (let i = 0; i < size * 3; i++) arr[i] = reader.readFloat32();
|
|
1449
|
+
return arr;
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
case TypeEnum.Vec4f: {
|
|
1453
|
+
const arr = new Float32Array(checkedLength(size * 4));
|
|
1454
|
+
for (let i = 0; i < size * 4; i++) arr[i] = reader.readFloat32();
|
|
1455
|
+
return arr;
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
case TypeEnum.Vec3h: {
|
|
1459
|
+
// Half-precision vec3 array (used for scales in skeletal animation)
|
|
1460
|
+
const arr = new Float32Array(checkedLength(size * 3));
|
|
1461
|
+
for (let i = 0; i < size * 3; i++) arr[i] = this._readHalf();
|
|
1462
|
+
return arr;
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
case TypeEnum.Quatf: {
|
|
1466
|
+
const arr = new Float32Array(checkedLength(size * 4));
|
|
1467
|
+
for (let i = 0; i < size * 4; i++) arr[i] = reader.readFloat32();
|
|
1468
|
+
return arr;
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
case TypeEnum.Quath: {
|
|
1472
|
+
// Half-precision quaternion array
|
|
1473
|
+
const arr = new Float32Array(checkedLength(size * 4));
|
|
1474
|
+
for (let i = 0; i < size * 4; i++) arr[i] = this._readHalf();
|
|
1475
|
+
return arr;
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
case TypeEnum.Matrix4d: {
|
|
1479
|
+
// 4x4 matrix array (16 doubles per matrix, row-major)
|
|
1480
|
+
const arr = new Float64Array(checkedLength(size * 16));
|
|
1481
|
+
for (let i = 0; i < size * 16; i++) arr[i] = reader.readFloat64();
|
|
1482
|
+
return arr;
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
case TypeEnum.String:
|
|
1486
|
+
case TypeEnum.Token: {
|
|
1487
|
+
const arr = [];
|
|
1488
|
+
for (let i = 0; i < size; i++) {
|
|
1489
|
+
const index = reader.readUint32();
|
|
1490
|
+
const tokenIndex = type === TypeEnum.String ? this.strings[index] : index;
|
|
1491
|
+
const value = this.tokens[tokenIndex];
|
|
1492
|
+
if (typeof value !== 'string') throw new Error('USDC: invalid string array index');
|
|
1493
|
+
arr.push(value);
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
return arr;
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
case TypeEnum.Half: {
|
|
1500
|
+
const arr = new Float32Array(checkedLength(size));
|
|
1501
|
+
for (let i = 0; i < size; i++) arr[i] = this._readHalf();
|
|
1502
|
+
return arr;
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
default:
|
|
1506
|
+
throw new Error(
|
|
1507
|
+
'USDC: unsupported encoding: ' + ['USDCParser: Unsupported array type', type].join(' ')
|
|
1508
|
+
);
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
_readCompressedArray(type, size) {
|
|
1513
|
+
const reader = this.reader;
|
|
1514
|
+
|
|
1515
|
+
switch (type) {
|
|
1516
|
+
case TypeEnum.Int:
|
|
1517
|
+
case TypeEnum.UInt: {
|
|
1518
|
+
const compressedSize = reader.readUint64();
|
|
1519
|
+
const compressed = reader.readBytes(compressedSize);
|
|
1520
|
+
const values = decompressIntegers32(
|
|
1521
|
+
compressed.buffer.slice(compressed.byteOffset, compressed.byteOffset + compressedSize),
|
|
1522
|
+
size
|
|
1523
|
+
);
|
|
1524
|
+
return type === TypeEnum.UInt
|
|
1525
|
+
? new Uint32Array(values.buffer, values.byteOffset, values.length)
|
|
1526
|
+
: values;
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
case TypeEnum.Half:
|
|
1530
|
+
case TypeEnum.Double:
|
|
1531
|
+
case TypeEnum.Float: {
|
|
1532
|
+
// Float compression: 'i' = compressed as ints, 't' = lookup table
|
|
1533
|
+
const code = reader.readInt8();
|
|
1534
|
+
|
|
1535
|
+
if (code === FLOAT_COMPRESSION_INT) {
|
|
1536
|
+
const compressedSize = reader.readUint64();
|
|
1537
|
+
const compressed = reader.readBytes(compressedSize);
|
|
1538
|
+
const ints = decompressIntegers32(
|
|
1539
|
+
compressed.buffer.slice(compressed.byteOffset, compressed.byteOffset + compressedSize),
|
|
1540
|
+
size
|
|
1541
|
+
);
|
|
1542
|
+
const floats =
|
|
1543
|
+
type === TypeEnum.Double
|
|
1544
|
+
? new Float64Array(checkedLength(size))
|
|
1545
|
+
: new Float32Array(checkedLength(size));
|
|
1546
|
+
for (let i = 0; i < size; i++)
|
|
1547
|
+
floats[i] = type === TypeEnum.Half ? this._convertHalfInteger(ints[i]) : ints[i];
|
|
1548
|
+
return floats;
|
|
1549
|
+
} else if (code === FLOAT_COMPRESSION_LUT) {
|
|
1550
|
+
const lutSize = checkedCount(reader.readUint32());
|
|
1551
|
+
if (lutSize === 0) throw new Error('USDC: invalid float lookup table');
|
|
1552
|
+
const lut =
|
|
1553
|
+
type === TypeEnum.Double
|
|
1554
|
+
? new Float64Array(checkedLength(lutSize))
|
|
1555
|
+
: new Float32Array(checkedLength(lutSize));
|
|
1556
|
+
for (let i = 0; i < lutSize; i++)
|
|
1557
|
+
lut[i] =
|
|
1558
|
+
type === TypeEnum.Half
|
|
1559
|
+
? this._readHalf()
|
|
1560
|
+
: type === TypeEnum.Double
|
|
1561
|
+
? reader.readFloat64()
|
|
1562
|
+
: reader.readFloat32();
|
|
1563
|
+
|
|
1564
|
+
const compressedSize = reader.readUint64();
|
|
1565
|
+
const compressed = reader.readBytes(compressedSize);
|
|
1566
|
+
const indices = decompressIntegers32(
|
|
1567
|
+
compressed.buffer.slice(compressed.byteOffset, compressed.byteOffset + compressedSize),
|
|
1568
|
+
size
|
|
1569
|
+
);
|
|
1570
|
+
|
|
1571
|
+
const floats =
|
|
1572
|
+
type === TypeEnum.Double
|
|
1573
|
+
? new Float64Array(checkedLength(size))
|
|
1574
|
+
: new Float32Array(checkedLength(size));
|
|
1575
|
+
for (let i = 0; i < size; i++) {
|
|
1576
|
+
if (indices[i] < 0 || indices[i] >= lutSize)
|
|
1577
|
+
throw new Error('USDC: invalid float lookup index');
|
|
1578
|
+
floats[i] = lut[indices[i]];
|
|
1579
|
+
}
|
|
1580
|
+
return floats;
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
throw new Error(
|
|
1584
|
+
'USDC: unsupported encoding: ' +
|
|
1585
|
+
['USDCParser: Unknown float compression code', code].join(' ')
|
|
1586
|
+
);
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
default:
|
|
1590
|
+
throw new Error(
|
|
1591
|
+
'USDC: unsupported encoding: ' +
|
|
1592
|
+
['USDCParser: Unsupported compressed array type', type].join(' ')
|
|
1593
|
+
);
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
/** Rounds integer-compressed half samples using IEEE ties-to-even semantics. */
|
|
1598
|
+
_convertHalfInteger(value) {
|
|
1599
|
+
const absoluteValue = Math.abs(value);
|
|
1600
|
+
if (absoluteValue <= 2048) return value;
|
|
1601
|
+
if (absoluteValue >= 65520) return Math.sign(value) * Infinity;
|
|
1602
|
+
const spacing = 2 ** (Math.floor(Math.log2(absoluteValue)) - 10);
|
|
1603
|
+
const scaledValue = absoluteValue / spacing;
|
|
1604
|
+
const lowerValue = Math.floor(scaledValue);
|
|
1605
|
+
const fractionValue = scaledValue - lowerValue;
|
|
1606
|
+
const roundedValue =
|
|
1607
|
+
fractionValue > 0.5 || (fractionValue === 0.5 && lowerValue % 2 !== 0)
|
|
1608
|
+
? lowerValue + 1
|
|
1609
|
+
: lowerValue;
|
|
1610
|
+
return Math.sign(value) * roundedValue * spacing;
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
_readHalf() {
|
|
1614
|
+
return this._halfToFloat(this.reader.readUint16());
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
_halfToFloat(h) {
|
|
1618
|
+
const sign = (h & 0x8000) >> 15;
|
|
1619
|
+
const exp = (h & 0x7c00) >> 10;
|
|
1620
|
+
const frac = h & 0x03ff;
|
|
1621
|
+
|
|
1622
|
+
if (exp === 0) {
|
|
1623
|
+
// Zero or denormalized number
|
|
1624
|
+
if (frac === 0) {
|
|
1625
|
+
return sign ? -0 : 0;
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
// Denormalized: value = ±2^-14 × (frac/1024)
|
|
1629
|
+
return (sign ? -1 : 1) * HALF_DENORM_SCALE * (frac / 1024);
|
|
1630
|
+
} else if (exp === 31) {
|
|
1631
|
+
return frac ? NaN : sign ? -Infinity : Infinity;
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
return (sign ? -1 : 1) * HALF_EXPONENT_TABLE[exp] * (1 + frac / 1024);
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
_getFieldsForSpec(spec) {
|
|
1638
|
+
const fields = Object.create(null);
|
|
1639
|
+
let fieldSetIndex = spec.fieldSetIndex;
|
|
1640
|
+
|
|
1641
|
+
// Field sets are terminated by FIELD_SET_TERMINATOR
|
|
1642
|
+
// Limit iterations to prevent infinite loops from malformed data
|
|
1643
|
+
const maxIterations = 10000;
|
|
1644
|
+
let iterations = 0;
|
|
1645
|
+
|
|
1646
|
+
while (fieldSetIndex < this.fieldSets.length && iterations < maxIterations) {
|
|
1647
|
+
const fieldIndex = this.fieldSets[fieldSetIndex];
|
|
1648
|
+
|
|
1649
|
+
// Terminator
|
|
1650
|
+
if (fieldIndex === FIELD_SET_TERMINATOR || fieldIndex === -1) break;
|
|
1651
|
+
|
|
1652
|
+
const field = this.fields[fieldIndex];
|
|
1653
|
+
if (!field) throw new Error('USDC: invalid field index');
|
|
1654
|
+
if (field) {
|
|
1655
|
+
const name = this.tokens[field.tokenIndex];
|
|
1656
|
+
const value = this._readValue(field.valueRep);
|
|
1657
|
+
fields[name] = value;
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
fieldSetIndex++;
|
|
1661
|
+
iterations++;
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
if (iterations >= maxIterations) throw new Error('USDC: field traversal limit exceeded');
|
|
1665
|
+
return fields;
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
export {USDCParser};
|