@babylonjs/loaders 9.25.0 → 9.26.0

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 (42) hide show
  1. package/SPLAT/gaussianSplattingStream.d.ts +31 -0
  2. package/SPLAT/gaussianSplattingStream.js +49 -0
  3. package/SPLAT/gaussianSplattingStream.js.map +1 -1
  4. package/USD/index.d.ts +2 -0
  5. package/USD/index.js +4 -0
  6. package/USD/index.js.map +1 -0
  7. package/USD/pure.d.ts +3 -0
  8. package/USD/pure.js +5 -0
  9. package/USD/pure.js.map +1 -0
  10. package/USD/usdCommandProtocol.d.ts +67 -0
  11. package/USD/usdCommandProtocol.js +151 -0
  12. package/USD/usdCommandProtocol.js.map +1 -0
  13. package/USD/usdFileLoader.d.ts +6 -0
  14. package/USD/usdFileLoader.js +9 -0
  15. package/USD/usdFileLoader.js.map +1 -0
  16. package/USD/usdFileLoader.metadata.d.ts +20 -0
  17. package/USD/usdFileLoader.metadata.js +18 -0
  18. package/USD/usdFileLoader.metadata.js.map +1 -0
  19. package/USD/usdFileLoader.pure.d.ts +102 -0
  20. package/USD/usdFileLoader.pure.js +339 -0
  21. package/USD/usdFileLoader.pure.js.map +1 -0
  22. package/USD/usdFileLoader.types.d.ts +11 -0
  23. package/USD/usdFileLoader.types.js +2 -0
  24. package/USD/usdFileLoader.types.js.map +1 -0
  25. package/USD/usdLoadingOptions.d.ts +123 -0
  26. package/USD/usdLoadingOptions.js +3 -0
  27. package/USD/usdLoadingOptions.js.map +1 -0
  28. package/USD/usdSceneMaterializer.d.ts +9 -0
  29. package/USD/usdSceneMaterializer.js +644 -0
  30. package/USD/usdSceneMaterializer.js.map +1 -0
  31. package/USD/usdWorkerMessages.d.ts +57 -0
  32. package/USD/usdWorkerMessages.js +3 -0
  33. package/USD/usdWorkerMessages.js.map +1 -0
  34. package/dynamic.js +10 -0
  35. package/dynamic.js.map +1 -1
  36. package/index.d.ts +1 -0
  37. package/index.js +1 -0
  38. package/index.js.map +1 -1
  39. package/package.json +4 -3
  40. package/pure.d.ts +1 -0
  41. package/pure.js +1 -0
  42. package/pure.js.map +1 -1
