three-usd-robot 0.3.0 → 0.4.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.
- package/README.md +26 -9
- package/dist/{ThreeUsdRobot-C6uqpNZA.d.ts → ThreeUsdRobot-Deoh7zam.d.ts} +15 -1
- package/dist/{buildKinematicTree-BJuC_-5_.d.ts → buildKinematicTree-CZjBMA1I.d.ts} +27 -1
- package/dist/{chunk-XH3L7XDJ.js → chunk-FYVZ7YPW.js} +500 -347
- package/dist/chunk-FYVZ7YPW.js.map +1 -0
- package/dist/core.d.ts +23 -5
- package/dist/core.js +1 -1
- package/dist/extras.d.ts +2 -2
- package/dist/helpers.d.ts +2 -2
- package/dist/index.d.ts +40 -14
- package/dist/index.js +103 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-XH3L7XDJ.js.map +0 -1
|
@@ -1040,6 +1040,21 @@ var Stage = class _Stage {
|
|
|
1040
1040
|
const v = this._layer.GetMetadata("metersPerUnit");
|
|
1041
1041
|
return typeof v === "number" ? v : DEFAULT_METERS_PER_UNIT;
|
|
1042
1042
|
}
|
|
1043
|
+
/** Animation start time code, if authored. */
|
|
1044
|
+
GetStartTimeCode() {
|
|
1045
|
+
const v = this._layer.GetMetadata("startTimeCode");
|
|
1046
|
+
return typeof v === "number" ? v : void 0;
|
|
1047
|
+
}
|
|
1048
|
+
/** Animation end time code, if authored. */
|
|
1049
|
+
GetEndTimeCode() {
|
|
1050
|
+
const v = this._layer.GetMetadata("endTimeCode");
|
|
1051
|
+
return typeof v === "number" ? v : void 0;
|
|
1052
|
+
}
|
|
1053
|
+
/** Time codes per second for playback; defaults to 24. */
|
|
1054
|
+
GetTimeCodesPerSecond() {
|
|
1055
|
+
const v = this._layer.GetMetadata("timeCodesPerSecond") ?? this._layer.GetMetadata("framesPerSecond");
|
|
1056
|
+
return typeof v === "number" && v > 0 ? v : 24;
|
|
1057
|
+
}
|
|
1043
1058
|
};
|
|
1044
1059
|
|
|
1045
1060
|
// src/usd/AssetResolver.ts
|
|
@@ -1063,14 +1078,21 @@ var DefaultAssetResolver = class {
|
|
|
1063
1078
|
}
|
|
1064
1079
|
};
|
|
1065
1080
|
function createMemoryResolver(files) {
|
|
1081
|
+
const decoder = new TextDecoder();
|
|
1082
|
+
const encoder = new TextEncoder();
|
|
1066
1083
|
return {
|
|
1067
1084
|
resolve(assetPath, baseUrl) {
|
|
1068
1085
|
return joinPosix(baseUrl, assetPath);
|
|
1069
1086
|
},
|
|
1070
1087
|
fetchText(url) {
|
|
1071
|
-
const
|
|
1072
|
-
if (
|
|
1073
|
-
return Promise.resolve(
|
|
1088
|
+
const v = files[url];
|
|
1089
|
+
if (v === void 0) return Promise.reject(new Error(`asset not found: ${url}`));
|
|
1090
|
+
return Promise.resolve(typeof v === "string" ? v : decoder.decode(v));
|
|
1091
|
+
},
|
|
1092
|
+
fetchBytes(url) {
|
|
1093
|
+
const v = files[url];
|
|
1094
|
+
if (v === void 0) return Promise.reject(new Error(`asset not found: ${url}`));
|
|
1095
|
+
return Promise.resolve(typeof v === "string" ? encoder.encode(v) : v);
|
|
1074
1096
|
}
|
|
1075
1097
|
};
|
|
1076
1098
|
}
|
|
@@ -1090,261 +1112,6 @@ function normalizePosix(path) {
|
|
|
1090
1112
|
return (isAbsolute ? "/" : "") + out.join("/");
|
|
1091
1113
|
}
|
|
1092
1114
|
|
|
1093
|
-
// src/usd/composition.ts
|
|
1094
|
-
var ARC_KEYS = ["references", "payload", "payloads", "inherits", "specializes"];
|
|
1095
|
-
var STRIP_KEYS = [...ARC_KEYS, "variants", "variantSets"];
|
|
1096
|
-
async function composeLayer(text, baseUrl, resolver, options = {}, stack = /* @__PURE__ */ new Set()) {
|
|
1097
|
-
const warn = options.onWarn ?? (() => {
|
|
1098
|
-
});
|
|
1099
|
-
const file = parseUsda(text);
|
|
1100
|
-
let weak = [];
|
|
1101
|
-
const subLayers = toArcs(file.metadata.subLayers);
|
|
1102
|
-
for (let i = subLayers.length - 1; i >= 0; i--) {
|
|
1103
|
-
const sub = await loadExternalFile(subLayers[i], baseUrl, resolver, options, stack, warn);
|
|
1104
|
-
if (sub) weak = mergePrimLists(weak, sub.prims);
|
|
1105
|
-
}
|
|
1106
|
-
const ctx = {
|
|
1107
|
-
baseUrl,
|
|
1108
|
-
resolver,
|
|
1109
|
-
options,
|
|
1110
|
-
warn,
|
|
1111
|
-
stack,
|
|
1112
|
-
index: buildPathIndex(file.prims),
|
|
1113
|
-
resolving: /* @__PURE__ */ new Set()
|
|
1114
|
-
};
|
|
1115
|
-
const resolved = [];
|
|
1116
|
-
for (const prim of file.prims) resolved.push(await resolvePrim(prim, ctx));
|
|
1117
|
-
const prims = weak.length > 0 ? mergePrimLists(weak, resolved) : resolved;
|
|
1118
|
-
return { version: file.version, metadata: stripKeys(file.metadata, STRIP_KEYS), prims };
|
|
1119
|
-
}
|
|
1120
|
-
async function resolvePrim(spec, ctx) {
|
|
1121
|
-
let properties = spec.properties;
|
|
1122
|
-
let children = spec.children;
|
|
1123
|
-
const selection = spec.metadata.variants;
|
|
1124
|
-
if (spec.variantSets && isDictionary(selection)) {
|
|
1125
|
-
for (const [setName, variantName] of Object.entries(selection)) {
|
|
1126
|
-
const variant = spec.variantSets[setName]?.[String(variantName)];
|
|
1127
|
-
if (!variant) continue;
|
|
1128
|
-
properties = mergeProperties(variant.properties, properties);
|
|
1129
|
-
children = mergePrimLists(variant.children, children);
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
const resolvedChildren = [];
|
|
1133
|
-
for (const child of children) resolvedChildren.push(await resolvePrim(child, ctx));
|
|
1134
|
-
const local = {
|
|
1135
|
-
specifier: spec.specifier,
|
|
1136
|
-
typeName: spec.typeName,
|
|
1137
|
-
name: spec.name,
|
|
1138
|
-
metadata: stripKeys(spec.metadata, STRIP_KEYS),
|
|
1139
|
-
properties,
|
|
1140
|
-
children: resolvedChildren,
|
|
1141
|
-
line: spec.line
|
|
1142
|
-
};
|
|
1143
|
-
const arcs = ARC_KEYS.flatMap((k) => toArcs(spec.metadata[k]));
|
|
1144
|
-
let base = null;
|
|
1145
|
-
for (const arc of arcs) {
|
|
1146
|
-
const target = await loadReferencedPrim(arc, ctx);
|
|
1147
|
-
if (target) base = base ? mergePrim(target, base) : target;
|
|
1148
|
-
}
|
|
1149
|
-
return base ? mergePrim(base, local) : local;
|
|
1150
|
-
}
|
|
1151
|
-
async function loadReferencedPrim(arc, ctx) {
|
|
1152
|
-
if (arc.assetPath) {
|
|
1153
|
-
const composed = await loadExternalFile(
|
|
1154
|
-
arc,
|
|
1155
|
-
ctx.baseUrl,
|
|
1156
|
-
ctx.resolver,
|
|
1157
|
-
ctx.options,
|
|
1158
|
-
ctx.stack,
|
|
1159
|
-
ctx.warn
|
|
1160
|
-
);
|
|
1161
|
-
if (!composed) return null;
|
|
1162
|
-
const target = arc.primPath ? findPrimByPath(composed, arc.primPath) : defaultPrim(composed, ctx.warn);
|
|
1163
|
-
if (!target) {
|
|
1164
|
-
ctx.warn(
|
|
1165
|
-
`reference target ${arc.primPath ?? "(defaultPrim)"} not found in ${arc.assetPath.path}`
|
|
1166
|
-
);
|
|
1167
|
-
return null;
|
|
1168
|
-
}
|
|
1169
|
-
return target;
|
|
1170
|
-
}
|
|
1171
|
-
if (arc.primPath) {
|
|
1172
|
-
if (ctx.resolving.has(arc.primPath)) {
|
|
1173
|
-
ctx.warn(`internal composition cycle at ${arc.primPath}; skipping`);
|
|
1174
|
-
return null;
|
|
1175
|
-
}
|
|
1176
|
-
const target = ctx.index.get(arc.primPath);
|
|
1177
|
-
if (!target) {
|
|
1178
|
-
ctx.warn(`internal reference target ${arc.primPath} not found`);
|
|
1179
|
-
return null;
|
|
1180
|
-
}
|
|
1181
|
-
return resolvePrim(target, { ...ctx, resolving: /* @__PURE__ */ new Set([...ctx.resolving, arc.primPath]) });
|
|
1182
|
-
}
|
|
1183
|
-
return null;
|
|
1184
|
-
}
|
|
1185
|
-
async function loadExternalFile(arc, baseUrl, resolver, options, stack, warn) {
|
|
1186
|
-
if (!arc.assetPath) return null;
|
|
1187
|
-
const url = resolver.resolve(arc.assetPath.path, baseUrl);
|
|
1188
|
-
if (stack.has(url)) {
|
|
1189
|
-
warn(`composition cycle detected at ${url}; skipping`);
|
|
1190
|
-
return null;
|
|
1191
|
-
}
|
|
1192
|
-
if (stack.size >= (options.maxDepth ?? 64)) {
|
|
1193
|
-
warn(`composition exceeded max depth at ${url}; skipping`);
|
|
1194
|
-
return null;
|
|
1195
|
-
}
|
|
1196
|
-
let text;
|
|
1197
|
-
try {
|
|
1198
|
-
text = await resolver.fetchText(url);
|
|
1199
|
-
} catch (err) {
|
|
1200
|
-
warn(`cannot resolve "${arc.assetPath.path}" -> ${url}: ${err.message}`);
|
|
1201
|
-
return null;
|
|
1202
|
-
}
|
|
1203
|
-
return composeLayer(text, url, resolver, options, /* @__PURE__ */ new Set([...stack, url]));
|
|
1204
|
-
}
|
|
1205
|
-
function mergePrim(base, over) {
|
|
1206
|
-
return {
|
|
1207
|
-
specifier: over.specifier === "over" ? base.specifier : over.specifier,
|
|
1208
|
-
typeName: over.typeName || base.typeName,
|
|
1209
|
-
name: over.name,
|
|
1210
|
-
metadata: mergeMetadata(base.metadata, over.metadata),
|
|
1211
|
-
properties: mergeProperties(base.properties, over.properties),
|
|
1212
|
-
children: mergePrimLists(base.children, over.children),
|
|
1213
|
-
line: over.line
|
|
1214
|
-
};
|
|
1215
|
-
}
|
|
1216
|
-
function mergePrimLists(base, over) {
|
|
1217
|
-
const byName = /* @__PURE__ */ new Map();
|
|
1218
|
-
for (const p of base) byName.set(p.name, p);
|
|
1219
|
-
for (const p of over) {
|
|
1220
|
-
const existing = byName.get(p.name);
|
|
1221
|
-
byName.set(p.name, existing ? mergePrim(existing, p) : p);
|
|
1222
|
-
}
|
|
1223
|
-
return [...byName.values()];
|
|
1224
|
-
}
|
|
1225
|
-
function mergeProperties(base, over) {
|
|
1226
|
-
const byName = /* @__PURE__ */ new Map();
|
|
1227
|
-
for (const p of base) byName.set(p.name, p);
|
|
1228
|
-
for (const p of over) {
|
|
1229
|
-
const existing = byName.get(p.name);
|
|
1230
|
-
byName.set(p.name, existing ? mergeProperty(existing, p) : p);
|
|
1231
|
-
}
|
|
1232
|
-
return [...byName.values()];
|
|
1233
|
-
}
|
|
1234
|
-
function mergeProperty(base, over) {
|
|
1235
|
-
if (base.kind !== over.kind) return over;
|
|
1236
|
-
if (base.kind === "attribute" && over.kind === "attribute") {
|
|
1237
|
-
const merged = {
|
|
1238
|
-
...over,
|
|
1239
|
-
typeName: over.typeName || base.typeName,
|
|
1240
|
-
metadata: mergeMetadata(base.metadata, over.metadata)
|
|
1241
|
-
};
|
|
1242
|
-
const value = over.value !== void 0 ? over.value : base.value;
|
|
1243
|
-
if (value !== void 0) merged.value = value;
|
|
1244
|
-
const timeSamples = over.timeSamples ?? base.timeSamples;
|
|
1245
|
-
if (timeSamples) merged.timeSamples = timeSamples;
|
|
1246
|
-
const connections = over.connections ?? base.connections;
|
|
1247
|
-
if (connections) merged.connections = connections;
|
|
1248
|
-
return merged;
|
|
1249
|
-
}
|
|
1250
|
-
if (base.kind === "relationship" && over.kind === "relationship") {
|
|
1251
|
-
return {
|
|
1252
|
-
...over,
|
|
1253
|
-
targets: over.targets.length > 0 ? over.targets : base.targets,
|
|
1254
|
-
metadata: mergeMetadata(base.metadata, over.metadata)
|
|
1255
|
-
};
|
|
1256
|
-
}
|
|
1257
|
-
return over;
|
|
1258
|
-
}
|
|
1259
|
-
function mergeMetadata(base, over) {
|
|
1260
|
-
const merged = { ...base, ...over };
|
|
1261
|
-
const a = base.apiSchemas;
|
|
1262
|
-
const b = over.apiSchemas;
|
|
1263
|
-
if (Array.isArray(a) || Array.isArray(b)) {
|
|
1264
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1265
|
-
const union = [];
|
|
1266
|
-
for (const v of [...Array.isArray(a) ? a : [], ...Array.isArray(b) ? b : []]) {
|
|
1267
|
-
if (!seen.has(v)) {
|
|
1268
|
-
seen.add(v);
|
|
1269
|
-
union.push(v);
|
|
1270
|
-
}
|
|
1271
|
-
}
|
|
1272
|
-
merged.apiSchemas = union;
|
|
1273
|
-
}
|
|
1274
|
-
return merged;
|
|
1275
|
-
}
|
|
1276
|
-
function buildPathIndex(prims, parent = "/", map = /* @__PURE__ */ new Map()) {
|
|
1277
|
-
for (const p of prims) {
|
|
1278
|
-
const path = parent === "/" ? `/${p.name}` : `${parent}/${p.name}`;
|
|
1279
|
-
map.set(path, p);
|
|
1280
|
-
buildPathIndex(p.children, path, map);
|
|
1281
|
-
}
|
|
1282
|
-
return map;
|
|
1283
|
-
}
|
|
1284
|
-
function findPrimByPath(file, path) {
|
|
1285
|
-
const segments = path.split("/").filter(Boolean);
|
|
1286
|
-
let level = file.prims;
|
|
1287
|
-
let found = null;
|
|
1288
|
-
for (const seg of segments) {
|
|
1289
|
-
found = level.find((p) => p.name === seg) ?? null;
|
|
1290
|
-
if (!found) return null;
|
|
1291
|
-
level = found.children;
|
|
1292
|
-
}
|
|
1293
|
-
return found;
|
|
1294
|
-
}
|
|
1295
|
-
function defaultPrim(file, warn) {
|
|
1296
|
-
const name = file.metadata.defaultPrim;
|
|
1297
|
-
if (typeof name === "string") return file.prims.find((p) => p.name === name) ?? null;
|
|
1298
|
-
const first = file.prims[0];
|
|
1299
|
-
if (first) warn(`referenced layer has no defaultPrim; using first root prim "${first.name}"`);
|
|
1300
|
-
return first ?? null;
|
|
1301
|
-
}
|
|
1302
|
-
function toArcs(value) {
|
|
1303
|
-
if (value === void 0) return [];
|
|
1304
|
-
const list = Array.isArray(value) ? value : [value];
|
|
1305
|
-
const arcs = [];
|
|
1306
|
-
for (const v of list) {
|
|
1307
|
-
if (v instanceof AssetPath) arcs.push({ assetPath: v });
|
|
1308
|
-
else if (v && typeof v === "object" && ("assetPath" in v || "primPath" in v))
|
|
1309
|
-
arcs.push(v);
|
|
1310
|
-
}
|
|
1311
|
-
return arcs;
|
|
1312
|
-
}
|
|
1313
|
-
function isDictionary(v) {
|
|
1314
|
-
return typeof v === "object" && v !== null && !Array.isArray(v) && !(v instanceof Quat) && !(v instanceof UsdMatrix) && !(v instanceof AssetPath);
|
|
1315
|
-
}
|
|
1316
|
-
function stripKeys(meta, keys) {
|
|
1317
|
-
const out = {};
|
|
1318
|
-
for (const [k, v] of Object.entries(meta)) {
|
|
1319
|
-
if (!keys.includes(k)) out[k] = v;
|
|
1320
|
-
}
|
|
1321
|
-
return out;
|
|
1322
|
-
}
|
|
1323
|
-
var USD_ENTRY = /\.(usda|usdc|usd)$/i;
|
|
1324
|
-
function openUsdz(bytes) {
|
|
1325
|
-
const entries = unzipSync(bytes);
|
|
1326
|
-
const names = Object.keys(entries);
|
|
1327
|
-
const rootEntry = names.find((n) => USD_ENTRY.test(n)) ?? names[0];
|
|
1328
|
-
if (!rootEntry) throw new Error("usdz package contains no entries");
|
|
1329
|
-
const decoder = new TextDecoder();
|
|
1330
|
-
const resolver = {
|
|
1331
|
-
resolve(assetPath, baseUrl) {
|
|
1332
|
-
return joinPosix(baseUrl, assetPath);
|
|
1333
|
-
},
|
|
1334
|
-
fetchText(url) {
|
|
1335
|
-
const data = entries[url] ?? entries[url.replace(/^\/+/, "")];
|
|
1336
|
-
if (!data) return Promise.reject(new Error(`not found in usdz: ${url}`));
|
|
1337
|
-
if (/\.usdc$/i.test(url)) {
|
|
1338
|
-
return Promise.reject(
|
|
1339
|
-
new Error(`USDC (binary crate) entries are not supported yet (M10): ${url}`)
|
|
1340
|
-
);
|
|
1341
|
-
}
|
|
1342
|
-
return Promise.resolve(decoder.decode(data));
|
|
1343
|
-
}
|
|
1344
|
-
};
|
|
1345
|
-
return { rootEntry, resolver };
|
|
1346
|
-
}
|
|
1347
|
-
|
|
1348
1115
|
// src/usd/crate/lz4.ts
|
|
1349
1116
|
var MAX_CHUNK_INPUT = 2113929216;
|
|
1350
1117
|
function lz4DecompressBlock(src, dst) {
|
|
@@ -1459,12 +1226,14 @@ var CrateType = {
|
|
|
1459
1226
|
Vec4f: 28,
|
|
1460
1227
|
TokenListOp: 32,
|
|
1461
1228
|
PathListOp: 34,
|
|
1229
|
+
ReferenceListOp: 35,
|
|
1462
1230
|
IntListOp: 36,
|
|
1463
1231
|
PathVector: 40,
|
|
1464
1232
|
TokenVector: 41,
|
|
1465
1233
|
Specifier: 42,
|
|
1466
1234
|
Permission: 43,
|
|
1467
|
-
Variability: 44
|
|
1235
|
+
Variability: 44,
|
|
1236
|
+
PayloadListOp: 55};
|
|
1468
1237
|
var ListOpBits = {
|
|
1469
1238
|
HasExplicit: 1 << 1,
|
|
1470
1239
|
HasAdded: 1 << 2,
|
|
@@ -1811,6 +1580,10 @@ var CrateReader = class {
|
|
|
1811
1580
|
return this.readListOp(off, "token");
|
|
1812
1581
|
case CrateType.PathListOp:
|
|
1813
1582
|
return this.readListOp(off, "path");
|
|
1583
|
+
case CrateType.ReferenceListOp:
|
|
1584
|
+
return this.readArcListOp(off, true);
|
|
1585
|
+
case CrateType.PayloadListOp:
|
|
1586
|
+
return this.readArcListOp(off, false);
|
|
1814
1587
|
case CrateType.TokenVector:
|
|
1815
1588
|
return this.readIndexVector(off, "token").items;
|
|
1816
1589
|
case CrateType.PathVector:
|
|
@@ -1914,6 +1687,41 @@ var CrateReader = class {
|
|
|
1914
1687
|
if (bits & ListOpBits.HasOrdered) read([]);
|
|
1915
1688
|
return [...explicit, ...prepended, ...added, ...appended];
|
|
1916
1689
|
}
|
|
1690
|
+
/**
|
|
1691
|
+
* Read a Reference/Payload list-op into composition arcs. Each item is
|
|
1692
|
+
* `[assetPath: string-index][primPath: path-index][layerOffset: 2 doubles]`,
|
|
1693
|
+
* and a Reference additionally carries a (usually empty) customData dict.
|
|
1694
|
+
*/
|
|
1695
|
+
readArcListOp(off, isReference) {
|
|
1696
|
+
const bits = this.bytes[off];
|
|
1697
|
+
let p = off + 1;
|
|
1698
|
+
const out = [];
|
|
1699
|
+
const readList = (collect) => {
|
|
1700
|
+
const count = this.u64(p);
|
|
1701
|
+
p += 8;
|
|
1702
|
+
for (let i = 0; i < count; i++) {
|
|
1703
|
+
const assetStrIndex = this.view.getUint32(p, true);
|
|
1704
|
+
p += 4;
|
|
1705
|
+
const primPathIndex = this.view.getInt32(p, true);
|
|
1706
|
+
p += 4;
|
|
1707
|
+
p += 16;
|
|
1708
|
+
if (isReference) p += 8;
|
|
1709
|
+
if (!collect) continue;
|
|
1710
|
+
const assetPath = this.getToken(this.getStrings()[assetStrIndex] ?? -1);
|
|
1711
|
+
const primPath = this.getPaths()[primPathIndex] ?? "";
|
|
1712
|
+
const arc = { assetPath: new AssetPath(assetPath) };
|
|
1713
|
+
if (primPath) arc.primPath = primPath;
|
|
1714
|
+
out.push(arc);
|
|
1715
|
+
}
|
|
1716
|
+
};
|
|
1717
|
+
if (bits & ListOpBits.HasExplicit) readList(true);
|
|
1718
|
+
if (bits & ListOpBits.HasAdded) readList(true);
|
|
1719
|
+
if (bits & ListOpBits.HasPrepended) readList(true);
|
|
1720
|
+
if (bits & ListOpBits.HasAppended) readList(true);
|
|
1721
|
+
if (bits & ListOpBits.HasDeleted) readList(false);
|
|
1722
|
+
if (bits & ListOpBits.HasOrdered) readList(false);
|
|
1723
|
+
return out;
|
|
1724
|
+
}
|
|
1917
1725
|
};
|
|
1918
1726
|
function appendElement(parent, elem, isProperty) {
|
|
1919
1727
|
if (isProperty) return `${parent}.${elem}`;
|
|
@@ -1957,108 +1765,410 @@ function crateToUsdaFile(crate) {
|
|
|
1957
1765
|
layerMetadata = buildLayerMetadata(crate, fieldsOf(spec.fieldSetIndex));
|
|
1958
1766
|
continue;
|
|
1959
1767
|
}
|
|
1960
|
-
if (spec.specType !== SPEC_PRIM) continue;
|
|
1961
|
-
const fm = fieldsOf(spec.fieldSetIndex);
|
|
1962
|
-
primByPath.set(path, {
|
|
1963
|
-
specifier: SPECIFIERS2[asNumber(crate, fm.get("specifier")) ?? 0] ?? "def",
|
|
1964
|
-
typeName: asString(crate, fm.get("typeName")) ?? "",
|
|
1965
|
-
name: leaf(path),
|
|
1966
|
-
metadata: buildPrimMetadata(crate, fm),
|
|
1967
|
-
properties: [],
|
|
1968
|
-
children: [],
|
|
1969
|
-
line: 0
|
|
1768
|
+
if (spec.specType !== SPEC_PRIM) continue;
|
|
1769
|
+
const fm = fieldsOf(spec.fieldSetIndex);
|
|
1770
|
+
primByPath.set(path, {
|
|
1771
|
+
specifier: SPECIFIERS2[asNumber(crate, fm.get("specifier")) ?? 0] ?? "def",
|
|
1772
|
+
typeName: asString(crate, fm.get("typeName")) ?? "",
|
|
1773
|
+
name: leaf(path),
|
|
1774
|
+
metadata: buildPrimMetadata(crate, fm),
|
|
1775
|
+
properties: [],
|
|
1776
|
+
children: [],
|
|
1777
|
+
line: 0
|
|
1778
|
+
});
|
|
1779
|
+
}
|
|
1780
|
+
for (const spec of specs) {
|
|
1781
|
+
if (spec.specType !== SPEC_ATTRIBUTE && spec.specType !== SPEC_RELATIONSHIP) continue;
|
|
1782
|
+
const split = splitProperty(paths[spec.pathIndex] ?? "");
|
|
1783
|
+
if (!split) continue;
|
|
1784
|
+
const prim = primByPath.get(split.primPath);
|
|
1785
|
+
if (!prim) continue;
|
|
1786
|
+
const fm = fieldsOf(spec.fieldSetIndex);
|
|
1787
|
+
prim.properties.push(
|
|
1788
|
+
spec.specType === SPEC_ATTRIBUTE ? buildAttribute(crate, split.propName, fm) : buildRelationship(crate, split.propName, fm)
|
|
1789
|
+
);
|
|
1790
|
+
}
|
|
1791
|
+
for (const [path, prim] of primByPath) {
|
|
1792
|
+
const parentPath = parentOf(path);
|
|
1793
|
+
if (parentPath === "/") rootPrims.push(prim);
|
|
1794
|
+
else primByPath.get(parentPath)?.children.push(prim);
|
|
1795
|
+
}
|
|
1796
|
+
return { version: crate.version.join("."), metadata: layerMetadata, prims: rootPrims };
|
|
1797
|
+
}
|
|
1798
|
+
function buildAttribute(crate, name, fm) {
|
|
1799
|
+
const defaultRep = fm.get("default");
|
|
1800
|
+
const attr = {
|
|
1801
|
+
kind: "attribute",
|
|
1802
|
+
name,
|
|
1803
|
+
typeName: asString(crate, fm.get("typeName")) ?? "",
|
|
1804
|
+
isArray: defaultRep !== void 0 ? decodeRepBits(defaultRep).isArray : false,
|
|
1805
|
+
variability: asNumber(crate, fm.get("variability")) === 1 ? "uniform" : "varying",
|
|
1806
|
+
custom: false,
|
|
1807
|
+
metadata: {},
|
|
1808
|
+
line: 0
|
|
1809
|
+
};
|
|
1810
|
+
if (defaultRep !== void 0) {
|
|
1811
|
+
const value = crate.getValue(defaultRep);
|
|
1812
|
+
if (value !== void 0) attr.value = value;
|
|
1813
|
+
}
|
|
1814
|
+
return attr;
|
|
1815
|
+
}
|
|
1816
|
+
function buildRelationship(crate, name, fm) {
|
|
1817
|
+
const targetsValue = fm.has("targetPaths") ? crate.getValue(fm.get("targetPaths")) : void 0;
|
|
1818
|
+
const targets = Array.isArray(targetsValue) ? targetsValue.filter((t) => typeof t === "string") : [];
|
|
1819
|
+
return {
|
|
1820
|
+
kind: "relationship",
|
|
1821
|
+
name,
|
|
1822
|
+
custom: false,
|
|
1823
|
+
listOp: "explicit",
|
|
1824
|
+
targets,
|
|
1825
|
+
metadata: {},
|
|
1826
|
+
line: 0
|
|
1827
|
+
};
|
|
1828
|
+
}
|
|
1829
|
+
var ARC_FIELDS = ["references", "payload", "payloads", "inherits", "specializes"];
|
|
1830
|
+
function buildPrimMetadata(crate, fm) {
|
|
1831
|
+
const meta = {};
|
|
1832
|
+
const apiSchemas = fm.has("apiSchemas") ? crate.getValue(fm.get("apiSchemas")) : void 0;
|
|
1833
|
+
if (Array.isArray(apiSchemas)) meta.apiSchemas = apiSchemas;
|
|
1834
|
+
const kind = asString(crate, fm.get("kind"));
|
|
1835
|
+
if (kind !== void 0) meta.kind = kind;
|
|
1836
|
+
for (const key of ARC_FIELDS) {
|
|
1837
|
+
if (!fm.has(key)) continue;
|
|
1838
|
+
const arcs = crate.getValue(fm.get(key));
|
|
1839
|
+
if (Array.isArray(arcs) && arcs.length > 0) meta[key] = arcs;
|
|
1840
|
+
}
|
|
1841
|
+
return meta;
|
|
1842
|
+
}
|
|
1843
|
+
function buildLayerMetadata(crate, fm) {
|
|
1844
|
+
const meta = {};
|
|
1845
|
+
const upAxis = asString(crate, fm.get("upAxis"));
|
|
1846
|
+
if (upAxis !== void 0) meta.upAxis = upAxis;
|
|
1847
|
+
const defaultPrim2 = asString(crate, fm.get("defaultPrim"));
|
|
1848
|
+
if (defaultPrim2 !== void 0) meta.defaultPrim = defaultPrim2;
|
|
1849
|
+
const metersPerUnit = asNumber(crate, fm.get("metersPerUnit"));
|
|
1850
|
+
if (metersPerUnit !== void 0) meta.metersPerUnit = metersPerUnit;
|
|
1851
|
+
return meta;
|
|
1852
|
+
}
|
|
1853
|
+
function asString(crate, rep) {
|
|
1854
|
+
if (rep === void 0) return void 0;
|
|
1855
|
+
const v = crate.getValue(rep);
|
|
1856
|
+
return typeof v === "string" ? v : void 0;
|
|
1857
|
+
}
|
|
1858
|
+
function asNumber(crate, rep) {
|
|
1859
|
+
if (rep === void 0) return void 0;
|
|
1860
|
+
const v = crate.getValue(rep);
|
|
1861
|
+
return typeof v === "number" ? v : void 0;
|
|
1862
|
+
}
|
|
1863
|
+
function splitProperty(path) {
|
|
1864
|
+
const slash = path.lastIndexOf("/");
|
|
1865
|
+
const dot = path.indexOf(".", slash < 0 ? 0 : slash);
|
|
1866
|
+
if (dot === -1) return null;
|
|
1867
|
+
if (path.includes("[")) return null;
|
|
1868
|
+
return { primPath: path.slice(0, dot), propName: path.slice(dot + 1) };
|
|
1869
|
+
}
|
|
1870
|
+
function parentOf(path) {
|
|
1871
|
+
const i = path.lastIndexOf("/");
|
|
1872
|
+
return i <= 0 ? "/" : path.slice(0, i);
|
|
1873
|
+
}
|
|
1874
|
+
function leaf(path) {
|
|
1875
|
+
return path.slice(path.lastIndexOf("/") + 1);
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
// src/usd/composition.ts
|
|
1879
|
+
var ARC_KEYS = ["references", "payload", "payloads", "inherits", "specializes"];
|
|
1880
|
+
var STRIP_KEYS = [...ARC_KEYS, "variants", "variantSets"];
|
|
1881
|
+
async function composeLayer(text, baseUrl, resolver, options = {}, stack = /* @__PURE__ */ new Set()) {
|
|
1882
|
+
return composeFile(parseUsda(text), baseUrl, resolver, options, stack);
|
|
1883
|
+
}
|
|
1884
|
+
async function composeFile(file, baseUrl, resolver, options = {}, stack = /* @__PURE__ */ new Set()) {
|
|
1885
|
+
const warn = options.onWarn ?? (() => {
|
|
1886
|
+
});
|
|
1887
|
+
let weak = [];
|
|
1888
|
+
const subLayers = toArcs(file.metadata.subLayers);
|
|
1889
|
+
for (let i = subLayers.length - 1; i >= 0; i--) {
|
|
1890
|
+
const sub = await loadExternalFile(subLayers[i], baseUrl, resolver, options, stack, warn);
|
|
1891
|
+
if (sub) weak = mergePrimLists(weak, sub.prims);
|
|
1892
|
+
}
|
|
1893
|
+
const ctx = {
|
|
1894
|
+
baseUrl,
|
|
1895
|
+
resolver,
|
|
1896
|
+
options,
|
|
1897
|
+
warn,
|
|
1898
|
+
stack,
|
|
1899
|
+
index: buildPathIndex(file.prims),
|
|
1900
|
+
resolving: /* @__PURE__ */ new Set()
|
|
1901
|
+
};
|
|
1902
|
+
const resolved = [];
|
|
1903
|
+
for (const prim of file.prims) resolved.push(await resolvePrim(prim, "", ctx));
|
|
1904
|
+
const prims = weak.length > 0 ? mergePrimLists(weak, resolved) : resolved;
|
|
1905
|
+
return { version: file.version, metadata: stripKeys(file.metadata, STRIP_KEYS), prims };
|
|
1906
|
+
}
|
|
1907
|
+
async function resolvePrim(spec, parentPath, ctx) {
|
|
1908
|
+
const path = `${parentPath}/${spec.name}`;
|
|
1909
|
+
let properties = spec.properties;
|
|
1910
|
+
let children = spec.children;
|
|
1911
|
+
const selection = spec.metadata.variants;
|
|
1912
|
+
if (spec.variantSets && isDictionary(selection)) {
|
|
1913
|
+
for (const [setName, variantName] of Object.entries(selection)) {
|
|
1914
|
+
const variant = spec.variantSets[setName]?.[String(variantName)];
|
|
1915
|
+
if (!variant) continue;
|
|
1916
|
+
properties = mergeProperties(variant.properties, properties);
|
|
1917
|
+
children = mergePrimLists(variant.children, children);
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
const resolvedChildren = [];
|
|
1921
|
+
for (const child of children) resolvedChildren.push(await resolvePrim(child, path, ctx));
|
|
1922
|
+
const local = {
|
|
1923
|
+
specifier: spec.specifier,
|
|
1924
|
+
typeName: spec.typeName,
|
|
1925
|
+
name: spec.name,
|
|
1926
|
+
metadata: stripKeys(spec.metadata, STRIP_KEYS),
|
|
1927
|
+
properties,
|
|
1928
|
+
children: resolvedChildren,
|
|
1929
|
+
line: spec.line
|
|
1930
|
+
};
|
|
1931
|
+
const arcs = ARC_KEYS.flatMap((k) => toArcs(spec.metadata[k]));
|
|
1932
|
+
let base = null;
|
|
1933
|
+
for (const arc of arcs) {
|
|
1934
|
+
const target = await loadReferencedPrim(arc, ctx, path);
|
|
1935
|
+
if (target) base = base ? mergePrim(target, base) : target;
|
|
1936
|
+
}
|
|
1937
|
+
return base ? mergePrim(base, local) : local;
|
|
1938
|
+
}
|
|
1939
|
+
async function loadReferencedPrim(arc, ctx, destPath) {
|
|
1940
|
+
if (arc.assetPath) {
|
|
1941
|
+
const composed = await loadExternalFile(
|
|
1942
|
+
arc,
|
|
1943
|
+
ctx.baseUrl,
|
|
1944
|
+
ctx.resolver,
|
|
1945
|
+
ctx.options,
|
|
1946
|
+
ctx.stack,
|
|
1947
|
+
ctx.warn
|
|
1948
|
+
);
|
|
1949
|
+
if (!composed) return null;
|
|
1950
|
+
const target = arc.primPath ? findPrimByPath(composed, arc.primPath) : defaultPrim(composed, ctx.warn);
|
|
1951
|
+
if (!target) {
|
|
1952
|
+
ctx.warn(
|
|
1953
|
+
`reference target ${arc.primPath ?? "(defaultPrim)"} not found in ${arc.assetPath.path}`
|
|
1954
|
+
);
|
|
1955
|
+
return null;
|
|
1956
|
+
}
|
|
1957
|
+
const sourceRoot = arc.primPath ?? `/${target.name}`;
|
|
1958
|
+
return remapPaths(target, sourceRoot, destPath);
|
|
1959
|
+
}
|
|
1960
|
+
if (arc.primPath) {
|
|
1961
|
+
if (ctx.resolving.has(arc.primPath)) {
|
|
1962
|
+
ctx.warn(`internal composition cycle at ${arc.primPath}; skipping`);
|
|
1963
|
+
return null;
|
|
1964
|
+
}
|
|
1965
|
+
const target = ctx.index.get(arc.primPath);
|
|
1966
|
+
if (!target) {
|
|
1967
|
+
ctx.warn(`internal reference target ${arc.primPath} not found`);
|
|
1968
|
+
return null;
|
|
1969
|
+
}
|
|
1970
|
+
const parentPath = arc.primPath.slice(0, arc.primPath.lastIndexOf("/"));
|
|
1971
|
+
const composed = await resolvePrim(target, parentPath, {
|
|
1972
|
+
...ctx,
|
|
1973
|
+
resolving: /* @__PURE__ */ new Set([...ctx.resolving, arc.primPath])
|
|
1970
1974
|
});
|
|
1975
|
+
return remapPaths(composed, arc.primPath, destPath);
|
|
1971
1976
|
}
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
spec.specType === SPEC_ATTRIBUTE ? buildAttribute(crate, split.propName, fm) : buildRelationship(crate, split.propName, fm)
|
|
1981
|
-
);
|
|
1977
|
+
return null;
|
|
1978
|
+
}
|
|
1979
|
+
async function loadExternalFile(arc, baseUrl, resolver, options, stack, warn) {
|
|
1980
|
+
if (!arc.assetPath) return null;
|
|
1981
|
+
const url = resolver.resolve(arc.assetPath.path, baseUrl);
|
|
1982
|
+
if (stack.has(url)) {
|
|
1983
|
+
warn(`composition cycle detected at ${url}; skipping`);
|
|
1984
|
+
return null;
|
|
1982
1985
|
}
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
else primByPath.get(parentPath)?.children.push(prim);
|
|
1986
|
+
if (stack.size >= (options.maxDepth ?? 64)) {
|
|
1987
|
+
warn(`composition exceeded max depth at ${url}; skipping`);
|
|
1988
|
+
return null;
|
|
1987
1989
|
}
|
|
1988
|
-
|
|
1990
|
+
let bytes;
|
|
1991
|
+
try {
|
|
1992
|
+
bytes = await fetchLayerBytes(resolver, url);
|
|
1993
|
+
} catch (err) {
|
|
1994
|
+
warn(`cannot resolve "${arc.assetPath.path}" -> ${url}: ${err.message}`);
|
|
1995
|
+
return null;
|
|
1996
|
+
}
|
|
1997
|
+
const childStack = /* @__PURE__ */ new Set([...stack, url]);
|
|
1998
|
+
if (CrateReader.isCrate(bytes)) {
|
|
1999
|
+
return composeFile(crateToUsdaFile(new CrateReader(bytes)), url, resolver, options, childStack);
|
|
2000
|
+
}
|
|
2001
|
+
return composeLayer(new TextDecoder().decode(bytes), url, resolver, options, childStack);
|
|
1989
2002
|
}
|
|
1990
|
-
function
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
line: 0
|
|
2003
|
+
async function fetchLayerBytes(resolver, url) {
|
|
2004
|
+
if (resolver.fetchBytes) return resolver.fetchBytes(url);
|
|
2005
|
+
return new TextEncoder().encode(await resolver.fetchText(url));
|
|
2006
|
+
}
|
|
2007
|
+
function remapPaths(prim, from, to) {
|
|
2008
|
+
if (from === to) return prim;
|
|
2009
|
+
return {
|
|
2010
|
+
...prim,
|
|
2011
|
+
properties: prim.properties.map((p) => remapProperty(p, from, to)),
|
|
2012
|
+
children: prim.children.map((c) => remapPaths(c, from, to))
|
|
2001
2013
|
};
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2014
|
+
}
|
|
2015
|
+
function remapProperty(prop, from, to) {
|
|
2016
|
+
if (prop.kind === "relationship") {
|
|
2017
|
+
return { ...prop, targets: prop.targets.map((t) => remapPath(t, from, to)) };
|
|
2005
2018
|
}
|
|
2006
|
-
|
|
2019
|
+
if (prop.kind === "attribute" && prop.connections) {
|
|
2020
|
+
return { ...prop, connections: prop.connections.map((c) => remapPath(c, from, to)) };
|
|
2021
|
+
}
|
|
2022
|
+
return prop;
|
|
2007
2023
|
}
|
|
2008
|
-
function
|
|
2009
|
-
|
|
2010
|
-
|
|
2024
|
+
function remapPath(path, from, to) {
|
|
2025
|
+
if (path === from) return to;
|
|
2026
|
+
if (path.startsWith(from) && /[/.[{]/.test(path[from.length] ?? "")) {
|
|
2027
|
+
return to + path.slice(from.length);
|
|
2028
|
+
}
|
|
2029
|
+
return path;
|
|
2030
|
+
}
|
|
2031
|
+
function mergePrim(base, over) {
|
|
2011
2032
|
return {
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
line:
|
|
2033
|
+
specifier: over.specifier === "over" ? base.specifier : over.specifier,
|
|
2034
|
+
typeName: over.typeName || base.typeName,
|
|
2035
|
+
name: over.name,
|
|
2036
|
+
metadata: mergeMetadata(base.metadata, over.metadata),
|
|
2037
|
+
properties: mergeProperties(base.properties, over.properties),
|
|
2038
|
+
children: mergePrimLists(base.children, over.children),
|
|
2039
|
+
line: over.line
|
|
2019
2040
|
};
|
|
2020
2041
|
}
|
|
2021
|
-
function
|
|
2022
|
-
const
|
|
2023
|
-
const
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2042
|
+
function mergePrimLists(base, over) {
|
|
2043
|
+
const byName = /* @__PURE__ */ new Map();
|
|
2044
|
+
for (const p of base) byName.set(p.name, p);
|
|
2045
|
+
for (const p of over) {
|
|
2046
|
+
const existing = byName.get(p.name);
|
|
2047
|
+
byName.set(p.name, existing ? mergePrim(existing, p) : p);
|
|
2048
|
+
}
|
|
2049
|
+
return [...byName.values()];
|
|
2028
2050
|
}
|
|
2029
|
-
function
|
|
2030
|
-
const
|
|
2031
|
-
const
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
return meta;
|
|
2051
|
+
function mergeProperties(base, over) {
|
|
2052
|
+
const byName = /* @__PURE__ */ new Map();
|
|
2053
|
+
for (const p of base) byName.set(p.name, p);
|
|
2054
|
+
for (const p of over) {
|
|
2055
|
+
const existing = byName.get(p.name);
|
|
2056
|
+
byName.set(p.name, existing ? mergeProperty(existing, p) : p);
|
|
2057
|
+
}
|
|
2058
|
+
return [...byName.values()];
|
|
2038
2059
|
}
|
|
2039
|
-
function
|
|
2040
|
-
if (
|
|
2041
|
-
|
|
2042
|
-
|
|
2060
|
+
function mergeProperty(base, over) {
|
|
2061
|
+
if (base.kind !== over.kind) return over;
|
|
2062
|
+
if (base.kind === "attribute" && over.kind === "attribute") {
|
|
2063
|
+
const merged = {
|
|
2064
|
+
...over,
|
|
2065
|
+
typeName: over.typeName || base.typeName,
|
|
2066
|
+
metadata: mergeMetadata(base.metadata, over.metadata)
|
|
2067
|
+
};
|
|
2068
|
+
const value = over.value !== void 0 ? over.value : base.value;
|
|
2069
|
+
if (value !== void 0) merged.value = value;
|
|
2070
|
+
const timeSamples = over.timeSamples ?? base.timeSamples;
|
|
2071
|
+
if (timeSamples) merged.timeSamples = timeSamples;
|
|
2072
|
+
const connections = over.connections ?? base.connections;
|
|
2073
|
+
if (connections) merged.connections = connections;
|
|
2074
|
+
return merged;
|
|
2075
|
+
}
|
|
2076
|
+
if (base.kind === "relationship" && over.kind === "relationship") {
|
|
2077
|
+
return {
|
|
2078
|
+
...over,
|
|
2079
|
+
targets: over.targets.length > 0 ? over.targets : base.targets,
|
|
2080
|
+
metadata: mergeMetadata(base.metadata, over.metadata)
|
|
2081
|
+
};
|
|
2082
|
+
}
|
|
2083
|
+
return over;
|
|
2043
2084
|
}
|
|
2044
|
-
function
|
|
2045
|
-
|
|
2046
|
-
const
|
|
2047
|
-
|
|
2085
|
+
function mergeMetadata(base, over) {
|
|
2086
|
+
const merged = { ...base, ...over };
|
|
2087
|
+
const a = base.apiSchemas;
|
|
2088
|
+
const b = over.apiSchemas;
|
|
2089
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
2090
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2091
|
+
const union = [];
|
|
2092
|
+
for (const v of [...Array.isArray(a) ? a : [], ...Array.isArray(b) ? b : []]) {
|
|
2093
|
+
if (!seen.has(v)) {
|
|
2094
|
+
seen.add(v);
|
|
2095
|
+
union.push(v);
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
merged.apiSchemas = union;
|
|
2099
|
+
}
|
|
2100
|
+
return merged;
|
|
2048
2101
|
}
|
|
2049
|
-
function
|
|
2050
|
-
const
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2102
|
+
function buildPathIndex(prims, parent = "/", map = /* @__PURE__ */ new Map()) {
|
|
2103
|
+
for (const p of prims) {
|
|
2104
|
+
const path = parent === "/" ? `/${p.name}` : `${parent}/${p.name}`;
|
|
2105
|
+
map.set(path, p);
|
|
2106
|
+
buildPathIndex(p.children, path, map);
|
|
2107
|
+
}
|
|
2108
|
+
return map;
|
|
2055
2109
|
}
|
|
2056
|
-
function
|
|
2057
|
-
const
|
|
2058
|
-
|
|
2110
|
+
function findPrimByPath(file, path) {
|
|
2111
|
+
const segments = path.split("/").filter(Boolean);
|
|
2112
|
+
let level = file.prims;
|
|
2113
|
+
let found = null;
|
|
2114
|
+
for (const seg of segments) {
|
|
2115
|
+
found = level.find((p) => p.name === seg) ?? null;
|
|
2116
|
+
if (!found) return null;
|
|
2117
|
+
level = found.children;
|
|
2118
|
+
}
|
|
2119
|
+
return found;
|
|
2059
2120
|
}
|
|
2060
|
-
function
|
|
2061
|
-
|
|
2121
|
+
function defaultPrim(file, warn) {
|
|
2122
|
+
const name = file.metadata.defaultPrim;
|
|
2123
|
+
if (typeof name === "string") return file.prims.find((p) => p.name === name) ?? null;
|
|
2124
|
+
const first = file.prims[0];
|
|
2125
|
+
if (first) warn(`referenced layer has no defaultPrim; using first root prim "${first.name}"`);
|
|
2126
|
+
return first ?? null;
|
|
2127
|
+
}
|
|
2128
|
+
function toArcs(value) {
|
|
2129
|
+
if (value === void 0) return [];
|
|
2130
|
+
const list = Array.isArray(value) ? value : [value];
|
|
2131
|
+
const arcs = [];
|
|
2132
|
+
for (const v of list) {
|
|
2133
|
+
if (v instanceof AssetPath) arcs.push({ assetPath: v });
|
|
2134
|
+
else if (v && typeof v === "object" && ("assetPath" in v || "primPath" in v))
|
|
2135
|
+
arcs.push(v);
|
|
2136
|
+
}
|
|
2137
|
+
return arcs;
|
|
2138
|
+
}
|
|
2139
|
+
function isDictionary(v) {
|
|
2140
|
+
return typeof v === "object" && v !== null && !Array.isArray(v) && !(v instanceof Quat) && !(v instanceof UsdMatrix) && !(v instanceof AssetPath);
|
|
2141
|
+
}
|
|
2142
|
+
function stripKeys(meta, keys) {
|
|
2143
|
+
const out = {};
|
|
2144
|
+
for (const [k, v] of Object.entries(meta)) {
|
|
2145
|
+
if (!keys.includes(k)) out[k] = v;
|
|
2146
|
+
}
|
|
2147
|
+
return out;
|
|
2148
|
+
}
|
|
2149
|
+
var USD_ENTRY = /\.(usda|usdc|usd)$/i;
|
|
2150
|
+
function openUsdz(bytes) {
|
|
2151
|
+
const entries = unzipSync(bytes);
|
|
2152
|
+
const names = Object.keys(entries);
|
|
2153
|
+
const rootEntry = names.find((n) => USD_ENTRY.test(n)) ?? names[0];
|
|
2154
|
+
if (!rootEntry) throw new Error("usdz package contains no entries");
|
|
2155
|
+
const decoder = new TextDecoder();
|
|
2156
|
+
const resolver = {
|
|
2157
|
+
resolve(assetPath, baseUrl) {
|
|
2158
|
+
return joinPosix(baseUrl, assetPath);
|
|
2159
|
+
},
|
|
2160
|
+
fetchText(url) {
|
|
2161
|
+
const data = entries[url] ?? entries[url.replace(/^\/+/, "")];
|
|
2162
|
+
if (!data) return Promise.reject(new Error(`not found in usdz: ${url}`));
|
|
2163
|
+
if (/\.usdc$/i.test(url)) {
|
|
2164
|
+
return Promise.reject(
|
|
2165
|
+
new Error(`USDC (binary crate) entries are not supported yet (M10): ${url}`)
|
|
2166
|
+
);
|
|
2167
|
+
}
|
|
2168
|
+
return Promise.resolve(decoder.decode(data));
|
|
2169
|
+
}
|
|
2170
|
+
};
|
|
2171
|
+
return { rootEntry, resolver };
|
|
2062
2172
|
}
|
|
2063
2173
|
|
|
2064
2174
|
// src/kinematics/transforms.ts
|
|
@@ -2406,6 +2516,33 @@ function asMatrix(v, where) {
|
|
|
2406
2516
|
throw new Error(`${where}: expected a matrix`);
|
|
2407
2517
|
}
|
|
2408
2518
|
|
|
2519
|
+
// src/kinematics/sampling.ts
|
|
2520
|
+
function interpolate(channel, t) {
|
|
2521
|
+
const { times, values } = channel;
|
|
2522
|
+
const n = times.length;
|
|
2523
|
+
if (n === 0) return 0;
|
|
2524
|
+
if (t <= times[0]) return values[0];
|
|
2525
|
+
if (t >= times[n - 1]) return values[n - 1];
|
|
2526
|
+
let lo = 0;
|
|
2527
|
+
let hi = n - 1;
|
|
2528
|
+
while (lo < hi) {
|
|
2529
|
+
const mid = lo + hi >> 1;
|
|
2530
|
+
if (times[mid] <= t) lo = mid + 1;
|
|
2531
|
+
else hi = mid;
|
|
2532
|
+
}
|
|
2533
|
+
const i = lo - 1;
|
|
2534
|
+
const t0 = times[i];
|
|
2535
|
+
const t1 = times[i + 1];
|
|
2536
|
+
const span = t1 - t0;
|
|
2537
|
+
const f = span > 0 ? (t - t0) / span : 0;
|
|
2538
|
+
return values[i] + (values[i + 1] - values[i]) * f;
|
|
2539
|
+
}
|
|
2540
|
+
function channelFromSamples(samples) {
|
|
2541
|
+
const times = [...samples.keys()].sort((a, b) => a - b);
|
|
2542
|
+
const values = times.map((t) => samples.get(t) ?? 0);
|
|
2543
|
+
return { times, values };
|
|
2544
|
+
}
|
|
2545
|
+
|
|
2409
2546
|
// src/schemas/usdGeom.ts
|
|
2410
2547
|
function isXform(prim) {
|
|
2411
2548
|
return prim.GetTypeName() === "Xform";
|
|
@@ -2683,8 +2820,13 @@ function extractRobotDescription(stage, options = {}) {
|
|
|
2683
2820
|
joints,
|
|
2684
2821
|
upAxis: stage.GetUpAxis(),
|
|
2685
2822
|
metersPerUnit: stage.GetMetersPerUnit(),
|
|
2823
|
+
timeCodesPerSecond: stage.GetTimeCodesPerSecond(),
|
|
2686
2824
|
...articulationRoots.length ? { articulationRoots } : {}
|
|
2687
2825
|
};
|
|
2826
|
+
const startTimeCode = stage.GetStartTimeCode();
|
|
2827
|
+
if (startTimeCode !== void 0) robot.startTimeCode = startTimeCode;
|
|
2828
|
+
const endTimeCode = stage.GetEndTimeCode();
|
|
2829
|
+
if (endTimeCode !== void 0) robot.endTimeCode = endTimeCode;
|
|
2688
2830
|
const tree = buildKinematicTree(robot, { onWarn: warn });
|
|
2689
2831
|
robot.rootLink = tree.root;
|
|
2690
2832
|
if (tree.loopJoints.length) robot.loopJoints = tree.loopJoints;
|
|
@@ -2747,6 +2889,17 @@ function buildJoint(prim, linkKeyByPath, warn) {
|
|
|
2747
2889
|
...drive.maxForce !== void 0 ? { maxForce: drive.maxForce } : {}
|
|
2748
2890
|
};
|
|
2749
2891
|
if (Object.keys(driveDesc).length > 0) joint.drive = driveDesc;
|
|
2892
|
+
const stateSamples = prim.GetAttribute(`state:${kind}:physics:position`).GetTimeSamples();
|
|
2893
|
+
const driveSamples = prim.GetAttribute(`drive:${kind}:physics:targetPosition`).GetTimeSamples();
|
|
2894
|
+
const samples = stateSamples.size > 0 ? stateSamples : driveSamples;
|
|
2895
|
+
if (samples.size > 0) {
|
|
2896
|
+
const times = [...samples.keys()].sort((a, b) => a - b);
|
|
2897
|
+
const values = times.map((t) => {
|
|
2898
|
+
const v = samples.get(t);
|
|
2899
|
+
return typeof v === "number" ? jointValueToSI(angular, v) : 0;
|
|
2900
|
+
});
|
|
2901
|
+
joint.valueSamples = { times, values };
|
|
2902
|
+
}
|
|
2750
2903
|
return joint;
|
|
2751
2904
|
}
|
|
2752
2905
|
function buildKeyMap(paths) {
|
|
@@ -2767,6 +2920,6 @@ function leafName(path) {
|
|
|
2767
2920
|
return parts[parts.length - 1] ?? path;
|
|
2768
2921
|
}
|
|
2769
2922
|
|
|
2770
|
-
export { ARTICULATION_ROOT_API, AssetPath, Attribute, COLLISION_API, CrateReader, DEFAULT_METERS_PER_UNIT, DEG2RAD, DefaultAssetResolver, Layer, PACKAGE_NAME, ParseError, Prim, Quat, RAD2DEG, RIGID_BODY_API, Relationship, Stage, TokenizeError, UsdMatrix, VERSION, buildKinematicTree, composeLayer, computeLocalTransform, crateToUsdaFile, createMemoryResolver, driveKindFor, extractRobotDescription, fromUsdMatrix, gatherMeshDescendants, getJointAxis, getJointBodies, getJointDrive, getJointLimits, getJointLocalFrame, getJointStatePosition, getJointType, getTranslation, hasArticulationRootAPI, hasCollisionAPI, hasRigidBodyAPI, identity4, invert, isMesh, isScope, isXform, iterDescendants, joinPosix, jointValueToSI, makeEuler, makeRotationFromQuat, makeRotationX, makeRotationY, makeRotationZ, makeScale, makeTranslation, multiply, multiplyAll, normalizeJointLimits, openUsdz, parseOpType, parseUsda, refineJointType, tokenize };
|
|
2771
|
-
//# sourceMappingURL=chunk-
|
|
2772
|
-
//# sourceMappingURL=chunk-
|
|
2923
|
+
export { ARTICULATION_ROOT_API, AssetPath, Attribute, COLLISION_API, CrateReader, DEFAULT_METERS_PER_UNIT, DEG2RAD, DefaultAssetResolver, Layer, PACKAGE_NAME, ParseError, Prim, Quat, RAD2DEG, RIGID_BODY_API, Relationship, Stage, TokenizeError, UsdMatrix, VERSION, buildKinematicTree, channelFromSamples, composeFile, composeLayer, computeLocalTransform, crateToUsdaFile, createMemoryResolver, driveKindFor, extractRobotDescription, fromUsdMatrix, gatherMeshDescendants, getJointAxis, getJointBodies, getJointDrive, getJointLimits, getJointLocalFrame, getJointStatePosition, getJointType, getTranslation, hasArticulationRootAPI, hasCollisionAPI, hasRigidBodyAPI, identity4, interpolate, invert, isMesh, isScope, isXform, iterDescendants, joinPosix, jointValueToSI, makeEuler, makeRotationFromQuat, makeRotationX, makeRotationY, makeRotationZ, makeScale, makeTranslation, multiply, multiplyAll, normalizeJointLimits, openUsdz, parseOpType, parseUsda, refineJointType, tokenize };
|
|
2924
|
+
//# sourceMappingURL=chunk-FYVZ7YPW.js.map
|
|
2925
|
+
//# sourceMappingURL=chunk-FYVZ7YPW.js.map
|