@forgeax/engine-gltf 0.1.6 → 0.1.19

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.
Files changed (39) hide show
  1. package/README.md +9 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/__tests__/transmission-pack-carrier.integration.test.d.ts +2 -0
  4. package/dist/__tests__/transmission-pack-carrier.integration.test.d.ts.map +1 -0
  5. package/dist/bridge.d.ts.map +1 -1
  6. package/dist/check-extensions.d.ts +3 -3
  7. package/dist/check-extensions.d.ts.map +1 -1
  8. package/dist/cli-gltf.mjs +161 -69
  9. package/dist/cli-gltf.mjs.map +1 -1
  10. package/dist/errors.d.ts +7 -0
  11. package/dist/errors.d.ts.map +1 -1
  12. package/dist/gltf-importer.d.ts.map +1 -1
  13. package/dist/importer-entry.mjs +177 -72
  14. package/dist/importer-entry.mjs.map +1 -1
  15. package/dist/index.d.ts +1 -1
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.mjs +177 -72
  18. package/dist/index.mjs.map +1 -1
  19. package/dist/material/parse-material.d.ts +118 -0
  20. package/dist/material/parse-material.d.ts.map +1 -0
  21. package/dist/node-file-entry.mjs +161 -69
  22. package/dist/node-file-entry.mjs.map +1 -1
  23. package/dist/parse-gltf.d.ts +17 -103
  24. package/dist/parse-gltf.d.ts.map +1 -1
  25. package/package.json +12 -12
  26. package/src/__tests__/bridge-material-values.unit.test.ts +46 -0
  27. package/src/__tests__/gltf-error-derived-views.test-d.ts +4 -0
  28. package/src/__tests__/gltf-error-policy-owner.unit.test.ts +26 -178
  29. package/src/__tests__/gltf.unit.test.ts +28 -4
  30. package/src/__tests__/material-pack-refs.integration.test.ts +12 -0
  31. package/src/__tests__/parse-gltf.unit.test.ts +121 -0
  32. package/src/__tests__/transmission-pack-carrier.integration.test.ts +82 -0
  33. package/src/bridge.ts +12 -1
  34. package/src/check-extensions.ts +14 -9
  35. package/src/errors.ts +12 -0
  36. package/src/gltf-importer.ts +6 -0
  37. package/src/index.ts +1 -0
  38. package/src/material/parse-material.ts +342 -0
  39. package/src/parse-gltf.ts +50 -277
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=transmission-pack-carrier.integration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transmission-pack-carrier.integration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/transmission-pack-carrier.integration.test.ts"],"names":[],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EACV,SAAS,EACT,MAAM,EAEN,aAAa,EACb,aAAa,EAEb,SAAS,EAIT,MAAM,EACN,UAAU,EAIX,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAA4B,KAAK,SAAS,EAAe,MAAM,aAAa,CAAC;AACpF,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,UAAU,EACV,UAAU,EAGX,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,SAAS,UAAU,EAAE,EAC5B,SAAS,GAAE;IACT,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpD,GACL,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,CA0U9B;AAED,MAAM,WAAW,iBAAiB;IAChC,oEAAoE;IACpE,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;IACzE,4DAA4D;IAC5D,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC,CAAC;IACjF;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,uBAAuB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChE;AA+DD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB,GAAG,UAAU,CA8NpF;AAED,uFAAuF;AACvF,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC;AAEtC,MAAM,WAAW,qBAAqB;IACpC,0DAA0D;IAC1D,QAAQ,CAAC,cAAc,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC;IAChF,0DAA0D;IAC1D,QAAQ,CAAC,cAAc,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC;IAChF,8EAA8E;IAC9E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,CAAC;IACtC;;;;;;;;OAQG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAqDD,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,cAAc,EACnB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,SAAS,MAAM,EAAE,GAC/B,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC,CA0B7B;AAED,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,GAAG,EAAE,cAAc,EAAE,GAAG,CAAC,EAAE,qBAAqB,GAAG,aAAa,CA0E/F"}
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EACV,SAAS,EACT,MAAM,EAEN,aAAa,EACb,aAAa,EAEb,SAAS,EAIT,MAAM,EACN,UAAU,EAIX,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAA4B,KAAK,SAAS,EAAe,MAAM,aAAa,CAAC;AACpF,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,UAAU,EACV,UAAU,EAGX,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,SAAS,UAAU,EAAE,EAC5B,SAAS,GAAE;IACT,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpD,GACL,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,CA0U9B;AAED,MAAM,WAAW,iBAAiB;IAChC,oEAAoE;IACpE,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;IACzE,4DAA4D;IAC5D,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC,CAAC;IACjF;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,uBAAuB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChE;AA+DD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB,GAAG,UAAU,CA8NpF;AAED,uFAAuF;AACvF,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC;AAEtC,MAAM,WAAW,qBAAqB;IACpC,0DAA0D;IAC1D,QAAQ,CAAC,cAAc,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC;IAChF,0DAA0D;IAC1D,QAAQ,CAAC,cAAc,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC;IAChF,8EAA8E;IAC9E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,CAAC;IACtC;;;;;;;;OAQG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAuDD,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,cAAc,EACnB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,SAAS,MAAM,EAAE,GAC/B,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC,CA4B7B;AAED,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,GAAG,EAAE,cAAc,EAAE,GAAG,CAAC,EAAE,qBAAqB,GAAG,aAAa,CAiF/F"}
@@ -1,8 +1,8 @@
1
1
  import { type GltfError, type Result } from './errors.js';
