@babylonjs/loaders 9.26.0 → 9.26.2

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 (129) hide show
  1. package/FBX/fbxConstraintBehavior.d.ts +188 -0
  2. package/FBX/fbxConstraintBehavior.js +532 -0
  3. package/FBX/fbxConstraintBehavior.js.map +1 -0
  4. package/FBX/fbxFileLoader.pure.d.ts +175 -6
  5. package/FBX/fbxFileLoader.pure.js +1521 -286
  6. package/FBX/fbxFileLoader.pure.js.map +1 -1
  7. package/FBX/index.d.ts +4 -1
  8. package/FBX/index.js +1 -0
  9. package/FBX/index.js.map +1 -1
  10. package/FBX/interpreter/animation.d.ts +73 -33
  11. package/FBX/interpreter/animation.js +620 -223
  12. package/FBX/interpreter/animation.js.map +1 -1
  13. package/FBX/interpreter/animationCurve.d.ts +91 -0
  14. package/FBX/interpreter/animationCurve.js +623 -0
  15. package/FBX/interpreter/animationCurve.js.map +1 -0
  16. package/FBX/interpreter/blendShapes.js +9 -18
  17. package/FBX/interpreter/blendShapes.js.map +1 -1
  18. package/FBX/interpreter/connections.d.ts +1 -1
  19. package/FBX/interpreter/connections.js +173 -34
  20. package/FBX/interpreter/connections.js.map +1 -1
  21. package/FBX/interpreter/constraints.d.ts +68 -0
  22. package/FBX/interpreter/constraints.js +143 -0
  23. package/FBX/interpreter/constraints.js.map +1 -0
  24. package/FBX/interpreter/fbxInterpreter.d.ts +89 -4
  25. package/FBX/interpreter/fbxInterpreter.js +474 -122
  26. package/FBX/interpreter/fbxInterpreter.js.map +1 -1
  27. package/FBX/interpreter/geometry.d.ts +1 -1
  28. package/FBX/interpreter/geometry.js +150 -92
  29. package/FBX/interpreter/geometry.js.map +1 -1
  30. package/FBX/interpreter/legacyDocument.d.ts +11 -0
  31. package/FBX/interpreter/legacyDocument.js +425 -0
  32. package/FBX/interpreter/legacyDocument.js.map +1 -0
  33. package/FBX/interpreter/materialModel.d.ts +71 -0
  34. package/FBX/interpreter/materialModel.js +622 -0
  35. package/FBX/interpreter/materialModel.js.map +1 -0
  36. package/FBX/interpreter/materials.d.ts +13 -1
  37. package/FBX/interpreter/materials.js +88 -5
  38. package/FBX/interpreter/materials.js.map +1 -1
  39. package/FBX/interpreter/nodeTransform.d.ts +32 -0
  40. package/FBX/interpreter/nodeTransform.js +54 -0
  41. package/FBX/interpreter/nodeTransform.js.map +1 -0
  42. package/FBX/interpreter/nurbs.d.ts +99 -0
  43. package/FBX/interpreter/nurbs.js +627 -0
  44. package/FBX/interpreter/nurbs.js.map +1 -0
  45. package/FBX/interpreter/propertyTemplates.d.ts +23 -0
  46. package/FBX/interpreter/propertyTemplates.js +109 -2
  47. package/FBX/interpreter/propertyTemplates.js.map +1 -1
  48. package/FBX/interpreter/rig.js +16 -0
  49. package/FBX/interpreter/rig.js.map +1 -1
  50. package/FBX/interpreter/sceneDiagnostics.js +28 -3
  51. package/FBX/interpreter/sceneDiagnostics.js.map +1 -1
  52. package/FBX/interpreter/skeleton.d.ts +4 -18
  53. package/FBX/interpreter/skeleton.js +16 -94
  54. package/FBX/interpreter/skeleton.js.map +1 -1
  55. package/FBX/parsers/fbxAsciiParser.js +119 -9
  56. package/FBX/parsers/fbxAsciiParser.js.map +1 -1
  57. package/FBX/parsers/fbxBinaryParser.js +74 -22
  58. package/FBX/parsers/fbxBinaryParser.js.map +1 -1
  59. package/FBX/pure.d.ts +1 -0
  60. package/FBX/pure.js +1 -0
  61. package/FBX/pure.js.map +1 -1
  62. package/FBX/types/fbxTypes.d.ts +18 -2
  63. package/FBX/types/fbxTypes.js +40 -12
  64. package/FBX/types/fbxTypes.js.map +1 -1
  65. package/SPLAT/gaussianSplattingStream.d.ts +79 -25
  66. package/SPLAT/gaussianSplattingStream.js +320 -95
  67. package/SPLAT/gaussianSplattingStream.js.map +1 -1
  68. package/USD/usdCommandProtocol.d.ts +20 -4
  69. package/USD/usdCommandProtocol.js +25 -3
  70. package/USD/usdCommandProtocol.js.map +1 -1
  71. package/USD/usdFileLoader.pure.js +2 -0
  72. package/USD/usdFileLoader.pure.js.map +1 -1
  73. package/USD/usdSceneMaterializer.js +430 -92
  74. package/USD/usdSceneMaterializer.js.map +1 -1
  75. package/glTF/2.0/Extensions/KHR_interactivity/declarationMapper.d.ts +110 -3
  76. package/glTF/2.0/Extensions/KHR_interactivity/declarationMapper.js +468 -74
  77. package/glTF/2.0/Extensions/KHR_interactivity/declarationMapper.js.map +1 -1
  78. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphEventReferenceBlock.d.ts +47 -0
  79. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphEventReferenceBlock.js +68 -0
  80. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphEventReferenceBlock.js.map +1 -0
  81. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphGLTFDataProvider.d.ts +2 -2
  82. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphGLTFDataProvider.js +1 -1
  83. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphGLTFDataProvider.js.map +1 -1
  84. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphObjectReferenceBlock.d.ts +24 -0
  85. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphObjectReferenceBlock.js +38 -0
  86. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphObjectReferenceBlock.js.map +1 -0
  87. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphUnsupportedInteractivityBlock.d.ts +41 -0
  88. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphUnsupportedInteractivityBlock.js +63 -0
  89. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphUnsupportedInteractivityBlock.js.map +1 -0
  90. package/glTF/2.0/Extensions/KHR_interactivity/index.d.ts +5 -0
  91. package/glTF/2.0/Extensions/KHR_interactivity/index.js +5 -0
  92. package/glTF/2.0/Extensions/KHR_interactivity/index.js.map +1 -1
  93. package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphModel.d.ts +112 -0
  94. package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphModel.js +773 -0
  95. package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphModel.js.map +1 -0
  96. package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphParser.d.ts +18 -10
  97. package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphParser.js +299 -54
  98. package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphParser.js.map +1 -1
  99. package/glTF/2.0/Extensions/KHR_interactivity/interactivityHostResolver.d.ts +2 -1
  100. package/glTF/2.0/Extensions/KHR_interactivity/interactivityHostResolver.js +7 -2
  101. package/glTF/2.0/Extensions/KHR_interactivity/interactivityHostResolver.js.map +1 -1
  102. package/glTF/2.0/Extensions/KHR_interactivity/interactivityNodeState.d.ts +24 -0
  103. package/glTF/2.0/Extensions/KHR_interactivity/interactivityNodeState.js +89 -0
  104. package/glTF/2.0/Extensions/KHR_interactivity/interactivityNodeState.js.map +1 -0
  105. package/glTF/2.0/Extensions/KHR_interactivity/pure.d.ts +5 -0
  106. package/glTF/2.0/Extensions/KHR_interactivity/pure.js +5 -0
  107. package/glTF/2.0/Extensions/KHR_interactivity/pure.js.map +1 -1
  108. package/glTF/2.0/Extensions/KHR_interactivity.pure.d.ts +55 -1
  109. package/glTF/2.0/Extensions/KHR_interactivity.pure.js +124 -76
  110. package/glTF/2.0/Extensions/KHR_interactivity.pure.js.map +1 -1
  111. package/glTF/2.0/Extensions/KHR_interactivity.types.d.ts +18 -1
  112. package/glTF/2.0/Extensions/KHR_interactivity.types.js.map +1 -1
  113. package/glTF/2.0/Extensions/KHR_node_hoverability.pure.d.ts +2 -0
  114. package/glTF/2.0/Extensions/KHR_node_hoverability.pure.js +114 -56
  115. package/glTF/2.0/Extensions/KHR_node_hoverability.pure.js.map +1 -1
  116. package/glTF/2.0/Extensions/KHR_node_selectability.pure.d.ts +2 -0
  117. package/glTF/2.0/Extensions/KHR_node_selectability.pure.js +80 -35
  118. package/glTF/2.0/Extensions/KHR_node_selectability.pure.js.map +1 -1
  119. package/glTF/2.0/Extensions/interactivityRefPathToObjectConverter.js +3 -2
  120. package/glTF/2.0/Extensions/interactivityRefPathToObjectConverter.js.map +1 -1
  121. package/glTF/2.0/Extensions/objectModelMapping.d.ts +4 -2
  122. package/glTF/2.0/Extensions/objectModelMapping.js +33 -4
  123. package/glTF/2.0/Extensions/objectModelMapping.js.map +1 -1
  124. package/glTF/2.0/glTFLoader.pure.d.ts +1 -1
  125. package/glTF/2.0/glTFLoader.pure.js +9 -4
  126. package/glTF/2.0/glTFLoader.pure.js.map +1 -1
  127. package/glTF/2.0/glTFLoaderExtension.d.ts +2 -1
  128. package/glTF/2.0/glTFLoaderExtension.js.map +1 -1
  129. package/package.json +3 -3
