three-usd-robot 0.6.0 → 0.8.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.
@@ -1,381 +1,6 @@
1
+ import { Quat, multiply, makeTranslation, makeRotationFromQuat, identity4, invert, makeEuler, DEG2RAD, makeRotationZ, makeRotationY, makeRotationX, fromUsdMatrix, makeScale, AssetPath, RAD2DEG, UsdMatrix } from './chunk-IYKPVUZ2.js';
1
2
  import { unzipSync } from 'fflate';
2
3
 
3
- // src/parser/ast.ts
4
- var Quat = class _Quat {
5
- constructor(real, imaginary) {
6
- this.real = real;
7
- this.imaginary = imaginary;
8
- }
9
- real;
10
- imaginary;
11
- /** Components in Three.js order `[x, y, z, w]`. */
12
- toXYZW() {
13
- return [this.imaginary[0], this.imaginary[1], this.imaginary[2], this.real];
14
- }
15
- static identity() {
16
- return new _Quat(1, [0, 0, 0]);
17
- }
18
- };
19
- var UsdMatrix = class _UsdMatrix {
20
- constructor(values, dim) {
21
- this.values = values;
22
- this.dim = dim;
23
- }
24
- values;
25
- dim;
26
- static identity4() {
27
- return new _UsdMatrix([
28
- 1,
29
- 0,
30
- 0,
31
- 0,
32
- 0,
33
- 1,
34
- 0,
35
- 0,
36
- 0,
37
- 0,
38
- 1,
39
- 0,
40
- 0,
41
- 0,
42
- 0,
43
- 1
44
- ], 4);
45
- }
46
- };
47
- var AssetPath = class {
48
- constructor(path) {
49
- this.path = path;
50
- }
51
- path;
52
- };
53
-
54
- // src/kinematics/transforms.ts
55
- var DEG2RAD = Math.PI / 180;
56
- var RAD2DEG = 180 / Math.PI;
57
- function identity4() {
58
- return [
59
- 1,
60
- 0,
61
- 0,
62
- 0,
63
- 0,
64
- 1,
65
- 0,
66
- 0,
67
- 0,
68
- 0,
69
- 1,
70
- 0,
71
- 0,
72
- 0,
73
- 0,
74
- 1
75
- ];
76
- }
77
- function multiply(a, b) {
78
- const a11 = a[0], a21 = a[1], a31 = a[2], a41 = a[3];
79
- const a12 = a[4], a22 = a[5], a32 = a[6], a42 = a[7];
80
- const a13 = a[8], a23 = a[9], a33 = a[10], a43 = a[11];
81
- const a14 = a[12], a24 = a[13], a34 = a[14], a44 = a[15];
82
- const b11 = b[0], b21 = b[1], b31 = b[2], b41 = b[3];
83
- const b12 = b[4], b22 = b[5], b32 = b[6], b42 = b[7];
84
- const b13 = b[8], b23 = b[9], b33 = b[10], b43 = b[11];
85
- const b14 = b[12], b24 = b[13], b34 = b[14], b44 = b[15];
86
- return [
87
- a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41,
88
- a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41,
89
- a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41,
90
- a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41,
91
- a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42,
92
- a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42,
93
- a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42,
94
- a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42,
95
- a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43,
96
- a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43,
97
- a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43,
98
- a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43,
99
- a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44,
100
- a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44,
101
- a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44,
102
- a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44
103
- ];
104
- }
105
- function multiplyAll(matrices) {
106
- let m = identity4();
107
- for (const next of matrices) m = multiply(m, next);
108
- return m;
109
- }
110
- function invert(m) {
111
- const n11 = m[0], n21 = m[1], n31 = m[2], n41 = m[3];
112
- const n12 = m[4], n22 = m[5], n32 = m[6], n42 = m[7];
113
- const n13 = m[8], n23 = m[9], n33 = m[10], n43 = m[11];
114
- const n14 = m[12], n24 = m[13], n34 = m[14], n44 = m[15];
115
- const t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44;
116
- const t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44;
117
- const t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44;
118
- const t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
119
- const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
120
- if (det === 0) throw new Error("cannot invert a singular matrix");
121
- const idet = 1 / det;
122
- return [
123
- t11 * idet,
124
- (n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44) * idet,
125
- (n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44) * idet,
126
- (n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43) * idet,
127
- t12 * idet,
128
- (n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44) * idet,
129
- (n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44) * idet,
130
- (n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43) * idet,
131
- t13 * idet,
132
- (n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44) * idet,
133
- (n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44) * idet,
134
- (n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43) * idet,
135
- t14 * idet,
136
- (n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34) * idet,
137
- (n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34) * idet,
138
- (n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33) * idet
139
- ];
140
- }
141
- function makeTranslation([x, y, z]) {
142
- return [
143
- 1,
144
- 0,
145
- 0,
146
- 0,
147
- 0,
148
- 1,
149
- 0,
150
- 0,
151
- 0,
152
- 0,
153
- 1,
154
- 0,
155
- x,
156
- y,
157
- z,
158
- 1
159
- ];
160
- }
161
- function makeScale([x, y, z]) {
162
- return [
163
- x,
164
- 0,
165
- 0,
166
- 0,
167
- 0,
168
- y,
169
- 0,
170
- 0,
171
- 0,
172
- 0,
173
- z,
174
- 0,
175
- 0,
176
- 0,
177
- 0,
178
- 1
179
- ];
180
- }
181
- function makeRotationX(rad) {
182
- const c = Math.cos(rad);
183
- const s = Math.sin(rad);
184
- return [
185
- 1,
186
- 0,
187
- 0,
188
- 0,
189
- 0,
190
- c,
191
- s,
192
- 0,
193
- 0,
194
- -s,
195
- c,
196
- 0,
197
- 0,
198
- 0,
199
- 0,
200
- 1
201
- ];
202
- }
203
- function makeRotationY(rad) {
204
- const c = Math.cos(rad);
205
- const s = Math.sin(rad);
206
- return [
207
- c,
208
- 0,
209
- -s,
210
- 0,
211
- 0,
212
- 1,
213
- 0,
214
- 0,
215
- s,
216
- 0,
217
- c,
218
- 0,
219
- 0,
220
- 0,
221
- 0,
222
- 1
223
- ];
224
- }
225
- function makeRotationZ(rad) {
226
- const c = Math.cos(rad);
227
- const s = Math.sin(rad);
228
- return [
229
- c,
230
- s,
231
- 0,
232
- 0,
233
- -s,
234
- c,
235
- 0,
236
- 0,
237
- 0,
238
- 0,
239
- 1,
240
- 0,
241
- 0,
242
- 0,
243
- 0,
244
- 1
245
- ];
246
- }
247
- function makeRotationFromQuat(q) {
248
- let x = q.imaginary[0];
249
- let y = q.imaginary[1];
250
- let z = q.imaginary[2];
251
- let w = q.real;
252
- const len = Math.hypot(x, y, z, w);
253
- if (len > 0 && Math.abs(len - 1) > 1e-9) {
254
- x /= len;
255
- y /= len;
256
- z /= len;
257
- w /= len;
258
- }
259
- const x2 = x + x, y2 = y + y, z2 = z + z;
260
- const xx = x * x2, xy = x * y2, xz = x * z2;
261
- const yy = y * y2, yz = y * z2, zz = z * z2;
262
- const wx = w * x2, wy = w * y2, wz = w * z2;
263
- return [
264
- 1 - (yy + zz),
265
- xy + wz,
266
- xz - wy,
267
- 0,
268
- xy - wz,
269
- 1 - (xx + zz),
270
- yz + wx,
271
- 0,
272
- xz + wy,
273
- yz - wx,
274
- 1 - (xx + yy),
275
- 0,
276
- 0,
277
- 0,
278
- 0,
279
- 1
280
- ];
281
- }
282
- function makeEuler(angles, order) {
283
- const perAxis = {
284
- X: makeRotationX(angles[0]),
285
- Y: makeRotationY(angles[1]),
286
- Z: makeRotationZ(angles[2])
287
- };
288
- let m = identity4();
289
- for (let i = order.length - 1; i >= 0; i--) {
290
- const axis = perAxis[order[i]];
291
- if (!axis)
292
- throw new Error(
293
- `invalid euler axis ${JSON.stringify(order[i])} in order ${JSON.stringify(order)}`
294
- );
295
- m = multiply(m, axis);
296
- }
297
- return m;
298
- }
299
- function fromUsdMatrix(m) {
300
- if (m.dim !== 4 || m.values.length !== 16) {
301
- throw new Error(`expected a 4x4 matrix but got dim=${m.dim}, length=${m.values.length}`);
302
- }
303
- return [...m.values];
304
- }
305
- function getTranslation(m) {
306
- return [m[12], m[13], m[14]];
307
- }
308
- function toUsdMatrix(m) {
309
- if (m.length !== 16) {
310
- throw new Error(`expected 16 matrix elements but got ${m.length}`);
311
- }
312
- return new UsdMatrix([...m], 4);
313
- }
314
- function decomposeRigid(m) {
315
- const position = [m[12], m[13], m[14]];
316
- const b0 = [m[0], m[1], m[2]];
317
- const b1 = [m[4], m[5], m[6]];
318
- const b2 = [m[8], m[9], m[10]];
319
- const EPS = 1e-6;
320
- const rigid = Math.abs(norm(b0) - 1) < EPS && Math.abs(norm(b1) - 1) < EPS && Math.abs(norm(b2) - 1) < EPS && Math.abs(dot(b0, b1)) < EPS && Math.abs(dot(b1, b2)) < EPS && Math.abs(dot(b0, b2)) < EPS && dot(cross(b0, b1), b2) > 0;
321
- const c0 = normalizeVec(b0);
322
- const c1 = normalizeVec(subVec(b1, scaleVec(c0, dot(c0, b1))));
323
- const c2 = cross(c0, c1);
324
- const r11 = c0[0], r12 = c1[0], r13 = c2[0];
325
- const r21 = c0[1], r22 = c1[1], r23 = c2[1];
326
- const r31 = c0[2], r32 = c1[2], r33 = c2[2];
327
- const trace = r11 + r22 + r33;
328
- let w;
329
- let x;
330
- let y;
331
- let z;
332
- if (trace > 0) {
333
- const s = 0.5 / Math.sqrt(trace + 1);
334
- w = 0.25 / s;
335
- x = (r32 - r23) * s;
336
- y = (r13 - r31) * s;
337
- z = (r21 - r12) * s;
338
- } else if (r11 > r22 && r11 > r33) {
339
- const s = 2 * Math.sqrt(1 + r11 - r22 - r33);
340
- w = (r32 - r23) / s;
341
- x = 0.25 * s;
342
- y = (r12 + r21) / s;
343
- z = (r13 + r31) / s;
344
- } else if (r22 > r33) {
345
- const s = 2 * Math.sqrt(1 + r22 - r11 - r33);
346
- w = (r13 - r31) / s;
347
- x = (r12 + r21) / s;
348
- y = 0.25 * s;
349
- z = (r23 + r32) / s;
350
- } else {
351
- const s = 2 * Math.sqrt(1 + r33 - r11 - r22);
352
- w = (r21 - r12) / s;
353
- x = (r13 + r31) / s;
354
- y = (r23 + r32) / s;
355
- z = 0.25 * s;
356
- }
357
- return { position, orientation: new Quat(w, [x, y, z]), rigid };
358
- }
359
- function dot(a, b) {
360
- return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
361
- }
362
- function norm(v) {
363
- return Math.hypot(v[0], v[1], v[2]);
364
- }
365
- function subVec(a, b) {
366
- return [a[0] - b[0], a[1] - b[1], a[2] - b[2]];
367
- }
368
- function scaleVec(v, s) {
369
- return [v[0] * s, v[1] * s, v[2] * s];
370
- }
371
- function normalizeVec(v) {
372
- const n = norm(v);
373
- return n > 0 ? scaleVec(v, 1 / n) : [1, 0, 0];
374
- }
375
- function cross(a, b) {
376
- return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];
377
- }
378
-
379
4
  // src/schemas/usdGeom.ts