@@ -0,0 +1,644 @@
1
+ /* eslint-disable @typescript-eslint/naming-convention */
2
+ import { Animation } from "@babylonjs/core/Animations/animation.pure.js";
3
+ import { AnimationGroup } from "@babylonjs/core/Animations/animationGroup.pure.js";
4
+ import { AbstractAssetContainer, AssetContainer } from "@babylonjs/core/assetContainer.js";
5
+ import { Bone } from "@babylonjs/core/Bones/bone.js";
6
+ import { Skeleton } from "@babylonjs/core/Bones/skeleton.js";
7
+ import { Color3 } from "@babylonjs/core/Maths/math.color.pure.js";
8
+ import { Matrix, Quaternion, Vector3 } from "@babylonjs/core/Maths/math.vector.pure.js";
9
+ import { Material } from "@babylonjs/core/Materials/material.pure.js";
10
+ import { MultiMaterial } from "@babylonjs/core/Materials/multiMaterial.pure.js";
11
+ import { PBRMaterial } from "@babylonjs/core/Materials/PBR/pbrMaterial.pure.js";
12
+ import { Texture } from "@babylonjs/core/Materials/Textures/texture.pure.js";
13
+ import { CreateBox } from "@babylonjs/core/Meshes/Builders/boxBuilder.pure.js";
14
+ import { CreateCylinder } from "@babylonjs/core/Meshes/Builders/cylinderBuilder.pure.js";
15
+ import { CreateSphere } from "@babylonjs/core/Meshes/Builders/sphereBuilder.pure.js";
16
+ import { Mesh } from "@babylonjs/core/Meshes/mesh.pure.js";
17
+ import { SubMesh } from "@babylonjs/core/Meshes/subMesh.js";
18
+ import { TransformNode } from "@babylonjs/core/Meshes/transformNode.pure.js";
19
+ import { VertexData } from "@babylonjs/core/Meshes/mesh.vertexData.js";
20
+ import { MISSING_OFFSET, PayloadReader, readCommands, } from "./usdCommandProtocol.js";
21
+ class DirectAssetContainer extends AbstractAssetContainer {
22
+ dispose() {
23
+ for (const animationGroup of this.animationGroups.splice(0)) {
24
+ animationGroup.dispose();
25
+ }
26
+ for (const mesh of this.meshes.splice(0)) {
27
+ mesh.dispose();
28
+ }
29
+ for (const skeleton of this.skeletons.splice(0)) {
30
+ skeleton.dispose();
31
+ }
32
+ for (const multiMaterial of this.multiMaterials.splice(0)) {
33
+ multiMaterial.dispose();
34
+ }
35
+ for (const material of this.materials.splice(0)) {
36
+ material.dispose();
37
+ }
38
+ for (const geometry of this.geometries.splice(0)) {
39
+ geometry.dispose();
40
+ }
41
+ for (const transformNode of this.transformNodes.splice(0)) {
42
+ transformNode.dispose();
43
+ }
44
+ for (const texture of this.textures.splice(0)) {
45
+ texture.dispose();
46
+ }
47
+ this.rootNodes.length = 0;
48
+ }
49
+ }
50
+ const decoder = new TextDecoder();
51
+ const NODE_MATRIX_PROPERTY = "__babylonUsdLocalMatrix";
52
+ function assertRange(data, offset, count, bytesPerElement, label) {
53
+ if (!Number.isInteger(offset) ||
54
+ !Number.isInteger(count) ||
55
+ offset < 0 ||
56
+ count < 0 ||
57
+ offset % Math.min(bytesPerElement, 4) !== 0 ||
58
+ count > Math.floor((data.byteLength - offset) / bytesPerElement)) {
59
+ throw new Error(`Invalid ${label} range in OpenUSD Babylon data buffer.`);
60
+ }
61
+ }
62
+ function stringAt(data, offset, length) {
63
+ assertRange(data, offset, length, 1, "string");
64
+ return decoder.decode(new Uint8Array(data, offset, length));
65
+ }
66
+ function matrixAt(data, offset) {
67
+ assertRange(data, offset, 16, 4, "matrix");
68
+ const values = new Float32Array(data, offset, 16);
69
+ return Matrix.FromValues(values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8], values[9], values[10], values[11], values[12], values[13], values[14], values[15]);
70
+ }
71
+ function mimeType(value) {
72
+ switch (value) {
73
+ case 2:
74
+ return "image/jpeg";
75
+ case 3:
76
+ return "image/bmp";
77
+ case 4:
78
+ return "image/webp";
79
+ default:
80
+ return "image/png";
81
+ }
82
+ }
83
+ function wrapMode(value) {
84
+ switch (value) {
85
+ case 0:
86
+ return Texture.CLAMP_ADDRESSMODE;
87
+ case 1:
88
+ return Texture.WRAP_ADDRESSMODE;
89
+ case 2:
90
+ return Texture.MIRROR_ADDRESSMODE;
91
+ default:
92
+ throw new Error(`Invalid texture wrap mode ${value}.`);
93
+ }
94
+ }
95
+ export async function materializeCommandBuffers(scene, commandBuffer, dataBuffer, addToScene, signal) {
96
+ signal?.throwIfAborted();
97
+ const started = performance.now();
98
+ const commands = readCommands(commandBuffer);
99
+ const container = addToScene ? new DirectAssetContainer() : new AssetContainer(scene);
100
+ const nodes = new Map();
101
+ const pendingParents = [];
102
+ const textures = new Map();
103
+ const materials = new Map();
104
+ const doubleSidedMaterials = new Map();
105
+ const skeletons = new Map();
106
+ const bones = new Map();
107
+ const geometries = new Map();
108
+ const meshes = new Map();
109
+ const animationGroups = new Map();
110
+ const textureLoads = [];
111
+ const textureUrls = new Set();
112
+ const assetContainer = container instanceof AssetContainer ? container : undefined;
113
+ let root;
114
+ let timeCodesPerSecond = 24;
115
+ const trackAsset = (assets, asset) => {
116
+ assets.push(asset);
117
+ if (assetContainer) {
118
+ asset._parentContainer = assetContainer;
119
+ }
120
+ };
121
+ const applyMeshOrientation = (mesh, flags) => {
122
+ const sourceIsRightHanded = !(flags & 2 /* MeshFlags.LeftHanded */);
123
+ mesh.sideOrientation = scene.useRightHandedSystem === sourceIsRightHanded ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation;
124
+ };
125
+ const materialForMesh = (id, doubleSided) => {
126
+ const material = materials.get(id);
127
+ if (!material || !doubleSided || !material.backFaceCulling) {
128
+ return material ?? null;
129
+ }
130
+ let variant = doubleSidedMaterials.get(id);
131
+ if (!variant) {
132
+ variant = material.clone(`${material.name} (double-sided)`);
133
+ trackAsset(container.materials, variant);
134
+ variant.backFaceCulling = false;
135
+ variant.twoSidedLighting = true;
136
+ doubleSidedMaterials.set(id, variant);
137
+ }
138
+ return variant;
139
+ };
140
+ try {
141
+ const previousBlockEntityCollection = scene._blockEntityCollection;
142
+ if (!addToScene) {
143
+ scene._blockEntityCollection = true;
144
+ }
145
+ try {
146
+ for (const command of commands) {
147
+ const payload = new PayloadReader(commandBuffer, command.payloadOffset, command.payloadLength);
148
+ switch (command.opcode) {
149
+ case 1 /* Command.Scene */: {
150
+ const zUp = payload.u32() === 1;
151
+ const metersPerUnit = payload.f32();
152
+ timeCodesPerSecond = payload.f32() || 24;
153
+ root = new TransformNode("USD Root", scene);
154
+ trackAsset(container.transformNodes, root);
155
+ container.rootNodes.push(root);
156
+ root.rotationQuaternion = zUp ? Quaternion.FromArray([-0.7071068, 0, 0, 0.7071068]) : Quaternion.Identity();
157
+ root.scaling.copyFrom(scene.useRightHandedSystem
158
+ ? new Vector3(metersPerUnit, metersPerUnit, metersPerUnit)
159
+ : zUp
160
+ ? new Vector3(metersPerUnit, -metersPerUnit, metersPerUnit)
161
+ : new Vector3(metersPerUnit, metersPerUnit, -metersPerUnit));
162
+ break;
163
+ }
164
+ case 2 /* Command.Texture */: {
165
+ const id = payload.u32();
166
+ const nameOffset = payload.u32();
167
+ const nameLength = payload.u32();
168
+ const mime = mimeType(payload.u32());
169
+ const imageOffset = payload.u32();
170
+ const imageLength = payload.u32();
171
+ const coordinatesIndex = payload.u32();
172
+ const transformOffset = payload.u32();
173
+ const wrapU = payload.u32();
174
+ const wrapV = payload.u32();
175
+ assertRange(dataBuffer, transformOffset, 5, 4, "texture transform");
176
+ assertRange(dataBuffer, imageOffset, imageLength, 1, "texture image");
177
+ const transform = new Float32Array(dataBuffer, transformOffset, 5);
178
+ const bytes = new Uint8Array(dataBuffer, imageOffset, imageLength);
179
+ const url = URL.createObjectURL(new Blob([bytes], { type: mime }));
180
+ textureUrls.add(url);
181
+ let resolveLoad;
182
+ let rejectLoad;
183
+ const loaded = new Promise((resolve, reject) => {
184
+ resolveLoad = resolve;
185
+ rejectLoad = reject;
186
+ });
187
+ textureLoads.push(loaded);
188
+ const texture = new Texture(url, scene, false, false, Texture.TRILINEAR_SAMPLINGMODE, resolveLoad, (message, exception) => {
189
+ URL.revokeObjectURL(url);
190
+ rejectLoad(exception instanceof Error ? exception : new Error(message || `Could not load texture '${url}'.`));
191
+ });
192
+ trackAsset(container.textures, texture);
193
+ texture.onDisposeObservable.addOnce(() => URL.revokeObjectURL(url));
194
+ texture.name = stringAt(dataBuffer, nameOffset, nameLength);
195
+ texture.coordinatesIndex = coordinatesIndex;
196
+ texture.uScale = transform[0];
197
+ texture.vScale = transform[1];
198
+ texture.uRotationCenter = 0;
199
+ texture.vRotationCenter = 0;
200
+ texture.uOffset = transform[2] - transform[1] * Math.sin(transform[4]);
201
+ texture.vOffset = 1 - transform[1] * Math.cos(transform[4]) - transform[3];
202
+ texture.wAng = -transform[4];
203
+ texture.wrapU = wrapMode(wrapU);
204
+ texture.wrapV = wrapMode(wrapV);
205
+ textures.set(id, texture);
206
+ break;
207
+ }
208
+ case 3 /* Command.Material */: {
209
+ const id = payload.u32();
210
+ const nameOffset = payload.u32();
211
+ const nameLength = payload.u32();
212
+ const baseOffset = payload.u32();
213
+ const emissiveOffset = payload.u32();
214
+ const metallic = payload.f32();
215
+ const roughness = payload.f32();
216
+ const normalScale = payload.f32();
217
+ const alphaCutoff = payload.f32();
218
+ 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();
228
+ assertRange(dataBuffer, baseOffset, 4, 4, "material base color");
229
+ assertRange(dataBuffer, emissiveOffset, 3, 4, "material emissive color");
230
+ const base = new Float32Array(dataBuffer, baseOffset, 4);
231
+ const emissive = new Float32Array(dataBuffer, emissiveOffset, 3);
232
+ const material = new PBRMaterial(stringAt(dataBuffer, nameOffset, nameLength), scene);
233
+ trackAsset(container.materials, material);
234
+ material.id = `usd-material-${id}`;
235
+ material.albedoColor = new Color3(base[0], base[1], base[2]);
236
+ material.alpha = base[3];
237
+ material.metallic = metallic;
238
+ material.roughness = roughness;
239
+ material.emissiveColor = new Color3(emissive[0], emissive[1], emissive[2]);
240
+ const doubleSided = Boolean(flags & 1 /* MaterialFlags.DoubleSided */);
241
+ material.backFaceCulling = !doubleSided;
242
+ material.twoSidedLighting = doubleSided;
243
+ material.unlit = Boolean(flags & 2 /* MaterialFlags.Unlit */);
244
+ if (flags & 4 /* MaterialFlags.AlphaBlend */) {
245
+ material.transparencyMode = 2;
246
+ }
247
+ if (alphaCutoff > 0) {
248
+ material.transparencyMode = 1;
249
+ material.alphaCutOff = alphaCutoff;
250
+ }
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
+ }
285
+ materials.set(id, material);
286
+ break;
287
+ }
288
+ case 4 /* Command.TransformNode */: {
289
+ const id = payload.u32();
290
+ const parentId = payload.u32();
291
+ const nameOffset = payload.u32();
292
+ const nameLength = payload.u32();
293
+ const matrixOffset = payload.u32();
294
+ const node = new TransformNode(stringAt(dataBuffer, nameOffset, nameLength), scene);
295
+ trackAsset(container.transformNodes, node);
296
+ node.setPreTransformMatrix(matrixAt(dataBuffer, matrixOffset));
297
+ Object.defineProperty(node, NODE_MATRIX_PROPERTY, {
298
+ configurable: true,
299
+ get: () => node.getPivotMatrix(),
300
+ set: (matrix) => node.setPreTransformMatrix(matrix),
301
+ });
302
+ nodes.set(id, node);
303
+ if (parentId === MISSING_OFFSET) {
304
+ node.parent = root ?? null;
305
+ }
306
+ else {
307
+ pendingParents.push({ node, parentId });
308
+ }
309
+ break;
310
+ }
311
+ case 5 /* Command.Skeleton */: {
312
+ const id = payload.u32();
313
+ const nameOffset = payload.u32();
314
+ const nameLength = payload.u32();
315
+ const jointCount = payload.u32();
316
+ const jointsOffset = payload.u32();
317
+ const skeleton = new Skeleton(stringAt(dataBuffer, nameOffset, nameLength), `usd-skeleton-${id}`, scene);
318
+ trackAsset(container.skeletons, skeleton);
319
+ const jointView = new DataView(dataBuffer);
320
+ assertRange(dataBuffer, jointsOffset, jointCount * 5, 4, "skeleton joints");
321
+ const created = [];
322
+ for (let index = 0; index < jointCount; ++index) {
323
+ const offset = jointsOffset + index * 20;
324
+ const parentIndex = jointView.getUint32(offset, true);
325
+ const boneId = jointView.getUint32(offset + 4, true);
326
+ const jointNameOffset = jointView.getUint32(offset + 8, true);
327
+ const jointNameLength = jointView.getUint32(offset + 12, true);
328
+ const matrixOffset = jointView.getUint32(offset + 16, true);
329
+ if (parentIndex !== MISSING_OFFSET && parentIndex >= index) {
330
+ throw new Error(`Skeleton ${id} has an invalid parent joint index.`);
331
+ }
332
+ const bone = new Bone(stringAt(dataBuffer, jointNameOffset, jointNameLength), skeleton, parentIndex === MISSING_OFFSET ? null : created[parentIndex], matrixAt(dataBuffer, matrixOffset), matrixAt(dataBuffer, matrixOffset), undefined, index);
333
+ created.push(bone);
334
+ bones.set(boneId, bone);
335
+ }
336
+ skeletons.set(id, skeleton);
337
+ break;
338
+ }
339
+ case 6 /* Command.Geometry */: {
340
+ const id = payload.u32();
341
+ geometries.set(id, {
342
+ vertexCount: payload.u32(),
343
+ indexCount: payload.u32(),
344
+ flags: payload.u32(),
345
+ positions: payload.u32(),
346
+ normals: payload.u32(),
347
+ tangents: payload.u32(),
348
+ uv0: payload.u32(),
349
+ colors: payload.u32(),
350
+ joints0: payload.u32(),
351
+ weights0: payload.u32(),
352
+ joints1: payload.u32(),
353
+ weights1: payload.u32(),
354
+ indices: payload.u32(),
355
+ influences: payload.u32(),
356
+ });
357
+ break;
358
+ }
359
+ case 7 /* Command.Mesh */: {
360
+ const id = payload.u32();
361
+ const nodeId = payload.u32();
362
+ const geometryId = payload.u32();
363
+ const materialId = payload.u32();
364
+ const nameOffset = payload.u32();
365
+ const nameLength = payload.u32();
366
+ const flags = payload.u32();
367
+ const skeletonId = payload.u32();
368
+ const submeshesOffset = payload.u32();
369
+ const submeshCount = payload.u32();
370
+ const descriptor = geometries.get(geometryId);
371
+ if (!descriptor) {
372
+ throw new Error(`Mesh ${id} references missing geometry ${geometryId}.`);
373
+ }
374
+ const mesh = new Mesh(stringAt(dataBuffer, nameOffset, nameLength), scene);
375
+ trackAsset(container.meshes, mesh);
376
+ applyMeshOrientation(mesh, flags);
377
+ mesh.parent = nodes.get(nodeId) ?? root ?? null;
378
+ const vertexData = new VertexData();
379
+ assertRange(dataBuffer, descriptor.positions, descriptor.vertexCount * 3, 4, "positions");
380
+ vertexData.positions = new Float32Array(dataBuffer, descriptor.positions, descriptor.vertexCount * 3);
381
+ if (descriptor.flags & 1 /* GeometryFlags.Normals */) {
382
+ assertRange(dataBuffer, descriptor.normals, descriptor.vertexCount * 3, 4, "normals");
383
+ vertexData.normals = new Float32Array(dataBuffer, descriptor.normals, descriptor.vertexCount * 3);
384
+ }
385
+ if (descriptor.flags & 2 /* GeometryFlags.Tangents */) {
386
+ assertRange(dataBuffer, descriptor.tangents, descriptor.vertexCount * 4, 4, "tangents");
387
+ vertexData.tangents = new Float32Array(dataBuffer, descriptor.tangents, descriptor.vertexCount * 4);
388
+ }
389
+ if (descriptor.flags & 4 /* GeometryFlags.Uv0 */) {
390
+ assertRange(dataBuffer, descriptor.uv0, descriptor.vertexCount * 2, 4, "texture coordinates");
391
+ vertexData.uvs = new Float32Array(dataBuffer, descriptor.uv0, descriptor.vertexCount * 2);
392
+ }
393
+ if (descriptor.flags & 8 /* GeometryFlags.Colors */) {
394
+ assertRange(dataBuffer, descriptor.colors, descriptor.vertexCount * 4, 4, "vertex colors");
395
+ vertexData.colors = new Float32Array(dataBuffer, descriptor.colors, descriptor.vertexCount * 4);
396
+ }
397
+ if (descriptor.flags & 16 /* GeometryFlags.Skin0 */) {
398
+ assertRange(dataBuffer, descriptor.joints0, descriptor.vertexCount * 4, 2, "joint indices");
399
+ assertRange(dataBuffer, descriptor.weights0, descriptor.vertexCount * 4, 4, "joint weights");
400
+ vertexData.matricesIndices = Float32Array.from(new Uint16Array(dataBuffer, descriptor.joints0, descriptor.vertexCount * 4));
401
+ vertexData.matricesWeights = new Float32Array(dataBuffer, descriptor.weights0, descriptor.vertexCount * 4);
402
+ }
403
+ if (descriptor.flags & 32 /* GeometryFlags.Skin1 */) {
404
+ assertRange(dataBuffer, descriptor.joints1, descriptor.vertexCount * 4, 2, "extra joint indices");
405
+ assertRange(dataBuffer, descriptor.weights1, descriptor.vertexCount * 4, 4, "extra joint weights");
406
+ vertexData.matricesIndicesExtra = Float32Array.from(new Uint16Array(dataBuffer, descriptor.joints1, descriptor.vertexCount * 4));
407
+ vertexData.matricesWeightsExtra = new Float32Array(dataBuffer, descriptor.weights1, descriptor.vertexCount * 4);
408
+ }
409
+ assertRange(dataBuffer, descriptor.indices, descriptor.indexCount, 4, "indices");
410
+ vertexData.indices = new Uint32Array(dataBuffer, descriptor.indices, descriptor.indexCount);
411
+ vertexData.applyToMesh(mesh, true);
412
+ if (mesh.geometry) {
413
+ trackAsset(container.geometries, mesh.geometry);
414
+ }
415
+ mesh.numBoneInfluencers = Math.min(descriptor.influences, 8);
416
+ if (skeletonId !== MISSING_OFFSET) {
417
+ mesh.skeleton = skeletons.get(skeletonId) ?? null;
418
+ }
419
+ const submeshView = new DataView(dataBuffer);
420
+ assertRange(dataBuffer, submeshesOffset, submeshCount * 5, 4, "submeshes");
421
+ const doubleSided = Boolean(flags & 1 /* MeshFlags.DoubleSided */);
422
+ if (submeshCount === 1 && materialId !== MISSING_OFFSET) {
423
+ mesh.material = materialForMesh(materialId, doubleSided);
424
+ }
425
+ else {
426
+ const multi = new MultiMaterial(`${mesh.name} materials`, scene);
427
+ trackAsset(container.multiMaterials, multi);
428
+ for (let index = 0; index < submeshCount; ++index) {
429
+ const offset = submeshesOffset + index * 20;
430
+ multi.subMaterials.push(materialForMesh(submeshView.getUint32(offset, true), doubleSided));
431
+ }
432
+ mesh.material = multi;
433
+ }
434
+ mesh.releaseSubMeshes();
435
+ for (let index = 0; index < submeshCount; ++index) {
436
+ const offset = submeshesOffset + index * 20;
437
+ new SubMesh(index, submeshView.getUint32(offset + 12, true), submeshView.getUint32(offset + 16, true), submeshView.getUint32(offset + 4, true), submeshView.getUint32(offset + 8, true), mesh);
438
+ }
439
+ meshes.set(id, mesh);
440
+ break;
441
+ }
442
+ case 10 /* Command.AnalyticPrimitive */: {
443
+ const id = payload.u32();
444
+ const nodeId = payload.u32();
445
+ const type = payload.u32();
446
+ const materialId = payload.u32();
447
+ const nameOffset = payload.u32();
448
+ const nameLength = payload.u32();
449
+ const flags = payload.u32();
450
+ const axis = payload.u32();
451
+ const sizeOrRadius = payload.f32();
452
+ const height = payload.f32();
453
+ const tessellation = payload.u32();
454
+ const name = stringAt(dataBuffer, nameOffset, nameLength);
455
+ if (!Number.isFinite(sizeOrRadius) || sizeOrRadius <= 0) {
456
+ throw new Error(`Analytic primitive ${id} has an invalid size or radius.`);
457
+ }
458
+ if ((type === 2 /* AnalyticPrimitiveType.Cylinder */ || type === 3 /* AnalyticPrimitiveType.Cone */) && (!Number.isFinite(height) || height <= 0)) {
459
+ throw new Error(`Analytic primitive ${id} has an invalid height.`);
460
+ }
461
+ if (type !== 0 /* AnalyticPrimitiveType.Cube */ && (!Number.isInteger(tessellation) || tessellation < 3 || tessellation > 512)) {
462
+ throw new Error(`Analytic primitive ${id} has invalid tessellation.`);
463
+ }
464
+ let mesh;
465
+ switch (type) {
466
+ case 0 /* AnalyticPrimitiveType.Cube */:
467
+ mesh = CreateBox(name, { size: sizeOrRadius }, scene);
468
+ break;
469
+ case 1 /* AnalyticPrimitiveType.Sphere */:
470
+ mesh = CreateSphere(name, {
471
+ diameter: sizeOrRadius * 2,
472
+ segments: tessellation,
473
+ }, scene);
474
+ break;
475
+ case 2 /* AnalyticPrimitiveType.Cylinder */:
476
+ case 3 /* AnalyticPrimitiveType.Cone */:
477
+ mesh = CreateCylinder(name, {
478
+ height,
479
+ diameterTop: type === 3 /* AnalyticPrimitiveType.Cone */ ? 0 : sizeOrRadius * 2,
480
+ diameterBottom: sizeOrRadius * 2,
481
+ tessellation,
482
+ }, scene);
483
+ break;
484
+ default:
485
+ throw new Error(`Unsupported analytic primitive type ${type}.`);
486
+ }
487
+ trackAsset(container.meshes, mesh);
488
+ if (mesh.geometry) {
489
+ trackAsset(container.geometries, mesh.geometry);
490
+ }
491
+ // Babylon builders emit left-handed local winding. Reverse only for USD's
492
+ // default right-handed convention; normals already point outward.
493
+ if (!(flags & 2 /* MeshFlags.LeftHanded */)) {
494
+ const sourceIndices = mesh.getIndices();
495
+ if (!sourceIndices) {
496
+ throw new Error(`Analytic primitive ${id} has no generated indices.`);
497
+ }
498
+ const reversed = Array.from(sourceIndices);
499
+ for (let index = 0; index < reversed.length; index += 3) {
500
+ [reversed[index], reversed[index + 2]] = [reversed[index + 2], reversed[index]];
501
+ }
502
+ mesh.setIndices(reversed);
503
+ }
504
+ if (axis === 0 /* PrimitiveAxis.X */) {
505
+ mesh.rotationQuaternion = Quaternion.RotationAxis(new Vector3(0, 0, 1), -Math.PI / 2);
506
+ }
507
+ else if (axis === 2 /* PrimitiveAxis.Z */) {
508
+ mesh.rotationQuaternion = Quaternion.RotationAxis(new Vector3(1, 0, 0), Math.PI / 2);
509
+ }
510
+ else if (axis !== 1 /* PrimitiveAxis.Y */) {
511
+ throw new Error(`Unsupported analytic primitive axis ${axis}.`);
512
+ }
513
+ applyMeshOrientation(mesh, flags);
514
+ mesh.parent = nodes.get(nodeId) ?? root ?? null;
515
+ mesh.material = materialForMesh(materialId, Boolean(flags & 1 /* MeshFlags.DoubleSided */));
516
+ meshes.set(id, mesh);
517
+ break;
518
+ }
519
+ case 8 /* Command.Instance */: {
520
+ const sourceId = payload.u32();
521
+ const nodeId = payload.u32();
522
+ const nameOffset = payload.u32();
523
+ const nameLength = payload.u32();
524
+ const source = meshes.get(sourceId);
525
+ if (!source) {
526
+ throw new Error(`Instance references missing mesh ${sourceId}.`);
527
+ }
528
+ const instance = source.createInstance(stringAt(dataBuffer, nameOffset, nameLength));
529
+ trackAsset(container.meshes, instance);
530
+ instance.parent = nodes.get(nodeId) ?? root ?? null;
531
+ break;
532
+ }
533
+ case 9 /* Command.Animation */: {
534
+ const targetKind = payload.u32();
535
+ const targetId = payload.u32();
536
+ const property = payload.u32();
537
+ const trackIndex = payload.u32();
538
+ const keyCount = payload.u32();
539
+ const timesOffset = payload.u32();
540
+ const valuesOffset = payload.u32();
541
+ const stride = payload.u32();
542
+ if (targetKind !== 0 /* AnimationTarget.Node */ && targetKind !== 1 /* AnimationTarget.Bone */) {
543
+ throw new Error(`Invalid animation target kind ${targetKind}.`);
544
+ }
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;
552
+ if (stride !== expectedStride) {
553
+ throw new Error(`Invalid animation value stride ${stride} for property ${property}.`);
554
+ }
555
+ const target = targetKind === 0 /* AnimationTarget.Node */ ? nodes.get(targetId) : bones.get(targetId);
556
+ if (!target) {
557
+ break;
558
+ }
559
+ const propertyName = property === 0 /* AnimationProperty.Position */
560
+ ? "position"
561
+ : property === 1 /* AnimationProperty.RotationQuaternion */
562
+ ? "rotationQuaternion"
563
+ : property === 2 /* AnimationProperty.Scaling */
564
+ ? "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;
573
+ const animation = new Animation(`USD ${propertyName}`, propertyName, timeCodesPerSecond, dataType, Animation.ANIMATIONLOOPMODE_CYCLE);
574
+ assertRange(dataBuffer, timesOffset, keyCount, 4, "animation times");
575
+ assertRange(dataBuffer, valuesOffset, keyCount * stride, 4, "animation values");
576
+ const times = new Float32Array(dataBuffer, timesOffset, keyCount);
577
+ const values = new Float32Array(dataBuffer, valuesOffset, keyCount * stride);
578
+ animation.setKeys(Array.from({ length: keyCount }, (_, index) => ({
579
+ frame: times[index],
580
+ value: dataType === Animation.ANIMATIONTYPE_QUATERNION
581
+ ? Quaternion.FromArray(values, index * stride)
582
+ : dataType === Animation.ANIMATIONTYPE_MATRIX
583
+ ? Matrix.FromArray(values, index * stride)
584
+ : Vector3.FromArray(values, index * stride),
585
+ })));
586
+ let group = animationGroups.get(trackIndex);
587
+ if (!group) {
588
+ group = new AnimationGroup(`USD Animation ${trackIndex + 1}`, scene);
589
+ animationGroups.set(trackIndex, group);
590
+ trackAsset(container.animationGroups, group);
591
+ }
592
+ group.addTargetedAnimation(animation, target);
593
+ break;
594
+ }
595
+ }
596
+ }
597
+ }
598
+ finally {
599
+ if (!addToScene) {
600
+ scene._blockEntityCollection = previousBlockEntityCollection;
601
+ }
602
+ }
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
+ }
628
+ for (const { node, parentId } of pendingParents) {
629
+ node.parent = nodes.get(parentId) ?? root ?? null;
630
+ }
631
+ return { container, materializeMs: performance.now() - started };
632
+ }
633
+ catch (error) {
634
+ // Decode callbacks can arrive after rollback; observe their rejections without
635
+ // delaying cancellation on an image load that may never finish.
636
+ void Promise.allSettled(textureLoads);
637
+ container.dispose();
638
+ for (const url of textureUrls) {
639
+ URL.revokeObjectURL(url);
640
+ }
641
+ throw error;
642
+ }
643
+ }
644
+ //# sourceMappingURL=usdSceneMaterializer.js.map