@luma.gl/gltf 9.3.5 → 9.4.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dist.dev.js CHANGED
@@ -264,7 +264,7 @@ var __exports__ = (() => {
264
264
  }
265
265
 
266
266
  // ../../node_modules/@loaders.gl/images/dist/lib/utils/version.js
267
- var VERSION = true ? "4.4.0" : "latest";
267
+ var VERSION = true ? "4.4.2" : "latest";
268
268
 
269
269
  // ../../node_modules/@loaders.gl/images/dist/lib/category-api/image-type.js
270
270
  var parseImageNode = globalThis.loaders?.parseImageNode;
@@ -4141,6 +4141,15 @@ var __exports__ = (() => {
4141
4141
  }
4142
4142
 
4143
4143
  // src/parsers/parse-pbr-material.ts
4144
+ var GLTF_ATTRIBUTE_ALIASES = {
4145
+ NORMAL: ["NORMAL", "normals"],
4146
+ TANGENT: ["TANGENT"],
4147
+ TEXCOORD_0: ["TEXCOORD_0", "texCoords"],
4148
+ TEXCOORD_1: ["TEXCOORD_1", "texCoords1"],
4149
+ JOINTS_0: ["JOINTS_0"],
4150
+ WEIGHTS_0: ["WEIGHTS_0"],
4151
+ COLOR_0: ["COLOR_0", "colors"]
4152
+ };
4144
4153
  function parsePBRMaterial(device, material, attributes, options) {
4145
4154
  const parsedMaterial = {
4146
4155
  defines: {
@@ -4174,17 +4183,19 @@ var __exports__ = (() => {
4174
4183
  parsedMaterial.uniforms.scaleDiffBaseMR = [0, 0, 0, 0];
4175
4184
  parsedMaterial.uniforms.scaleFGDSpec = [0, 0, 0, 0];
4176
4185
  }
4177
- if (attributes["NORMAL"])
4186
+ if (hasGLTFAttribute(attributes, "NORMAL"))
4178
4187
  parsedMaterial.defines["HAS_NORMALS"] = true;
4179
- if (attributes["TANGENT"] && options?.useTangents)
4188
+ if (hasGLTFAttribute(attributes, "TANGENT") && options?.useTangents) {
4180
4189
  parsedMaterial.defines["HAS_TANGENTS"] = true;
4181
- if (attributes["TEXCOORD_0"])
4190
+ }
4191
+ if (hasGLTFAttribute(attributes, "TEXCOORD_0"))
4182
4192
  parsedMaterial.defines["HAS_UV"] = true;
4183
- if (attributes["TEXCOORD_1"])
4193
+ if (hasGLTFAttribute(attributes, "TEXCOORD_1"))
4184
4194
  parsedMaterial.defines["HAS_UV_1"] = true;
4185
- if (attributes["JOINTS_0"] && attributes["WEIGHTS_0"])
4195
+ if (hasGLTFAttribute(attributes, "JOINTS_0") && hasGLTFAttribute(attributes, "WEIGHTS_0")) {
4186
4196
  parsedMaterial.defines["HAS_SKIN"] = true;
4187
- if (attributes["COLOR_0"])
4197
+ }
4198
+ if (hasGLTFAttribute(attributes, "COLOR_0"))
4188
4199
  parsedMaterial.defines["HAS_COLORS"] = true;
4189
4200
  if (options?.imageBasedLightingEnvironment)
4190
4201
  parsedMaterial.defines["USE_IBL"] = true;
@@ -4200,19 +4211,19 @@ var __exports__ = (() => {
4200
4211
  }
4201
4212
  function warnOnMissingExpectedAttributes(material, attributes) {
4202
4213
  const uvDependentTextureSlots = getUvDependentTextureSlots(material, 0);
4203
- if (uvDependentTextureSlots.length > 0 && !attributes["TEXCOORD_0"]) {
4214
+ if (uvDependentTextureSlots.length > 0 && !hasGLTFAttribute(attributes, "TEXCOORD_0")) {
4204
4215
  import_core2.log.warn(
4205
4216
  `glTF material uses ${uvDependentTextureSlots.join(", ")} but primitive is missing TEXCOORD_0; textured shading will sample the default UV coordinates`
4206
4217
  )();
4207
4218
  }
4208
4219
  const uv1DependentTextureSlots = getUvDependentTextureSlots(material, 1);
4209
- if (uv1DependentTextureSlots.length > 0 && !attributes["TEXCOORD_1"]) {
4220
+ if (uv1DependentTextureSlots.length > 0 && !hasGLTFAttribute(attributes, "TEXCOORD_1")) {
4210
4221
  import_core2.log.warn(
4211
4222
  `glTF material uses ${uv1DependentTextureSlots.join(", ")} with TEXCOORD_1 but primitive is missing TEXCOORD_1; those textures will be skipped`
4212
4223
  )();
4213
4224
  }
4214
4225
  const isUnlitMaterial = Boolean(material.unlit || material.extensions?.KHR_materials_unlit);
4215
- if (isUnlitMaterial || attributes["NORMAL"]) {
4226
+ if (isUnlitMaterial || hasGLTFAttribute(attributes, "NORMAL")) {
4216
4227
  return;
4217
4228
  }
4218
4229
  const missingNormalReason = material.normalTexture ? "lit PBR shading with normalTexture" : "lit PBR shading";
@@ -4233,6 +4244,9 @@ var __exports__ = (() => {
4233
4244
  }
4234
4245
  return uvDependentTextureSlots;
4235
4246
  }
4247
+ function hasGLTFAttribute(attributes, attributeName) {
4248
+ return GLTF_ATTRIBUTE_ALIASES[attributeName].some((alias) => Boolean(attributes[alias]));
4249
+ }
4236
4250
  function getNestedTextureInfo(material, pathSegments) {
4237
4251
  let value = material;
4238
4252
  for (const pathSegment of pathSegments) {
@@ -4700,7 +4714,7 @@ var __exports__ = (() => {
4700
4714
  )();
4701
4715
  return;
4702
4716
  }
4703
- if (textureCoordinateSet === 1 && !attributes["TEXCOORD_1"]) {
4717
+ if (textureCoordinateSet === 1 && !hasGLTFAttribute(attributes, "TEXCOORD_1")) {
4704
4718
  import_core2.log.warn(
4705
4719
  `Skipping ${String(uniformName)} because it requires TEXCOORD_1 but the primitive does not provide TEXCOORD_1`
4706
4720
  )();
@@ -5471,7 +5485,7 @@ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
5471
5485
  }
5472
5486
 
5473
5487
  // src/gltf/gltf-animator.ts
5474
- var import_core7 = __toESM(require_core(), 1);
5488
+ var import_engine5 = __toESM(require_engine(), 1);
5475
5489
 
5476
5490
  // src/gltf/animations/interpolate.ts
5477
5491
  var import_core5 = __toESM(require_core(), 1);
@@ -5560,27 +5574,23 @@ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
5560
5574
  }
5561
5575
 
5562
5576
  // src/gltf/gltf-animator.ts
5563
- var GLTFSingleAnimator = class {
5577
+ var GLTFAnimationClip = class extends import_engine5.AnimationClipController {
5564
5578
  /** Animation definition being played. */
5565
5579
  animation;
5566
5580
  /** Target scenegraph lookup table. */
5567
5581
  gltfNodeIdToNodeMap;
5568
5582
  /** Materials aligned with the source glTF materials array. */
5569
5583
  materials;
5570
- /** Playback start time in seconds. */
5571
- startTime = 0;
5572
- /** Whether playback is currently enabled. */
5573
- playing = true;
5574
- /** Playback speed multiplier. */
5575
- speed = 1;
5576
5584
  /** Mutable runtime texture-transform state for animated material slots. */
5577
5585
  materialTextureTransformState = /* @__PURE__ */ new Map();
5578
5586
  /** Creates a single-animation controller. */
5579
5587
  constructor(props) {
5588
+ super({ name: props.animation.name || "unnamed" });
5580
5589
  this.animation = props.animation;
5581
5590
  this.gltfNodeIdToNodeMap = props.gltfNodeIdToNodeMap;
5582
5591
  this.materials = props.materials || [];
5583
5592
  this.animation.name ||= "unnamed";
5593
+ this.name = this.animation.name;
5584
5594
  Object.assign(this, props);
5585
5595
  if (this.animation.channels.some((channel) => channel.type !== "node") && !this.materials.length) {
5586
5596
  throw new Error(
@@ -5588,13 +5598,8 @@ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
5588
5598
  );
5589
5599
  }
5590
5600
  }
5591
- /** Advances the animation to the supplied wall-clock time in milliseconds. */
5592
- setTime(timeMs) {
5593
- if (!this.playing) {
5594
- return;
5595
- }
5596
- const absTime = timeMs / 1e3;
5597
- const time = (absTime - this.startTime) * this.speed;
5601
+ /** Applies the resolved local clip time in seconds. */
5602
+ applyTime(time) {
5598
5603
  this.animation.channels.forEach((channel) => {
5599
5604
  if (channel.type === "node") {
5600
5605
  const { sampler, targetNodeId, path } = channel;
@@ -5627,32 +5632,19 @@ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
5627
5632
  });
5628
5633
  }
5629
5634
  };
5630
- var GLTFAnimator = class {
5631
- /** Individual animation controllers. */
5632
- animations;
5635
+ var GLTFAnimator = class extends import_engine5.Animator {
5633
5636
  /** Creates an animator for the supplied glTF scenegraph. */
5634
5637
  constructor(props) {
5635
- this.animations = props.animations.map((animation, index) => {
5636
- const name = animation.name || `Animation-${index}`;
5637
- return new GLTFSingleAnimator({
5638
- gltfNodeIdToNodeMap: props.gltfNodeIdToNodeMap,
5639
- materials: props.materials,
5640
- animation: { name, channels: animation.channels }
5641
- });
5642
- });
5643
- }
5644
- /** @deprecated Use .setTime(). Will be removed (deck.gl is using this) */
5645
- animate(time) {
5646
- import_core7.log.warn("GLTFAnimator#animate is deprecated. Use GLTFAnimator#setTime instead")();
5647
- this.setTime(time);
5648
- }
5649
- /** Advances every animation to the supplied wall-clock time in milliseconds. */
5650
- setTime(time) {
5651
- this.animations.forEach((animation) => animation.setTime(time));
5652
- }
5653
- /** Returns the per-animation controllers managed by this animator. */
5654
- getAnimations() {
5655
- return this.animations;
5638
+ super(
5639
+ props.animations.map((animation, index) => {
5640
+ const name = animation.name || `Animation-${index}`;
5641
+ return new GLTFAnimationClip({
5642
+ gltfNodeIdToNodeMap: props.gltfNodeIdToNodeMap,
5643
+ materials: props.materials,
5644
+ animation: { name, channels: animation.channels }
5645
+ });
5646
+ })
5647
+ );
5656
5648
  }
5657
5649
  };
5658
5650
  function applyMaterialAnimationValue(material, channel, value) {
@@ -5728,7 +5720,7 @@ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
5728
5720
  }
5729
5721
 
5730
5722
  // src/parsers/parse-gltf-animations.ts
5731
- var import_core8 = __toESM(require_core(), 1);
5723
+ var import_core7 = __toESM(require_core(), 1);
5732
5724
 
5733
5725
  // src/gltf/gltf-extension-support.ts
5734
5726
  var UNKNOWN_EXTENSION_SUPPORT = {
@@ -5984,7 +5976,7 @@ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
5984
5976
  function parseAnimationPointerChannel(gltf, target, sampler) {
5985
5977
  const pointer = target.extensions?.["KHR_animation_pointer"]?.pointer;
5986
5978
  if (typeof pointer !== "string" || !pointer.startsWith("/")) {
5987
- import_core8.log.warn("KHR_animation_pointer channel is missing a valid JSON pointer and will be skipped")();
5979
+ import_core7.log.warn("KHR_animation_pointer channel is missing a valid JSON pointer and will be skipped")();
5988
5980
  return null;
5989
5981
  }
5990
5982
  const pointerSegments = splitJsonPointer(pointer);
@@ -6012,7 +6004,7 @@ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
6012
6004
  const nodeIndex = Number(pointerSegments[1]);
6013
6005
  const targetNode = gltf.nodes[nodeIndex];
6014
6006
  if (!Number.isInteger(nodeIndex) || !targetNode) {
6015
- import_core8.log.warn(
6007
+ import_core7.log.warn(
6016
6008
  `KHR_animation_pointer target ${pointer} references a missing node and will be skipped`
6017
6009
  )();
6018
6010
  return null;
@@ -6026,7 +6018,7 @@ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
6026
6018
  return null;
6027
6019
  }
6028
6020
  if (path === "weights") {
6029
- import_core8.log.warn(
6021
+ import_core7.log.warn(
6030
6022
  `KHR_animation_pointer target ${pointer} will be skipped because morph weights are not implemented in GLTFAnimator`
6031
6023
  )();
6032
6024
  return null;
@@ -6049,7 +6041,7 @@ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
6049
6041
  const materialIndex = Number(pointerSegments[1]);
6050
6042
  const material = gltf.materials[materialIndex];
6051
6043
  if (!Number.isInteger(materialIndex) || !material) {
6052
- import_core8.log.warn(
6044
+ import_core7.log.warn(
6053
6045
  `KHR_animation_pointer target ${pointer} references a missing material and will be skipped`
6054
6046
  )();
6055
6047
  return null;
@@ -6238,7 +6230,7 @@ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
6238
6230
  return extensionIndex >= 0 && extensionName ? extensionName : null;
6239
6231
  }
6240
6232
  function warnUnsupportedAnimationPointer(pointer, reason) {
6241
- import_core8.log.warn(`KHR_animation_pointer target ${pointer} will be skipped because ${reason}`)();
6233
+ import_core7.log.warn(`KHR_animation_pointer target ${pointer} will be skipped because ${reason}`)();
6242
6234
  }
6243
6235
  function accessorToJsArray1D(accessor, accessorCache) {
6244
6236
  if (accessorCache.has(accessor)) {