380
5
  function isXform(prim) {
381
6
  return prim.GetTypeName() === "Xform";
@@ -386,6 +11,19 @@ function isScope(prim) {
386
11
  function isMesh(prim) {
387
12
  return prim.GetTypeName() === "Mesh";
388
13
  }
14
+ var SOLID_GPRIM_TYPES = /* @__PURE__ */ new Set([
15
+ "Cube",
16
+ "Sphere",
17
+ "Cylinder",
18
+ "Capsule",
19
+ "Cone"
20
+ ]);
21
+ function isSolidGprim(prim) {
22
+ return SOLID_GPRIM_TYPES.has(prim.GetTypeName());
23
+ }
24
+ function isRenderableGprim(prim) {
25
+ return isMesh(prim) || isSolidGprim(prim);
26
+ }
389
27
  function getPurpose(prim) {
390
28
  const v = prim.GetAttribute("purpose").Get();
391
29
  return typeof v === "string" ? v : "default";
@@ -394,6 +32,24 @@ function isNonVisualPurpose(prim) {
394
32
  const p = getPurpose(prim);
395
33
  return p === "guide" || p === "proxy";
396
34
  }
35
+ function getMaterialSubsets(meshPrim) {
36
+ const out = [];
37
+ for (const child of meshPrim.GetChildren()) {
38
+ if (child.GetTypeName() !== "GeomSubset") continue;
39
+ const elementType = child.GetAttribute("elementType").Get();
40
+ if (elementType !== void 0 && elementType !== "face") continue;
41
+ const family = child.GetAttribute("familyName").Get();
42
+ if (family !== void 0 && family !== "materialBind") continue;
43
+ const indices = child.GetAttribute("indices").Get();
44
+ if (!Array.isArray(indices)) continue;
45
+ const faces = [];
46
+ for (const i of indices) {
47
+ if (typeof i === "number") faces.push(i);
48
+ }
49
+ if (faces.length > 0) out.push({ prim: child, faces });
50
+ }
51
+ return out;
52
+ }
397
53
  function* iterDescendants(prim) {
398
54
  for (const child of prim.GetChildren()) {
399
55
  yield child;
@@ -407,6 +63,13 @@ function gatherMeshDescendants(prim) {
407
63
  }
408
64
  return paths;
409
65
  }
66
+ function gatherGprimDescendants(prim) {
67
+ const paths = [];
68
+ for (const d of iterDescendants(prim)) {
69
+ if (isRenderableGprim(d)) paths.push(d.GetPath());
70
+ }
71
+ return paths;
72
+ }
410
73
 
411
74
  // src/schemas/usdPhysics.ts
412
75
  var JOINT_TYPE_BY_SCHEMA = {
@@ -549,9 +212,7 @@ function computeLocalTransform(prim) {
549
212
  opName = opName.slice(INVERT_PREFIX.length);
550
213
  }
551
214
  const attr = prim.GetAttribute(opName);
552
- if (!attr.IsValid()) {
553
- throw new Error(`${prim.GetPath()}: xformOpOrder references missing op "${opName}"`);
554
- }
215
+ if (!attr.IsValid()) continue;
555
216
  const opValue = attr.Get();
556
217
  if (opValue === void 0) continue;
557
218
  let opMatrix = opMatrixFor(parseOpType(opName), opValue, `${prim.GetPath()}.${opName}`);
@@ -660,7 +321,7 @@ function resolveBoundMaterial(stage, prim) {
660
321
  if (!material) return void 0;
661
322
  const shader = findSurfaceShader(material);
662
323
  if (!shader) return void 0;
663
- const result = {};
324
+ const result = { name: material.GetName() };
664
325
  const color = firstColor(shader, DIFFUSE_INPUTS);
665
326
  if (color) result.color = color;
666
327
  const opacity = firstNumber(shader, OPACITY_INPUTS);
@@ -779,33 +440,6 @@ function firstNumber(shader, names) {
779
440
  return void 0;
780
441
  }
781
442
 
782
- // src/kinematics/sampling.ts
783
- function interpolate(channel, t) {
784
- const { times, values } = channel;
785
- const n = times.length;
786
- if (n === 0) return 0;
787
- if (t <= times[0]) return values[0];
788
- if (t >= times[n - 1]) return values[n - 1];
789
- let lo = 0;
790
- let hi = n - 1;
791
- while (lo < hi) {
792
- const mid = lo + hi >> 1;
793
- if (times[mid] <= t) lo = mid + 1;
794
- else hi = mid;
795
- }
796
- const i = lo - 1;
797
- const t0 = times[i];
798
- const t1 = times[i + 1];
799
- const span = t1 - t0;
800
- const f = span > 0 ? (t - t0) / span : 0;
801
- return values[i] + (values[i + 1] - values[i]) * f;
802
- }
803
- function channelFromSamples(samples) {
804
- const times = [...samples.keys()].sort((a, b) => a - b);
805
- const values = times.map((t) => samples.get(t) ?? 0);
806
- return { times, values };
807
- }
808
-
809
443
  // src/robot/buildKinematicTree.ts
810
444
  var WORLD = "";
811
445
  function buildKinematicTree(robot, options = {}) {
@@ -992,10 +626,12 @@ function buildLink(path, prim) {
992
626
  if (!prim) return { name, primPath: path, visualPrims: [] };
993
627
  const visualPrims = [];
994
628
  const collisionPrims = [];
995
- for (const meshPath of gatherMeshDescendants(prim)) {
629
+ for (const meshPath of gatherGprimDescendants(prim)) {
996
630
  const mp = prim.GetStage().GetPrimAtPath(meshPath);
997
- if (mp && (hasCollisionAPI(mp) || isNonVisualPurpose(mp))) collisionPrims.push(meshPath);
998
- else visualPrims.push(meshPath);
631
+ if (!mp) continue;
632
+ const nonVisual = isNonVisualPurpose(mp);
633
+ if (!nonVisual) visualPrims.push(meshPath);
634
+ if (nonVisual || hasCollisionAPI(mp)) collisionPrims.push(meshPath);
999
635
  }
1000
636
  const inertial = getMassProperties(prim);
1001
637
  const worldTransform = computeWorldTransform(prim);
@@ -1631,11 +1267,11 @@ function parseVariantSet(r) {
1631
1267
  const variants = {};
1632
1268
  while (!r.is("rbrace") && !r.atEnd()) {
1633
1269
  const variantName = r.expect("string").value;
1634
- if (r.is("lparen")) parseMetadataBlock(r);
1270
+ const metadata = r.is("lparen") ? parseMetadataBlock(r) : {};
1635
1271
  r.expect("lbrace");
1636
1272
  const body = parseBody(r);
1637
1273
  r.expect("rbrace");
1638
- variants[variantName] = { properties: body.properties, children: body.children };
1274
+ variants[variantName] = { properties: body.properties, children: body.children, metadata };
1639
1275
  }
1640
1276
  r.expect("rbrace");
1641
1277
  return { setName, variants };
@@ -1845,7 +1481,13 @@ function pushPrimBody(out, properties, children, variantSets, level) {
1845
1481
  for (const [setName, variants] of Object.entries(variantSets)) {
1846
1482
  out.push(`${pad}variantSet ${quoteString(setName)} = {`);
1847
1483
  for (const [variantName, content] of Object.entries(variants)) {
1848
- out.push(`${pad}${INDENT}${quoteString(variantName)} {`);
1484
+ const head = `${pad}${INDENT}${quoteString(variantName)}`;
1485
+ if (Object.keys(content.metadata).length > 0) {
1486
+ pushWithMetadata(out, head, content.metadata, level + 1);
1487
+ out.push(`${pad}${INDENT}{`);
1488
+ } else {
1489
+ out.push(`${head} {`);
1490
+ }
1849
1491
  pushPrimBody(out, content.properties, content.children, void 0, level + 2);
1850
1492
  out.push(`${pad}${INDENT}}`);
1851
1493
  }
@@ -2389,6 +2031,17 @@ var Stage = class _Stage {
2389
2031
  }
2390
2032
  };
2391
2033
 
2034
+ // src/usd/bytes.ts
2035
+ async function toBytes(data) {
2036
+ if (data instanceof Uint8Array) return data;
2037
+ if (ArrayBuffer.isView(data))
2038
+ return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
2039
+ if (typeof data.arrayBuffer === "function") {
2040
+ return new Uint8Array(await data.arrayBuffer());
2041
+ }
2042
+ return new Uint8Array(data);
2043
+ }
2044
+
2392
2045
  // src/usd/crate/lz4.ts
2393
2046
  var MAX_CHUNK_INPUT = 2113929216;
2394
2047
  function lz4DecompressBlock(src, dst) {
@@ -2510,6 +2163,8 @@ var CrateType = {
2510
2163
  Specifier: 42,
2511
2164
  Permission: 43,
2512
2165
  Variability: 44,
2166
+ VariantSelectionMap: 45,
2167
+ StringVector: 50,
2513
2168
  PayloadListOp: 55};
2514
2169
  var ListOpBits = {
2515
2170
  HasExplicit: 1 << 1,
@@ -2865,6 +2520,10 @@ var CrateReader = class {
2865
2520
  return this.readIndexVector(off, "token").items;
2866
2521
  case CrateType.PathVector:
2867
2522
  return this.readIndexVector(off, "path").items;
2523
+ case CrateType.StringVector:
2524
+ return this.readIndexVector(off, "string").items;
2525
+ case CrateType.VariantSelectionMap:
2526
+ return this.readVariantSelectionMap(off);
2868
2527
  default:
2869
2528
  return void 0;
2870
2529
  }
@@ -2931,6 +2590,24 @@ var CrateReader = class {
2931
2590
  }
2932
2591
  return out;
2933
2592
  }
2593
+ /**
2594
+ * Read an `SdfVariantSelectionMap`: `[u64 count]` then `count` pairs of
2595
+ * string indexes (`variantSetName → variantName`). Surfaces as a dictionary
2596
+ * so it maps straight onto the USDA `variants = { ... }` metadatum.
2597
+ */
2598
+ readVariantSelectionMap(off) {
2599
+ const count = this.u64(off);
2600
+ const strings = this.getStrings();
2601
+ const out = {};
2602
+ let p = off + 8;
2603
+ for (let i = 0; i < count; i++) {
2604
+ const key = this.getToken(strings[this.view.getUint32(p, true)] ?? 0);
2605
+ const value = this.getToken(strings[this.view.getUint32(p + 4, true)] ?? 0);
2606
+ if (key) out[key] = value;
2607
+ p += 8;
2608
+ }
2609
+ return out;
2610
+ }
2934
2611
  /** Read a `[u64 count][count × uint32|int32 index]` vector → resolved strings. */
2935
2612
  readIndexVector(off, kind) {
2936
2613
  const count = this.u64(off);
@@ -2938,7 +2615,7 @@ var CrateReader = class {
2938
2615
  const items = new Array(count);
2939
2616
  for (let i = 0; i < count; i++) {
2940
2617
  const idx = this.view.getInt32(p, true);
2941
- items[i] = kind === "token" ? this.getToken(idx) : this.getPaths()[idx] ?? "";
2618
+ items[i] = kind === "token" ? this.getToken(idx) : kind === "string" ? this.getToken(this.getStrings()[idx] ?? 0) : this.getPaths()[idx] ?? "";
2942
2619
  p += 4;
2943
2620
  }
2944
2621
  return { items, next: p };
@@ -3020,6 +2697,7 @@ var SPEC_PRIM = 6;
3020
2697
  var SPEC_PSEUDO_ROOT = 7;
3021
2698
  var SPEC_ATTRIBUTE = 1;
3022
2699
  var SPEC_RELATIONSHIP = 8;
2700
+ var SPEC_VARIANT = 10;
3023
2701
  var SPECIFIERS2 = ["def", "over", "class"];
3024
2702
  function crateToUsdaFile(crate) {
3025
2703
  const paths = crate.getPaths();
@@ -3034,8 +2712,26 @@ function crateToUsdaFile(crate) {
3034
2712
  return map;
3035
2713
  };
3036
2714
  const primByPath = /* @__PURE__ */ new Map();
2715
+ const variantByPath = /* @__PURE__ */ new Map();
3037
2716
  const rootPrims = [];
3038
2717
  let layerMetadata = {};
2718
+ const containerAt = (path) => {
2719
+ const prim = primByPath.get(path);
2720
+ if (prim) return prim;
2721
+ const cached = variantByPath.get(path);
2722
+ if (cached) return cached;
2723
+ const selection = variantNode(path);
2724
+ if (!selection) return void 0;
2725
+ const owner = primByPath.get(selection.owner);
2726
+ if (!owner) return void 0;
2727
+ owner.variantSets ??= {};
2728
+ owner.variantSets[selection.setName] ??= {};
2729
+ const set = owner.variantSets[selection.setName];
2730
+ set[selection.variantName] ??= { properties: [], children: [], metadata: {} };
2731
+ const content = set[selection.variantName];
2732
+ variantByPath.set(path, content);
2733
+ return content;
2734
+ };
3039
2735
  for (const spec of specs) {
3040
2736
  const path = paths[spec.pathIndex] ?? "";
3041
2737
  if (spec.specType === SPEC_PSEUDO_ROOT) {
@@ -3054,24 +2750,41 @@ function crateToUsdaFile(crate) {
3054
2750
  line: 0
3055
2751
  });
3056
2752
  }
2753
+ for (const spec of specs) {
2754
+ if (spec.specType !== SPEC_VARIANT) continue;
2755
+ const content = containerAt(paths[spec.pathIndex] ?? "");
2756
+ if (content)
2757
+ Object.assign(content.metadata, buildPrimMetadata(crate, fieldsOf(spec.fieldSetIndex)));
2758
+ }
3057
2759
  for (const spec of specs) {
3058
2760
  if (spec.specType !== SPEC_ATTRIBUTE && spec.specType !== SPEC_RELATIONSHIP) continue;
3059
2761
  const split = splitProperty(paths[spec.pathIndex] ?? "");
3060
2762
  if (!split) continue;
3061
- const prim = primByPath.get(split.primPath);
3062
- if (!prim) continue;
2763
+ const owner = containerAt(split.primPath);
2764
+ if (!owner) continue;
3063
2765
  const fm = fieldsOf(spec.fieldSetIndex);
3064
- prim.properties.push(
2766
+ owner.properties.push(
3065
2767
  spec.specType === SPEC_ATTRIBUTE ? buildAttribute(crate, split.propName, fm) : buildRelationship(crate, split.propName, fm)
3066
2768
  );
3067
2769
  }
3068
2770
  for (const [path, prim] of primByPath) {
3069
2771
  const parentPath = parentOf(path);
3070
2772
  if (parentPath === "/") rootPrims.push(prim);
3071
- else primByPath.get(parentPath)?.children.push(prim);
2773
+ else containerAt(parentPath)?.children.push(prim);
3072
2774
  }
3073
2775
  return { version: crate.version.join("."), metadata: layerMetadata, prims: rootPrims };
3074
2776
  }
2777
+ function variantNode(path) {
2778
+ if (!path.endsWith("}")) return null;
2779
+ const open = path.lastIndexOf("{");
2780
+ if (open < 0) return null;
2781
+ const selection = path.slice(open + 1, -1);
2782
+ const eq = selection.indexOf("=");
2783
+ if (eq < 0) return null;
2784
+ const variantName = selection.slice(eq + 1);
2785
+ if (variantName === "") return null;
2786
+ return { owner: path.slice(0, open), setName: selection.slice(0, eq), variantName };
2787
+ }
3075
2788
  function buildAttribute(crate, name, fm) {
3076
2789
  const defaultRep = fm.get("default");
3077
2790
  const rawType = asString(crate, fm.get("typeName")) ?? "";
@@ -3112,6 +2825,10 @@ function buildPrimMetadata(crate, fm) {
3112
2825
  if (Array.isArray(apiSchemas)) meta.apiSchemas = apiSchemas;
3113
2826
  const kind = asString(crate, fm.get("kind"));
3114
2827
  if (kind !== void 0) meta.kind = kind;
2828
+ const variants = fm.has("variantSelection") ? crate.getValue(fm.get("variantSelection")) : void 0;
2829
+ if (variants && typeof variants === "object" && !Array.isArray(variants)) {
2830
+ meta.variants = variants;
2831
+ }
3115
2832
  for (const key of ARC_FIELDS) {
3116
2833
  if (!fm.has(key)) continue;
3117
2834
  const arcs = crate.getValue(fm.get(key));
@@ -3121,6 +2838,11 @@ function buildPrimMetadata(crate, fm) {
3121
2838
  }
3122
2839
  function buildLayerMetadata(crate, fm) {
3123
2840
  const meta = {};
2841
+ const subLayers = fm.has("subLayers") ? crate.getValue(fm.get("subLayers")) : void 0;
2842
+ if (Array.isArray(subLayers)) {
2843
+ const paths = subLayers.filter((s) => typeof s === "string" && s.length > 0);
2844
+ if (paths.length > 0) meta.subLayers = paths.map((p) => new AssetPath(p));
2845
+ }
3124
2846
  const upAxis = asString(crate, fm.get("upAxis"));
3125
2847
  if (upAxis !== void 0) meta.upAxis = upAxis;
3126
2848
  const defaultPrim2 = asString(crate, fm.get("defaultPrim"));
@@ -3141,10 +2863,10 @@ function asNumber2(crate, rep) {
3141
2863
  }
3142
2864
  function splitProperty(path) {
3143
2865
  const slash = path.lastIndexOf("/");
3144
- const dot2 = path.indexOf(".", slash < 0 ? 0 : slash);
3145
- if (dot2 === -1) return null;
2866
+ const dot = path.indexOf(".", slash < 0 ? 0 : slash);
2867
+ if (dot === -1) return null;
3146
2868
  if (path.includes("[")) return null;
3147
- return { primPath: path.slice(0, dot2), propName: path.slice(dot2 + 1) };
2869
+ return { primPath: path.slice(0, dot), propName: path.slice(dot + 1) };
3148
2870
  }
3149
2871
  function parentOf(path) {
3150
2872
  const i = path.lastIndexOf("/");
@@ -3157,16 +2879,24 @@ function leaf(path) {
3157
2879
  // src/usd/composition.ts
3158
2880
  var ARC_KEYS = ["references", "payload", "payloads", "inherits", "specializes"];
3159
2881
  var STRIP_KEYS = [...ARC_KEYS, "variants", "variantSets"];
3160
- async function composeLayer(text, baseUrl, resolver, options = {}, stack = /* @__PURE__ */ new Set()) {
3161
- return composeFile(parseUsda(text), baseUrl, resolver, options, stack);
2882
+ async function composeLayer(text, baseUrl, resolver, options = {}, stack = /* @__PURE__ */ new Set(), cache = /* @__PURE__ */ new Map()) {
2883
+ return composeFile(parseUsda(text), baseUrl, resolver, options, stack, cache);
3162
2884
  }
3163
- async function composeFile(file, baseUrl, resolver, options = {}, stack = /* @__PURE__ */ new Set()) {
2885
+ async function composeFile(file, baseUrl, resolver, options = {}, stack = /* @__PURE__ */ new Set(), cache = /* @__PURE__ */ new Map()) {
3164
2886
  const warn = options.onWarn ?? (() => {
3165
2887
  });
3166
2888
  let weak = [];
3167
2889
  const subLayers = toArcs(file.metadata.subLayers);
3168
2890
  for (let i = subLayers.length - 1; i >= 0; i--) {
3169
- const sub = await loadExternalFile(subLayers[i], baseUrl, resolver, options, stack, warn);
2891
+ const sub = await loadExternalFile(
2892
+ subLayers[i],
2893
+ baseUrl,
2894
+ resolver,
2895
+ options,
2896
+ stack,
2897
+ warn,
2898
+ cache
2899
+ );
3170
2900
  if (sub) weak = mergePrimLists(weak, sub.prims);
3171
2901
  }
3172
2902
  const ctx = {
@@ -3176,7 +2906,8 @@ async function composeFile(file, baseUrl, resolver, options = {}, stack = /* @__
3176
2906
  warn,
3177
2907
  stack,
3178
2908
  index: buildPathIndex(file.prims),
3179
- resolving: /* @__PURE__ */ new Set()
2909
+ resolving: /* @__PURE__ */ new Set(),
2910
+ cache
3180
2911
  };
3181
2912
  const resolved = [];
3182
2913
  for (const prim of file.prims) resolved.push(await resolvePrim(prim, "", ctx));
@@ -3187,6 +2918,7 @@ async function resolvePrim(spec, parentPath, ctx) {
3187
2918
  const path = `${parentPath}/${spec.name}`;
3188
2919
  let properties = spec.properties;
3189
2920
  let children = spec.children;
2921
+ const variantArcs = [];
3190
2922
  const selection = spec.metadata.variants;
3191
2923
  if (spec.variantSets && isDictionary2(selection)) {
3192
2924
  for (const [setName, variantName] of Object.entries(selection)) {
@@ -3194,6 +2926,7 @@ async function resolvePrim(spec, parentPath, ctx) {
3194
2926
  if (!variant) continue;
3195
2927
  properties = mergeProperties(variant.properties, properties);
3196
2928
  children = mergePrimLists(variant.children, children);
2929
+ for (const key of ARC_KEYS) variantArcs.push(...toArcs(variant.metadata[key]));
3197
2930
  }
3198
2931
  }
3199
2932
  const resolvedChildren = [];
@@ -3207,7 +2940,7 @@ async function resolvePrim(spec, parentPath, ctx) {
3207
2940
  children: resolvedChildren,
3208
2941
  line: spec.line
3209
2942
  };
3210
- const arcs = ARC_KEYS.flatMap((k) => toArcs(spec.metadata[k]));
2943
+ const arcs = [...variantArcs, ...ARC_KEYS.flatMap((k) => toArcs(spec.metadata[k]))];
3211
2944
  let base = null;
3212
2945
  for (const arc of arcs) {
3213
2946
  const target = await loadReferencedPrim(arc, ctx, path);
@@ -3216,20 +2949,21 @@ async function resolvePrim(spec, parentPath, ctx) {
3216
2949
  return base ? mergePrim(base, local) : local;
3217
2950
  }
3218
2951
  async function loadReferencedPrim(arc, ctx, destPath) {
3219
- if (arc.assetPath) {
2952
+ if (arc.assetPath?.path) {
3220
2953
  const composed = await loadExternalFile(
3221
2954
  arc,
3222
2955
  ctx.baseUrl,
3223
2956
  ctx.resolver,
3224
2957
  ctx.options,
3225
2958
  ctx.stack,
3226
- ctx.warn
2959
+ ctx.warn,
2960
+ ctx.cache
3227
2961
  );
3228
2962
  if (!composed) return null;
3229
2963
  const target = arc.primPath ? findPrimByPath(composed, arc.primPath) : defaultPrim(composed, ctx.warn);
3230
2964
  if (!target) {
3231
2965
  ctx.warn(
3232
- `reference target ${arc.primPath ?? "(defaultPrim)"} not found in ${arc.assetPath.path}`
2966
+ `reference target ${arc.primPath ?? "(defaultPrim)"} not found in ${arc.assetPath?.path}`
3233
2967
  );
3234
2968
  return null;
3235
2969
  }
@@ -3255,9 +2989,10 @@ async function loadReferencedPrim(arc, ctx, destPath) {
3255
2989
  }
3256
2990
  return null;
3257
2991
  }
3258
- async function loadExternalFile(arc, baseUrl, resolver, options, stack, warn) {
3259
- if (!arc.assetPath) return null;
3260
- const url = resolver.resolve(arc.assetPath.path, baseUrl);
2992
+ async function loadExternalFile(arc, baseUrl, resolver, options, stack, warn, cache) {
2993
+ if (!arc.assetPath?.path) return null;
2994
+ const assetPath = arc.assetPath.path;
2995
+ const url = resolver.resolve(assetPath, baseUrl);
3261
2996
  if (stack.has(url)) {
3262
2997
  warn(`composition cycle detected at ${url}; skipping`);
3263
2998
  return null;
@@ -3266,18 +3001,31 @@ async function loadExternalFile(arc, baseUrl, resolver, options, stack, warn) {
3266
3001
  warn(`composition exceeded max depth at ${url}; skipping`);
3267
3002
  return null;
3268
3003
  }
3269
- let bytes;
3270
- try {
3271
- bytes = await fetchLayerBytes(resolver, url);
3272
- } catch (err) {
3273
- warn(`cannot resolve "${arc.assetPath.path}" -> ${url}: ${err.message}`);
3274
- return null;
3275
- }
3276
- const childStack = /* @__PURE__ */ new Set([...stack, url]);
3277
- if (CrateReader.isCrate(bytes)) {
3278
- return composeFile(crateToUsdaFile(new CrateReader(bytes)), url, resolver, options, childStack);
3279
- }
3280
- return composeLayer(new TextDecoder().decode(bytes), url, resolver, options, childStack);
3004
+ const cached = cache.get(url);
3005
+ if (cached) return cached;
3006
+ const pending = (async () => {
3007
+ let bytes;
3008
+ try {
3009
+ bytes = await fetchLayerBytes(resolver, url);
3010
+ } catch (err) {
3011
+ warn(`cannot resolve "${assetPath}" -> ${url}: ${err.message}`);
3012
+ return null;
3013
+ }
3014
+ const childStack = /* @__PURE__ */ new Set([...stack, url]);
3015
+ if (CrateReader.isCrate(bytes)) {
3016
+ return composeFile(
3017
+ crateToUsdaFile(new CrateReader(bytes)),
3018
+ url,
3019
+ resolver,
3020
+ options,
3021
+ childStack,
3022
+ cache
3023
+ );
3024
+ }
3025
+ return composeLayer(new TextDecoder().decode(bytes), url, resolver, options, childStack, cache);
3026
+ })();
3027
+ cache.set(url, pending);
3028
+ return pending;
3281
3029
  }
3282
3030
  async function fetchLayerBytes(resolver, url) {
3283
3031
  if (resolver.fetchBytes) return resolver.fetchBytes(url);
@@ -3426,6 +3174,12 @@ function stripKeys(meta, keys) {
3426
3174
  return out;
3427
3175
  }
3428
3176
  var USD_ENTRY = /\.(usda|usdc|usd)$/i;
3177
+ function isZip(bytes) {
3178
+ if (bytes.length < 4 || bytes[0] !== 80 || bytes[1] !== 75) return false;
3179
+ const a = bytes[2];
3180
+ const b = bytes[3];
3181
+ return a === 3 && b === 4 || a === 5 && b === 6 || a === 7 && b === 8;
3182
+ }
3429
3183
  function openUsdz(bytes) {
3430
3184
  const entries = unzipSync(bytes);
3431
3185
  const names = Object.keys(entries);
@@ -3455,6 +3209,6 @@ function openUsdz(bytes) {
3455
3209
  return { rootEntry, resolver };
3456
3210
  }
3457
3211
 
3458
- export { ARTICULATION_ROOT_API, AssetPath, Attribute, COLLISION_API, CrateReader, DEFAULT_METERS_PER_UNIT, DEG2RAD, DefaultAssetResolver, Layer, MASS_API, MESH_COLLISION_API, PHYSICS_MATERIAL_API, ParseError, Prim, Quat, RAD2DEG, RIGID_BODY_API, Relationship, Stage, TokenizeError, UsdMatrix, buildKinematicTree, channelFromSamples, composeFile, composeLayer, computeLocalTransform, computeWorldTransform, crateToUsdaFile, createMemoryResolver, decomposeRigid, driveKindFor, extractRobotDescription, fromUsdMatrix, gatherMeshDescendants, getJointAxis, getJointBodies, getJointDrive, getJointLimits, getJointLocalFrame, getJointStatePosition, getJointType, getMassProperties, getTranslation, hasArticulationRootAPI, hasCollisionAPI, hasRigidBodyAPI, identity4, interpolate, invert, isMesh, isNonVisualPurpose, isScope, isXform, iterDescendants, joinPosix, jointValueFromSI, jointValueToSI, makeEuler, makeRotationFromQuat, makeRotationX, makeRotationY, makeRotationZ, makeScale, makeTranslation, multiply, multiplyAll, normalizeJointLimits, openUsdz, parseOpType, parseUsda, refineJointType, resolveBoundMaterial, serializeUsda, toUsdMatrix, tokenize };
3459
- //# sourceMappingURL=chunk-4MEZM763.js.map
3460
- //# sourceMappingURL=chunk-4MEZM763.js.map
3212
+ export { ARTICULATION_ROOT_API, Attribute, COLLISION_API, CrateReader, DEFAULT_METERS_PER_UNIT, DefaultAssetResolver, Layer, MASS_API, MESH_COLLISION_API, PHYSICS_MATERIAL_API, ParseError, Prim, RIGID_BODY_API, Relationship, Stage, TokenizeError, buildKinematicTree, composeFile, composeLayer, computeLocalTransform, computeWorldTransform, crateToUsdaFile, createMemoryResolver, driveKindFor, extractRobotDescription, gatherGprimDescendants, gatherMeshDescendants, getJointAxis, getJointBodies, getJointDrive, getJointLimits, getJointLocalFrame, getJointStatePosition, getJointType, getMassProperties, getMaterialSubsets, hasArticulationRootAPI, hasCollisionAPI, hasRigidBodyAPI, isMesh, isNonVisualPurpose, isRenderableGprim, isScope, isSolidGprim, isXform, isZip, iterDescendants, joinPosix, jointValueFromSI, jointValueToSI, normalizeJointLimits, openUsdz, parseOpType, parseUsda, refineJointType, resolveBoundMaterial, serializeUsda, toBytes, tokenize };
3213
+ //# sourceMappingURL=chunk-PHHMWMCA.js.map
3214
+ //# sourceMappingURL=chunk-PHHMWMCA.js.map