2
- /** Hard-coded v1 allowlist (plan-strategy decision section 2 D-1 / D-3). */
2
+ /** Legacy v1 mesh-only list kept for callers that display that surface. */
3
3
  export declare const EXTENSION_ALLOWLIST: readonly string[];
4
4
  export interface ExtensionsCheckResult {
5
- /** Names listed in extensionsUsed but not in the allowlist. */
5
+ /** Names listed in extensionsUsed but not in the supported extension set. */
6
6
  readonly unsupportedUsed: readonly string[];
7
7
  }
8
8
  export interface GltfExtensionsJson {
@@ -10,7 +10,7 @@ export interface GltfExtensionsJson {
10
10
  readonly extensionsUsed?: readonly string[];
11
11
  }
12
12
  /**
13
- * Validate the glTF JSON's extension declarations against the v1 allowlist.
13
+ * Validate the glTF JSON's extension declarations against the supported set.
14
14
  *
15
15
  * Returns:
16
16
  * - `Result.err(gltf-extension-unsupported)` for the FIRST entry of
@@ -1 +1 @@
1
- {"version":3,"file":"check-extensions.d.ts","sourceRoot":"","sources":["../src/check-extensions.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAO,KAAK,SAAS,EAAe,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAE5E,4EAA4E;AAC5E,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAGhD,CAAC;AAOF,MAAM,WAAW,qBAAqB;IACpC,+DAA+D;IAC/D,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7C;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChD,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7C;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,kBAAkB,GACvB,MAAM,CAAC,qBAAqB,EAAE,SAAS,CAAC,CAsB1C"}
1
+ {"version":3,"file":"check-extensions.d.ts","sourceRoot":"","sources":["../src/check-extensions.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAO,KAAK,SAAS,EAAe,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAE5E,2EAA2E;AAC3E,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAGhD,CAAC;AAUF,MAAM,WAAW,qBAAqB;IACpC,6EAA6E;IAC7E,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7C;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChD,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7C;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,kBAAkB,GACvB,MAAM,CAAC,qBAAqB,EAAE,SAAS,CAAC,CAsB1C"}
package/dist/cli-gltf.mjs CHANGED
@@ -27,6 +27,10 @@ var gltfErrorPolicy = {
27
27
  expected: "extension listed in v1 allowlist (see EXTENSION_ALLOWLIST in @forgeax/engine-gltf)",
28
28
  hint: "see feat-future-gltf-extensions-allowlist; remove this extension or wait for the allowlist to expand"
29
29
  },
30
+ "gltf-material-transmission-invalid": {
31
+ expected: "KHR transmission, IOR, and volume values are finite and within their glTF ranges",
32
+ hint: "repair the named glTF material extension value and re-import the source"
33
+ },
30
34
  "gltf-accessor-type-mismatch": {
31
35
  expected: "dense fixed-stride accessor with supported componentType",
32
36
  hint: "sparse: see feat-future-gltf-sparse-accessor; morph: see feat-future-gltf-morph; interleaved: see feat-future-gltf-mesh-multi-section"
@@ -395,7 +399,10 @@ var EXTENSION_ALLOWLIST = [
395
399
  var SUPPORTED_EXTENSIONS = [
396
400
  ...EXTENSION_ALLOWLIST,
397
401
  "KHR_lights_punctual",
398
- "KHR_texture_transform"
402
+ "KHR_texture_transform",
403
+ "KHR_materials_transmission",
404
+ "KHR_materials_ior",
405
+ "KHR_materials_volume"
399
406
  ];
400
407
  function checkExtensions(json) {
401
408
  const required = json.extensionsRequired ?? [];
@@ -447,6 +454,152 @@ function decodeBase64(b64) {
447
454
  return out;
448
455
  }
449
456
 
457
+ // src/material/parse-material.ts
458
+ function tuple2(values) {
459
+ if (values === void 0 || values.length < 2) return void 0;
460
+ return [values[0] ?? 0, values[1] ?? 0];
461
+ }
462
+ function tuple3(values) {
463
+ if (values === void 0 || values.length < 3) return void 0;
464
+ return [values[0] ?? 0, values[1] ?? 0, values[2] ?? 0];
465
+ }
466
+ function parseTextureInfo(info, textures) {
467
+ const transformJson = info.extensions?.KHR_texture_transform;
468
+ const offset = tuple2(transformJson?.offset);
469
+ const scale = tuple2(transformJson?.scale);
470
+ const transform = offset === void 0 && transformJson?.rotation === void 0 && scale === void 0 ? void 0 : {
471
+ ...offset === void 0 ? {} : { offset },
472
+ ...transformJson?.rotation === void 0 ? {} : { rotation: transformJson.rotation },
473
+ ...scale === void 0 ? {} : { scale }
474
+ };
475
+ const sampler = textures[info.index]?.sampler;
476
+ return {
477
+ texture: info.index,
478
+ ...sampler === void 0 ? {} : { sampler },
479
+ ...info.texCoord === void 0 && transformJson?.texCoord === void 0 ? {} : { texCoord: transformJson?.texCoord ?? info.texCoord },
480
+ ...transform === void 0 ? {} : { transform }
481
+ };
482
+ }
483
+ function finiteOrUndefined(value) {
484
+ return value !== void 0 && Number.isFinite(value) ? value : void 0;
485
+ }
486
+ function parseMaterial(matJson, textures) {
487
+ const pbr = matJson.pbrMetallicRoughness;
488
+ const baseColor = pbr?.baseColorFactor ?? [1, 1, 1, 1];
489
+ const baseColor4 = [
490
+ baseColor[0] ?? 1,
491
+ baseColor[1] ?? 1,
492
+ baseColor[2] ?? 1,
493
+ baseColor[3] ?? 1
494
+ ];
495
+ const alphaMode = matJson.alphaMode === "MASK" || matJson.alphaMode === "BLEND" ? matJson.alphaMode : void 0;
496
+ const alphaCutoff = alphaMode === "MASK" ? matJson.alphaCutoff ?? 0.5 : void 0;
497
+ const emissiveFactor = tuple3(matJson.emissiveFactor);
498
+ const transmission = matJson.extensions?.KHR_materials_transmission;
499
+ const ior = matJson.extensions?.KHR_materials_ior;
500
+ const volume = matJson.extensions?.KHR_materials_volume;
501
+ const attenuationColor = tuple3(volume?.attenuationColor);
502
+ const invalid = (extension, field, reason, actual) => err(
503
+ gltfErr("gltf-material-transmission-invalid", {
504
+ extension,
505
+ field,
506
+ reason,
507
+ ...actual === void 0 ? {} : { actual }
508
+ })
509
+ );
510
+ if (transmission?.transmissionFactor !== void 0 && (typeof transmission.transmissionFactor !== "number" || !Number.isFinite(transmission.transmissionFactor))) {
511
+ return invalid(
512
+ "KHR_materials_transmission",
513
+ "transmissionFactor",
514
+ "non-finite",
515
+ transmission.transmissionFactor
516
+ );
517
+ }
518
+ if (transmission?.transmissionFactor !== void 0 && (transmission.transmissionFactor < 0 || transmission.transmissionFactor > 1)) {
519
+ return invalid(
520
+ "KHR_materials_transmission",
521
+ "transmissionFactor",
522
+ "range",
523
+ transmission.transmissionFactor
524
+ );
525
+ }
526
+ if (ior?.ior !== void 0 && (typeof ior.ior !== "number" || !Number.isFinite(ior.ior))) {
527
+ return invalid("KHR_materials_ior", "ior", "non-finite", ior.ior);
528
+ }
529
+ if (ior?.ior !== void 0 && ior.ior < 1) {
530
+ return invalid("KHR_materials_ior", "ior", "range", ior.ior);
531
+ }
532
+ if (volume?.thicknessFactor !== void 0 && !Number.isFinite(volume.thicknessFactor)) {
533
+ return invalid("KHR_materials_volume", "thicknessFactor", "non-finite", volume.thicknessFactor);
534
+ }
535
+ if (volume?.thicknessFactor !== void 0 && volume.thicknessFactor < 0) {
536
+ return invalid("KHR_materials_volume", "thicknessFactor", "range", volume.thicknessFactor);
537
+ }
538
+ if (volume?.attenuationColor !== void 0 && (attenuationColor === void 0 || attenuationColor.some((value) => !Number.isFinite(value) || value < 0 || value > 1))) {
539
+ return invalid("KHR_materials_volume", "attenuationColor", "range", volume.attenuationColor);
540
+ }
541
+ if (volume?.attenuationDistance !== void 0 && !Number.isFinite(volume.attenuationDistance) && volume.attenuationDistance !== Number.POSITIVE_INFINITY) {
542
+ return invalid(
543
+ "KHR_materials_volume",
544
+ "attenuationDistance",
545
+ "non-finite",
546
+ volume.attenuationDistance
547
+ );
548
+ }
549
+ if (volume?.attenuationDistance !== void 0 && Number.isFinite(volume.attenuationDistance) && volume.attenuationDistance <= 0) {
550
+ return invalid(
551
+ "KHR_materials_volume",
552
+ "attenuationDistance",
553
+ "range",
554
+ volume.attenuationDistance
555
+ );
556
+ }
557
+ if (alphaMode === "BLEND" && (transmission?.transmissionFactor ?? 0) > 0) {
558
+ return invalid("KHR_materials_transmission", "alphaMode", "blend", alphaMode);
559
+ }
560
+ return ok({
561
+ ...matJson.name === void 0 ? {} : { name: matJson.name },
562
+ baseColorFactor: baseColor4,
563
+ ...emissiveFactor === void 0 ? {} : { emissiveFactor },
564
+ metallicFactor: pbr?.metallicFactor ?? 1,
565
+ roughnessFactor: pbr?.roughnessFactor ?? 1,
566
+ ...pbr?.baseColorTexture === void 0 ? {} : { baseColorTexture: parseTextureInfo(pbr.baseColorTexture, textures) },
567
+ ...pbr?.metallicRoughnessTexture === void 0 ? {} : { metallicRoughnessTexture: parseTextureInfo(pbr.metallicRoughnessTexture, textures) },
568
+ ...matJson.normalTexture === void 0 ? {} : {
569
+ normalTexture: {
570
+ ...parseTextureInfo(matJson.normalTexture, textures),
571
+ ...matJson.normalTexture.scale === void 0 ? {} : { scale: matJson.normalTexture.scale }
572
+ }
573
+ },
574
+ ...matJson.occlusionTexture === void 0 ? {} : {
575
+ occlusionTexture: {
576
+ ...parseTextureInfo(matJson.occlusionTexture, textures),
577
+ ...matJson.occlusionTexture.strength === void 0 ? {} : { strength: matJson.occlusionTexture.strength }
578
+ }
579
+ },
580
+ ...matJson.emissiveTexture === void 0 ? {} : { emissiveTexture: parseTextureInfo(matJson.emissiveTexture, textures) },
581
+ ...transmission === void 0 ? {} : {
582
+ transmissionFactor: transmission.transmissionFactor ?? 0,
583
+ transmissionChannel: 0,
584
+ ...transmission.transmissionTexture === void 0 ? {} : {
585
+ transmissionTexture: parseTextureInfo(transmission.transmissionTexture, textures)
586
+ }
587
+ },
588
+ ...ior === void 0 ? {} : { ior: ior.ior ?? 1.5 },
589
+ ...volume === void 0 ? {} : {
590
+ thicknessFactor: volume.thicknessFactor ?? 0,
591
+ thicknessChannel: 1,
592
+ ...volume.thicknessTexture === void 0 ? {} : { thicknessTexture: parseTextureInfo(volume.thicknessTexture, textures) },
593
+ ...attenuationColor === void 0 ? {} : { attenuationColor },
594
+ ...finiteOrUndefined(volume.attenuationDistance) === void 0 ? {} : { attenuationDistance: volume.attenuationDistance }
595
+ },
596
+ ...alphaMode === void 0 ? {} : { alphaMode },
597
+ ...alphaCutoff === void 0 ? {} : { alphaCutoff },
598
+ ...matJson.doubleSided === true ? { doubleSided: true } : {},
599
+ ...pbr?.baseColorTexture?.texCoord === void 0 || pbr.baseColorTexture.texCoord === 0 ? {} : { baseColorTexCoord: pbr.baseColorTexture.texCoord }
600
+ });
601
+ }
602
+
450
603
  // src/meshopt-decode.ts
451
604
  function viewBytes(view, buffers) {
452
605
  const buffer = buffers[view.buffer];
@@ -1085,7 +1238,7 @@ var IDENTITY = {
1085
1238
  rotation: [0, 0, 0, 1],
1086
1239
  scale: [1, 1, 1]
1087
1240
  };
1088
- function tuple3(arr, fallback) {
1241
+ function tuple32(arr, fallback) {
1089
1242
  if (arr === void 0 || arr.length < 3) return fallback;
1090
1243
  return [arr[0] ?? fallback[0], arr[1] ?? fallback[1], arr[2] ?? fallback[2]];
1091
1244
  }
@@ -1121,9 +1274,9 @@ function decomposeNodeTransform(node, nodeIndex, diagnostics) {
1121
1274
  return IDENTITY;
1122
1275
  }
1123
1276
  return {
1124
- translation: tuple3(node.translation, IDENTITY.translation),
1277
+ translation: tuple32(node.translation, IDENTITY.translation),
1125
1278
  rotation: tuple4(node.rotation, IDENTITY.rotation),
1126
- scale: tuple3(node.scale, IDENTITY.scale)
1279
+ scale: tuple32(node.scale, IDENTITY.scale)
1127
1280
  };
1128
1281
  }
1129
1282
 
@@ -1244,27 +1397,6 @@ function decodeAttributeAccessor(accessorIndex, accessor, bufferViews, buffers)
1244
1397
  if (decoded.value.kind !== "f32") return err(unknownAccessor(accessorIndex));
1245
1398
  return ok(decoded.value.data);
1246
1399
  }
1247
- function tuple2(values) {
1248
- if (values === void 0 || values.length < 2) return void 0;
1249
- return [values[0] ?? 0, values[1] ?? 0];
1250
- }
1251
- function parseTextureInfo(info, textures) {
1252
- const transformJson = info.extensions?.KHR_texture_transform;
1253
- const offset = tuple2(transformJson?.offset);
1254
- const scale = tuple2(transformJson?.scale);
1255
- const transform = offset === void 0 && transformJson?.rotation === void 0 && scale === void 0 ? void 0 : {
1256
- ...offset === void 0 ? {} : { offset },
1257
- ...transformJson?.rotation === void 0 ? {} : { rotation: transformJson.rotation },
1258
- ...scale === void 0 ? {} : { scale }
1259
- };
1260
- const sampler = textures[info.index]?.sampler;
1261
- return {
1262
- texture: info.index,
1263
- ...sampler === void 0 ? {} : { sampler },
1264
- ...info.texCoord === void 0 && transformJson?.texCoord === void 0 ? {} : { texCoord: transformJson?.texCoord ?? info.texCoord },
1265
- ...transform === void 0 ? {} : { transform }
1266
- };
1267
- }
1268
1400
  async function resolveBuffer(buf, externalLoader, binChunk) {
1269
1401
  if (buf.uri === void 0) {
1270
1402
  if (binChunk === void 0) {
@@ -1812,51 +1944,11 @@ async function parseGltfWithBin(json, ctx) {
1812
1944
  ...sampJson.name === void 0 ? {} : { name: sampJson.name }
1813
1945
  });
1814
1946
  }
1815
- const materialsJson = json.materials ?? [];
1816
1947
  const materials = [];
1817
- for (const matJson of materialsJson) {
1818
- const pbr = matJson.pbrMetallicRoughness;
1819
- const baseColor = pbr?.baseColorFactor ?? [1, 1, 1, 1];
1820
- const baseColor4 = [
1821
- baseColor[0] ?? 1,
1822
- baseColor[1] ?? 1,
1823
- baseColor[2] ?? 1,
1824
- baseColor[3] ?? 1
1825
- ];
1826
- const alphaMode = matJson.alphaMode === "MASK" || matJson.alphaMode === "BLEND" ? matJson.alphaMode : void 0;
1827
- const alphaCutoff = alphaMode === "MASK" ? matJson.alphaCutoff ?? 0.5 : void 0;
1828
- const emissiveFactor = matJson.emissiveFactor;
1829
- const emissiveFactor3 = [
1830
- emissiveFactor?.[0] ?? 0,
1831
- emissiveFactor?.[1] ?? 0,
1832
- emissiveFactor?.[2] ?? 0
1833
- ];
1834
- materials.push({
1835
- ...matJson.name === void 0 ? {} : { name: matJson.name },
1836
- baseColorFactor: baseColor4,
1837
- ...emissiveFactor === void 0 ? {} : { emissiveFactor: emissiveFactor3 },
1838
- metallicFactor: pbr?.metallicFactor ?? 1,
1839
- roughnessFactor: pbr?.roughnessFactor ?? 1,
1840
- ...pbr?.baseColorTexture === void 0 ? {} : { baseColorTexture: parseTextureInfo(pbr.baseColorTexture, textures) },
1841
- ...pbr?.metallicRoughnessTexture === void 0 ? {} : { metallicRoughnessTexture: parseTextureInfo(pbr.metallicRoughnessTexture, textures) },
1842
- ...matJson.normalTexture === void 0 ? {} : {
1843
- normalTexture: {
1844
- ...parseTextureInfo(matJson.normalTexture, textures),
1845
- ...matJson.normalTexture.scale === void 0 ? {} : { scale: matJson.normalTexture.scale }
1846
- }
1847
- },
1848
- ...matJson.occlusionTexture === void 0 ? {} : {
1849
- occlusionTexture: {
1850
- ...parseTextureInfo(matJson.occlusionTexture, textures),
1851
- ...matJson.occlusionTexture.strength === void 0 ? {} : { strength: matJson.occlusionTexture.strength }
1852
- }
1853
- },
1854
- ...matJson.emissiveTexture === void 0 ? {} : { emissiveTexture: parseTextureInfo(matJson.emissiveTexture, textures) },
1855
- ...alphaMode === void 0 ? {} : { alphaMode },
1856
- ...alphaCutoff === void 0 ? {} : { alphaCutoff },
1857
- ...matJson.doubleSided === true ? { doubleSided: true } : {},
1858
- ...pbr?.baseColorTexture?.texCoord === void 0 || pbr.baseColorTexture.texCoord === 0 ? {} : { baseColorTexCoord: pbr.baseColorTexture.texCoord }
1859
- });
1948
+ for (const material of json.materials ?? []) {
1949
+ const parsedMaterial = parseMaterial(material, textures);
1950
+ if (!parsedMaterial.ok) return err(parsedMaterial.error);
1951
+ materials.push(parsedMaterial.value);
1860
1952
  }
1861
1953
  const diagnostics = {
1862
1954
  nodeNames: [],