@@ -4,12 +4,15 @@ import { AnimationGroup } from "@babylonjs/core/Animations/animationGroup.pure.j
4
4
  import { AbstractAssetContainer, AssetContainer } from "@babylonjs/core/assetContainer.js";
5
5
  import { Bone } from "@babylonjs/core/Bones/bone.js";
6
6
  import { Skeleton } from "@babylonjs/core/Bones/skeleton.js";
7
- import { Color3 } from "@babylonjs/core/Maths/math.color.pure.js";
7
+ import { Color3, Color4 } from "@babylonjs/core/Maths/math.color.pure.js";
8
8
  import { Matrix, Quaternion, Vector3 } from "@babylonjs/core/Maths/math.vector.pure.js";
9
9
  import { Material } from "@babylonjs/core/Materials/material.pure.js";
10
10
  import { MultiMaterial } from "@babylonjs/core/Materials/multiMaterial.pure.js";
11
11
  import { PBRMaterial } from "@babylonjs/core/Materials/PBR/pbrMaterial.pure.js";
12
12
  import { Texture } from "@babylonjs/core/Materials/Textures/texture.pure.js";
13
+ import { CreateFactorOperand, CreateTextureOperand, LerpTexturesAsync, TextureChannel, TextureColorSpace, } from "@babylonjs/core/Materials/Textures/textureProcessor.js";
14
+ import { MorphTarget } from "@babylonjs/core/Morph/morphTarget.js";
15
+ import { MorphTargetManager } from "@babylonjs/core/Morph/morphTargetManager.js";
13
16
  import { CreateBox } from "@babylonjs/core/Meshes/Builders/boxBuilder.pure.js";
14
17
  import { CreateCylinder } from "@babylonjs/core/Meshes/Builders/cylinderBuilder.pure.js";
15
18
  import { CreateSphere } from "@babylonjs/core/Meshes/Builders/sphereBuilder.pure.js";
@@ -17,6 +20,7 @@ import { Mesh } from "@babylonjs/core/Meshes/mesh.pure.js";
17
20
  import { SubMesh } from "@babylonjs/core/Meshes/subMesh.js";
18
21
  import { TransformNode } from "@babylonjs/core/Meshes/transformNode.pure.js";
19
22
  import { VertexData } from "@babylonjs/core/Meshes/mesh.vertexData.js";
23
+ import { Constants } from "@babylonjs/core/Engines/constants.js";
20
24
  import { MISSING_OFFSET, PayloadReader, readCommands, } from "./usdCommandProtocol.js";
