@luma.gl/gltf 9.2.0-alpha.1 → 9.2.0-alpha.3

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 (89) hide show
  1. package/dist/dist.dev.js +649 -580
  2. package/dist/dist.min.js +4 -4
  3. package/dist/gltf/animations/animations.d.ts +16 -0
  4. package/dist/gltf/animations/animations.d.ts.map +1 -0
  5. package/dist/gltf/animations/animations.js +5 -0
  6. package/dist/gltf/animations/animations.js.map +1 -0
  7. package/dist/gltf/animations/interpolate.d.ts +4 -0
  8. package/dist/gltf/animations/interpolate.d.ts.map +1 -0
  9. package/dist/gltf/animations/interpolate.js +94 -0
  10. package/dist/gltf/animations/interpolate.js.map +1 -0
  11. package/dist/gltf/create-gltf-model.d.ts +4 -4
  12. package/dist/gltf/create-gltf-model.d.ts.map +1 -1
  13. package/dist/gltf/create-gltf-model.js +7 -8
  14. package/dist/gltf/create-gltf-model.js.map +1 -1
  15. package/dist/gltf/{create-gltf-objects.d.ts → create-scenegraph-from-gltf.d.ts} +4 -3
  16. package/dist/gltf/create-scenegraph-from-gltf.d.ts.map +1 -0
  17. package/dist/gltf/create-scenegraph-from-gltf.js +16 -0
  18. package/dist/gltf/create-scenegraph-from-gltf.js.map +1 -0
  19. package/dist/gltf/gltf-animator.d.ts +13 -28
  20. package/dist/gltf/gltf-animator.d.ts.map +1 -1
  21. package/dist/gltf/gltf-animator.js +17 -145
  22. package/dist/gltf/gltf-animator.js.map +1 -1
  23. package/dist/index.cjs +478 -443
  24. package/dist/index.cjs.map +4 -4
  25. package/dist/index.d.ts +5 -5
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +2 -2
  28. package/dist/index.js.map +1 -1
  29. package/dist/parsers/parse-gltf-animations.d.ts +4 -0
  30. package/dist/parsers/parse-gltf-animations.d.ts.map +1 -0
  31. package/dist/parsers/parse-gltf-animations.js +40 -0
  32. package/dist/parsers/parse-gltf-animations.js.map +1 -0
  33. package/dist/parsers/parse-gltf.d.ts +17 -0
  34. package/dist/parsers/parse-gltf.d.ts.map +1 -0
  35. package/dist/parsers/parse-gltf.js +118 -0
  36. package/dist/parsers/parse-gltf.js.map +1 -0
  37. package/dist/parsers/parse-pbr-material.d.ts +50 -0
  38. package/dist/parsers/parse-pbr-material.d.ts.map +1 -0
  39. package/dist/{pbr → parsers}/parse-pbr-material.js +29 -46
  40. package/dist/parsers/parse-pbr-material.js.map +1 -0
  41. package/dist/pbr/pbr-material.d.ts +13 -0
  42. package/dist/pbr/pbr-material.d.ts.map +1 -0
  43. package/dist/pbr/pbr-material.js +2 -0
  44. package/dist/pbr/pbr-material.js.map +1 -0
  45. package/dist/utils/deep-copy.d.ts +3 -0
  46. package/dist/utils/deep-copy.d.ts.map +1 -0
  47. package/dist/utils/deep-copy.js +21 -0
  48. package/dist/utils/deep-copy.js.map +1 -0
  49. package/dist/webgl-to-webgpu/convert-webgl-attribute.d.ts +21 -0
  50. package/dist/webgl-to-webgpu/convert-webgl-attribute.d.ts.map +1 -0
  51. package/dist/webgl-to-webgpu/convert-webgl-attribute.js +29 -0
  52. package/dist/webgl-to-webgpu/convert-webgl-attribute.js.map +1 -0
  53. package/dist/webgl-to-webgpu/convert-webgl-sampler.d.ts +11 -0
  54. package/dist/webgl-to-webgpu/convert-webgl-sampler.d.ts.map +1 -0
  55. package/dist/webgl-to-webgpu/convert-webgl-sampler.js +53 -0
  56. package/dist/webgl-to-webgpu/convert-webgl-sampler.js.map +1 -0
  57. package/dist/{gltf/gl-utils.d.ts → webgl-to-webgpu/convert-webgl-topology.d.ts} +1 -1
  58. package/dist/webgl-to-webgpu/convert-webgl-topology.d.ts.map +1 -0
  59. package/dist/{gltf/gl-utils.js → webgl-to-webgpu/convert-webgl-topology.js} +1 -1
  60. package/dist/webgl-to-webgpu/convert-webgl-topology.js.map +1 -0
  61. package/package.json +7 -5
  62. package/src/gltf/animations/animations.ts +22 -0
  63. package/src/gltf/animations/interpolate.ts +153 -0
  64. package/src/gltf/create-gltf-model.ts +11 -12
  65. package/src/gltf/create-scenegraph-from-gltf.ts +27 -0
  66. package/src/gltf/gltf-animator.ts +33 -180
  67. package/src/index.ts +5 -5
  68. package/src/parsers/parse-gltf-animations.ts +55 -0
  69. package/src/parsers/parse-gltf.ts +192 -0
  70. package/src/{pbr → parsers}/parse-pbr-material.ts +75 -64
  71. package/src/pbr/pbr-material.ts +13 -0
  72. package/src/utils/deep-copy.ts +22 -0
  73. package/src/webgl-to-webgpu/convert-webgl-attribute.ts +47 -0
  74. package/src/webgl-to-webgpu/convert-webgl-sampler.ts +86 -0
  75. package/dist/gltf/create-gltf-objects.d.ts.map +0 -1
  76. package/dist/gltf/create-gltf-objects.js +0 -11
  77. package/dist/gltf/create-gltf-objects.js.map +0 -1
  78. package/dist/gltf/gl-utils.d.ts.map +0 -1
  79. package/dist/gltf/gl-utils.js.map +0 -1
  80. package/dist/gltf/gltf-instantiator.d.ts +0 -33
  81. package/dist/gltf/gltf-instantiator.d.ts.map +0 -1
  82. package/dist/gltf/gltf-instantiator.js +0 -184
  83. package/dist/gltf/gltf-instantiator.js.map +0 -1
  84. package/dist/pbr/parse-pbr-material.d.ts +0 -27
  85. package/dist/pbr/parse-pbr-material.d.ts.map +0 -1
  86. package/dist/pbr/parse-pbr-material.js.map +0 -1
  87. package/src/gltf/create-gltf-objects.ts +0 -22
  88. package/src/gltf/gltf-instantiator.ts +0 -232
  89. /package/src/{gltf/gl-utils.ts → webgl-to-webgpu/convert-webgl-topology.ts} +0 -0
package/dist/dist.dev.js CHANGED
@@ -52,6 +52,13 @@ var __exports__ = (() => {
52
52
  }
53
53
  });
54
54
 
55
+ // external-global-plugin:@luma.gl/constants
56
+ var require_constants = __commonJS({
57
+ "external-global-plugin:@luma.gl/constants"(exports, module) {
58
+ module.exports = globalThis.luma;
59
+ }
60
+ });
61
+
55
62
  // external-global-plugin:@luma.gl/shadertools
