@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,118 @@
1
+ export interface GltfTextureIr {
2
+ readonly sampler?: number;
3
+ readonly source: number;
4
+ readonly name?: string;
5
+ }
6
+ export interface GltfImageIr {
7
+ readonly uri?: string;
8
+ readonly mimeType?: string;
9
+ readonly bufferView?: number;
10
+ readonly name?: string;
11
+ }
12
+ export interface GltfSamplerIr {
13
+ readonly magFilter?: number;
14
+ readonly minFilter?: number;
15
+ readonly wrapS: number;
16
+ readonly wrapT: number;
17
+ readonly name?: string;
18
+ }
19
+ export interface GltfTextureTransformIr {
20
+ readonly offset?: readonly [number, number];
21
+ readonly rotation?: number;
22
+ readonly scale?: readonly [number, number];
23
+ }
24
+ export interface GltfTextureInfoIr {
25
+ readonly texture: number;
26
+ readonly sampler?: number;
27
+ readonly texCoord?: number;
28
+ readonly transform?: GltfTextureTransformIr;
29
+ }
30
+ export interface GltfNormalTextureInfoIr extends GltfTextureInfoIr {
31
+ readonly scale?: number;
32
+ }
33
+ export interface GltfOcclusionTextureInfoIr extends GltfTextureInfoIr {
34
+ readonly strength?: number;
35
+ }
36
+ export interface TextureTransformJson {
37
+ readonly offset?: readonly number[];
38
+ readonly rotation?: number;
39
+ readonly scale?: readonly number[];
40
+ readonly texCoord?: number;
41
+ }
42
+ export interface TextureInfoJson {
43
+ readonly index: number;
44
+ readonly texCoord?: number;
45
+ readonly extensions?: {
46
+ readonly KHR_texture_transform?: TextureTransformJson;
47
+ };
48
+ }
49
+ export interface NormalTextureInfoJson extends TextureInfoJson {
50
+ readonly scale?: number;
51
+ }
52
+ export interface OcclusionTextureInfoJson extends TextureInfoJson {
53
+ readonly strength?: number;
54
+ }
55
+ export interface GltfMaterialJson {
56
+ readonly name?: string;
57
+ readonly pbrMetallicRoughness?: {
58
+ readonly baseColorFactor?: readonly number[];
59
+ readonly baseColorTexture?: TextureInfoJson;
60
+ readonly metallicFactor?: number;
61
+ readonly roughnessFactor?: number;
62
+ readonly metallicRoughnessTexture?: TextureInfoJson;
63
+ };
64
+ readonly normalTexture?: NormalTextureInfoJson;
65
+ readonly emissiveFactor?: readonly number[];
66
+ readonly emissiveTexture?: TextureInfoJson;
67
+ readonly occlusionTexture?: OcclusionTextureInfoJson;
68
+ readonly alphaMode?: string;
69
+ readonly alphaCutoff?: number;
70
+ readonly doubleSided?: boolean;
71
+ readonly extensions?: {
72
+ readonly KHR_materials_transmission?: {
73
+ readonly transmissionFactor?: number;
74
+ readonly transmissionTexture?: TextureInfoJson;
75
+ };
76
+ readonly KHR_materials_ior?: {
77
+ readonly ior?: number;
78
+ };
79
+ readonly KHR_materials_volume?: {
80
+ readonly thicknessFactor?: number;
81
+ readonly thicknessTexture?: TextureInfoJson;
82
+ readonly attenuationColor?: readonly number[];
83
+ readonly attenuationDistance?: number;
84
+ };
85
+ };
86
+ }
87
+ export interface GltfMaterialIr {
88
+ readonly name?: string;
89
+ readonly baseColorFactor: readonly [number, number, number, number];
90
+ /** glTF emissiveFactor; omitted means the glTF default [0, 0, 0]. */
91
+ readonly emissiveFactor?: readonly [number, number, number];
92
+ readonly baseColorTexture?: GltfTextureInfoIr | number;
93
+ readonly emissiveTexture?: GltfTextureInfoIr | number;
94
+ readonly metallicFactor: number;
95
+ readonly roughnessFactor: number;
96
+ readonly metallicRoughnessTexture?: GltfTextureInfoIr | number;
97
+ readonly normalTexture?: GltfNormalTextureInfoIr | number;
98
+ readonly occlusionTexture?: GltfOcclusionTextureInfoIr | number;
99
+ readonly transmissionFactor?: number;
100
+ readonly transmissionTexture?: GltfTextureInfoIr | number;
101
+ /** KHR_materials_transmission uses the red texture channel. */
102
+ readonly transmissionChannel?: number;
103
+ readonly ior?: number;
104
+ readonly thicknessFactor?: number;
105
+ readonly thicknessTexture?: GltfTextureInfoIr | number;
106
+ /** KHR_materials_volume uses the green texture channel. */
107
+ readonly thicknessChannel?: number;
108
+ readonly attenuationColor?: readonly [number, number, number];
109
+ readonly attenuationDistance?: number;
110
+ readonly alphaMode?: 'OPAQUE' | 'MASK' | 'BLEND';
111
+ readonly alphaCutoff?: number;
112
+ readonly doubleSided?: boolean;
113
+ readonly baseColorTexCoord?: number;
114
+ }
115
+ export declare function parseTextureInfo(info: TextureInfoJson, textures: readonly GltfTextureIr[]): GltfTextureInfoIr;
116
+ export declare function parseMaterial(matJson: GltfMaterialJson, textures: readonly GltfTextureIr[]): Result<GltfMaterialIr, GltfError>;
117
+ import { type GltfError, type Result } from '../errors.js';
118
+ //# sourceMappingURL=parse-material.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-material.d.ts","sourceRoot":"","sources":["../../src/material/parse-material.ts"],"names":[],"mappings":"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"}
@@ -22,6 +22,10 @@ var gltfErrorPolicy = {
22
22
  expected: "extension listed in v1 allowlist (see EXTENSION_ALLOWLIST in @forgeax/engine-gltf)",
23
23
  hint: "see feat-future-gltf-extensions-allowlist; remove this extension or wait for the allowlist to expand"
24
24
  },