21
25
  class DirectAssetContainer extends AbstractAssetContainer {
22
26
  dispose() {
@@ -26,6 +30,9 @@ class DirectAssetContainer extends AbstractAssetContainer {
26
30
  for (const mesh of this.meshes.splice(0)) {
27
31
  mesh.dispose();
28
32
  }
33
+ for (const manager of this.morphTargetManagers.splice(0)) {
34
+ manager.dispose();
35
+ }
29
36
  for (const skeleton of this.skeletons.splice(0)) {
30
37
  skeleton.dispose();
31
38
  }
@@ -92,6 +99,27 @@ function wrapMode(value) {
92
99
  throw new Error(`Invalid texture wrap mode ${value}.`);
93
100
  }
94
101
  }
102
+ async function awaitAbortableAsync(promise, signal) {
103
+ if (!signal) {
104
+ return await promise;
105
+ }
106
+ let onAbort;
107
+ const aborted = new Promise((_resolve, reject) => {
108
+ onAbort = () => reject(signal.reason instanceof Error ? signal.reason : new Error("USD materialization was aborted."));
109
+ signal.addEventListener("abort", onAbort, { once: true });
110
+ if (signal.aborted) {
111
+ onAbort();
112
+ }
113
+ });
114
+ try {
115
+ return await Promise.race([promise, aborted]);
116
+ }
117
+ finally {
118
+ if (onAbort) {
119
+ signal.removeEventListener("abort", onAbort);
120
+ }
121
+ }
122
+ }
95
123
  export async function materializeCommandBuffers(scene, commandBuffer, dataBuffer, addToScene, signal) {
96
124
  signal?.throwIfAborted();
97
125
  const started = performance.now();
@@ -106,12 +134,25 @@ export async function materializeCommandBuffers(scene, commandBuffer, dataBuffer
106
134
  const bones = new Map();
107
135
  const geometries = new Map();
108
136
  const meshes = new Map();
137
+ const morphTargetManagers = new Map();
138
+ const morphTargets = new Map();
139
+ const classicInstanceSources = new Set();
140
+ const thinInstanceSources = new Set();
109
141
  const animationGroups = new Map();
110
142
  const textureLoads = [];
111
143
  const textureUrls = new Set();
144
+ const materialTextureBindings = [];
145
+ const processedTextures = new Map();
112
146
  const assetContainer = container instanceof AssetContainer ? container : undefined;
113
147
  let root;
114
148
  let timeCodesPerSecond = 24;
149
+ let rollingBack = false;
150
+ const caps = scene.getEngine().getCaps();
151
+ const processedTextureType = caps.textureHalfFloatRender && caps.textureHalfFloatLinearFiltering
152
+ ? Constants.TEXTURETYPE_HALF_FLOAT
153
+ : caps.textureFloatRender && caps.textureFloatLinearFiltering
154
+ ? Constants.TEXTURETYPE_FLOAT
155
+ : Constants.TEXTURETYPE_UNSIGNED_BYTE;
115
156
  const trackAsset = (assets, asset) => {
116
157
  assets.push(asset);
117
158
  if (assetContainer) {
@@ -137,6 +178,255 @@ export async function materializeCommandBuffers(scene, commandBuffer, dataBuffer
137
178
  }
138
179
  return variant;
139
180
  };
181
+ const binding = (textureId, channel, label) => {
182
+ if (textureId === MISSING_OFFSET) {
183
+ if (channel !== MISSING_OFFSET) {
184
+ throw new Error(`USD ${label} binding has a channel without a texture.`);
185
+ }
186
+ return undefined;
187
+ }
188
+ const descriptor = textures.get(textureId);
189
+ if (!descriptor) {
190
+ throw new Error(`USD ${label} binding references missing texture ${textureId}.`);
191
+ }
192
+ if (channel < 0 /* TextureOutputChannel.R */ || channel > 4 /* TextureOutputChannel.RGB */) {
193
+ throw new Error(`USD ${label} binding has invalid output channel ${channel}.`);
194
+ }
195
+ return { descriptor, channel };
196
+ };
197
+ const channelIndex = (channel) => {
198
+ if (channel === 4 /* TextureOutputChannel.RGB */) {
199
+ throw new Error("A scalar USD texture binding cannot use the RGB output.");
200
+ }
201
+ return channel;
202
+ };
203
+ const processorChannel = (channel) => {
204
+ switch (channel) {
205
+ case 0 /* TextureOutputChannel.R */:
206
+ return TextureChannel.R;
207
+ case 1 /* TextureOutputChannel.G */:
208
+ return TextureChannel.G;
209
+ case 2 /* TextureOutputChannel.B */:
210
+ return TextureChannel.B;
211
+ case 3 /* TextureOutputChannel.A */:
212
+ return TextureChannel.A;
213
+ default:
214
+ return TextureChannel.RGBA;
215
+ }
216
+ };
217
+ const processorColorSpace = (descriptor) => descriptor.sourceColorSpace === 1 /* USDTextureColorSpace.Raw */ ? TextureColorSpace.Linear : TextureColorSpace.SRGB;
218
+ const scalarTextureIsLinear = (binding) => binding.descriptor.sourceColorSpace === 1 /* USDTextureColorSpace.Raw */;
219
+ const valueTransformIs = (descriptor, scale, bias) => scale.every((value, index) => descriptor.scale[index] === value) && bias.every((value, index) => descriptor.bias[index] === value);
220
+ const trackProcessedTexture = (texture) => {
221
+ trackAsset(container.textures, texture);
222
+ return texture;
223
+ };
224
+ const processTextureAsync = async (name, binding, scale, bias, channel = binding.channel, preserveRange = false) => {
225
+ const source = binding.descriptor;
226
+ const size = source.texture.getSize();
227
+ const supportsMipMaps = !scene.getEngine().needPOTTextures || ((size.width & (size.width - 1)) === 0 && (size.height & (size.height - 1)) === 0);
228
+ const outputOptions = {
229
+ textureType: preserveRange ? processedTextureType : Constants.TEXTURETYPE_UNSIGNED_BYTE,
230
+ samplingMode: supportsMipMaps ? Constants.TEXTURE_TRILINEAR_SAMPLINGMODE : Constants.TEXTURE_BILINEAR_SAMPLINGMODE,
231
+ generateMipMaps: supportsMipMaps,
232
+ };
233
+ if (preserveRange &&
234
+ processedTextureType === Constants.TEXTURETYPE_UNSIGNED_BYTE &&
235
+ scale.slice(0, 3).some((value, index) => Math.min(bias[index], bias[index] + value) < 0)) {
236
+ throw new Error(`USD texture processing for '${name}' requires a floating-point render target to preserve signed values.`);
237
+ }
238
+ const key = `${source.id}:${channel}:${scale.join(",")}:${bias.join(",")}:${preserveRange}`;
239
+ const cached = processedTextures.get(key);
240
+ if (cached) {
241
+ return await cached;
242
+ }
243
+ const processing = (async () => {
244
+ const a = new Color4(bias[0], bias[1], bias[2], bias[3]);
245
+ const b = new Color4(bias[0] + scale[0], bias[1] + scale[1], bias[2] + scale[2], bias[3] + scale[3]);
246
+ const previousBlockEntityCollection = scene._blockEntityCollection;
247
+ scene._blockEntityCollection = true;
248
+ let processingPromise;
249
+ try {
250
+ processingPromise = LerpTexturesAsync(name, CreateFactorOperand(a), CreateFactorOperand(b), CreateTextureOperand(source.texture, processorChannel(channel), processorColorSpace(source)), scene, TextureColorSpace.Linear, undefined, outputOptions);
251
+ }
252
+ finally {
253
+ scene._blockEntityCollection = previousBlockEntityCollection;
254
+ }
255
+ const processed = await processingPromise;
256
+ if (!processed.texture) {
257
+ throw new Error(`USD texture processing for '${name}' did not produce a texture.`);
258
+ }
259
+ if (rollingBack || signal?.aborted) {
260
+ processed.dispose?.();
261
+ if (signal?.aborted) {
262
+ signal.throwIfAborted();
263
+ }
264
+ throw new Error("USD materialization was rolled back.");
265
+ }
266
+ if (!assetContainer) {
267
+ scene.addTexture(processed.texture);
268
+ }
269
+ const texture = trackProcessedTexture(processed.texture);
270
+ texture.gammaSpace = false;
271
+ const transformedTexture = texture;
272
+ transformedTexture.uRotationCenter = source.texture.uRotationCenter;
273
+ transformedTexture.vRotationCenter = source.texture.vRotationCenter;
274
+ transformedTexture.wRotationCenter = source.texture.wRotationCenter;
275
+ transformedTexture.homogeneousRotationInUVTransform = source.texture.homogeneousRotationInUVTransform;
276
+ return texture;
277
+ })();
278
+ processedTextures.set(key, processing);
279
+ try {
280
+ return await processing;
281
+ }
282
+ catch (error) {
283
+ processedTextures.delete(key);
284
+ throw error;
285
+ }
286
+ };
287
+ const processScalarTextureAsync = async (name, binding) => {
288
+ const index = channelIndex(binding.channel);
289
+ const scale = binding.descriptor.scale[index];
290
+ const bias = binding.descriptor.bias[index];
291
+ return await processTextureAsync(name, binding, [scale, scale, scale, 1], [bias, bias, bias, 0], binding.channel);
292
+ };
293
+ const applyMaterialTextureBindingsAsync = async (bindings) => {
294
+ const { material, normalScale, base, opacity, normal, metallic, roughness, occlusion, emissive } = bindings;
295
+ if (base) {
296
+ if (base.channel !== 4 /* TextureOutputChannel.RGB */) {
297
+ throw new Error("A USD base-color texture must use the RGB output.");
298
+ }
299
+ material.albedoColor = Color3.White();
300
+ material.albedoTexture = valueTransformIs(base.descriptor, [1, 1, 1, 1], [0, 0, 0, 0])
301
+ ? base.descriptor.texture
302
+ : await processTextureAsync(`${material.name} base color`, base, base.descriptor.scale, base.descriptor.bias);
303
+ }
304
+ if (emissive) {
305
+ if (emissive.channel !== 4 /* TextureOutputChannel.RGB */) {
306
+ throw new Error("A USD emissive texture must use the RGB output.");
307
+ }
308
+ const descriptor = emissive.descriptor;
309
+ const zeroBias = descriptor.bias.slice(0, 3).every((value) => value === 0);
310
+ if (zeroBias) {
311
+ material.emissiveColor = new Color3(descriptor.scale[0], descriptor.scale[1], descriptor.scale[2]);
312
+ material.emissiveTexture = descriptor.texture;
313
+ }
314
+ else {
315
+ const factors = Array.from({ length: 3 }, (_, index) => Math.max(1, Math.abs(descriptor.bias[index]), Math.abs(descriptor.bias[index] + descriptor.scale[index])));
316
+ const scale = descriptor.scale.map((value, index) => (index < 3 ? value / factors[index] : value));
317
+ const bias = descriptor.bias.map((value, index) => (index < 3 ? value / factors[index] : value));
318
+ material.emissiveColor = new Color3(factors[0], factors[1], factors[2]);
319
+ material.emissiveTexture = await processTextureAsync(`${material.name} emissive`, emissive, scale, bias, emissive.channel, true);
320
+ }
321
+ }
322
+ if (normal) {
323
+ if (normal.channel !== 4 /* TextureOutputChannel.RGB */) {
324
+ throw new Error("A USD normal texture must use the RGB output.");
325
+ }
326
+ const canonicalNormal = normal.descriptor.sourceColorSpace === 1 /* USDTextureColorSpace.Raw */ && valueTransformIs(normal.descriptor, [2, 2, 2, 1], [-1, -1, -1, 0]);
327
+ if (canonicalNormal) {
328
+ material.bumpTexture = normal.descriptor.texture;
329
+ }
330
+ else {
331
+ const scale = Array.from(normal.descriptor.scale, (value) => value * 0.5);
332
+ const bias = Array.from(normal.descriptor.bias, (value, index) => (index < 3 ? (value + 1) * 0.5 : value));
333
+ material.bumpTexture = await processTextureAsync(`${material.name} normal`, normal, scale, bias);
334
+ }
335
+ material.bumpTexture.gammaSpace = false;
336
+ material.bumpTexture.level = normalScale;
337
+ }
338
+ const packedMetallicRoughness = metallic &&
339
+ roughness &&
340
+ metallic.descriptor === roughness.descriptor &&
341
+ (metallic.channel === 0 /* TextureOutputChannel.R */ || metallic.channel === 2 /* TextureOutputChannel.B */) &&
342
+ (roughness.channel === 1 /* TextureOutputChannel.G */ || roughness.channel === 3 /* TextureOutputChannel.A */) &&
343
+ scalarTextureIsLinear(metallic) &&
344
+ metallic.descriptor.bias[channelIndex(metallic.channel)] === 0 &&
345
+ roughness.descriptor.bias[channelIndex(roughness.channel)] === 0;
346
+ let packedOcclusion = false;
347
+ if (packedMetallicRoughness) {
348
+ const descriptor = metallic.descriptor;
349
+ material.metallicTexture = descriptor.texture;
350
+ material.metallic = (material.metallic ?? 1) * descriptor.scale[channelIndex(metallic.channel)];
351
+ material.roughness = (material.roughness ?? 1) * descriptor.scale[channelIndex(roughness.channel)];
352
+ material.useRoughnessFromMetallicTextureAlpha = roughness.channel === 3 /* TextureOutputChannel.A */;
353
+ material.useRoughnessFromMetallicTextureGreen = roughness.channel === 1 /* TextureOutputChannel.G */;
354
+ material.useMetallnessFromMetallicTextureBlue = metallic.channel === 2 /* TextureOutputChannel.B */;
355
+ packedOcclusion =
356
+ occlusion?.descriptor === descriptor &&
357
+ occlusion.channel === 0 /* TextureOutputChannel.R */ &&
358
+ descriptor.scale[0 /* TextureOutputChannel.R */] === 1 &&
359
+ descriptor.bias[0 /* TextureOutputChannel.R */] === 0;
360
+ material.useAmbientOcclusionFromMetallicTextureRed = packedOcclusion;
361
+ }
362
+ else {
363
+ if (metallic) {
364
+ const index = channelIndex(metallic.channel);
365
+ const direct = scalarTextureIsLinear(metallic) &&
366
+ (metallic.channel === 0 /* TextureOutputChannel.R */ || metallic.channel === 2 /* TextureOutputChannel.B */) &&
367
+ metallic.descriptor.bias[index] === 0;
368
+ material.metallicTexture = direct ? metallic.descriptor.texture : await processScalarTextureAsync(`${material.name} metallic`, metallic);
369
+ material.useRoughnessFromMetallicTextureAlpha = false;
370
+ material.useRoughnessFromMetallicTextureGreen = false;
371
+ material.useMetallnessFromMetallicTextureBlue = direct && metallic.channel === 2 /* TextureOutputChannel.B */;
372
+ material.metallic = direct ? (material.metallic ?? 1) * metallic.descriptor.scale[index] : 1;
373
+ }
374
+ if (roughness) {
375
+ const index = channelIndex(roughness.channel);
376
+ const direct = scalarTextureIsLinear(roughness) && roughness.channel === 0 /* TextureOutputChannel.R */ && roughness.descriptor.bias[index] === 0;
377
+ material.microSurfaceTexture = direct ? roughness.descriptor.texture : await processScalarTextureAsync(`${material.name} roughness`, roughness);
378
+ material.microSurfaceTexture.gammaSpace = direct ? roughness.descriptor.texture.gammaSpace : false;
379
+ material.roughness = direct ? (material.roughness ?? 1) * roughness.descriptor.scale[index] : 1;
380
+ }
381
+ }
382
+ if (occlusion && !packedOcclusion) {
383
+ const index = channelIndex(occlusion.channel);
384
+ const direct = scalarTextureIsLinear(occlusion) &&
385
+ occlusion.channel === 0 /* TextureOutputChannel.R */ &&
386
+ occlusion.descriptor.scale[index] === 1 &&
387
+ occlusion.descriptor.bias[index] === 0;
388
+ material.ambientTexture = direct ? occlusion.descriptor.texture : await processScalarTextureAsync(`${material.name} occlusion`, occlusion);
389
+ material.useAmbientInGrayScale = true;
390
+ }
391
+ if (opacity) {
392
+ if (base &&
393
+ material.albedoTexture &&
394
+ opacity.descriptor === base.descriptor &&
395
+ opacity.channel === 3 /* TextureOutputChannel.A */ &&
396
+ opacity.descriptor.scale[3 /* TextureOutputChannel.A */] === 1 &&
397
+ opacity.descriptor.bias[3 /* TextureOutputChannel.A */] === 0) {
398
+ material.albedoTexture.hasAlpha = true;
399
+ material.useAlphaFromAlbedoTexture = true;
400
+ }
401
+ else {
402
+ const direct = opacity.channel === 3 /* TextureOutputChannel.A */ && opacity.descriptor.scale[3 /* TextureOutputChannel.A */] === 1 && opacity.descriptor.bias[3 /* TextureOutputChannel.A */] === 0;
403
+ material.opacityTexture = direct ? opacity.descriptor.texture : await processScalarTextureAsync(`${material.name} opacity`, opacity);
404
+ material.opacityTexture.gammaSpace = direct ? opacity.descriptor.texture.gammaSpace : false;
405
+ material.opacityTexture.getAlphaFromRGB = !direct;
406
+ }
407
+ }
408
+ const doubleSidedVariant = doubleSidedMaterials.get(bindings.id);
409
+ if (doubleSidedVariant) {
410
+ doubleSidedVariant.albedoColor.copyFrom(material.albedoColor);
411
+ doubleSidedVariant.albedoTexture = material.albedoTexture;
412
+ doubleSidedVariant.emissiveColor.copyFrom(material.emissiveColor);
413
+ doubleSidedVariant.emissiveTexture = material.emissiveTexture;
414
+ doubleSidedVariant.bumpTexture = material.bumpTexture;
415
+ doubleSidedVariant.metallic = material.metallic;
416
+ doubleSidedVariant.roughness = material.roughness;
417
+ doubleSidedVariant.metallicTexture = material.metallicTexture;
418
+ doubleSidedVariant.microSurfaceTexture = material.microSurfaceTexture;
419
+ doubleSidedVariant.ambientTexture = material.ambientTexture;
420
+ doubleSidedVariant.opacityTexture = material.opacityTexture;
421
+ doubleSidedVariant.alpha = material.alpha;
422
+ doubleSidedVariant.useAlphaFromAlbedoTexture = material.useAlphaFromAlbedoTexture;
423
+ doubleSidedVariant.useRoughnessFromMetallicTextureAlpha = material.useRoughnessFromMetallicTextureAlpha;
424
+ doubleSidedVariant.useRoughnessFromMetallicTextureGreen = material.useRoughnessFromMetallicTextureGreen;
425
+ doubleSidedVariant.useMetallnessFromMetallicTextureBlue = material.useMetallnessFromMetallicTextureBlue;
426
+ doubleSidedVariant.useAmbientOcclusionFromMetallicTextureRed = material.useAmbientOcclusionFromMetallicTextureRed;
427
+ doubleSidedVariant.useAmbientInGrayScale = material.useAmbientInGrayScale;
428
+ }
429
+ };
140
430
  try {
141
431
  const previousBlockEntityCollection = scene._blockEntityCollection;
142
432
  if (!addToScene) {
@@ -163,6 +453,9 @@ export async function materializeCommandBuffers(scene, commandBuffer, dataBuffer
163
453
  }
164
454
  case 2 /* Command.Texture */: {
165
455
  const id = payload.u32();
456
+ if (textures.has(id)) {
457
+ throw new Error(`Duplicate USD texture ${id}.`);
458
+ }
166
459
  const nameOffset = payload.u32();
167
460
  const nameLength = payload.u32();
168
461
  const mime = mimeType(payload.u32());
@@ -172,9 +465,19 @@ export async function materializeCommandBuffers(scene, commandBuffer, dataBuffer
172
465
  const transformOffset = payload.u32();
173
466
  const wrapU = payload.u32();
174
467
  const wrapV = payload.u32();
468
+ const sourceColorSpace = payload.u32();
469
+ const valueTransformOffset = payload.u32();
175
470
  assertRange(dataBuffer, transformOffset, 5, 4, "texture transform");
471
+ assertRange(dataBuffer, valueTransformOffset, 8, 4, "texture value transform");
176
472
  assertRange(dataBuffer, imageOffset, imageLength, 1, "texture image");
473
+ if (sourceColorSpace < 0 /* USDTextureColorSpace.Auto */ || sourceColorSpace > 2 /* USDTextureColorSpace.SRGB */) {
474
+ throw new Error(`Invalid USD texture color space ${sourceColorSpace}.`);
475
+ }
177
476
  const transform = new Float32Array(dataBuffer, transformOffset, 5);
477
+ const valueTransform = new Float32Array(dataBuffer, valueTransformOffset, 8);
478
+ if (![...transform, ...valueTransform].every(Number.isFinite)) {
479
+ throw new Error(`USD texture ${id} has a non-finite transform.`);
480
+ }
178
481
  const bytes = new Uint8Array(dataBuffer, imageOffset, imageLength);
179
482
  const url = URL.createObjectURL(new Blob([bytes], { type: mime }));
180
483
  textureUrls.add(url);
@@ -202,7 +505,14 @@ export async function materializeCommandBuffers(scene, commandBuffer, dataBuffer
202
505
  texture.wAng = -transform[4];
203
506
  texture.wrapU = wrapMode(wrapU);
204
507
  texture.wrapV = wrapMode(wrapV);
205
- textures.set(id, texture);
508
+ texture.gammaSpace = sourceColorSpace !== 1 /* USDTextureColorSpace.Raw */;
509
+ textures.set(id, {
510
+ id,
511
+ texture,
512
+ sourceColorSpace,
513
+ scale: valueTransform.subarray(0, 4),
514
+ bias: valueTransform.subarray(4, 8),
515
+ });
206
516
  break;
207
517
  }
208
518
  case 3 /* Command.Material */: {
@@ -216,15 +526,8 @@ export async function materializeCommandBuffers(scene, commandBuffer, dataBuffer
216
526
  const normalScale = payload.f32();
217
527
  const alphaCutoff = payload.f32();
218
528
  const flags = payload.u32();
219
- const baseTexture = payload.u32();
220
- const opacityTexture = payload.u32();
221
- const normalTexture = payload.u32();
222
- const ormTexture = payload.u32();
223
- const emissiveTexture = payload.u32();
224
- const opacityChannel = payload.u32();
225
- const roughnessChannel = payload.u32();
226
- const metallicChannel = payload.u32();
227
- const occlusionChannel = payload.u32();
529
+ const textureIds = Array.from({ length: 7 }, () => payload.u32());
530
+ const textureChannels = Array.from({ length: 7 }, () => payload.u32());
228
531
  assertRange(dataBuffer, baseOffset, 4, 4, "material base color");
229
532
  assertRange(dataBuffer, emissiveOffset, 3, 4, "material emissive color");
230
533
  const base = new Float32Array(dataBuffer, baseOffset, 4);
@@ -248,40 +551,18 @@ export async function materializeCommandBuffers(scene, commandBuffer, dataBuffer
248
551
  material.transparencyMode = 1;
249
552
  material.alphaCutOff = alphaCutoff;
250
553
  }
251
- if (baseTexture !== MISSING_OFFSET) {
252
- material.albedoTexture = textures.get(baseTexture) ?? null;
253
- if (material.albedoTexture && opacityTexture === MISSING_OFFSET && flags & 4 /* MaterialFlags.AlphaBlend */) {
254
- material.albedoTexture.hasAlpha = true;
255
- material.useAlphaFromAlbedoTexture = true;
256
- }
257
- }
258
- if (opacityTexture !== MISSING_OFFSET) {
259
- material.opacityTexture = textures.get(opacityTexture) ?? null;
260
- if (material.opacityTexture) {
261
- material.opacityTexture.gammaSpace = false;
262
- material.opacityTexture.getAlphaFromRGB = opacityChannel !== 3;
263
- }
264
- }
265
- if (normalTexture !== MISSING_OFFSET) {
266
- material.bumpTexture = textures.get(normalTexture) ?? null;
267
- if (material.bumpTexture) {
268
- material.bumpTexture.gammaSpace = false;
269
- material.bumpTexture.level = normalScale;
270
- }
271
- }
272
- if (ormTexture !== MISSING_OFFSET) {
273
- material.metallicTexture = textures.get(ormTexture) ?? null;
274
- if (material.metallicTexture) {
275
- material.metallicTexture.gammaSpace = false;
276
- material.useRoughnessFromMetallicTextureAlpha = roughnessChannel === 3;
277
- material.useRoughnessFromMetallicTextureGreen = roughnessChannel === 1;
278
- material.useMetallnessFromMetallicTextureBlue = metallicChannel === 2;
279
- material.useAmbientOcclusionFromMetallicTextureRed = occlusionChannel === 0;
280
- }
281
- }
282
- if (emissiveTexture !== MISSING_OFFSET) {
283
- material.emissiveTexture = textures.get(emissiveTexture) ?? null;
284
- }
554
+ materialTextureBindings.push({
555
+ id,
556
+ material,
557
+ normalScale,
558
+ base: binding(textureIds[0], textureChannels[0], "base-color texture"),
559
+ opacity: binding(textureIds[1], textureChannels[1], "opacity texture"),
560
+ normal: binding(textureIds[2], textureChannels[2], "normal texture"),
561
+ metallic: binding(textureIds[3], textureChannels[3], "metallic texture"),
562
+ roughness: binding(textureIds[4], textureChannels[4], "roughness texture"),
563
+ occlusion: binding(textureIds[5], textureChannels[5], "occlusion texture"),
564
+ emissive: binding(textureIds[6], textureChannels[6], "emissive texture"),
565
+ });
285
566
  materials.set(id, material);
286
567
  break;
287
568
  }
@@ -317,19 +598,20 @@ export async function materializeCommandBuffers(scene, commandBuffer, dataBuffer
317
598
  const skeleton = new Skeleton(stringAt(dataBuffer, nameOffset, nameLength), `usd-skeleton-${id}`, scene);
318
599
  trackAsset(container.skeletons, skeleton);
319
600
  const jointView = new DataView(dataBuffer);
320
- assertRange(dataBuffer, jointsOffset, jointCount * 5, 4, "skeleton joints");
601
+ assertRange(dataBuffer, jointsOffset, jointCount * 6, 4, "skeleton joints");
321
602
  const created = [];
322
603
  for (let index = 0; index < jointCount; ++index) {
323
- const offset = jointsOffset + index * 20;
604
+ const offset = jointsOffset + index * 24;
324
605
  const parentIndex = jointView.getUint32(offset, true);
325
606
  const boneId = jointView.getUint32(offset + 4, true);
326
607
  const jointNameOffset = jointView.getUint32(offset + 8, true);
327
608
  const jointNameLength = jointView.getUint32(offset + 12, true);
328
- const matrixOffset = jointView.getUint32(offset + 16, true);
609
+ const restMatrixOffset = jointView.getUint32(offset + 16, true);
610
+ const bindMatrixOffset = jointView.getUint32(offset + 20, true);
329
611
  if (parentIndex !== MISSING_OFFSET && parentIndex >= index) {
330
612
  throw new Error(`Skeleton ${id} has an invalid parent joint index.`);
331
613
  }
332
- const bone = new Bone(stringAt(dataBuffer, jointNameOffset, jointNameLength), skeleton, parentIndex === MISSING_OFFSET ? null : created[parentIndex], matrixAt(dataBuffer, matrixOffset), matrixAt(dataBuffer, matrixOffset), undefined, index);
614
+ const bone = new Bone(stringAt(dataBuffer, jointNameOffset, jointNameLength), skeleton, parentIndex === MISSING_OFFSET ? null : created[parentIndex], matrixAt(dataBuffer, restMatrixOffset), matrixAt(dataBuffer, restMatrixOffset), matrixAt(dataBuffer, bindMatrixOffset), index);
333
615
  created.push(bone);
334
616
  bones.set(boneId, bone);
335
617
  }
@@ -439,6 +721,41 @@ export async function materializeCommandBuffers(scene, commandBuffer, dataBuffer
439
721
  meshes.set(id, mesh);
440
722
  break;
441
723
  }
724
+ case 12 /* Command.MorphTarget */: {
725
+ const id = payload.u32();
726
+ const meshId = payload.u32();
727
+ const nameOffset = payload.u32();
728
+ const nameLength = payload.u32();
729
+ const vertexCount = payload.u32();
730
+ const positionsOffset = payload.u32();
731
+ const normalsOffset = payload.u32();
732
+ const influence = payload.f32();
733
+ const mesh = meshes.get(meshId);
734
+ if (!mesh) {
735
+ throw new Error(`Morph target references missing mesh ${meshId}.`);
736
+ }
737
+ if (morphTargets.has(id) || vertexCount !== mesh.getTotalVertices() || !Number.isFinite(influence)) {
738
+ throw new Error(`Morph target ${id} has invalid metadata.`);
739
+ }
740
+ assertRange(dataBuffer, positionsOffset, vertexCount * 3, 4, "morph target positions");
741
+ let manager = morphTargetManagers.get(meshId);
742
+ if (!manager) {
743
+ manager = new MorphTargetManager(scene, mesh.name);
744
+ manager.areUpdatesFrozen = true;
745
+ trackAsset(container.morphTargetManagers, manager);
746
+ morphTargetManagers.set(meshId, manager);
747
+ }
748
+ const target = new MorphTarget(stringAt(dataBuffer, nameOffset, nameLength), influence, scene, manager);
749
+ target.id = `usd-morph-target-${id}`;
750
+ target.setPositions(new Float32Array(dataBuffer, positionsOffset, vertexCount * 3));
751
+ if (normalsOffset !== MISSING_OFFSET) {
752
+ assertRange(dataBuffer, normalsOffset, vertexCount * 3, 4, "morph target normals");
753
+ target.setNormals(new Float32Array(dataBuffer, normalsOffset, vertexCount * 3));
754
+ }
755
+ manager.addTarget(target);
756
+ morphTargets.set(id, target);
757
+ break;
758
+ }
442
759
  case 10 /* Command.AnalyticPrimitive */: {
443
760
  const id = payload.u32();
444
761
  const nodeId = payload.u32();
@@ -525,11 +842,32 @@ export async function materializeCommandBuffers(scene, commandBuffer, dataBuffer
525
842
  if (!source) {
526
843
  throw new Error(`Instance references missing mesh ${sourceId}.`);
527
844
  }
845
+ if (thinInstanceSources.has(sourceId)) {
846
+ throw new Error(`Mesh ${sourceId} cannot mix classic and thin instances.`);
847
+ }
848
+ classicInstanceSources.add(sourceId);
528
849
  const instance = source.createInstance(stringAt(dataBuffer, nameOffset, nameLength));
529
850
  trackAsset(container.meshes, instance);
530
851
  instance.parent = nodes.get(nodeId) ?? root ?? null;
531
852
  break;
532
853
  }
854
+ case 11 /* Command.ThinInstances */: {
855
+ const sourceId = payload.u32();
856
+ const transformsOffset = payload.u32();
857
+ const instanceCount = payload.u32();
858
+ const source = meshes.get(sourceId);
859
+ if (!source) {
860
+ throw new Error(`Thin instances reference missing mesh ${sourceId}.`);
861
+ }
862
+ if (thinInstanceSources.has(sourceId) || classicInstanceSources.has(sourceId)) {
863
+ throw new Error(`Mesh ${sourceId} has duplicate or mixed thin instances.`);
864
+ }
865
+ assertRange(dataBuffer, transformsOffset, instanceCount * 16, 4, "thin instance transforms");
866
+ source.thinInstanceSetBuffer("matrix", new Float32Array(dataBuffer, transformsOffset, instanceCount * 16), 16, true);
867
+ source.thinInstanceEnablePicking = true;
868
+ thinInstanceSources.add(sourceId);
869
+ break;
870
+ }
533
871
  case 9 /* Command.Animation */: {
534
872
  const targetKind = payload.u32();
535
873
  const targetId = payload.u32();
@@ -539,20 +877,25 @@ export async function materializeCommandBuffers(scene, commandBuffer, dataBuffer
539
877
  const timesOffset = payload.u32();
540
878
  const valuesOffset = payload.u32();
541
879
  const stride = payload.u32();
542
- if (targetKind !== 0 /* AnimationTarget.Node */ && targetKind !== 1 /* AnimationTarget.Bone */) {
880
+ if (targetKind !== 0 /* AnimationTarget.Node */ && targetKind !== 1 /* AnimationTarget.Bone */ && targetKind !== 2 /* AnimationTarget.MorphTarget */) {
543
881
  throw new Error(`Invalid animation target kind ${targetKind}.`);
544
882
  }
545
- const expectedStride = property === 0 /* AnimationProperty.Position */ || property === 2 /* AnimationProperty.Scaling */
546
- ? 3
547
- : property === 1 /* AnimationProperty.RotationQuaternion */
548
- ? 4
549
- : property === 3 /* AnimationProperty.Matrix */
550
- ? 16
551
- : 0;
883
+ if ((targetKind === 2 /* AnimationTarget.MorphTarget */) !== (property === 4 /* AnimationProperty.Influence */)) {
884
+ throw new Error(`Invalid animation property ${property} for target kind ${targetKind}.`);
885
+ }
886
+ const expectedStride = property === 4 /* AnimationProperty.Influence */
887
+ ? 1
888
+ : property === 0 /* AnimationProperty.Position */ || property === 2 /* AnimationProperty.Scaling */
889
+ ? 3
890
+ : property === 1 /* AnimationProperty.RotationQuaternion */
891
+ ? 4
892
+ : property === 3 /* AnimationProperty.Matrix */
893
+ ? 16
894
+ : 0;
552
895
  if (stride !== expectedStride) {
553
896
  throw new Error(`Invalid animation value stride ${stride} for property ${property}.`);
554
897
  }
555
- const target = targetKind === 0 /* AnimationTarget.Node */ ? nodes.get(targetId) : bones.get(targetId);
898
+ const target = targetKind === 0 /* AnimationTarget.Node */ ? nodes.get(targetId) : targetKind === 1 /* AnimationTarget.Bone */ ? bones.get(targetId) : morphTargets.get(targetId);
556
899
  if (!target) {
557
900
  break;
558
901
  }
@@ -562,14 +905,18 @@ export async function materializeCommandBuffers(scene, commandBuffer, dataBuffer
562
905
  ? "rotationQuaternion"
563
906
  : property === 2 /* AnimationProperty.Scaling */
564
907
  ? "scaling"
565
- : targetKind === 0 /* AnimationTarget.Node */
566
- ? NODE_MATRIX_PROPERTY
567
- : "_matrix";
568
- const dataType = property === 1 /* AnimationProperty.RotationQuaternion */
569
- ? Animation.ANIMATIONTYPE_QUATERNION
570
- : property === 3 /* AnimationProperty.Matrix */
571
- ? Animation.ANIMATIONTYPE_MATRIX
572
- : Animation.ANIMATIONTYPE_VECTOR3;
908
+ : property === 4 /* AnimationProperty.Influence */
909
+ ? "influence"
910
+ : targetKind === 0 /* AnimationTarget.Node */
911
+ ? NODE_MATRIX_PROPERTY
912
+ : "_matrix";
913
+ const dataType = property === 4 /* AnimationProperty.Influence */
914
+ ? Animation.ANIMATIONTYPE_FLOAT
915
+ : property === 1 /* AnimationProperty.RotationQuaternion */
916
+ ? Animation.ANIMATIONTYPE_QUATERNION
917
+ : property === 3 /* AnimationProperty.Matrix */
918
+ ? Animation.ANIMATIONTYPE_MATRIX
919
+ : Animation.ANIMATIONTYPE_VECTOR3;
573
920
  const animation = new Animation(`USD ${propertyName}`, propertyName, timeCodesPerSecond, dataType, Animation.ANIMATIONLOOPMODE_CYCLE);
574
921
  assertRange(dataBuffer, timesOffset, keyCount, 4, "animation times");
575
922
  assertRange(dataBuffer, valuesOffset, keyCount * stride, 4, "animation values");
@@ -581,7 +928,9 @@ export async function materializeCommandBuffers(scene, commandBuffer, dataBuffer
581
928
  ? Quaternion.FromArray(values, index * stride)
582
929
  : dataType === Animation.ANIMATIONTYPE_MATRIX
583
930
  ? Matrix.FromArray(values, index * stride)
584
- : Vector3.FromArray(values, index * stride),
931
+ : dataType === Animation.ANIMATIONTYPE_FLOAT
932
+ ? values[index * stride]
933
+ : Vector3.FromArray(values, index * stride),
585
934
  })));
586
935
  let group = animationGroups.get(trackIndex);
587
936
  if (!group) {
@@ -594,46 +943,35 @@ export async function materializeCommandBuffers(scene, commandBuffer, dataBuffer
594
943
  }
595
944
  }
596
945
  }
946
+ for (const [meshId, manager] of morphTargetManagers) {
947
+ manager.areUpdatesFrozen = false;
948
+ if (!manager.isUsingTextureForTargets && manager.numTargets <= MorphTargetManager.MaxActiveMorphTargetsInVertexAttributeMode) {
949
+ manager.optimizeInfluencers = false;
950
+ manager.numMaxInfluencers = manager.numTargets;
951
+ }
952
+ meshes.get(meshId).morphTargetManager = manager;
953
+ }
597
954
  }
598
955
  finally {
599
956
  if (!addToScene) {
600
957
  scene._blockEntityCollection = previousBlockEntityCollection;
601
958
  }
602
959
  }
603
- const texturesLoaded = Promise.all(textureLoads);
604
- if (signal) {
605
- let onAbort;
606
- const aborted = new Promise((_resolve, reject) => {
607
- onAbort = () => reject(signal.reason instanceof Error ? signal.reason : new Error("USD materialization was aborted."));
608
- if (signal.aborted) {
609
- onAbort();
610
- }
611
- else {
612
- signal.addEventListener("abort", onAbort, { once: true });
613
- }
614
- });
615
- try {
616
- await Promise.race([texturesLoaded, aborted]);
617
- signal.throwIfAborted();
618
- }
619
- finally {
620
- if (onAbort) {
621
- signal.removeEventListener("abort", onAbort);
622
- }
623
- }
624
- }
625
- else {
626
- await texturesLoaded;
627
- }
960
+ await awaitAbortableAsync(Promise.all(textureLoads), signal);
961
+ await awaitAbortableAsync(Promise.all(materialTextureBindings.map(async (bindings) => {
962
+ await applyMaterialTextureBindingsAsync(bindings);
963
+ })), signal);
628
964
  for (const { node, parentId } of pendingParents) {
629
965
  node.parent = nodes.get(parentId) ?? root ?? null;
630
966
  }
631
967
  return { container, materializeMs: performance.now() - started };
632
968
  }
633
969
  catch (error) {
970
+ rollingBack = true;
634
971
  // Decode callbacks can arrive after rollback; observe their rejections without
635
972
  // delaying cancellation on an image load that may never finish.
636
973
  void Promise.allSettled(textureLoads);
974
+ void Promise.allSettled(processedTextures.values());
637
975
  container.dispose();
638
976
  for (const url of textureUrls) {
639
977
  URL.revokeObjectURL(url);