three-usd-robot 0.8.1 → 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
@@ -1907,6 +2005,15 @@ var Prim = class {
1907
2005
  GetAllMetadata() {
1908
2006
  return this._spec?.metadata ?? {};
1909
2007
  }
2008
+ /**
2009
+ * Model-hierarchy kind from the `kind` metadata — `"component"`, `"group"`,
2010
+ * `"assembly"`, `"subcomponent"`, … — or `""` when unauthored. The standard
2011
+ * signal for selection granularity (usdview's "select by kind").
2012
+ */
2013
+ GetKind() {
2014
+ const kind = this._spec?.metadata.kind;
2015
+ return typeof kind === "string" ? kind : "";
2016
+ }
1910
2017
  /** Applied API schema names from `apiSchemas` (e.g. `PhysicsArticulationRootAPI`). */
1911
2018
  GetAppliedSchemas() {
1912
2019
  const raw = this._spec?.metadata.apiSchemas;
@@ -2150,10 +2257,17 @@ var CrateType = {
2150
2257
  Quatf: 17,
2151
2258
  Vec2d: 19,
2152
2259
  Vec2f: 20,
2260
+ Vec2h: 21,
2261
+ Vec2i: 22,
2153
2262
  Vec3d: 23,
2154
2263
  Vec3f: 24,
2264
+ Vec3h: 25,
2265
+ Vec3i: 26,
2155
2266
  Vec4d: 27,
2156
2267
  Vec4f: 28,
2268
+ Vec4h: 29,
2269
+ Vec4i: 30,
2270
+ Dictionary: 31,
2157
2271
  TokenListOp: 32,
2158
2272
  PathListOp: 34,
2159
2273
  ReferenceListOp: 35,
@@ -2164,6 +2278,8 @@ var CrateType = {
2164
2278
  Permission: 43,
2165
2279
  Variability: 44,
2166
2280
  VariantSelectionMap: 45,
2281
+ TimeSamples: 46,
2282
+ DoubleVector: 48,
2167
2283
  StringVector: 50,
2168
2284
  PayloadListOp: 55};
2169
2285
  var ListOpBits = {
@@ -2198,6 +2314,12 @@ function halfToFloat(h) {
2198
2314
  var MAGIC = "PXR-USDC";
2199
2315
  var scratch = new DataView(new ArrayBuffer(8));
2200
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
+ }
2201
2323
  var CrateReader = class {
2202
2324
  version;
2203
2325
  view;
@@ -2431,6 +2553,33 @@ var CrateReader = class {
2431
2553
  if (b.isInlined) return this.readInlined(b.type, b.payload);
2432
2554
  return this.readScalar(b.type, Number(b.payload));
2433
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
+ }
2434
2583
  readInlined(type, payload) {
2435
2584
  const low = Number(payload & 0xffffffffn);
2436
2585
  switch (type) {
@@ -2460,6 +2609,62 @@ var CrateReader = class {
2460
2609
  case CrateType.Permission:
2461
2610
  case CrateType.Variability:
2462
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 {};
2463
2668
  default:
2464
2669
  return void 0;
2465
2670
  }
@@ -2477,6 +2682,12 @@ var CrateReader = class {
2477
2682
  return v.getInt32(off, true);
2478
2683
  case CrateType.UInt:
2479
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));
2480
2691
  case CrateType.Token:
2481
2692
  return this.getToken(v.getUint32(off, true));
2482
2693
  case CrateType.String:
@@ -2495,6 +2706,18 @@ var CrateReader = class {
2495
2706
  return this.readFloat64s(off, 3);
2496
2707
  case CrateType.Vec4d:
2497
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);
2498
2721
  case CrateType.Quatf: {
2499
2722
  const q = this.readFloat32s(off, 4);
2500
2723
  return new Quat(q[3], [q[0], q[1], q[2]]);
@@ -2524,41 +2747,176 @@ var CrateReader = class {
2524
2747
  return this.readIndexVector(off, "string").items;
2525
2748
  case CrateType.VariantSelectionMap:
2526
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);
2527
2756
  default:
2528
2757
  return void 0;
2529
2758
  }
2530
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
+ }
2531
2767
  readArray(type, off, compressed) {
2532
2768
  if (off === 0) return [];
2533
- const count = this.u64(off);
2534
- let p = off + 8;
2535
- if (compressed) {
2536
- const compressedSize = this.u64(p);
2537
- p += 8;
2538
- return decodeIntegers32(this.bytes.subarray(p, p + compressedSize), count);
2539
- }
2769
+ const { count, next: p } = this.arrayHeader(off);
2770
+ if (count === 0) return [];
2771
+ if (compressed) return this.readCompressedArray(type, p, count);
2540
2772
  const v = this.view;
2541
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
+ }
2542
2784
  case CrateType.Int:
2543
2785
  case CrateType.UInt: {
2544
2786
  const out = new Array(count);
2545
2787
  for (let i = 0; i < count; i++) out[i] = v.getInt32(p + i * 4, true);
2546
2788
  return out;
2547
2789
  }
2548
- case CrateType.Float: {
2790
+ case CrateType.Int64: {
2549
2791
  const out = new Array(count);
2550
- 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));
2551
2793
  return out;
2552
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);
2553
2806
  case CrateType.Token: {
2554
2807
  const out = new Array(count);
2555
2808
  for (let i = 0; i < count; i++) out[i] = this.getToken(v.getUint32(p + i * 4, true));
2556
2809
  return out;
2557
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");
2558
2829
  case CrateType.Vec3f:
2559
- 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");
2560
2835
  case CrateType.Vec3d:
2561
- 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
+ }
2562
2920
  default:
2563
2921
  return void 0;
2564
2922
  }
@@ -2573,20 +2931,45 @@ var CrateReader = class {
2573
2931
  for (let i = 0; i < n; i++) out[i] = this.view.getFloat64(off + i * 8, true);
2574
2932
  return out;
2575
2933
  }
2576
- 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;
2577
2947
  const out = new Array(count);
2578
- const stride = double ? 24 : 12;
2579
2948
  for (let i = 0; i < count; i++) {
2580
- const o = off + i * stride;
2581
- out[i] = double ? [
2582
- this.view.getFloat64(o, true),
2583
- this.view.getFloat64(o + 8, true),
2584
- this.view.getFloat64(o + 16, true)
2585
- ] : [
2586
- this.view.getFloat32(o, true),
2587
- this.view.getFloat32(o + 4, true),
2588
- this.view.getFloat32(o + 8, true)
2589
- ];
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;
2590
2973
  }
2591
2974
  return out;
2592
2975
  }
@@ -2789,13 +3172,14 @@ function buildAttribute(crate, name, fm) {
2789
3172
  const defaultRep = fm.get("default");
2790
3173
  const rawType = asString(crate, fm.get("typeName")) ?? "";
2791
3174
  const isArrayType = rawType.endsWith("[]");
3175
+ const customRep = fm.get("custom");
2792
3176
  const attr = {
2793
3177
  kind: "attribute",
2794
3178
  name,
2795
3179
  typeName: isArrayType ? rawType.slice(0, -2) : rawType,
2796
3180
  isArray: isArrayType || (defaultRep !== void 0 ? decodeRepBits(defaultRep).isArray : false),
2797
3181
  variability: asNumber2(crate, fm.get("variability")) === 1 ? "uniform" : "varying",
2798
- custom: false,
3182
+ custom: customRep !== void 0 && crate.getValue(customRep) === true,
2799
3183
  metadata: {},
2800
3184
  line: 0
2801
3185
  };
@@ -2803,6 +3187,25 @@ function buildAttribute(crate, name, fm) {
2803
3187
  const value = crate.getValue(defaultRep);
2804
3188
  if (value !== void 0) attr.value = value;
2805
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
+ }
2806
3209
  return attr;
2807
3210
  }
2808
3211
  function buildRelationship(crate, name, fm) {
@@ -2849,6 +3252,14 @@ function buildLayerMetadata(crate, fm) {
2849
3252
  if (defaultPrim2 !== void 0) meta.defaultPrim = defaultPrim2;
2850
3253
  const metersPerUnit = asNumber2(crate, fm.get("metersPerUnit"));
2851
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
+ }
2852
3263
  return meta;
2853
3264
  }
2854
3265
  function asString(crate, rep) {
@@ -3209,6 +3620,6 @@ function openUsdz(bytes) {
3209
3620
  return { rootEntry, resolver };
3210
3621
  }
3211
3622
 
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
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