25
+ "gltf-material-transmission-invalid": {
26
+ expected: "KHR transmission, IOR, and volume values are finite and within their glTF ranges",
27
+ hint: "repair the named glTF material extension value and re-import the source"
28
+ },
25
29
  "gltf-accessor-type-mismatch": {
26
30
  expected: "dense fixed-stride accessor with supported componentType",
27
31
  hint: "sparse: see feat-future-gltf-sparse-accessor; morph: see feat-future-gltf-morph; interleaved: see feat-future-gltf-mesh-multi-section"
@@ -390,7 +394,10 @@ var EXTENSION_ALLOWLIST = [
390
394
  var SUPPORTED_EXTENSIONS = [
391
395
  ...EXTENSION_ALLOWLIST,
392
396
  "KHR_lights_punctual",
393
- "KHR_texture_transform"
397
+ "KHR_texture_transform",
398
+ "KHR_materials_transmission",
399
+ "KHR_materials_ior",
400
+ "KHR_materials_volume"
394
401
  ];
395
402
  function checkExtensions(json) {
396
403
  const required = json.extensionsRequired ?? [];
@@ -442,6 +449,152 @@ function decodeBase64(b64) {
442
449
  return out;
443
450
  }
444
451
 
452
+ // src/material/parse-material.ts
453
+ function tuple2(values) {
454
+ if (values === void 0 || values.length < 2) return void 0;
455
+ return [values[0] ?? 0, values[1] ?? 0];
456
+ }
457
+ function tuple3(values) {
458
+ if (values === void 0 || values.length < 3) return void 0;
459
+ return [values[0] ?? 0, values[1] ?? 0, values[2] ?? 0];
460
+ }
461
+ function parseTextureInfo(info, textures) {
462
+ const transformJson = info.extensions?.KHR_texture_transform;
463
+ const offset = tuple2(transformJson?.offset);
464
+ const scale = tuple2(transformJson?.scale);
465
+ const transform = offset === void 0 && transformJson?.rotation === void 0 && scale === void 0 ? void 0 : {
466
+ ...offset === void 0 ? {} : { offset },
467
+ ...transformJson?.rotation === void 0 ? {} : { rotation: transformJson.rotation },
468
+ ...scale === void 0 ? {} : { scale }
469
+ };
470
+ const sampler = textures[info.index]?.sampler;
471
+ return {
472
+ texture: info.index,
473
+ ...sampler === void 0 ? {} : { sampler },
474
+ ...info.texCoord === void 0 && transformJson?.texCoord === void 0 ? {} : { texCoord: transformJson?.texCoord ?? info.texCoord },
475
+ ...transform === void 0 ? {} : { transform }
476
+ };
477
+ }
478
+ function finiteOrUndefined(value) {
479
+ return value !== void 0 && Number.isFinite(value) ? value : void 0;
480
+ }
481
+ function parseMaterial(matJson, textures) {
482
+ const pbr = matJson.pbrMetallicRoughness;
483
+ const baseColor = pbr?.baseColorFactor ?? [1, 1, 1, 1];
484
+ const baseColor4 = [
485
+ baseColor[0] ?? 1,
486
+ baseColor[1] ?? 1,
487
+ baseColor[2] ?? 1,
488
+ baseColor[3] ?? 1
489
+ ];
490
+ const alphaMode = matJson.alphaMode === "MASK" || matJson.alphaMode === "BLEND" ? matJson.alphaMode : void 0;
491
+ const alphaCutoff = alphaMode === "MASK" ? matJson.alphaCutoff ?? 0.5 : void 0;
492
+ const emissiveFactor = tuple3(matJson.emissiveFactor);
493
+ const transmission = matJson.extensions?.KHR_materials_transmission;
494
+ const ior = matJson.extensions?.KHR_materials_ior;
495
+ const volume = matJson.extensions?.KHR_materials_volume;
496
+ const attenuationColor = tuple3(volume?.attenuationColor);
497
+ const invalid = (extension, field, reason, actual) => err(
498
+ gltfErr("gltf-material-transmission-invalid", {
499
+ extension,
500
+ field,
501
+ reason,
502
+ ...actual === void 0 ? {} : { actual }
503
+ })
504
+ );
505
+ if (transmission?.transmissionFactor !== void 0 && (typeof transmission.transmissionFactor !== "number" || !Number.isFinite(transmission.transmissionFactor))) {
506
+ return invalid(
507
+ "KHR_materials_transmission",
508
+ "transmissionFactor",
509
+ "non-finite",
510
+ transmission.transmissionFactor
511
+ );
512
+ }
513
+ if (transmission?.transmissionFactor !== void 0 && (transmission.transmissionFactor < 0 || transmission.transmissionFactor > 1)) {
514
+ return invalid(
515
+ "KHR_materials_transmission",
516
+ "transmissionFactor",
517
+ "range",
518
+ transmission.transmissionFactor
519
+ );
520
+ }
521
+ if (ior?.ior !== void 0 && (typeof ior.ior !== "number" || !Number.isFinite(ior.ior))) {
522
+ return invalid("KHR_materials_ior", "ior", "non-finite", ior.ior);
523
+ }
524
+ if (ior?.ior !== void 0 && ior.ior < 1) {
525
+ return invalid("KHR_materials_ior", "ior", "range", ior.ior);
526
+ }
527
+ if (volume?.thicknessFactor !== void 0 && !Number.isFinite(volume.thicknessFactor)) {
528
+ return invalid("KHR_materials_volume", "thicknessFactor", "non-finite", volume.thicknessFactor);
529
+ }
530
+ if (volume?.thicknessFactor !== void 0 && volume.thicknessFactor < 0) {
531
+ return invalid("KHR_materials_volume", "thicknessFactor", "range", volume.thicknessFactor);
532
+ }
533
+ if (volume?.attenuationColor !== void 0 && (attenuationColor === void 0 || attenuationColor.some((value) => !Number.isFinite(value) || value < 0 || value > 1))) {
534
+ return invalid("KHR_materials_volume", "attenuationColor", "range", volume.attenuationColor);
535
+ }
536
+ if (volume?.attenuationDistance !== void 0 && !Number.isFinite(volume.attenuationDistance) && volume.attenuationDistance !== Number.POSITIVE_INFINITY) {
537
+ return invalid(
538
+ "KHR_materials_volume",
539
+ "attenuationDistance",
540
+ "non-finite",
541
+ volume.attenuationDistance
542
+ );
543
+ }
544
+ if (volume?.attenuationDistance !== void 0 && Number.isFinite(volume.attenuationDistance) && volume.attenuationDistance <= 0) {
545
+ return invalid(
546
+ "KHR_materials_volume",
547
+ "attenuationDistance",
548
+ "range",
549
+ volume.attenuationDistance
550
+ );
551
+ }
552
+ if (alphaMode === "BLEND" && (transmission?.transmissionFactor ?? 0) > 0) {
553
+ return invalid("KHR_materials_transmission", "alphaMode", "blend", alphaMode);
554
+ }
555
+ return ok({
556
+ ...matJson.name === void 0 ? {} : { name: matJson.name },
557
+ baseColorFactor: baseColor4,
558
+ ...emissiveFactor === void 0 ? {} : { emissiveFactor },
559
+ metallicFactor: pbr?.metallicFactor ?? 1,
560
+ roughnessFactor: pbr?.roughnessFactor ?? 1,
561
+ ...pbr?.baseColorTexture === void 0 ? {} : { baseColorTexture: parseTextureInfo(pbr.baseColorTexture, textures) },
562
+ ...pbr?.metallicRoughnessTexture === void 0 ? {} : { metallicRoughnessTexture: parseTextureInfo(pbr.metallicRoughnessTexture, textures) },
563
+ ...matJson.normalTexture === void 0 ? {} : {
564
+ normalTexture: {
565
+ ...parseTextureInfo(matJson.normalTexture, textures),
566
+ ...matJson.normalTexture.scale === void 0 ? {} : { scale: matJson.normalTexture.scale }
567
+ }
568
+ },
569
+ ...matJson.occlusionTexture === void 0 ? {} : {
570
+ occlusionTexture: {
571
+ ...parseTextureInfo(matJson.occlusionTexture, textures),
572
+ ...matJson.occlusionTexture.strength === void 0 ? {} : { strength: matJson.occlusionTexture.strength }
573
+ }
574
+ },
575
+ ...matJson.emissiveTexture === void 0 ? {} : { emissiveTexture: parseTextureInfo(matJson.emissiveTexture, textures) },
576
+ ...transmission === void 0 ? {} : {
577
+ transmissionFactor: transmission.transmissionFactor ?? 0,
578
+ transmissionChannel: 0,
579
+ ...transmission.transmissionTexture === void 0 ? {} : {
580
+ transmissionTexture: parseTextureInfo(transmission.transmissionTexture, textures)
581
+ }
582
+ },
583
+ ...ior === void 0 ? {} : { ior: ior.ior ?? 1.5 },
584
+ ...volume === void 0 ? {} : {
585
+ thicknessFactor: volume.thicknessFactor ?? 0,
586
+ thicknessChannel: 1,
587
+ ...volume.thicknessTexture === void 0 ? {} : { thicknessTexture: parseTextureInfo(volume.thicknessTexture, textures) },
588
+ ...attenuationColor === void 0 ? {} : { attenuationColor },
589
+ ...finiteOrUndefined(volume.attenuationDistance) === void 0 ? {} : { attenuationDistance: volume.attenuationDistance }
590
+ },
591
+ ...alphaMode === void 0 ? {} : { alphaMode },
592
+ ...alphaCutoff === void 0 ? {} : { alphaCutoff },
593
+ ...matJson.doubleSided === true ? { doubleSided: true } : {},
594
+ ...pbr?.baseColorTexture?.texCoord === void 0 || pbr.baseColorTexture.texCoord === 0 ? {} : { baseColorTexCoord: pbr.baseColorTexture.texCoord }
595
+ });
596
+ }
597
+
445
598
  // src/meshopt-decode.ts
446
599
  function viewBytes(view, buffers) {
447
600
  const buffer = buffers[view.buffer];
@@ -980,7 +1133,7 @@ var IDENTITY = {
980
1133
  rotation: [0, 0, 0, 1],
981
1134
  scale: [1, 1, 1]
982
1135
  };
983
- function tuple3(arr, fallback) {
1136
+ function tuple32(arr, fallback) {
984
1137
  if (arr === void 0 || arr.length < 3) return fallback;
985
1138
  return [arr[0] ?? fallback[0], arr[1] ?? fallback[1], arr[2] ?? fallback[2]];
986
1139
  }
@@ -1016,9 +1169,9 @@ function decomposeNodeTransform(node, nodeIndex, diagnostics) {
1016
1169
  return IDENTITY;
1017
1170
  }
1018
1171
  return {
1019
- translation: tuple3(node.translation, IDENTITY.translation),
1172
+ translation: tuple32(node.translation, IDENTITY.translation),
1020
1173
  rotation: tuple4(node.rotation, IDENTITY.rotation),
1021
- scale: tuple3(node.scale, IDENTITY.scale)
1174
+ scale: tuple32(node.scale, IDENTITY.scale)
1022
1175
  };
1023
1176
  }
1024
1177
 
@@ -1139,27 +1292,6 @@ function decodeAttributeAccessor(accessorIndex, accessor, bufferViews, buffers)
1139
1292
  if (decoded.value.kind !== "f32") return err(unknownAccessor(accessorIndex));
1140
1293
  return ok(decoded.value.data);
1141
1294
  }
1142
- function tuple2(values) {
1143
- if (values === void 0 || values.length < 2) return void 0;
1144
- return [values[0] ?? 0, values[1] ?? 0];
1145
- }
1146
- function parseTextureInfo(info, textures) {
1147
- const transformJson = info.extensions?.KHR_texture_transform;
1148
- const offset = tuple2(transformJson?.offset);
1149
- const scale = tuple2(transformJson?.scale);
1150
- const transform = offset === void 0 && transformJson?.rotation === void 0 && scale === void 0 ? void 0 : {
1151
- ...offset === void 0 ? {} : { offset },
1152
- ...transformJson?.rotation === void 0 ? {} : { rotation: transformJson.rotation },
1153
- ...scale === void 0 ? {} : { scale }
1154
- };
1155
- const sampler = textures[info.index]?.sampler;
1156
- return {
1157
- texture: info.index,
1158
- ...sampler === void 0 ? {} : { sampler },
1159
- ...info.texCoord === void 0 && transformJson?.texCoord === void 0 ? {} : { texCoord: transformJson?.texCoord ?? info.texCoord },
1160
- ...transform === void 0 ? {} : { transform }
1161
- };
1162
- }
1163
1295
  async function resolveBuffer(buf, externalLoader, binChunk) {
1164
1296
  if (buf.uri === void 0) {
1165
1297
  if (binChunk === void 0) {
@@ -1707,51 +1839,11 @@ async function parseGltfWithBin(json, ctx) {
1707
1839
  ...sampJson.name === void 0 ? {} : { name: sampJson.name }
1708
1840
  });
1709
1841
  }
1710
- const materialsJson = json.materials ?? [];
1711
1842
  const materials = [];
1712
- for (const matJson of materialsJson) {
1713
- const pbr = matJson.pbrMetallicRoughness;
1714
- const baseColor = pbr?.baseColorFactor ?? [1, 1, 1, 1];
1715
- const baseColor4 = [
1716
- baseColor[0] ?? 1,
1717
- baseColor[1] ?? 1,
1718
- baseColor[2] ?? 1,
1719
- baseColor[3] ?? 1
1720
- ];
1721
- const alphaMode = matJson.alphaMode === "MASK" || matJson.alphaMode === "BLEND" ? matJson.alphaMode : void 0;
1722
- const alphaCutoff = alphaMode === "MASK" ? matJson.alphaCutoff ?? 0.5 : void 0;
1723
- const emissiveFactor = matJson.emissiveFactor;
1724
- const emissiveFactor3 = [
1725
- emissiveFactor?.[0] ?? 0,
1726
- emissiveFactor?.[1] ?? 0,
1727
- emissiveFactor?.[2] ?? 0
1728
- ];
1729
- materials.push({
1730
- ...matJson.name === void 0 ? {} : { name: matJson.name },
1731
- baseColorFactor: baseColor4,
1732
- ...emissiveFactor === void 0 ? {} : { emissiveFactor: emissiveFactor3 },
1733
- metallicFactor: pbr?.metallicFactor ?? 1,
1734
- roughnessFactor: pbr?.roughnessFactor ?? 1,
1735
- ...pbr?.baseColorTexture === void 0 ? {} : { baseColorTexture: parseTextureInfo(pbr.baseColorTexture, textures) },
1736
- ...pbr?.metallicRoughnessTexture === void 0 ? {} : { metallicRoughnessTexture: parseTextureInfo(pbr.metallicRoughnessTexture, textures) },
1737
- ...matJson.normalTexture === void 0 ? {} : {
1738
- normalTexture: {
1739
- ...parseTextureInfo(matJson.normalTexture, textures),
1740
- ...matJson.normalTexture.scale === void 0 ? {} : { scale: matJson.normalTexture.scale }
1741
- }
1742
- },
1743
- ...matJson.occlusionTexture === void 0 ? {} : {
1744
- occlusionTexture: {
1745
- ...parseTextureInfo(matJson.occlusionTexture, textures),
1746
- ...matJson.occlusionTexture.strength === void 0 ? {} : { strength: matJson.occlusionTexture.strength }
1747
- }
1748
- },
1749
- ...matJson.emissiveTexture === void 0 ? {} : { emissiveTexture: parseTextureInfo(matJson.emissiveTexture, textures) },
1750
- ...alphaMode === void 0 ? {} : { alphaMode },
1751
- ...alphaCutoff === void 0 ? {} : { alphaCutoff },
1752
- ...matJson.doubleSided === true ? { doubleSided: true } : {},
1753
- ...pbr?.baseColorTexture?.texCoord === void 0 || pbr.baseColorTexture.texCoord === 0 ? {} : { baseColorTexCoord: pbr.baseColorTexture.texCoord }
1754
- });
1843
+ for (const material of json.materials ?? []) {
1844
+ const parsedMaterial = parseMaterial(material, textures);
1845
+ if (!parsedMaterial.ok) return err(parsedMaterial.error);
1846
+ materials.push(parsedMaterial.value);
1755
1847
  }
1756
1848
  const diagnostics = {
1757
1849
  nodeNames: [],