56
63
  var require_shadertools = __commonJS({
57
64
  "external-global-plugin:@luma.gl/shadertools"(exports, module) {
@@ -69,170 +76,6 @@ var __exports__ = (() => {
69
76
  });
70
77
  __reExport(bundle_exports, __toESM(require_core(), 1));
71
78
 
72
- // src/pbr/parse-pbr-material.ts
73
- var import_core = __toESM(require_core(), 1);
74
- function parsePBRMaterial(device, material, attributes, options) {
75
- const parsedMaterial = {
76
- defines: {
77
- // TODO: Use EXT_sRGB if available (Standard in WebGL 2.0)
78
- MANUAL_SRGB: true,
79
- SRGB_FAST_APPROXIMATION: true
80
- },
81
- bindings: {},
82
- uniforms: {
83
- // TODO: find better values?
84
- camera: [0, 0, 0],
85
- // Model should override
86
- metallicRoughnessValues: [1, 1]
87
- // Default is 1 and 1
88
- },
89
- parameters: {},
90
- glParameters: {},
91
- generatedTextures: []
92
- };
93
- parsedMaterial.defines.USE_TEX_LOD = true;
94
- const { imageBasedLightingEnvironment } = options;
95
- if (imageBasedLightingEnvironment) {
96
- parsedMaterial.bindings.pbr_diffuseEnvSampler = imageBasedLightingEnvironment.diffuseEnvSampler.texture;
97
- parsedMaterial.bindings.pbr_specularEnvSampler = imageBasedLightingEnvironment.specularEnvSampler.texture;
98
- parsedMaterial.bindings.pbr_BrdfLUT = imageBasedLightingEnvironment.brdfLutTexture.texture;
99
- parsedMaterial.uniforms.scaleIBLAmbient = [1, 1];
100
- }
101
- if (options?.pbrDebug) {
102
- parsedMaterial.defines.PBR_DEBUG = true;
103
- parsedMaterial.uniforms.scaleDiffBaseMR = [0, 0, 0, 0];
104
- parsedMaterial.uniforms.scaleFGDSpec = [0, 0, 0, 0];
105
- }
106
- if (attributes.NORMAL)
107
- parsedMaterial.defines.HAS_NORMALS = true;
108
- if (attributes.TANGENT && options?.useTangents)
109
- parsedMaterial.defines.HAS_TANGENTS = true;
110
- if (attributes.TEXCOORD_0)
111
- parsedMaterial.defines.HAS_UV = true;
112
- if (options?.imageBasedLightingEnvironment)
113
- parsedMaterial.defines.USE_IBL = true;
114
- if (options?.lights)
115
- parsedMaterial.defines.USE_LIGHTS = true;
116
- if (material) {
117
- parseMaterial(device, material, parsedMaterial);
118
- }
119
- return parsedMaterial;
120
- }
121
- function parseMaterial(device, material, parsedMaterial) {
122
- parsedMaterial.uniforms.unlit = Boolean(material.unlit);
123
- if (material.pbrMetallicRoughness) {
124
- parsePbrMetallicRoughness(device, material.pbrMetallicRoughness, parsedMaterial);
125
- }
126
- if (material.normalTexture) {
127
- addTexture(
128
- device,
129
- material.normalTexture,
130
- "pbr_normalSampler",
131
- "HAS_NORMALMAP",
132
- parsedMaterial
133
- );
134
- const { scale: scale4 = 1 } = material.normalTexture;
135
- parsedMaterial.uniforms.normalScale = scale4;
136
- }
137
- if (material.occlusionTexture) {
138
- addTexture(
139
- device,
140
- material.occlusionTexture,
141
- "pbr_occlusionSampler",
142
- "HAS_OCCLUSIONMAP",
143
- parsedMaterial
144
- );
145
- const { strength = 1 } = material.occlusionTexture;
146
- parsedMaterial.uniforms.occlusionStrength = strength;
147
- }
148
- if (material.emissiveTexture) {
149
- addTexture(
150
- device,
151
- material.emissiveTexture,
152
- "pbr_emissiveSampler",
153
- "HAS_EMISSIVEMAP",
154
- parsedMaterial
155
- );
156
- parsedMaterial.uniforms.emissiveFactor = material.emissiveFactor || [0, 0, 0];
157
- }
158
- switch (material.alphaMode) {
159
- case "MASK":
160
- const { alphaCutoff = 0.5 } = material;
161
- parsedMaterial.defines.ALPHA_CUTOFF = true;
162
- parsedMaterial.uniforms.alphaCutoff = alphaCutoff;
163
- break;
164
- case "BLEND":
165
- import_core.log.warn("glTF BLEND alphaMode might not work well because it requires mesh sorting")();
166
- parsedMaterial.parameters.blendColorOperation = "add";
167
- parsedMaterial.parameters.blendColorSrcFactor = "src-alpha";
168
- parsedMaterial.parameters.blendColorDstFactor = "one-minus-src-alpha";
169
- parsedMaterial.parameters.blendAlphaOperation = "add";
170
- parsedMaterial.parameters.blendAlphaSrcFactor = "one";
171
- parsedMaterial.parameters.blendAlphaDstFactor = "one-minus-src-alpha";
172
- parsedMaterial.glParameters.blend = true;
173
- parsedMaterial.glParameters.blendEquation = 32774 /* FUNC_ADD */;
174
- parsedMaterial.glParameters.blendFunc = [
175
- 770 /* SRC_ALPHA */,
176
- 771 /* ONE_MINUS_SRC_ALPHA */,
177
- 1 /* ONE */,
178
- 771 /* ONE_MINUS_SRC_ALPHA */
179
- ];
180
- break;
181
- }
182
- }
183
- function parsePbrMetallicRoughness(device, pbrMetallicRoughness, parsedMaterial) {
184
- if (pbrMetallicRoughness.baseColorTexture) {
185
- addTexture(
186
- device,
187
- pbrMetallicRoughness.baseColorTexture,
188
- "pbr_baseColorSampler",
189
- "HAS_BASECOLORMAP",
190
- parsedMaterial
191
- );
192
- }
193
- parsedMaterial.uniforms.baseColorFactor = pbrMetallicRoughness.baseColorFactor || [1, 1, 1, 1];
194
- if (pbrMetallicRoughness.metallicRoughnessTexture) {
195
- addTexture(
196
- device,
197
- pbrMetallicRoughness.metallicRoughnessTexture,
198
- "pbr_metallicRoughnessSampler",
199
- "HAS_METALROUGHNESSMAP",
200
- parsedMaterial
201
- );
202
- }
203
- const { metallicFactor = 1, roughnessFactor = 1 } = pbrMetallicRoughness;
204
- parsedMaterial.uniforms.metallicRoughnessValues = [metallicFactor, roughnessFactor];
205
- }
206
- function addTexture(device, gltfTexture, uniformName, define, parsedMaterial) {
207
- const parameters = gltfTexture?.texture?.sampler?.parameters || {};
208
- const image = gltfTexture.texture.source.image;
209
- let textureOptions;
210
- let specialTextureParameters = {};
211
- if (image.compressed) {
212
- textureOptions = image;
213
- specialTextureParameters = {
214
- [10241 /* TEXTURE_MIN_FILTER */]: image.data.length > 1 ? 9985 /* LINEAR_MIPMAP_NEAREST */ : 9729 /* LINEAR */
215
- };
216
- } else {
217
- textureOptions = { data: image };
218
- }
219
- const texture = device.createTexture({
220
- id: gltfTexture.uniformName || gltfTexture.id,
221
- parameters: {
222
- ...parameters,
223
- ...specialTextureParameters
224
- },
225
- pixelStore: {
226
- [37440 /* UNPACK_FLIP_Y_WEBGL */]: false
227
- },
228
- ...textureOptions
229
- });
230
- parsedMaterial.bindings[uniformName] = texture;
231
- if (define)
232
- parsedMaterial.defines[define] = true;
233
- parsedMaterial.generatedTextures.push(texture);
234
- }
235
-
236
79
  // src/pbr/pbr-environment.ts
237
80
  var import_engine = __toESM(require_engine(), 1);
238
81
 
@@ -278,7 +121,7 @@ var __exports__ = (() => {
278
121
  }
279
122
 
280
123
  // ../../node_modules/@loaders.gl/images/dist/lib/utils/version.js
281
- var VERSION = true ? "4.2.3" : "latest";
124
+ var VERSION = true ? "4.3.2" : "latest";
282
125
 
283
126
  // ../../node_modules/@loaders.gl/images/dist/lib/category-api/image-type.js
284
127
  var parseImageNode = globalThis.loaders?.parseImageNode;
@@ -836,95 +679,310 @@ var __exports__ = (() => {
836
679
  });
837
680
  }
838
681
 
839
- // src/gltf/gltf-instantiator.ts
840
- var import_engine3 = __toESM(require_engine(), 1);
682
+ // src/parsers/parse-pbr-material.ts
683
+ var import_constants2 = __toESM(require_constants(), 1);
684
+ var import_core = __toESM(require_core(), 1);
841
685
 
842
- // ../../node_modules/@math.gl/core/dist/lib/common.js
843
- var RADIANS_TO_DEGREES = 1 / Math.PI * 180;
844
- var DEGREES_TO_RADIANS = 1 / 180 * Math.PI;
845
- var DEFAULT_CONFIG = {
846
- EPSILON: 1e-12,
847
- debug: false,
848
- precision: 4,
849
- printTypes: false,
850
- printDegrees: false,
851
- printRowMajor: true,
852
- _cartographicRadians: false
853
- };
854
- globalThis.mathgl = globalThis.mathgl || { config: { ...DEFAULT_CONFIG } };
855
- var config = globalThis.mathgl.config;
856
- function formatValue(value, { precision = config.precision } = {}) {
857
- value = round(value);
858
- return `${parseFloat(value.toPrecision(precision))}`;
859
- }
860
- function isArray(value) {
861
- return Array.isArray(value) || ArrayBuffer.isView(value) && !(value instanceof DataView);
686
+ // src/webgl-to-webgpu/convert-webgl-sampler.ts
687
+ var import_constants = __toESM(require_constants(), 1);
688
+ function convertSampler(gltfSampler) {
689
+ return {
690
+ addressModeU: convertSamplerWrapMode(gltfSampler.wrapS),
691
+ addressModeV: convertSamplerWrapMode(gltfSampler.wrapT),
692
+ magFilter: convertSamplerMagFilter(gltfSampler.magFilter),
693
+ ...convertSamplerMinFilter(gltfSampler.minFilter)
694
+ };
862
695
  }
863
- function equals(a, b, epsilon) {
864
- const oldEpsilon = config.EPSILON;
865
- if (epsilon) {
866
- config.EPSILON = epsilon;
867
- }
868
- try {
869
- if (a === b) {
870
- return true;
871
- }
872
- if (isArray(a) && isArray(b)) {
873
- if (a.length !== b.length) {
874
- return false;
875
- }
876
- for (let i = 0; i < a.length; ++i) {
877
- if (!equals(a[i], b[i])) {
878
- return false;
879
- }
880
- }
881
- return true;
882
- }
883
- if (a && a.equals) {
884
- return a.equals(b);
885
- }
886
- if (b && b.equals) {
887
- return b.equals(a);
888
- }
889
- if (typeof a === "number" && typeof b === "number") {
890
- return Math.abs(a - b) <= config.EPSILON * Math.max(1, Math.abs(a), Math.abs(b));
891
- }
892
- return false;
893
- } finally {
894
- config.EPSILON = oldEpsilon;
696
+ function convertSamplerWrapMode(mode) {
697
+ switch (mode) {
698
+ case import_constants.GL.CLAMP_TO_EDGE:
699
+ return "clamp-to-edge";
700
+ case import_constants.GL.REPEAT:
701
+ return "repeat";
702
+ case import_constants.GL.MIRRORED_REPEAT:
703
+ return "mirror-repeat";
704
+ default:
705
+ return void 0;
895
706
  }
896
707
  }
897
- function round(value) {
898
- return Math.round(value / config.EPSILON) * config.EPSILON;
708
+ function convertSamplerMagFilter(mode) {
709
+ switch (mode) {
710
+ case import_constants.GL.NEAREST:
711
+ return "nearest";
712
+ case import_constants.GL.LINEAR:
713
+ return "linear";
714
+ default:
715
+ return void 0;
716
+ }
717
+ }
718
+ function convertSamplerMinFilter(mode) {
719
+ switch (mode) {
720
+ case import_constants.GL.NEAREST:
721
+ return { minFilter: "nearest" };
722
+ case import_constants.GL.LINEAR:
723
+ return { minFilter: "linear" };
724
+ case import_constants.GL.NEAREST_MIPMAP_NEAREST:
725
+ return { minFilter: "nearest", mipmapFilter: "nearest" };
726
+ case import_constants.GL.LINEAR_MIPMAP_NEAREST:
727
+ return { minFilter: "linear", mipmapFilter: "nearest" };
728
+ case import_constants.GL.NEAREST_MIPMAP_LINEAR:
729
+ return { minFilter: "nearest", mipmapFilter: "linear" };
730
+ case import_constants.GL.LINEAR_MIPMAP_LINEAR:
731
+ return { minFilter: "linear", mipmapFilter: "linear" };
732
+ default:
733
+ return {};
734
+ }
899
735
  }
900
736
 
901
- // ../../node_modules/@math.gl/core/dist/classes/base/math-array.js
902
- var MathArray = class extends Array {
903
- // Common methods
904
- /**
905
- * Clone the current object
906
- * @returns a new copy of this object
907
- */
908
- clone() {
909
- return new this.constructor().copy(this);
910
- }
911
- fromArray(array, offset = 0) {
912
- for (let i = 0; i < this.ELEMENTS; ++i) {
913
- this[i] = array[i + offset];
914
- }
915
- return this.check();
737
+ // src/parsers/parse-pbr-material.ts
738
+ function parsePBRMaterial(device, material, attributes, options) {
739
+ const parsedMaterial = {
740
+ defines: {
741
+ // TODO: Use EXT_sRGB if available (Standard in WebGL 2.0)
742
+ MANUAL_SRGB: true,
743
+ SRGB_FAST_APPROXIMATION: true
744
+ },
745
+ bindings: {},
746
+ uniforms: {
747
+ // TODO: find better values?
748
+ camera: [0, 0, 0],
749
+ // Model should override
750
+ metallicRoughnessValues: [1, 1]
751
+ // Default is 1 and 1
752
+ },
753
+ parameters: {},
754
+ glParameters: {},
755
+ generatedTextures: []
756
+ };
757
+ parsedMaterial.defines["USE_TEX_LOD"] = true;
758
+ const { imageBasedLightingEnvironment } = options;
759
+ if (imageBasedLightingEnvironment) {
760
+ parsedMaterial.bindings.pbr_diffuseEnvSampler = imageBasedLightingEnvironment.diffuseEnvSampler.texture;
761
+ parsedMaterial.bindings.pbr_specularEnvSampler = imageBasedLightingEnvironment.specularEnvSampler.texture;
762
+ parsedMaterial.bindings.pbr_BrdfLUT = imageBasedLightingEnvironment.brdfLutTexture.texture;
763
+ parsedMaterial.uniforms.scaleIBLAmbient = [1, 1];
916
764
  }
917
- toArray(targetArray = [], offset = 0) {
918
- for (let i = 0; i < this.ELEMENTS; ++i) {
919
- targetArray[offset + i] = this[i];
920
- }
921
- return targetArray;
765
+ if (options?.pbrDebug) {
766
+ parsedMaterial.defines["PBR_DEBUG"] = true;
767
+ parsedMaterial.uniforms.scaleDiffBaseMR = [0, 0, 0, 0];
768
+ parsedMaterial.uniforms.scaleFGDSpec = [0, 0, 0, 0];
922
769
  }
923
- toObject(targetObject) {
924
- return targetObject;
770
+ if (attributes["NORMAL"])
771
+ parsedMaterial.defines["HAS_NORMALS"] = true;
772
+ if (attributes["TANGENT"] && options?.useTangents)
773
+ parsedMaterial.defines["HAS_TANGENTS"] = true;
774
+ if (attributes["TEXCOORD_0"])
775
+ parsedMaterial.defines["HAS_UV"] = true;
776
+ if (options?.imageBasedLightingEnvironment)
777
+ parsedMaterial.defines["USE_IBL"] = true;
778
+ if (options?.lights)
779
+ parsedMaterial.defines["USE_LIGHTS"] = true;
780
+ if (material) {
781
+ parseMaterial(device, material, parsedMaterial);
925
782
  }
926
- from(arrayOrObject) {
927
- return Array.isArray(arrayOrObject) ? this.copy(arrayOrObject) : (
783
+ return parsedMaterial;
784
+ }
785
+ function parseMaterial(device, material, parsedMaterial) {
786
+ parsedMaterial.uniforms.unlit = Boolean(material.unlit);
787
+ if (material.pbrMetallicRoughness) {
788
+ parsePbrMetallicRoughness(device, material.pbrMetallicRoughness, parsedMaterial);
789
+ }
790
+ if (material.normalTexture) {
791
+ addTexture(
792
+ device,
793
+ material.normalTexture,
794
+ "pbr_normalSampler",
795
+ "HAS_NORMALMAP",
796
+ parsedMaterial
797
+ );
798
+ const { scale: scale4 = 1 } = material.normalTexture;
799
+ parsedMaterial.uniforms.normalScale = scale4;
800
+ }
801
+ if (material.occlusionTexture) {
802
+ addTexture(
803
+ device,
804
+ material.occlusionTexture,
805
+ "pbr_occlusionSampler",
806
+ "HAS_OCCLUSIONMAP",
807
+ parsedMaterial
808
+ );
809
+ const { strength = 1 } = material.occlusionTexture;
810
+ parsedMaterial.uniforms.occlusionStrength = strength;
811
+ }
812
+ if (material.emissiveTexture) {
813
+ addTexture(
814
+ device,
815
+ material.emissiveTexture,
816
+ "pbr_emissiveSampler",
817
+ "HAS_EMISSIVEMAP",
818
+ parsedMaterial
819
+ );
820
+ parsedMaterial.uniforms.emissiveFactor = material.emissiveFactor || [0, 0, 0];
821
+ }
822
+ switch (material.alphaMode || "MASK") {
823
+ case "MASK":
824
+ const { alphaCutoff = 0.5 } = material;
825
+ parsedMaterial.defines["ALPHA_CUTOFF"] = true;
826
+ parsedMaterial.uniforms.alphaCutoff = alphaCutoff;
827
+ break;
828
+ case "BLEND":
829
+ import_core.log.warn("glTF BLEND alphaMode might not work well because it requires mesh sorting")();
830
+ parsedMaterial.parameters.blend = true;
831
+ parsedMaterial.parameters.blendColorOperation = "add";
832
+ parsedMaterial.parameters.blendColorSrcFactor = "src-alpha";
833
+ parsedMaterial.parameters.blendColorDstFactor = "one-minus-src-alpha";
834
+ parsedMaterial.parameters.blendAlphaOperation = "add";
835
+ parsedMaterial.parameters.blendAlphaSrcFactor = "one";
836
+ parsedMaterial.parameters.blendAlphaDstFactor = "one-minus-src-alpha";
837
+ parsedMaterial.glParameters["blend"] = true;
838
+ parsedMaterial.glParameters["blendEquation"] = import_constants2.GL.FUNC_ADD;
839
+ parsedMaterial.glParameters["blendFunc"] = [
840
+ import_constants2.GL.SRC_ALPHA,
841
+ import_constants2.GL.ONE_MINUS_SRC_ALPHA,
842
+ import_constants2.GL.ONE,
843
+ import_constants2.GL.ONE_MINUS_SRC_ALPHA
844
+ ];
845
+ break;
846
+ }
847
+ }
848
+ function parsePbrMetallicRoughness(device, pbrMetallicRoughness, parsedMaterial) {
849
+ if (pbrMetallicRoughness.baseColorTexture) {
850
+ addTexture(
851
+ device,
852
+ pbrMetallicRoughness.baseColorTexture,
853
+ "pbr_baseColorSampler",
854
+ "HAS_BASECOLORMAP",
855
+ parsedMaterial
856
+ );
857
+ }
858
+ parsedMaterial.uniforms.baseColorFactor = pbrMetallicRoughness.baseColorFactor || [1, 1, 1, 1];
859
+ if (pbrMetallicRoughness.metallicRoughnessTexture) {
860
+ addTexture(
861
+ device,
862
+ pbrMetallicRoughness.metallicRoughnessTexture,
863
+ "pbr_metallicRoughnessSampler",
864
+ "HAS_METALROUGHNESSMAP",
865
+ parsedMaterial
866
+ );
867
+ }
868
+ const { metallicFactor = 1, roughnessFactor = 1 } = pbrMetallicRoughness;
869
+ parsedMaterial.uniforms.metallicRoughnessValues = [metallicFactor, roughnessFactor];
870
+ }
871
+ function addTexture(device, gltfTexture, uniformName, define, parsedMaterial) {
872
+ const image = gltfTexture.texture.source.image;
873
+ let textureOptions;
874
+ if (image.compressed) {
875
+ textureOptions = image;
876
+ } else {
877
+ textureOptions = { data: image };
878
+ }
879
+ const gltfSampler = {
880
+ wrapS: 10497,
881
+ // default REPEAT S (U) wrapping mode.
882
+ wrapT: 10497,
883
+ // default REPEAT T (V) wrapping mode.
884
+ ...gltfTexture?.texture?.sampler
885
+ };
886
+ const texture = device.createTexture({
887
+ id: gltfTexture.uniformName || gltfTexture.id,
888
+ sampler: convertSampler(gltfSampler),
889
+ ...textureOptions
890
+ });
891
+ parsedMaterial.bindings[uniformName] = texture;
892
+ if (define)
893
+ parsedMaterial.defines[define] = true;
894
+ parsedMaterial.generatedTextures.push(texture);
895
+ }
896
+
897
+ // src/parsers/parse-gltf.ts
898
+ var import_engine3 = __toESM(require_engine(), 1);
899
+
900
+ // ../../node_modules/@math.gl/core/dist/lib/common.js
901
+ var RADIANS_TO_DEGREES = 1 / Math.PI * 180;
902
+ var DEGREES_TO_RADIANS = 1 / 180 * Math.PI;
903
+ var DEFAULT_CONFIG = {
904
+ EPSILON: 1e-12,
905
+ debug: false,
906
+ precision: 4,
907
+ printTypes: false,
908
+ printDegrees: false,
909
+ printRowMajor: true,
910
+ _cartographicRadians: false
911
+ };
912
+ globalThis.mathgl = globalThis.mathgl || { config: { ...DEFAULT_CONFIG } };
913
+ var config = globalThis.mathgl.config;
914
+ function formatValue(value, { precision = config.precision } = {}) {
915
+ value = round(value);
916
+ return `${parseFloat(value.toPrecision(precision))}`;
917
+ }
918
+ function isArray(value) {
919
+ return Array.isArray(value) || ArrayBuffer.isView(value) && !(value instanceof DataView);
920
+ }
921
+ function equals(a, b, epsilon) {
922
+ const oldEpsilon = config.EPSILON;
923
+ if (epsilon) {
924
+ config.EPSILON = epsilon;
925
+ }
926
+ try {
927
+ if (a === b) {
928
+ return true;
929
+ }
930
+ if (isArray(a) && isArray(b)) {
931
+ if (a.length !== b.length) {
932
+ return false;
933
+ }
934
+ for (let i = 0; i < a.length; ++i) {
935
+ if (!equals(a[i], b[i])) {
936
+ return false;
937
+ }
938
+ }
939
+ return true;
940
+ }
941
+ if (a && a.equals) {
942
+ return a.equals(b);
943
+ }
944
+ if (b && b.equals) {
945
+ return b.equals(a);
946
+ }
947
+ if (typeof a === "number" && typeof b === "number") {
948
+ return Math.abs(a - b) <= config.EPSILON * Math.max(1, Math.abs(a), Math.abs(b));
949
+ }
950
+ return false;
951
+ } finally {
952
+ config.EPSILON = oldEpsilon;
953
+ }
954
+ }
955
+ function round(value) {
956
+ return Math.round(value / config.EPSILON) * config.EPSILON;
957
+ }
958
+
959
+ // ../../node_modules/@math.gl/core/dist/classes/base/math-array.js
960
+ var MathArray = class extends Array {
961
+ // Common methods
962
+ /**
963
+ * Clone the current object
964
+ * @returns a new copy of this object
965
+ */
966
+ clone() {
967
+ return new this.constructor().copy(this);
968
+ }
969
+ fromArray(array, offset = 0) {
970
+ for (let i = 0; i < this.ELEMENTS; ++i) {
971
+ this[i] = array[i + offset];
972
+ }
973
+ return this.check();
974
+ }
975
+ toArray(targetArray = [], offset = 0) {
976
+ for (let i = 0; i < this.ELEMENTS; ++i) {
977
+ targetArray[offset + i] = this[i];
978
+ }
979
+ return targetArray;
980
+ }
981
+ toObject(targetObject) {
982
+ return targetObject;
983
+ }
984
+ from(arrayOrObject) {
985
+ return Array.isArray(arrayOrObject) ? this.copy(arrayOrObject) : (
928
986
  // @ts-ignore
929
987
  this.fromObject(arrayOrObject)
930
988
  );
@@ -1565,8 +1623,8 @@ var __exports__ = (() => {
1565
1623
  vec4_transformMat2(this, this, matrix2);
1566
1624
  return this.check();
1567
1625
  }
1568
- transformByQuaternion(quaternion2) {
1569
- transformQuat(this, this, quaternion2);
1626
+ transformByQuaternion(quaternion) {
1627
+ transformQuat(this, this, quaternion);
1570
1628
  return this.check();
1571
1629
  }
1572
1630
  // three.js compatibility
@@ -2550,8 +2608,8 @@ var __exports__ = (() => {
2550
2608
  * @param quaternion Quaternion to create matrix from
2551
2609
  * @returns self
2552
2610
  */
2553
- fromQuaternion(quaternion2) {
2554
- fromQuat(this, quaternion2);
2611
+ fromQuaternion(quaternion) {
2612
+ fromQuat(this, quaternion);
2555
2613
  return this.check();
2556
2614
  }
2557
2615
  /**
@@ -3410,188 +3468,26 @@ var __exports__ = (() => {
3410
3468
  }
3411
3469
  };
3412
3470
 
3413
- // src/gltf/gltf-animator.ts
3414
- var import_core2 = __toESM(require_core(), 1);
3415
- var ATTRIBUTE_TYPE_TO_COMPONENTS = {
3416
- SCALAR: 1,
3417
- VEC2: 2,
3418
- VEC3: 3,
3419
- VEC4: 4,
3420
- MAT2: 4,
3421
- MAT3: 9,
3422
- MAT4: 16
3423
- };
3424
- var ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY = {
3425
- 5120: Int8Array,
3426
- 5121: Uint8Array,
3427
- 5122: Int16Array,
3428
- 5123: Uint16Array,
3429
- 5125: Uint32Array,
3430
- 5126: Float32Array
3431
- };
3432
- var GLTFAnimation = class {
3433
- name = "unnamed";
3434
- startTime = 0;
3435
- playing = true;
3436
- speed = 1;
3437
- channels = [];
3438
- constructor(props) {
3439
- Object.assign(this, props);
3440
- }
3441
- animate(timeMs) {
3442
- if (!this.playing) {
3443
- return;
3444
- }
3445
- const absTime = timeMs / 1e3;
3446
- const time = (absTime - this.startTime) * this.speed;
3447
- this.channels.forEach(({ sampler, target, path }) => {
3448
- interpolate(time, sampler, target, path);
3449
- applyTranslationRotationScale(target, target._node);
3450
- });
3451
- }
3452
- };
3453
- var GLTFAnimator = class {
3454
- animations;
3455
- constructor(gltf) {
3456
- this.animations = gltf.animations.map((animation, index) => {
3457
- const name = animation.name || `Animation-${index}`;
3458
- const samplers = animation.samplers.map(({ input, interpolation = "LINEAR", output }) => ({
3459
- input: accessorToJsArray(gltf.accessors[input]),
3460
- interpolation,
3461
- output: accessorToJsArray(gltf.accessors[output])
3462
- }));
3463
- const channels = animation.channels.map(({ sampler, target }) => ({
3464
- sampler: samplers[sampler],
3465
- target: gltf.nodes[target.node],
3466
- path: target.path
3467
- }));
3468
- return new GLTFAnimation({ name, channels });
3469
- });
3470
- }
3471
- /** @deprecated Use .setTime(). Will be removed (deck.gl is using this) */
3472
- animate(time) {
3473
- this.setTime(time);
3474
- }
3475
- setTime(time) {
3476
- this.animations.forEach((animation) => animation.animate(time));
3477
- }
3478
- getAnimations() {
3479
- return this.animations;
3480
- }
3481
- };
3482
- function accessorToJsArray(accessor) {
3483
- if (!accessor._animation) {
3484
- const ArrayType = ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY[accessor.componentType];
3485
- const components = ATTRIBUTE_TYPE_TO_COMPONENTS[accessor.type];
3486
- const length4 = components * accessor.count;
3487
- const { buffer, byteOffset } = accessor.bufferView.data;
3488
- const array = new ArrayType(
3489
- buffer,
3490
- byteOffset + (accessor.byteOffset || 0),
3491
- length4
3492
- );
3493
- if (components === 1) {
3494
- accessor._animation = Array.from(array);
3495
- } else {
3496
- const slicedArray = [];
3497
- for (let i = 0; i < array.length; i += components) {
3498
- slicedArray.push(Array.from(array.slice(i, i + components)));
3499
- }
3500
- accessor._animation = slicedArray;
3501
- }
3502
- }
3503
- return accessor._animation;
3504
- }
3505
- var helperMatrix = new Matrix4();
3506
- function applyTranslationRotationScale(gltfNode, node) {
3507
- node.matrix.identity();
3508
- if (gltfNode.translation) {
3509
- node.matrix.translate(gltfNode.translation);
3510
- }
3511
- if (gltfNode.rotation) {
3512
- const rotationMatrix = helperMatrix.fromQuaternion(gltfNode.rotation);
3513
- node.matrix.multiplyRight(rotationMatrix);
3514
- }
3515
- if (gltfNode.scale) {
3516
- node.matrix.scale(gltfNode.scale);
3517
- }
3518
- }
3519
- var quaternion = new Quaternion();
3520
- function linearInterpolate(target, path, start, stop, ratio) {
3521
- if (path === "rotation") {
3522
- quaternion.slerp({ start, target: stop, ratio });
3523
- for (let i = 0; i < quaternion.length; i++) {
3524
- target[path][i] = quaternion[i];
3525
- }
3526
- } else {
3527
- for (let i = 0; i < start.length; i++) {
3528
- target[path][i] = ratio * stop[i] + (1 - ratio) * start[i];
3529
- }
3530
- }
3531
- }
3532
- function cubicsplineInterpolate(target, path, { p0, outTangent0, inTangent1, p1, tDiff, ratio: t }) {
3533
- for (let i = 0; i < target[path].length; i++) {
3534
- const m0 = outTangent0[i] * tDiff;
3535
- const m1 = inTangent1[i] * tDiff;
3536
- target[path][i] = (2 * Math.pow(t, 3) - 3 * Math.pow(t, 2) + 1) * p0[i] + (Math.pow(t, 3) - 2 * Math.pow(t, 2) + t) * m0 + (-2 * Math.pow(t, 3) + 3 * Math.pow(t, 2)) * p1[i] + (Math.pow(t, 3) - Math.pow(t, 2)) * m1;
3537
- }
3538
- }
3539
- function stepInterpolate(target, path, value) {
3540
- for (let i = 0; i < value.length; i++) {
3541
- target[path][i] = value[i];
3542
- }
3543
- }
3544
- function interpolate(time, { input, interpolation, output }, target, path) {
3545
- const maxTime = input[input.length - 1];
3546
- const animationTime = time % maxTime;
3547
- const nextIndex = input.findIndex((t) => t >= animationTime);
3548
- const previousIndex = Math.max(0, nextIndex - 1);
3549
- if (!Array.isArray(target[path])) {
3550
- switch (path) {
3551
- case "translation":
3552
- target[path] = [0, 0, 0];
3553
- break;
3554
- case "rotation":
3555
- target[path] = [0, 0, 0, 1];
3556
- break;
3557
- case "scale":
3558
- target[path] = [1, 1, 1];
3559
- break;
3560
- default:
3561
- import_core2.log.warn(`Bad animation path ${path}`)();
3562
- }
3563
- }
3564
- const previousTime = input[previousIndex];
3565
- const nextTime = input[nextIndex];
3566
- switch (interpolation) {
3567
- case "STEP":
3568
- stepInterpolate(target, path, output[previousIndex]);
3569
- break;
3570
- case "LINEAR":
3571
- if (nextTime > previousTime) {
3572
- const ratio = (animationTime - previousTime) / (nextTime - previousTime);
3573
- linearInterpolate(target, path, output[previousIndex], output[nextIndex], ratio);
3574
- }
3575
- break;
3576
- case "CUBICSPLINE":
3577
- if (nextTime > previousTime) {
3578
- const ratio = (animationTime - previousTime) / (nextTime - previousTime);
3579
- const tDiff = nextTime - previousTime;
3580
- const p0 = output[3 * previousIndex + 1];
3581
- const outTangent0 = output[3 * previousIndex + 2];
3582
- const inTangent1 = output[3 * nextIndex + 0];
3583
- const p1 = output[3 * nextIndex + 1];
3584
- cubicsplineInterpolate(target, path, { p0, outTangent0, inTangent1, p1, tDiff, ratio });
3585
- }
3586
- break;
3587
- default:
3588
- import_core2.log.warn(`Interpolation ${interpolation} not supported`)();
3589
- break;
3471
+ // src/webgl-to-webgpu/convert-webgl-topology.ts
3472
+ function convertGLDrawModeToTopology(drawMode) {
3473
+ switch (drawMode) {
3474
+ case 0 /* POINTS */:
3475
+ return "point-list";
3476
+ case 1 /* LINES */:
3477
+ return "line-list";
3478
+ case 3 /* LINE_STRIP */:
3479
+ return "line-strip";
3480
+ case 4 /* TRIANGLES */:
3481
+ return "triangle-list";
3482
+ case 5 /* TRIANGLE_STRIP */:
3483
+ return "triangle-strip";
3484
+ default:
3485
+ throw new Error(String(drawMode));
3590
3486
  }
3591
3487
  }
3592
3488
 
3593
3489
  // src/gltf/create-gltf-model.ts
3594
- var import_core4 = __toESM(require_core(), 1);
3490
+ var import_core2 = __toESM(require_core(), 1);
3595
3491
  var import_shadertools = __toESM(require_shadertools(), 1);
3596
3492
  var import_engine2 = __toESM(require_engine(), 1);
3597
3493
  var SHADER = (
@@ -3698,9 +3594,8 @@ layout(0) positions: vec4; // in vec4 POSITION;
3698
3594
  `
3699
3595
  );
3700
3596
  function createGLTFModel(device, options) {
3701
- const { id, geometry, material, vertexCount, materialOptions, modelOptions = {} } = options;
3702
- const parsedMaterial = parsePBRMaterial(device, material, geometry.attributes, materialOptions);
3703
- import_core4.log.info(4, "createGLTFModel defines: ", parsedMaterial.defines)();
3597
+ const { id, geometry, parsedPPBRMaterial, vertexCount, modelOptions = {} } = options;
3598
+ import_core2.log.info(4, "createGLTFModel defines: ", parsedPPBRMaterial.defines)();
3704
3599
  const managedResources = [];
3705
3600
  const parameters = {
3706
3601
  depthWriteEnabled: true,
@@ -3718,182 +3613,355 @@ layout(0) positions: vec4; // in vec4 POSITION;
3718
3613
  vertexCount,
3719
3614
  modules: [import_shadertools.pbrMaterial],
3720
3615
  ...modelOptions,
3721
- defines: { ...parsedMaterial.defines, ...modelOptions.defines },
3722
- parameters: { ...parameters, ...parsedMaterial.parameters, ...modelOptions.parameters }
3616
+ defines: { ...parsedPPBRMaterial.defines, ...modelOptions.defines },
3617
+ parameters: { ...parameters, ...parsedPPBRMaterial.parameters, ...modelOptions.parameters }
3723
3618
  };
3724
3619
  const model = new import_engine2.Model(device, modelProps);
3725
3620
  const { camera, ...pbrMaterialProps } = {
3726
- ...parsedMaterial.uniforms,
3621
+ ...parsedPPBRMaterial.uniforms,
3727
3622
  ...modelOptions.uniforms,
3728
- ...parsedMaterial.bindings,
3623
+ ...parsedPPBRMaterial.bindings,
3729
3624
  ...modelOptions.bindings
3730
3625
  };
3731
3626
  model.shaderInputs.setProps({ pbrMaterial: pbrMaterialProps, pbrProjection: { camera } });
3732
3627
  return new import_engine2.ModelNode({ managedResources, model });
3733
3628
  }
3734
3629
 
3735
- // src/gltf/gl-utils.ts
3736
- function convertGLDrawModeToTopology(drawMode) {
3737
- switch (drawMode) {
3738
- case 0 /* POINTS */:
3739
- return "point-list";
3740
- case 1 /* LINES */:
3741
- return "line-list";
3742
- case 3 /* LINE_STRIP */:
3743
- return "line-strip";
3744
- case 4 /* TRIANGLES */:
3745
- return "triangle-list";
3746
- case 5 /* TRIANGLE_STRIP */:
3747
- return "triangle-strip";
3748
- default:
3749
- throw new Error(String(drawMode));
3750
- }
3751
- }
3752
-
3753
- // src/gltf/gltf-instantiator.ts
3754
- var DEFAULT_OPTIONS = {
3630
+ // src/parsers/parse-gltf.ts
3631
+ var defaultOptions = {
3755
3632
  modelOptions: {},
3756
3633
  pbrDebug: false,
3757
3634
  imageBasedLightingEnvironment: void 0,
3758
3635
  lights: true,
3759
3636
  useTangents: false
3760
3637
  };
3761
- var GLTFInstantiator = class {
3762
- device;
3763
- options;
3764
- gltf;
3765
- constructor(device, options = {}) {
3766
- this.device = device;
3767
- this.options = { ...DEFAULT_OPTIONS, ...options };
3768
- }
3769
- instantiate(gltf) {
3770
- this.gltf = deepCopy(gltf);
3771
- const scenes = (this.gltf.scenes || []).map((scene) => this.createScene(scene));
3772
- return scenes;
3773
- }
3774
- createAnimator() {
3775
- if (Array.isArray(this.gltf.animations)) {
3776
- return new GLTFAnimator(this.gltf);
3638
+ function parseGLTF(device, gltf, options_ = {}) {
3639
+ const options = { ...defaultOptions, ...options_ };
3640
+ const sceneNodes = gltf.scenes.map(
3641
+ (gltfScene) => createScene(device, gltfScene, gltf.nodes, options)
3642
+ );
3643
+ return sceneNodes;
3644
+ }
3645
+ function createScene(device, gltfScene, gltfNodes, options) {
3646
+ const gltfSceneNodes = gltfScene.nodes || [];
3647
+ const nodes = gltfSceneNodes.map((node) => createNode(device, node, gltfNodes, options));
3648
+ const sceneNode = new import_engine3.GroupNode({
3649
+ id: gltfScene.name || gltfScene.id,
3650
+ children: nodes
3651
+ });
3652
+ return sceneNode;
3653
+ }
3654
+ function createNode(device, gltfNode, gltfNodes, options) {
3655
+ if (!gltfNode._node) {
3656
+ const gltfChildren = gltfNode.children || [];
3657
+ const children = gltfChildren.map((child) => createNode(device, child, gltfNodes, options));
3658
+ if (gltfNode.mesh) {
3659
+ children.push(createMesh(device, gltfNode.mesh, options));
3660
+ }
3661
+ const node = new import_engine3.GroupNode({
3662
+ id: gltfNode.name || gltfNode.id,
3663
+ children
3664
+ });
3665
+ if (gltfNode.matrix) {
3666
+ node.setMatrix(gltfNode.matrix);
3667
+ } else {
3668
+ node.matrix.identity();
3669
+ if (gltfNode.translation) {
3670
+ node.matrix.translate(gltfNode.translation);
3671
+ }
3672
+ if (gltfNode.rotation) {
3673
+ const rotationMatrix = new Matrix4().fromQuaternion(gltfNode.rotation);
3674
+ node.matrix.multiplyRight(rotationMatrix);
3675
+ }
3676
+ if (gltfNode.scale) {
3677
+ node.matrix.scale(gltfNode.scale);
3678
+ }
3777
3679
  }
3778
- return null;
3680
+ gltfNode._node = node;
3779
3681
  }
3780
- createScene(gltfScene) {
3781
- const gltfNodes = gltfScene.nodes || [];
3782
- const nodes = gltfNodes.map((node) => this.createNode(node));
3783
- const scene = new import_engine3.GroupNode({
3784
- id: gltfScene.name || gltfScene.id,
3785
- children: nodes
3682
+ const topLevelNode = gltfNodes.find((node) => node.id === gltfNode.id);
3683
+ topLevelNode._node = gltfNode._node;
3684
+ return gltfNode._node;
3685
+ }
3686
+ function createMesh(device, gltfMesh, options) {
3687
+ if (!gltfMesh._mesh) {
3688
+ const gltfPrimitives = gltfMesh.primitives || [];
3689
+ const primitives = gltfPrimitives.map(
3690
+ (gltfPrimitive, i) => createPrimitive(device, gltfPrimitive, i, gltfMesh, options)
3691
+ );
3692
+ const mesh = new import_engine3.GroupNode({
3693
+ id: gltfMesh.name || gltfMesh.id,
3694
+ children: primitives
3786
3695
  });
3787
- return scene;
3788
- }
3789
- createNode(gltfNode) {
3790
- if (!gltfNode._node) {
3791
- const gltfChildren = gltfNode.children || [];
3792
- const children = gltfChildren.map((child) => this.createNode(child));
3793
- if (gltfNode.mesh) {
3794
- children.push(this.createMesh(gltfNode.mesh));
3696
+ gltfMesh._mesh = mesh;
3697
+ }
3698
+ return gltfMesh._mesh;
3699
+ }
3700
+ function createPrimitive(device, gltfPrimitive, i, gltfMesh, options) {
3701
+ const id = gltfPrimitive.name || `${gltfMesh.name || gltfMesh.id}-primitive-${i}`;
3702
+ const topology = convertGLDrawModeToTopology(gltfPrimitive.mode || 4);
3703
+ const vertexCount = gltfPrimitive.indices ? gltfPrimitive.indices.count : getVertexCount(gltfPrimitive.attributes);
3704
+ const geometry = createGeometry(id, gltfPrimitive, topology);
3705
+ const parsedPPBRMaterial = parsePBRMaterial(
3706
+ device,
3707
+ gltfPrimitive.material,
3708
+ geometry.attributes,
3709
+ options
3710
+ );
3711
+ const modelNode = createGLTFModel(device, {
3712
+ id,
3713
+ geometry: createGeometry(id, gltfPrimitive, topology),
3714
+ parsedPPBRMaterial,
3715
+ modelOptions: options.modelOptions,
3716
+ vertexCount
3717
+ });
3718
+ modelNode.bounds = [gltfPrimitive.attributes.POSITION.min, gltfPrimitive.attributes.POSITION.max];
3719
+ return modelNode;
3720
+ }
3721
+ function getVertexCount(attributes) {
3722
+ throw new Error("getVertexCount not implemented");
3723
+ }
3724
+ function createGeometry(id, gltfPrimitive, topology) {
3725
+ const attributes = {};
3726
+ for (const [attributeName, attribute] of Object.entries(gltfPrimitive.attributes)) {
3727
+ const { components, size, value } = attribute;
3728
+ attributes[attributeName] = { size: size ?? components, value };
3729
+ }
3730
+ return new import_engine3.Geometry({
3731
+ id,
3732
+ topology,
3733
+ indices: gltfPrimitive.indices.value,
3734
+ attributes
3735
+ });
3736
+ }
3737
+
3738
+ // src/gltf/gltf-animator.ts
3739
+ var import_core6 = __toESM(require_core(), 1);
3740
+
3741
+ // src/gltf/animations/interpolate.ts
3742
+ var import_core4 = __toESM(require_core(), 1);
3743
+ var scratchQuaternion = new Quaternion();
3744
+ function interpolate(time, { input, interpolation, output }, target, path) {
3745
+ const maxTime = input[input.length - 1];
3746
+ const animationTime = time % maxTime;
3747
+ const nextIndex = input.findIndex((t) => t >= animationTime);
3748
+ const previousIndex = Math.max(0, nextIndex - 1);
3749
+ if (!Array.isArray(target[path])) {
3750
+ switch (path) {
3751
+ case "translation":
3752
+ target[path] = [0, 0, 0];
3753
+ break;
3754
+ case "rotation":
3755
+ target[path] = [0, 0, 0, 1];
3756
+ break;
3757
+ case "scale":
3758
+ target[path] = [1, 1, 1];
3759
+ break;
3760
+ default:
3761
+ import_core4.log.warn(`Bad animation path ${path}`)();
3762
+ }
3763
+ }
3764
+ const previousTime = input[previousIndex];
3765
+ const nextTime = input[nextIndex];
3766
+ switch (interpolation) {
3767
+ case "STEP":
3768
+ stepInterpolate(target, path, output[previousIndex]);
3769
+ break;
3770
+ case "LINEAR":
3771
+ if (nextTime > previousTime) {
3772
+ const ratio = (animationTime - previousTime) / (nextTime - previousTime);
3773
+ linearInterpolate(
3774
+ target,
3775
+ path,
3776
+ output[previousIndex],
3777
+ output[nextIndex],
3778
+ ratio
3779
+ );
3795
3780
  }
3796
- const node = new import_engine3.GroupNode({
3797
- id: gltfNode.name || gltfNode.id,
3798
- children
3799
- });
3800
- if (gltfNode.matrix) {
3801
- node.setMatrix(gltfNode.matrix);
3802
- } else {
3803
- node.matrix.identity();
3804
- if (gltfNode.translation) {
3805
- node.matrix.translate(gltfNode.translation);
3806
- }
3807
- if (gltfNode.rotation) {
3808
- const rotationMatrix = new Matrix4().fromQuaternion(gltfNode.rotation);
3809
- node.matrix.multiplyRight(rotationMatrix);
3810
- }
3811
- if (gltfNode.scale) {
3812
- node.matrix.scale(gltfNode.scale);
3813
- }
3781
+ break;
3782
+ case "CUBICSPLINE":
3783
+ if (nextTime > previousTime) {
3784
+ const ratio = (animationTime - previousTime) / (nextTime - previousTime);
3785
+ const tDiff = nextTime - previousTime;
3786
+ const p0 = output[3 * previousIndex + 1];
3787
+ const outTangent0 = output[3 * previousIndex + 2];
3788
+ const inTangent1 = output[3 * nextIndex + 0];
3789
+ const p1 = output[3 * nextIndex + 1];
3790
+ cubicsplineInterpolate(target, path, { p0, outTangent0, inTangent1, p1, tDiff, ratio });
3814
3791
  }
3815
- gltfNode._node = node;
3816
- }
3817
- const topLevelNode = this.gltf.nodes.find((node) => node.id === gltfNode.id);
3818
- topLevelNode._node = gltfNode._node;
3819
- return gltfNode._node;
3820
- }
3821
- createMesh(gltfMesh) {
3822
- if (!gltfMesh._mesh) {
3823
- const gltfPrimitives = gltfMesh.primitives || [];
3824
- const primitives = gltfPrimitives.map(
3825
- (gltfPrimitive, i) => this.createPrimitive(gltfPrimitive, i, gltfMesh)
3826
- );
3827
- const mesh = new import_engine3.GroupNode({
3828
- id: gltfMesh.name || gltfMesh.id,
3829
- children: primitives
3830
- });
3831
- gltfMesh._mesh = mesh;
3832
- }
3833
- return gltfMesh._mesh;
3834
- }
3835
- createPrimitive(gltfPrimitive, i, gltfMesh) {
3836
- const id = gltfPrimitive.name || `${gltfMesh.name || gltfMesh.id}-primitive-${i}`;
3837
- const topology = convertGLDrawModeToTopology(gltfPrimitive.mode || 4);
3838
- const vertexCount = gltfPrimitive.indices ? gltfPrimitive.indices.count : this.getVertexCount(gltfPrimitive.attributes);
3839
- const modelNode = createGLTFModel(this.device, {
3840
- id,
3841
- geometry: this.createGeometry(id, gltfPrimitive, topology),
3842
- material: gltfPrimitive.material,
3843
- materialOptions: this.options,
3844
- modelOptions: this.options.modelOptions,
3845
- vertexCount
3846
- });
3847
- modelNode.bounds = [
3848
- gltfPrimitive.attributes.POSITION.min,
3849
- gltfPrimitive.attributes.POSITION.max
3850
- ];
3851
- return modelNode;
3852
- }
3853
- getVertexCount(attributes) {
3854
- throw new Error("getVertexCount not implemented");
3855
- }
3856
- createGeometry(id, gltfPrimitive, topology) {
3857
- const attributes = {};
3858
- for (const [attributeName, attribute] of Object.entries(gltfPrimitive.attributes)) {
3859
- const { components, size, value } = attribute;
3860
- attributes[attributeName] = { size: size ?? components, value };
3861
- }
3862
- return new import_engine3.Geometry({
3863
- id,
3864
- topology,
3865
- indices: gltfPrimitive.indices.value,
3866
- attributes
3867
- });
3792
+ break;
3793
+ default:
3794
+ import_core4.log.warn(`Interpolation ${interpolation} not supported`)();
3795
+ break;
3868
3796
  }
3869
- createBuffer(attribute, usage) {
3870
- if (!attribute.bufferView) {
3871
- attribute.bufferView = {};
3797
+ }
3798
+ function linearInterpolate(target, path, start, stop, ratio) {
3799
+ if (!target[path]) {
3800
+ throw new Error();
3801
+ }
3802
+ if (path === "rotation") {
3803
+ scratchQuaternion.slerp({ start, target: stop, ratio });
3804
+ for (let i = 0; i < scratchQuaternion.length; i++) {
3805
+ target[path][i] = scratchQuaternion[i];
3872
3806
  }
3873
- const { bufferView } = attribute;
3874
- if (!bufferView.lumaBuffers) {
3875
- bufferView.lumaBuffers = {};
3807
+ } else {
3808
+ for (let i = 0; i < start.length; i++) {
3809
+ target[path][i] = ratio * stop[i] + (1 - ratio) * start[i];
3876
3810
  }
3877
- if (!bufferView.lumaBuffers[usage]) {
3878
- bufferView.lumaBuffers[usage] = this.device.createBuffer({
3879
- id: `from-${bufferView.id}`,
3880
- // Draco decoded files have attribute.value
3881
- data: bufferView.data || attribute.value
3882
- });
3811
+ }
3812
+ }
3813
+ function cubicsplineInterpolate(target, path, {
3814
+ p0,
3815
+ outTangent0,
3816
+ inTangent1,
3817
+ p1,
3818
+ tDiff,
3819
+ ratio: t
3820
+ }) {
3821
+ if (!target[path]) {
3822
+ throw new Error();
3823
+ }
3824
+ for (let i = 0; i < target[path].length; i++) {
3825
+ const m0 = outTangent0[i] * tDiff;
3826
+ const m1 = inTangent1[i] * tDiff;
3827
+ target[path][i] = (2 * Math.pow(t, 3) - 3 * Math.pow(t, 2) + 1) * p0[i] + (Math.pow(t, 3) - 2 * Math.pow(t, 2) + t) * m0 + (-2 * Math.pow(t, 3) + 3 * Math.pow(t, 2)) * p1[i] + (Math.pow(t, 3) - Math.pow(t, 2)) * m1;
3828
+ }
3829
+ }
3830
+ function stepInterpolate(target, path, value) {
3831
+ if (!target[path]) {
3832
+ throw new Error();
3833
+ }
3834
+ for (let i = 0; i < value.length; i++) {
3835
+ target[path][i] = value[i];
3836
+ }
3837
+ }
3838
+
3839
+ // src/gltf/gltf-animator.ts
3840
+ var GLTFSingleAnimator = class {
3841
+ animation;
3842
+ startTime = 0;
3843
+ playing = true;
3844
+ speed = 1;
3845
+ constructor(props) {
3846
+ this.animation = props.animation;
3847
+ this.animation.name ||= "unnamed";
3848
+ Object.assign(this, props);
3849
+ }
3850
+ setTime(timeMs) {
3851
+ if (!this.playing) {
3852
+ return;
3883
3853
  }
3884
- return bufferView.lumaBuffers[usage];
3854
+ const absTime = timeMs / 1e3;
3855
+ const time = (absTime - this.startTime) * this.speed;
3856
+ this.animation.channels.forEach(({ sampler, target, path }) => {
3857
+ interpolate(time, sampler, target, path);
3858
+ applyTranslationRotationScale(target, target._node);
3859
+ });
3860
+ }
3861
+ };
3862
+ var GLTFAnimator = class {
3863
+ animations;
3864
+ constructor(props) {
3865
+ this.animations = props.animations.map((animation, index) => {
3866
+ const name = animation.name || `Animation-${index}`;
3867
+ return new GLTFSingleAnimator({
3868
+ animation: { name, channels: animation.channels }
3869
+ });
3870
+ });
3885
3871
  }
3886
- // TODO - create sampler in WebGL2
3887
- createSampler(gltfSampler) {
3888
- return gltfSampler;
3872
+ /** @deprecated Use .setTime(). Will be removed (deck.gl is using this) */
3873
+ animate(time) {
3874
+ import_core6.log.warn("GLTFAnimator#animate is deprecated. Use GLTFAnimator#setTime instead")();
3875
+ this.setTime(time);
3889
3876
  }
3890
- // Helper methods (move to GLTFLoader.resolve...?)
3891
- needsPOT() {
3892
- return false;
3877
+ setTime(time) {
3878
+ this.animations.forEach((animation) => animation.setTime(time));
3893
3879
  }
3880
+ getAnimations() {
3881
+ return this.animations;
3882
+ }
3883
+ };
3884
+ var scratchMatrix = new Matrix4();
3885
+ function applyTranslationRotationScale(gltfNode, node) {
3886
+ node.matrix.identity();
3887
+ if (gltfNode.translation) {
3888
+ node.matrix.translate(gltfNode.translation);
3889
+ }
3890
+ if (gltfNode.rotation) {
3891
+ const rotationMatrix = scratchMatrix.fromQuaternion(gltfNode.rotation);
3892
+ node.matrix.multiplyRight(rotationMatrix);
3893
+ }
3894
+ if (gltfNode.scale) {
3895
+ node.matrix.scale(gltfNode.scale);
3896
+ }
3897
+ }
3898
+
3899
+ // src/webgl-to-webgpu/convert-webgl-attribute.ts
3900
+ var ATTRIBUTE_TYPE_TO_COMPONENTS = {
3901
+ SCALAR: 1,
3902
+ VEC2: 2,
3903
+ VEC3: 3,
3904
+ VEC4: 4,
3905
+ MAT2: 4,
3906
+ MAT3: 9,
3907
+ MAT4: 16
3908
+ };
3909
+ var ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY = {
3910
+ 5120: Int8Array,
3911
+ 5121: Uint8Array,
3912
+ 5122: Int16Array,
3913
+ 5123: Uint16Array,
3914
+ 5125: Uint32Array,
3915
+ 5126: Float32Array
3894
3916
  };
3917
+ function accessorToTypedArray(accessor) {
3918
+ const ArrayType = ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY[accessor.componentType];
3919
+ const components = ATTRIBUTE_TYPE_TO_COMPONENTS[accessor.type];
3920
+ const length4 = components * accessor.count;
3921
+ const { buffer, byteOffset = 0 } = accessor.bufferView?.data ?? {};
3922
+ const typedArray = new ArrayType(buffer, byteOffset + (accessor.byteOffset || 0), length4);
3923
+ return { typedArray, components };
3924
+ }
3925
+
3926
+ // src/parsers/parse-gltf-animations.ts
3927
+ function parseGLTFAnimations(gltf) {
3928
+ const gltfAnimations = gltf.animations || [];
3929
+ return gltfAnimations.map((animation, index) => {
3930
+ const name = animation.name || `Animation-${index}`;
3931
+ const samplers = animation.samplers.map(
3932
+ ({ input, interpolation = "LINEAR", output }) => ({
3933
+ input: accessorToJsArray(gltf.accessors[input]),
3934
+ interpolation,
3935
+ output: accessorToJsArray(gltf.accessors[output])
3936
+ })
3937
+ );
3938
+ const channels = animation.channels.map(({ sampler, target }) => ({
3939
+ sampler: samplers[sampler],
3940
+ target: gltf.nodes[target.node ?? 0],
3941
+ path: target.path
3942
+ }));
3943
+ return { name, channels };
3944
+ });
3945
+ }
3946
+ function accessorToJsArray(accessor) {
3947
+ if (!accessor._animation) {
3948
+ const { typedArray: array, components } = accessorToTypedArray(accessor);
3949
+ if (components === 1) {
3950
+ accessor._animation = Array.from(array);
3951
+ } else {
3952
+ const slicedArray = [];
3953
+ for (let i = 0; i < array.length; i += components) {
3954
+ slicedArray.push(Array.from(array.slice(i, i + components)));
3955
+ }
3956
+ accessor._animation = slicedArray;
3957
+ }
3958
+ }
3959
+ return accessor._animation;
3960
+ }
3961
+
3962
+ // src/utils/deep-copy.ts
3895
3963
  function deepCopy(object) {
3896
- if (ArrayBuffer.isView(object) || object instanceof ArrayBuffer) {
3964
+ if (ArrayBuffer.isView(object) || object instanceof ArrayBuffer || object instanceof ImageBitmap) {
3897
3965
  return object;
3898
3966
  }
3899
3967
  if (Array.isArray(object)) {
@@ -3909,11 +3977,12 @@ layout(0) positions: vec4; // in vec4 POSITION;
3909
3977
  return object;
3910
3978
  }
3911
3979
 
3912
- // src/gltf/create-gltf-objects.ts
3980
+ // src/gltf/create-scenegraph-from-gltf.ts
3913
3981
  function createScenegraphsFromGLTF(device, gltf, options) {
3914
- const instantiator = new GLTFInstantiator(device, options);
3915
- const scenes = instantiator.instantiate(gltf);
3916
- const animator = instantiator.createAnimator();
3982
+ gltf = deepCopy(gltf);
3983
+ const scenes = parseGLTF(device, gltf, options);
3984
+ const animations = parseGLTFAnimations(gltf);
3985
+ const animator = new GLTFAnimator({ animations });
3917
3986
  return { scenes, animator };
3918
3987
  }
3919
3988
  return __toCommonJS(bundle_exports);