three-usd-robot 0.9.0 → 0.10.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,4 +1,4 @@
1
- import { Quat, multiply, makeTranslation, makeRotationFromQuat, identity4, invert, makeEuler, DEG2RAD, makeRotationZ, makeRotationY, makeRotationX, fromUsdMatrix, makeScale, AssetPath, RAD2DEG, UsdMatrix } from './chunk-IYKPVUZ2.js';
1
+ import { Quat, multiply, makeTranslation, makeRotationFromQuat, identity4, invert, makeEuler, DEG2RAD, makeRotationZ, makeRotationY, makeRotationX, fromUsdMatrix, makeScale, RAD2DEG, AssetPath, UsdMatrix } from './chunk-IYKPVUZ2.js';
2
2
  import { unzipSync } from 'fflate';
3
3
 
4
4
  // src/schemas/usdGeom.ts
@@ -21,8 +21,22 @@ var SOLID_GPRIM_TYPES = /* @__PURE__ */ new Set([
21
21
  function isSolidGprim(prim) {
22
22
  return SOLID_GPRIM_TYPES.has(prim.GetTypeName());
23
23
  }
24
+ function isPoints(prim) {
25
+ return prim.GetTypeName() === "Points";
26
+ }
27
+ function isBasisCurves(prim) {
28
+ return prim.GetTypeName() === "BasisCurves";
29
+ }
30
+ var UNSUPPORTED_GPRIM_TYPES = /* @__PURE__ */ new Set([
31
+ "NurbsCurves",
32
+ "HermiteCurves",
33
+ "NurbsPatch"
34
+ ]);
35
+ function isUnsupportedGprim(prim) {
36
+ return UNSUPPORTED_GPRIM_TYPES.has(prim.GetTypeName());
37
+ }
24
38
  function isRenderableGprim(prim) {
25
- return isMesh(prim) || isSolidGprim(prim);
39
+ return isMesh(prim) || isSolidGprim(prim) || isPoints(prim) || isBasisCurves(prim);
26
40
  }
27
41
  function getPurpose(prim) {
28
42
  const v = prim.GetAttribute("purpose").Get();
@@ -335,6 +349,18 @@ function resolveBoundMaterial(stage, prim) {
335
349
  const emissive = firstColor(shader, EMISSIVE_INPUTS);
336
350
  if (emissive && shader.GetAttribute("inputs:enable_emission").Get() !== false) {
337
351
  result.emissiveColor = emissive;
352
+ const intensity = firstNumber(shader, ["inputs:emissive_intensity"]);
353
+ if (intensity !== void 0) result.emissiveIntensity = intensity;
354
+ }
355
+ const ior = firstNumber(shader, ["inputs:ior"]);
356
+ if (ior !== void 0) result.ior = ior;
357
+ const clearcoat = firstNumber(shader, ["inputs:clearcoat"]);
358
+ if (clearcoat !== void 0) result.clearcoat = clearcoat;
359
+ const clearcoatRoughness = firstNumber(shader, ["inputs:clearcoatRoughness"]);
360
+ if (clearcoatRoughness !== void 0) result.clearcoatRoughness = clearcoatRoughness;
361
+ if (shader.GetAttribute("inputs:useSpecularWorkflow").Get() === 1) {
362
+ const specular = firstColor(shader, ["inputs:specularColor"]);
363
+ if (specular) result.specularColor = specular;
338
364
  }
339
365
  const colorTex = findTexture(shader, TEXTURE_LOOKUPS.color);
340
366
  if (colorTex !== void 0) result.colorTexture = colorTex;
@@ -350,12 +376,23 @@ function resolveBoundMaterial(stage, prim) {
350
376
  if (aoTex !== void 0) result.occlusionTexture = aoTex;
351
377
  const emissiveTex = findTexture(shader, TEXTURE_LOOKUPS.emissive);
352
378
  if (emissiveTex !== void 0) result.emissiveTexture = emissiveTex;
379
+ const ormFile = shader.GetAttribute("inputs:ORM_texture").Get();
380
+ if (shader.GetAttribute("inputs:enable_ORM_texture").Get() === true && ormFile instanceof AssetPath && ormFile.path) {
381
+ const transform = mdlTextureTransform(shader);
382
+ const orm = { path: ormFile.path, ...transform ? { transform } : {} };
383
+ result.occlusionTexture = { ...orm, outputChannel: "r" };
384
+ result.roughnessTexture = { ...orm, outputChannel: "g" };
385
+ result.metalnessTexture = { ...orm, outputChannel: "b" };
386
+ }
353
387
  return result;
354
388
  }
355
389
  function findTexture(shader, lookup) {
356
390
  for (const name of lookup.direct) {
357
391
  const v = shader.GetAttribute(name).Get();
358
- if (v instanceof AssetPath && v.path) return { path: v.path };
392
+ if (v instanceof AssetPath && v.path) {
393
+ const transform = mdlTextureTransform(shader);
394
+ return { path: v.path, ...transform ? { transform } : {} };
395
+ }
359
396
  }
360
397
  for (const name of lookup.surface) {
361
398
  const conn = shader.GetAttribute(name).GetConnections()[0];
@@ -363,10 +400,40 @@ function findTexture(shader, lookup) {
363
400
  const texPrim = shader.GetStage().GetPrimAtPath(conn.split(".")[0]);
364
401
  if (!texPrim) continue;
365
402
  const file = texPrim.GetAttribute("inputs:file").Get();
366
- if (file instanceof AssetPath && file.path) return readUvTexture(texPrim, file.path);
403
+ if (file instanceof AssetPath && file.path) {
404
+ const tex = readUvTexture(texPrim, file.path);
405
+ const channel = outputChannelOf(conn);
406
+ if (channel) tex.outputChannel = channel;
407
+ return tex;
408
+ }
367
409
  }
368
410
  return void 0;
369
411
  }
412
+ function outputChannelOf(connection) {
413
+ const m = /\.outputs:(\w+)$/.exec(connection);
414
+ switch (m?.[1]) {
415
+ case "r":
416
+ case "g":
417
+ case "b":
418
+ case "a":
419
+ return m[1];
420
+ case "rgb":
421
+ case "rgba":
422
+ return "rgb";
423
+ default:
424
+ return void 0;
425
+ }
426
+ }
427
+ function mdlTextureTransform(shader) {
428
+ const transform = {};
429
+ const translation = numArray(shader, "inputs:texture_translate", 2);
430
+ if (translation) transform.translation = translation;
431
+ const scale = numArray(shader, "inputs:texture_scale", 2);
432
+ if (scale) transform.scale = scale;
433
+ const rotation = shader.GetAttribute("inputs:texture_rotate").Get();
434
+ if (typeof rotation === "number") transform.rotation = rotation;
435
+ return Object.keys(transform).length > 0 ? transform : void 0;
436
+ }
370
437
  var WRAP_VALUES = /* @__PURE__ */ new Set(["repeat", "clamp", "mirror", "black"]);
371
438
  function readUvTexture(texPrim, path) {
372
439
  const tex = { path };
@@ -378,23 +445,39 @@ function readUvTexture(texPrim, path) {
378
445
  if (scale) tex.scale = scale;
379
446
  const bias = numArray(texPrim, "inputs:bias", 4);
380
447
  if (bias) tex.bias = bias;
381
- const transform = readTransform2d(texPrim);
382
- if (transform) tex.transform = transform;
448
+ const sourceColorSpace = texPrim.GetAttribute("inputs:sourceColorSpace").Get();
449
+ if (sourceColorSpace === "raw" || sourceColorSpace === "sRGB" || sourceColorSpace === "auto") {
450
+ tex.sourceColorSpace = sourceColorSpace;
451
+ }
452
+ const st = readStChain(texPrim);
453
+ if (st.transform) tex.transform = st.transform;
454
+ if (st.uvSet) tex.uvSet = st.uvSet;
383
455
  return tex;
384
456
  }
385
- function readTransform2d(texPrim) {
386
- const conn = texPrim.GetAttribute("inputs:st").GetConnections()[0];
387
- if (!conn) return void 0;
388
- const node = texPrim.GetStage().GetPrimAtPath(conn.split(".")[0]);
389
- if (!node || node.GetAttribute("info:id").Get() !== "UsdTransform2d") return void 0;
390
- const transform = {};
391
- const translation = numArray(node, "inputs:translation", 2);
392
- if (translation) transform.translation = translation;
393
- const scale = numArray(node, "inputs:scale", 2);
394
- if (scale) transform.scale = scale;
395
- const rotation = node.GetAttribute("inputs:rotation").Get();
396
- if (typeof rotation === "number") transform.rotation = rotation;
397
- return Object.keys(transform).length > 0 ? transform : void 0;
457
+ function connectedPrim(prim, input) {
458
+ const conn = prim.GetAttribute(input).GetConnections()[0];
459
+ if (!conn) return null;
460
+ return prim.GetStage().GetPrimAtPath(conn.split(".")[0]);
461
+ }
462
+ function readStChain(texPrim) {
463
+ const out = {};
464
+ let node = connectedPrim(texPrim, "inputs:st");
465
+ if (node && node.GetAttribute("info:id").Get() === "UsdTransform2d") {
466
+ const transform = {};
467
+ const translation = numArray(node, "inputs:translation", 2);
468
+ if (translation) transform.translation = translation;
469
+ const scale = numArray(node, "inputs:scale", 2);
470
+ if (scale) transform.scale = scale;
471
+ const rotation = node.GetAttribute("inputs:rotation").Get();
472
+ if (typeof rotation === "number") transform.rotation = rotation;
473
+ if (Object.keys(transform).length > 0) out.transform = transform;
474
+ node = connectedPrim(node, "inputs:in");
475
+ }
476
+ if (node && node.GetAttribute("info:id").Get() === "UsdPrimvarReader_float2") {
477
+ const varname = node.GetAttribute("inputs:varname").Get();
478
+ if (typeof varname === "string" && varname.length > 0) out.uvSet = varname;
479
+ }
480
+ return out;
398
481
  }
399
482
  function numArray(prim, name, length) {
400
483
  const v = prim.GetAttribute(name).Get();
@@ -404,13 +487,20 @@ function numArray(prim, name, length) {
404
487
  return void 0;
405
488
  }
406
489
  function findBinding(prim) {
490
+ let chosen;
407
491
  let p = prim;
408
492
  while (p) {
409
- const targets = p.GetRelationship("material:binding").GetTargets();
410
- if (targets.length > 0) return targets[0];
493
+ for (const name of ["material:binding:preview", "material:binding"]) {
494
+ const rel = p.GetRelationship(name);
495
+ const target = rel.GetTargets()[0];
496
+ if (!target) continue;
497
+ const stronger = rel.GetMetadata("bindMaterialAs") === "strongerThanDescendants";
498
+ if (chosen === void 0 || stronger) chosen = target;
499
+ break;
500
+ }
411
501
  p = p.GetParent();
412
502
  }
413
- return void 0;
503
+ return chosen;
414
504
  }
415
505
  function findSurfaceShader(material) {
416
506
  for (const out of SURFACE_OUTPUTS) {
@@ -1776,6 +1866,10 @@ var Attribute = class {
1776
1866
  GetConnections() {
1777
1867
  return this._spec?.connections ?? [];
1778
1868
  }
1869
+ /** Authored attribute metadata (`interpolation`, `elementSize`, …). */
1870
+ GetMetadata(key) {
1871
+ return this._spec?.metadata[key];
1872
+ }
1779
1873
  };
1780
1874
  var Relationship = class {
1781
1875
  constructor(_prim, _name, _spec) {
@@ -1807,6 +1901,10 @@ var Relationship = class {
1807
1901
  GetTargets() {
1808
1902
  return this._spec?.targets ?? [];
1809
1903
  }
1904
+ /** Authored relationship metadata (`bindMaterialAs`, …). */
1905
+ GetMetadata(key) {
1906
+ return this._spec?.metadata[key];
1907
+ }
1810
1908
  };
1811
1909
 
1812
1910
  // src/usd/Prim.ts
@@ -2159,10 +2257,17 @@ var CrateType = {
2159
2257
  Quatf: 17,
2160
2258
  Vec2d: 19,
2161
2259
  Vec2f: 20,
2260
+ Vec2h: 21,
2261
+ Vec2i: 22,
2162
2262
  Vec3d: 23,
2163
2263
  Vec3f: 24,
2264
+ Vec3h: 25,
2265
+ Vec3i: 26,
2164
2266
  Vec4d: 27,
2165
2267
  Vec4f: 28,
2268
+ Vec4h: 29,
2269
+ Vec4i: 30,
2270
+ Dictionary: 31,
2166
2271
  TokenListOp: 32,
2167
2272
  PathListOp: 34,
2168
2273
  ReferenceListOp: 35,
@@ -2173,6 +2278,8 @@ var CrateType = {
2173
2278
  Permission: 43,
2174
2279
  Variability: 44,
2175
2280
  VariantSelectionMap: 45,
2281
+ TimeSamples: 46,
2282
+ DoubleVector: 48,
2176
2283
  StringVector: 50,
2177
2284
  PayloadListOp: 55};
2178
2285
  var ListOpBits = {
@@ -2207,6 +2314,12 @@ function halfToFloat(h) {
2207
2314
  var MAGIC = "PXR-USDC";
2208
2315
  var scratch = new DataView(new ArrayBuffer(8));
2209
2316
  var FIELDSET_END = -1;
2317
+ var MIN_COMPRESSED_ARRAY_SIZE = 16;
2318
+ function inlineInt8s(low, n) {
2319
+ const out = new Array(n);
2320
+ for (let i = 0; i < n; i++) out[i] = (low >>> i * 8 & 255) << 24 >> 24;
2321
+ return out;
2322
+ }
2210
2323
  var CrateReader = class {
2211
2324
  version;
2212
2325
  view;
@@ -2440,6 +2553,33 @@ var CrateReader = class {
2440
2553
  if (b.isInlined) return this.readInlined(b.type, b.payload);
2441
2554
  return this.readScalar(b.type, Number(b.payload));
2442
2555
  }
2556
+ /**
2557
+ * Decode a `timeSamples` field (a {@link CrateType.TimeSamples} rep) into
2558
+ * parallel times/values arrays; `undefined` if `rep` is some other type.
2559
+ *
2560
+ * Layout (pxr `crateFile.cpp`, `Write(TimeSamples)`): an `int64` offset —
2561
+ * relative to its own position — jumps over the recursively-written times
2562
+ * data to the times `ValueRep` (a `DoubleVector`); a second such offset
2563
+ * jumps over the samples' data to `[u64 count][count × ValueRep]`. Sample
2564
+ * reps decode through {@link getValue}, so every scalar/array type works.
2565
+ */
2566
+ getTimeSamples(rep) {
2567
+ const b = decodeRepBits(rep);
2568
+ if (b.type !== CrateType.TimeSamples || b.isArray || b.isInlined) return void 0;
2569
+ const off = Number(b.payload);
2570
+ let p = off + Number(this.i64(off));
2571
+ const times = this.getValue(this.view.getBigUint64(p, true));
2572
+ p += 8;
2573
+ if (!Array.isArray(times) || !times.every((t) => typeof t === "number")) return void 0;
2574
+ p += Number(this.i64(p));
2575
+ const count = this.u64(p);
2576
+ p += 8;
2577
+ const values = new Array(count);
2578
+ for (let i = 0; i < count; i++) {
2579
+ values[i] = this.getValue(this.view.getBigUint64(p + i * 8, true));
2580
+ }
2581
+ return { times, values };
2582
+ }
2443
2583
  readInlined(type, payload) {
2444
2584
  const low = Number(payload & 0xffffffffn);
2445
2585
  switch (type) {
@@ -2469,6 +2609,62 @@ var CrateReader = class {
2469
2609
  case CrateType.Permission:
2470
2610
  case CrateType.Variability:
2471
2611
  return low;
2612
+ // Vectors whose components are all small integers are inlined as one
2613
+ // int8 per component in the payload's low bytes (crateValueInliners.h).
2614
+ case CrateType.Vec2i:
2615
+ case CrateType.Vec2h:
2616
+ case CrateType.Vec2f:
2617
+ case CrateType.Vec2d:
2618
+ return inlineInt8s(low, 2);
2619
+ case CrateType.Vec3i:
2620
+ case CrateType.Vec3h:
2621
+ case CrateType.Vec3f:
2622
+ case CrateType.Vec3d:
2623
+ return inlineInt8s(low, 3);
2624
+ case CrateType.Vec4i:
2625
+ case CrateType.Vec4h:
2626
+ case CrateType.Vec4f:
2627
+ case CrateType.Vec4d:
2628
+ return inlineInt8s(low, 4);
2629
+ // Matrices inline when off-diagonal is zero and the diagonal fits int8.
2630
+ case CrateType.Matrix3d: {
2631
+ const [a, b, c] = inlineInt8s(low, 3);
2632
+ return new UsdMatrix([
2633
+ a,
2634
+ 0,
2635
+ 0,
2636
+ 0,
2637
+ b,
2638
+ 0,
2639
+ 0,
2640
+ 0,
2641
+ c
2642
+ ], 3);
2643
+ }
2644
+ case CrateType.Matrix4d: {
2645
+ const [a, b, c, d] = inlineInt8s(low, 4);
2646
+ return new UsdMatrix([
2647
+ a,
2648
+ 0,
2649
+ 0,
2650
+ 0,
2651
+ 0,
2652
+ b,
2653
+ 0,
2654
+ 0,
2655
+ 0,
2656
+ 0,
2657
+ c,
2658
+ 0,
2659
+ 0,
2660
+ 0,
2661
+ 0,
2662
+ d
2663
+ ], 4);
2664
+ }
2665
+ // Only the empty dictionary is inlined.
2666
+ case CrateType.Dictionary:
2667
+ return {};
2472
2668
  default:
2473
2669
  return void 0;
2474
2670
  }
@@ -2486,6 +2682,12 @@ var CrateReader = class {
2486
2682
  return v.getInt32(off, true);
2487
2683
  case CrateType.UInt:
2488
2684
  return v.getUint32(off, true);
2685
+ case CrateType.UChar:
2686
+ return v.getUint8(off);
2687
+ case CrateType.Int64:
2688
+ return Number(v.getBigInt64(off, true));
2689
+ case CrateType.UInt64:
2690
+ return Number(v.getBigUint64(off, true));
2489
2691
  case CrateType.Token:
2490
2692
  return this.getToken(v.getUint32(off, true));
2491
2693
  case CrateType.String:
@@ -2504,6 +2706,18 @@ var CrateReader = class {
2504
2706
  return this.readFloat64s(off, 3);
2505
2707
  case CrateType.Vec4d:
2506
2708
  return this.readFloat64s(off, 4);
2709
+ case CrateType.Vec2h:
2710
+ return this.readHalfs(off, 2);
2711
+ case CrateType.Vec3h:
2712
+ return this.readHalfs(off, 3);
2713
+ case CrateType.Vec4h:
2714
+ return this.readHalfs(off, 4);
2715
+ case CrateType.Vec2i:
2716
+ return this.readInt32s(off, 2);
2717
+ case CrateType.Vec3i:
2718
+ return this.readInt32s(off, 3);
2719
+ case CrateType.Vec4i:
2720
+ return this.readInt32s(off, 4);
2507
2721
  case CrateType.Quatf: {
2508
2722
  const q = this.readFloat32s(off, 4);
2509
2723
  return new Quat(q[3], [q[0], q[1], q[2]]);
@@ -2533,41 +2747,176 @@ var CrateReader = class {
2533
2747
  return this.readIndexVector(off, "string").items;
2534
2748
  case CrateType.VariantSelectionMap:
2535
2749
  return this.readVariantSelectionMap(off);
2750
+ case CrateType.DoubleVector: {
2751
+ const count = this.u64(off);
2752
+ return this.readFloat64s(off + 8, count);
2753
+ }
2754
+ case CrateType.Dictionary:
2755
+ return this.readDictionary(off, 0);
2536
2756
  default:
2537
2757
  return void 0;
2538
2758
  }
2539
2759
  }
2760
+ /** Array headers store a u32 count before crate 0.7.0, a u64 from 0.7.0 on. */
2761
+ arrayHeader(off) {
2762
+ if (this.version[0] === 0 && this.version[1] < 7) {
2763
+ return { count: this.view.getUint32(off, true), next: off + 4 };
2764
+ }
2765
+ return { count: this.u64(off), next: off + 8 };
2766
+ }
2540
2767
  readArray(type, off, compressed) {
2541
2768
  if (off === 0) return [];
2542
- const count = this.u64(off);
2543
- let p = off + 8;
2544
- if (compressed) {
2545
- const compressedSize = this.u64(p);
2546
- p += 8;
2547
- return decodeIntegers32(this.bytes.subarray(p, p + compressedSize), count);
2548
- }
2769
+ const { count, next: p } = this.arrayHeader(off);
2770
+ if (count === 0) return [];
2771
+ if (compressed) return this.readCompressedArray(type, p, count);
2549
2772
  const v = this.view;
2550
2773
  switch (type) {
2774
+ case CrateType.Bool: {
2775
+ const out = new Array(count);
2776
+ for (let i = 0; i < count; i++) out[i] = this.bytes[p + i] !== 0;
2777
+ return out;
2778
+ }
2779
+ case CrateType.UChar: {
2780
+ const out = new Array(count);
2781
+ for (let i = 0; i < count; i++) out[i] = this.bytes[p + i];
2782
+ return out;
2783
+ }
2551
2784
  case CrateType.Int:
2552
2785
  case CrateType.UInt: {
2553
2786
  const out = new Array(count);
2554
2787
  for (let i = 0; i < count; i++) out[i] = v.getInt32(p + i * 4, true);
2555
2788
  return out;
2556
2789
  }
2557
- case CrateType.Float: {
2790
+ case CrateType.Int64: {
2558
2791
  const out = new Array(count);
2559
- for (let i = 0; i < count; i++) out[i] = v.getFloat32(p + i * 4, true);
2792
+ for (let i = 0; i < count; i++) out[i] = Number(v.getBigInt64(p + i * 8, true));
2560
2793
  return out;
2561
2794
  }
2795
+ case CrateType.UInt64: {
2796
+ const out = new Array(count);
2797
+ for (let i = 0; i < count; i++) out[i] = Number(v.getBigUint64(p + i * 8, true));
2798
+ return out;
2799
+ }
2800
+ case CrateType.Half:
2801
+ return this.readHalfs(p, count);
2802
+ case CrateType.Float:
2803
+ return this.readFloat32s(p, count);
2804
+ case CrateType.Double:
2805
+ return this.readFloat64s(p, count);
2562
2806
  case CrateType.Token: {
2563
2807
  const out = new Array(count);
2564
2808
  for (let i = 0; i < count; i++) out[i] = this.getToken(v.getUint32(p + i * 4, true));
2565
2809
  return out;
2566
2810
  }
2811
+ case CrateType.String: {
2812
+ const out = new Array(count);
2813
+ for (let i = 0; i < count; i++) {
2814
+ out[i] = this.getToken(this.getStrings()[v.getUint32(p + i * 4, true)] ?? 0);
2815
+ }
2816
+ return out;
2817
+ }
2818
+ case CrateType.AssetPath: {
2819
+ const out = new Array(count);
2820
+ for (let i = 0; i < count; i++) {
2821
+ out[i] = new AssetPath(
2822
+ this.getToken(this.getStrings()[v.getUint32(p + i * 4, true)] ?? 0)
2823
+ );
2824
+ }
2825
+ return out;
2826
+ }
2827
+ case CrateType.Vec2f:
2828
+ return this.readTupleArray(p, count, 2, "f32");
2567
2829
  case CrateType.Vec3f:
2568
- return this.readVec3fArray(p, count, false);
2830
+ return this.readTupleArray(p, count, 3, "f32");
2831
+ case CrateType.Vec4f:
2832
+ return this.readTupleArray(p, count, 4, "f32");
2833
+ case CrateType.Vec2d:
2834
+ return this.readTupleArray(p, count, 2, "f64");
2569
2835
  case CrateType.Vec3d:
2570
- return this.readVec3fArray(p, count, true);
2836
+ return this.readTupleArray(p, count, 3, "f64");
2837
+ case CrateType.Vec4d:
2838
+ return this.readTupleArray(p, count, 4, "f64");
2839
+ case CrateType.Vec2h:
2840
+ return this.readTupleArray(p, count, 2, "f16");
2841
+ case CrateType.Vec3h:
2842
+ return this.readTupleArray(p, count, 3, "f16");
2843
+ case CrateType.Vec4h:
2844
+ return this.readTupleArray(p, count, 4, "f16");
2845
+ case CrateType.Vec2i:
2846
+ return this.readTupleArray(p, count, 2, "i32");
2847
+ case CrateType.Vec3i:
2848
+ return this.readTupleArray(p, count, 3, "i32");
2849
+ case CrateType.Vec4i:
2850
+ return this.readTupleArray(p, count, 4, "i32");
2851
+ case CrateType.Quatf: {
2852
+ const out = new Array(count);
2853
+ for (let i = 0; i < count; i++) {
2854
+ const q = this.readFloat32s(p + i * 16, 4);
2855
+ out[i] = new Quat(q[3], [q[0], q[1], q[2]]);
2856
+ }
2857
+ return out;
2858
+ }
2859
+ case CrateType.Quatd: {
2860
+ const out = new Array(count);
2861
+ for (let i = 0; i < count; i++) {
2862
+ const q = this.readFloat64s(p + i * 32, 4);
2863
+ out[i] = new Quat(q[3], [q[0], q[1], q[2]]);
2864
+ }
2865
+ return out;
2866
+ }
2867
+ case CrateType.Matrix3d: {
2868
+ const out = new Array(count);
2869
+ for (let i = 0; i < count; i++) out[i] = new UsdMatrix(this.readFloat64s(p + i * 72, 9), 3);
2870
+ return out;
2871
+ }
2872
+ case CrateType.Matrix4d: {
2873
+ const out = new Array(count);
2874
+ for (let i = 0; i < count; i++)
2875
+ out[i] = new UsdMatrix(this.readFloat64s(p + i * 128, 16), 4);
2876
+ return out;
2877
+ }
2878
+ default:
2879
+ return void 0;
2880
+ }
2881
+ }
2882
+ /**
2883
+ * Decode an array whose rep has the compressed bit. Int arrays are
2884
+ * integer-compressed; half/float/double arrays (crate 0.6.0+) carry a code
2885
+ * byte — `'i'` when every value is integral, `'t'` for a lookup table +
2886
+ * compressed indexes. Arrays under {@link MIN_COMPRESSED_ARRAY_SIZE} elements
2887
+ * are stored raw even when the bit is set (mirrors pxr's writer).
2888
+ */
2889
+ readCompressedArray(type, start, count) {
2890
+ let p = start;
2891
+ switch (type) {
2892
+ case CrateType.Int:
2893
+ case CrateType.UInt: {
2894
+ if (count < MIN_COMPRESSED_ARRAY_SIZE) {
2895
+ const out = new Array(count);
2896
+ for (let i = 0; i < count; i++) out[i] = this.view.getInt32(p + i * 4, true);
2897
+ return out;
2898
+ }
2899
+ return this.readCompressedInts(p, count).values;
2900
+ }
2901
+ case CrateType.Half:
2902
+ case CrateType.Float:
2903
+ case CrateType.Double: {
2904
+ const readRaw = (off, n) => type === CrateType.Double ? this.readFloat64s(off, n) : type === CrateType.Float ? this.readFloat32s(off, n) : this.readHalfs(off, n);
2905
+ if (count < MIN_COMPRESSED_ARRAY_SIZE) return readRaw(p, count);
2906
+ const code = this.bytes[p];
2907
+ p += 1;
2908
+ if (code === 105) {
2909
+ return this.readCompressedInts(p, count).values;
2910
+ }
2911
+ if (code === 116) {
2912
+ const lutSize = this.view.getUint32(p, true);
2913
+ p += 4;
2914
+ const lut = readRaw(p, lutSize);
2915
+ p += lutSize * (type === CrateType.Double ? 8 : type === CrateType.Float ? 4 : 2);
2916
+ return this.readCompressedInts(p, count).values.map((i) => lut[i] ?? 0);
2917
+ }
2918
+ return void 0;
2919
+ }
2571
2920
  default:
2572
2921
  return void 0;
2573
2922
  }
@@ -2582,20 +2931,45 @@ var CrateReader = class {
2582
2931
  for (let i = 0; i < n; i++) out[i] = this.view.getFloat64(off + i * 8, true);
2583
2932
  return out;
2584
2933
  }
2585
- readVec3fArray(off, count, double) {
2934
+ readHalfs(off, n) {
2935
+ const out = new Array(n);
2936
+ for (let i = 0; i < n; i++) out[i] = halfToFloat(this.view.getUint16(off + i * 2, true));
2937
+ return out;
2938
+ }
2939
+ readInt32s(off, n) {
2940
+ const out = new Array(n);
2941
+ for (let i = 0; i < n; i++) out[i] = this.view.getInt32(off + i * 4, true);
2942
+ return out;
2943
+ }
2944
+ /** Read `count` fixed-size `n`-tuples (vec2/3/4 of the given element kind). */
2945
+ readTupleArray(off, count, n, kind) {
2946
+ const elemSize = kind === "f64" ? 8 : kind === "f16" ? 2 : 4;
2586
2947
  const out = new Array(count);
2587
- const stride = double ? 24 : 12;
2588
2948
  for (let i = 0; i < count; i++) {
2589
- const o = off + i * stride;
2590
- out[i] = double ? [
2591
- this.view.getFloat64(o, true),
2592
- this.view.getFloat64(o + 8, true),
2593
- this.view.getFloat64(o + 16, true)
2594
- ] : [
2595
- this.view.getFloat32(o, true),
2596
- this.view.getFloat32(o + 4, true),
2597
- this.view.getFloat32(o + 8, true)
2598
- ];
2949
+ const o = off + i * n * elemSize;
2950
+ out[i] = kind === "f64" ? this.readFloat64s(o, n) : kind === "f32" ? this.readFloat32s(o, n) : kind === "f16" ? this.readHalfs(o, n) : this.readInt32s(o, n);
2951
+ }
2952
+ return out;
2953
+ }
2954
+ /**
2955
+ * Read a `VtDictionary`: `[u64 count]`, then per entry a string index (key)
2956
+ * followed by a recursive VtValue — an `int64` offset (relative to its own
2957
+ * position) over the value's data to an 8-byte `ValueRep`.
2958
+ */
2959
+ readDictionary(off, depth) {
2960
+ const out = {};
2961
+ if (depth > 16) return out;
2962
+ const count = this.u64(off);
2963
+ let p = off + 8;
2964
+ for (let i = 0; i < count; i++) {
2965
+ const key = this.getToken(this.getStrings()[this.view.getUint32(p, true)] ?? 0);
2966
+ p += 4;
2967
+ const repPos = p + Number(this.i64(p));
2968
+ const rep = this.view.getBigUint64(repPos, true);
2969
+ const b = decodeRepBits(rep);
2970
+ const value = b.type === CrateType.Dictionary && !b.isInlined && !b.isArray ? this.readDictionary(Number(b.payload), depth + 1) : this.getValue(rep);
2971
+ if (key && value !== void 0) out[key] = value;
2972
+ p = repPos + 8;
2599
2973
  }
2600
2974
  return out;
2601
2975
  }
@@ -2798,13 +3172,14 @@ function buildAttribute(crate, name, fm) {
2798
3172
  const defaultRep = fm.get("default");
2799
3173
  const rawType = asString(crate, fm.get("typeName")) ?? "";
2800
3174
  const isArrayType = rawType.endsWith("[]");
3175
+ const customRep = fm.get("custom");
2801
3176
  const attr = {
2802
3177
  kind: "attribute",
2803
3178
  name,
2804
3179
  typeName: isArrayType ? rawType.slice(0, -2) : rawType,
2805
3180
  isArray: isArrayType || (defaultRep !== void 0 ? decodeRepBits(defaultRep).isArray : false),
2806
3181
  variability: asNumber2(crate, fm.get("variability")) === 1 ? "uniform" : "varying",
2807
- custom: false,
3182
+ custom: customRep !== void 0 && crate.getValue(customRep) === true,
2808
3183
  metadata: {},
2809
3184
  line: 0
2810
3185
  };
@@ -2812,6 +3187,25 @@ function buildAttribute(crate, name, fm) {
2812
3187
  const value = crate.getValue(defaultRep);
2813
3188
  if (value !== void 0) attr.value = value;
2814
3189
  }
3190
+ const connections = fm.has("connectionPaths") ? crate.getValue(fm.get("connectionPaths")) : void 0;
3191
+ if (Array.isArray(connections)) {
3192
+ const paths = connections.filter((c) => typeof c === "string" && c.length > 0);
3193
+ if (paths.length > 0) attr.connections = paths;
3194
+ }
3195
+ const interpolation = asString(crate, fm.get("interpolation"));
3196
+ if (interpolation !== void 0) attr.metadata.interpolation = interpolation;
3197
+ const tsRep = fm.get("timeSamples");
3198
+ if (tsRep !== void 0) {
3199
+ const ts = crate.getTimeSamples(tsRep);
3200
+ if (ts) {
3201
+ const samples = /* @__PURE__ */ new Map();
3202
+ const pairs = ts.times.map((t, i) => [t, ts.values[i]]).sort((a, b) => a[0] - b[0]);
3203
+ for (const [t, v] of pairs) {
3204
+ if (v !== void 0) samples.set(t, v);
3205
+ }
3206
+ if (samples.size > 0) attr.timeSamples = samples;
3207
+ }
3208
+ }
2815
3209
  return attr;
2816
3210
  }
2817
3211
  function buildRelationship(crate, name, fm) {
@@ -2858,6 +3252,14 @@ function buildLayerMetadata(crate, fm) {
2858
3252
  if (defaultPrim2 !== void 0) meta.defaultPrim = defaultPrim2;
2859
3253
  const metersPerUnit = asNumber2(crate, fm.get("metersPerUnit"));
2860
3254
  if (metersPerUnit !== void 0) meta.metersPerUnit = metersPerUnit;
3255
+ for (const key of ["startTimeCode", "endTimeCode", "timeCodesPerSecond", "framesPerSecond"]) {
3256
+ const value = asNumber2(crate, fm.get(key));
3257
+ if (value !== void 0) meta[key] = value;
3258
+ }
3259
+ const customLayerData = fm.has("customLayerData") ? crate.getValue(fm.get("customLayerData")) : void 0;
3260
+ if (customLayerData && typeof customLayerData === "object" && !Array.isArray(customLayerData)) {
3261
+ meta.customLayerData = customLayerData;
3262
+ }
2861
3263
  return meta;
2862
3264
  }
2863
3265
  function asString(crate, rep) {
@@ -3218,6 +3620,6 @@ function openUsdz(bytes) {
3218
3620
  return { rootEntry, resolver };
3219
3621
  }
3220
3622
 
3221
- 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 };
3222
- //# sourceMappingURL=chunk-2UD32EGU.js.map
3223
- //# sourceMappingURL=chunk-2UD32EGU.js.map
3623
+ 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, isBasisCurves, isMesh, isNonVisualPurpose, isPoints, isRenderableGprim, isScope, isSolidGprim, isUnsupportedGprim, isXform, isZip, iterDescendants, joinPosix, jointValueFromSI, jointValueToSI, normalizeJointLimits, openUsdz, parseOpType, parseUsda, refineJointType, resolveBoundMaterial, serializeUsda, toBytes, tokenize };
3624
+ //# sourceMappingURL=chunk-NFKK5LJK.js.map
3625
+ //# sourceMappingURL=chunk-NFKK5LJK.js.map