three-usd-robot 0.5.0 → 0.7.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 +140 -38
- package/dist/{ThreeUsdRobot-D9AOUaVh.d.ts → ThreeUsdRobot-Ljh4PDVD.d.ts} +1 -1
- package/dist/{ThreeUsdRobotLoader-BgsnuJWd.d.ts → ThreeUsdRobotLoader-BSIVFA48.d.ts} +8 -2
- package/dist/{buildKinematicTree-3oKG00Sc.d.ts → buildKinematicTree-Ccd2DIKH.d.ts} +58 -16
- package/dist/{chunk-36T6YOEX.js → chunk-4GPCBXUS.js} +857 -204
- package/dist/chunk-4GPCBXUS.js.map +1 -0
- package/dist/{chunk-Y3NXBSX3.js → chunk-FL554IS5.js} +109 -190
- package/dist/chunk-FL554IS5.js.map +1 -0
- package/dist/chunk-O7XP5FQ4.js +935 -0
- package/dist/chunk-O7XP5FQ4.js.map +1 -0
- package/dist/core.d.ts +310 -110
- package/dist/core.js +2 -2
- package/dist/extras.d.ts +2 -2
- package/dist/helpers.d.ts +2 -2
- package/dist/index.d.ts +163 -10
- package/dist/index.js +335 -3
- package/dist/index.js.map +1 -1
- package/dist/react.d.ts +4 -4
- package/dist/react.js +2 -2
- package/package.json +6 -2
- package/dist/chunk-36T6YOEX.js.map +0 -1
- package/dist/chunk-OFUMT72H.js +0 -7
- package/dist/chunk-OFUMT72H.js.map +0 -1
- package/dist/chunk-Y3NXBSX3.js.map +0 -1
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
import { unzipSync } from 'fflate';
|
|
2
2
|
|
|
3
|
+
// src/parser/ast.ts
|
|
4
|
+
var Quat = class _Quat {
|
|
5
|
+
constructor(real, imaginary) {
|
|
6
|
+
this.real = real;
|
|
7
|
+
this.imaginary = imaginary;
|
|
8
|
+
}
|
|
9
|
+
real;
|
|
10
|
+
imaginary;
|
|
11
|
+
/** Components in Three.js order `[x, y, z, w]`. */
|
|
12
|
+
toXYZW() {
|
|
13
|
+
return [this.imaginary[0], this.imaginary[1], this.imaginary[2], this.real];
|
|
14
|
+
}
|
|
15
|
+
static identity() {
|
|
16
|
+
return new _Quat(1, [0, 0, 0]);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
var UsdMatrix = class _UsdMatrix {
|
|
20
|
+
constructor(values, dim) {
|
|
21
|
+
this.values = values;
|
|
22
|
+
this.dim = dim;
|
|
23
|
+
}
|
|
24
|
+
values;
|
|
25
|
+
dim;
|
|
26
|
+
static identity4() {
|
|
27
|
+
return new _UsdMatrix([
|
|
28
|
+
1,
|
|
29
|
+
0,
|
|
30
|
+
0,
|
|
31
|
+
0,
|
|
32
|
+
0,
|
|
33
|
+
1,
|
|
34
|
+
0,
|
|
35
|
+
0,
|
|
36
|
+
0,
|
|
37
|
+
0,
|
|
38
|
+
1,
|
|
39
|
+
0,
|
|
40
|
+
0,
|
|
41
|
+
0,
|
|
42
|
+
0,
|
|
43
|
+
1
|
|
44
|
+
], 4);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
var AssetPath = class {
|
|
48
|
+
constructor(path) {
|
|
49
|
+
this.path = path;
|
|
50
|
+
}
|
|
51
|
+
path;
|
|
52
|
+
};
|
|
53
|
+
|
|
3
54
|
// src/kinematics/transforms.ts
|
|
4
55
|
var DEG2RAD = Math.PI / 180;
|
|
5
56
|
var RAD2DEG = 180 / Math.PI;
|
|
@@ -254,6 +305,226 @@ function fromUsdMatrix(m) {
|
|
|
254
305
|
function getTranslation(m) {
|
|
255
306
|
return [m[12], m[13], m[14]];
|
|
256
307
|
}
|
|
308
|
+
function toUsdMatrix(m) {
|
|
309
|
+
if (m.length !== 16) {
|
|
310
|
+
throw new Error(`expected 16 matrix elements but got ${m.length}`);
|
|
311
|
+
}
|
|
312
|
+
return new UsdMatrix([...m], 4);
|
|
313
|
+
}
|
|
314
|
+
function decomposeRigid(m) {
|
|
315
|
+
const position = [m[12], m[13], m[14]];
|
|
316
|
+
const b0 = [m[0], m[1], m[2]];
|
|
317
|
+
const b1 = [m[4], m[5], m[6]];
|
|
318
|
+
const b2 = [m[8], m[9], m[10]];
|
|
319
|
+
const EPS = 1e-6;
|
|
320
|
+
const rigid = Math.abs(norm(b0) - 1) < EPS && Math.abs(norm(b1) - 1) < EPS && Math.abs(norm(b2) - 1) < EPS && Math.abs(dot(b0, b1)) < EPS && Math.abs(dot(b1, b2)) < EPS && Math.abs(dot(b0, b2)) < EPS && dot(cross(b0, b1), b2) > 0;
|
|
321
|
+
const c0 = normalizeVec(b0);
|
|
322
|
+
const c1 = normalizeVec(subVec(b1, scaleVec(c0, dot(c0, b1))));
|
|
323
|
+
const c2 = cross(c0, c1);
|
|
324
|
+
const r11 = c0[0], r12 = c1[0], r13 = c2[0];
|
|
325
|
+
const r21 = c0[1], r22 = c1[1], r23 = c2[1];
|
|
326
|
+
const r31 = c0[2], r32 = c1[2], r33 = c2[2];
|
|
327
|
+
const trace = r11 + r22 + r33;
|
|
328
|
+
let w;
|
|
329
|
+
let x;
|
|
330
|
+
let y;
|
|
331
|
+
let z;
|
|
332
|
+
if (trace > 0) {
|
|
333
|
+
const s = 0.5 / Math.sqrt(trace + 1);
|
|
334
|
+
w = 0.25 / s;
|
|
335
|
+
x = (r32 - r23) * s;
|
|
336
|
+
y = (r13 - r31) * s;
|
|
337
|
+
z = (r21 - r12) * s;
|
|
338
|
+
} else if (r11 > r22 && r11 > r33) {
|
|
339
|
+
const s = 2 * Math.sqrt(1 + r11 - r22 - r33);
|
|
340
|
+
w = (r32 - r23) / s;
|
|
341
|
+
x = 0.25 * s;
|
|
342
|
+
y = (r12 + r21) / s;
|
|
343
|
+
z = (r13 + r31) / s;
|
|
344
|
+
} else if (r22 > r33) {
|
|
345
|
+
const s = 2 * Math.sqrt(1 + r22 - r11 - r33);
|
|
346
|
+
w = (r13 - r31) / s;
|
|
347
|
+
x = (r12 + r21) / s;
|
|
348
|
+
y = 0.25 * s;
|
|
349
|
+
z = (r23 + r32) / s;
|
|
350
|
+
} else {
|
|
351
|
+
const s = 2 * Math.sqrt(1 + r33 - r11 - r22);
|
|
352
|
+
w = (r21 - r12) / s;
|
|
353
|
+
x = (r13 + r31) / s;
|
|
354
|
+
y = (r23 + r32) / s;
|
|
355
|
+
z = 0.25 * s;
|
|
356
|
+
}
|
|
357
|
+
return { position, orientation: new Quat(w, [x, y, z]), rigid };
|
|
358
|
+
}
|
|
359
|
+
function dot(a, b) {
|
|
360
|
+
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
361
|
+
}
|
|
362
|
+
function norm(v) {
|
|
363
|
+
return Math.hypot(v[0], v[1], v[2]);
|
|
364
|
+
}
|
|
365
|
+
function subVec(a, b) {
|
|
366
|
+
return [a[0] - b[0], a[1] - b[1], a[2] - b[2]];
|
|
367
|
+
}
|
|
368
|
+
function scaleVec(v, s) {
|
|
369
|
+
return [v[0] * s, v[1] * s, v[2] * s];
|
|
370
|
+
}
|
|
371
|
+
function normalizeVec(v) {
|
|
372
|
+
const n = norm(v);
|
|
373
|
+
return n > 0 ? scaleVec(v, 1 / n) : [1, 0, 0];
|
|
374
|
+
}
|
|
375
|
+
function cross(a, b) {
|
|
376
|
+
return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// src/schemas/usdGeom.ts
|
|
380
|
+
function isXform(prim) {
|
|
381
|
+
return prim.GetTypeName() === "Xform";
|
|
382
|
+
}
|
|
383
|
+
function isScope(prim) {
|
|
384
|
+
return prim.GetTypeName() === "Scope";
|
|
385
|
+
}
|
|
386
|
+
function isMesh(prim) {
|
|
387
|
+
return prim.GetTypeName() === "Mesh";
|
|
388
|
+
}
|
|
389
|
+
function getPurpose(prim) {
|
|
390
|
+
const v = prim.GetAttribute("purpose").Get();
|
|
391
|
+
return typeof v === "string" ? v : "default";
|
|
392
|
+
}
|
|
393
|
+
function isNonVisualPurpose(prim) {
|
|
394
|
+
const p = getPurpose(prim);
|
|
395
|
+
return p === "guide" || p === "proxy";
|
|
396
|
+
}
|
|
397
|
+
function getMaterialSubsets(meshPrim) {
|
|
398
|
+
const out = [];
|
|
399
|
+
for (const child of meshPrim.GetChildren()) {
|
|
400
|
+
if (child.GetTypeName() !== "GeomSubset") continue;
|
|
401
|
+
const elementType = child.GetAttribute("elementType").Get();
|
|
402
|
+
if (elementType !== void 0 && elementType !== "face") continue;
|
|
403
|
+
const family = child.GetAttribute("familyName").Get();
|
|
404
|
+
if (family !== void 0 && family !== "materialBind") continue;
|
|
405
|
+
const indices = child.GetAttribute("indices").Get();
|
|
406
|
+
if (!Array.isArray(indices)) continue;
|
|
407
|
+
const faces = [];
|
|
408
|
+
for (const i of indices) {
|
|
409
|
+
if (typeof i === "number") faces.push(i);
|
|
410
|
+
}
|
|
411
|
+
if (faces.length > 0) out.push({ prim: child, faces });
|
|
412
|
+
}
|
|
413
|
+
return out;
|
|
414
|
+
}
|
|
415
|
+
function* iterDescendants(prim) {
|
|
416
|
+
for (const child of prim.GetChildren()) {
|
|
417
|
+
yield child;
|
|
418
|
+
yield* iterDescendants(child);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
function gatherMeshDescendants(prim) {
|
|
422
|
+
const paths = [];
|
|
423
|
+
for (const d of iterDescendants(prim)) {
|
|
424
|
+
if (isMesh(d)) paths.push(d.GetPath());
|
|
425
|
+
}
|
|
426
|
+
return paths;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// src/schemas/usdPhysics.ts
|
|
430
|
+
var JOINT_TYPE_BY_SCHEMA = {
|
|
431
|
+
PhysicsFixedJoint: "fixed",
|
|
432
|
+
PhysicsRevoluteJoint: "revolute",
|
|
433
|
+
PhysicsPrismaticJoint: "prismatic"
|
|
434
|
+
};
|
|
435
|
+
var ARTICULATION_ROOT_API = "PhysicsArticulationRootAPI";
|
|
436
|
+
var RIGID_BODY_API = "PhysicsRigidBodyAPI";
|
|
437
|
+
var COLLISION_API = "PhysicsCollisionAPI";
|
|
438
|
+
var MASS_API = "PhysicsMassAPI";
|
|
439
|
+
var MESH_COLLISION_API = "PhysicsMeshCollisionAPI";
|
|
440
|
+
var PHYSICS_MATERIAL_API = "PhysicsMaterialAPI";
|
|
441
|
+
function getJointType(prim) {
|
|
442
|
+
return JOINT_TYPE_BY_SCHEMA[prim.GetTypeName()] ?? null;
|
|
443
|
+
}
|
|
444
|
+
function getJointBodies(prim) {
|
|
445
|
+
const body0 = prim.GetRelationship("physics:body0").GetTargets()[0];
|
|
446
|
+
const body1 = prim.GetRelationship("physics:body1").GetTargets()[0];
|
|
447
|
+
return {
|
|
448
|
+
...body0 !== void 0 ? { body0 } : {},
|
|
449
|
+
...body1 !== void 0 ? { body1 } : {}
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
function getJointAxis(prim) {
|
|
453
|
+
const v = prim.GetAttribute("physics:axis").Get();
|
|
454
|
+
return v === "Y" || v === "Z" ? v : "X";
|
|
455
|
+
}
|
|
456
|
+
function getJointLimits(prim) {
|
|
457
|
+
const lower = readNumber(prim, "physics:lowerLimit");
|
|
458
|
+
const upper = readNumber(prim, "physics:upperLimit");
|
|
459
|
+
return {
|
|
460
|
+
...lower !== void 0 ? { lower } : {},
|
|
461
|
+
...upper !== void 0 ? { upper } : {}
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
function getJointLocalFrame(prim, index) {
|
|
465
|
+
const pos = readVec3(prim, `physics:localPos${index}`, [0, 0, 0]);
|
|
466
|
+
const rot = readQuat(prim, `physics:localRot${index}`, Quat.identity());
|
|
467
|
+
return multiply(makeTranslation(pos), makeRotationFromQuat(rot));
|
|
468
|
+
}
|
|
469
|
+
function hasArticulationRootAPI(prim) {
|
|
470
|
+
return prim.HasAPI(ARTICULATION_ROOT_API);
|
|
471
|
+
}
|
|
472
|
+
function hasRigidBodyAPI(prim) {
|
|
473
|
+
return prim.HasAPI(RIGID_BODY_API);
|
|
474
|
+
}
|
|
475
|
+
function hasCollisionAPI(prim) {
|
|
476
|
+
return prim.HasAPI(COLLISION_API);
|
|
477
|
+
}
|
|
478
|
+
function driveKindFor(type) {
|
|
479
|
+
return type === "prismatic" ? "linear" : "angular";
|
|
480
|
+
}
|
|
481
|
+
function getJointDrive(prim, kind) {
|
|
482
|
+
const targetPosition = readNumber(prim, `drive:${kind}:physics:targetPosition`);
|
|
483
|
+
const stiffness = readNumber(prim, `drive:${kind}:physics:stiffness`);
|
|
484
|
+
const damping = readNumber(prim, `drive:${kind}:physics:damping`);
|
|
485
|
+
const maxForce = readNumber(prim, `drive:${kind}:physics:maxForce`);
|
|
486
|
+
return {
|
|
487
|
+
...targetPosition !== void 0 ? { targetPosition } : {},
|
|
488
|
+
...stiffness !== void 0 ? { stiffness } : {},
|
|
489
|
+
...damping !== void 0 ? { damping } : {},
|
|
490
|
+
...maxForce !== void 0 ? { maxForce } : {}
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
function getJointStatePosition(prim, kind) {
|
|
494
|
+
return readNumber(prim, `state:${kind}:physics:position`);
|
|
495
|
+
}
|
|
496
|
+
function getMassProperties(prim) {
|
|
497
|
+
const out = {};
|
|
498
|
+
const mass = readNumber(prim, "physics:mass");
|
|
499
|
+
if (mass !== void 0) out.mass = mass;
|
|
500
|
+
const density = readNumber(prim, "physics:density");
|
|
501
|
+
if (density !== void 0) out.density = density;
|
|
502
|
+
const centerOfMass = readVec3Opt(prim, "physics:centerOfMass");
|
|
503
|
+
if (centerOfMass) out.centerOfMass = centerOfMass;
|
|
504
|
+
const diagonalInertia = readVec3Opt(prim, "physics:diagonalInertia");
|
|
505
|
+
if (diagonalInertia) out.diagonalInertia = diagonalInertia;
|
|
506
|
+
const principalAxes = prim.GetAttribute("physics:principalAxes").Get();
|
|
507
|
+
if (principalAxes instanceof Quat) out.principalAxes = principalAxes;
|
|
508
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
509
|
+
}
|
|
510
|
+
function readNumber(prim, name) {
|
|
511
|
+
const v = prim.GetAttribute(name).Get();
|
|
512
|
+
return typeof v === "number" ? v : void 0;
|
|
513
|
+
}
|
|
514
|
+
function readVec3(prim, name, def) {
|
|
515
|
+
return readVec3Opt(prim, name) ?? def;
|
|
516
|
+
}
|
|
517
|
+
function readVec3Opt(prim, name) {
|
|
518
|
+
const v = prim.GetAttribute(name).Get();
|
|
519
|
+
if (Array.isArray(v) && v.length === 3 && v.every((n) => typeof n === "number")) {
|
|
520
|
+
return v;
|
|
521
|
+
}
|
|
522
|
+
return void 0;
|
|
523
|
+
}
|
|
524
|
+
function readQuat(prim, name, def) {
|
|
525
|
+
const v = prim.GetAttribute(name).Get();
|
|
526
|
+
return v instanceof Quat ? v : def;
|
|
527
|
+
}
|
|
257
528
|
|
|
258
529
|
// src/usd/xformOps.ts
|
|
259
530
|
var INVERT_PREFIX = "!invert!";
|
|
@@ -266,6 +537,15 @@ var ROTATE_ORDERS = /* @__PURE__ */ new Set([
|
|
|
266
537
|
"rotateZXY",
|
|
267
538
|
"rotateZYX"
|
|
268
539
|
]);
|
|
540
|
+
function computeWorldTransform(prim) {
|
|
541
|
+
const chain = [];
|
|
542
|
+
for (let p = prim; p && !p.IsPseudoRoot(); p = p.GetParent()) chain.push(p);
|
|
543
|
+
let m = identity4();
|
|
544
|
+
for (let i = chain.length - 1; i >= 0; i--) {
|
|
545
|
+
m = multiply(m, computeLocalTransform(chain[i]).matrix);
|
|
546
|
+
}
|
|
547
|
+
return m;
|
|
548
|
+
}
|
|
269
549
|
function computeLocalTransform(prim) {
|
|
270
550
|
const orderAttr = prim.GetAttribute("xformOpOrder");
|
|
271
551
|
const order = orderAttr.Get();
|
|
@@ -287,9 +567,7 @@ function computeLocalTransform(prim) {
|
|
|
287
567
|
opName = opName.slice(INVERT_PREFIX.length);
|
|
288
568
|
}
|
|
289
569
|
const attr = prim.GetAttribute(opName);
|
|
290
|
-
if (!attr.IsValid())
|
|
291
|
-
throw new Error(`${prim.GetPath()}: xformOpOrder references missing op "${opName}"`);
|
|
292
|
-
}
|
|
570
|
+
if (!attr.IsValid()) continue;
|
|
293
571
|
const opValue = attr.Get();
|
|
294
572
|
if (opValue === void 0) continue;
|
|
295
573
|
let opMatrix = opMatrixFor(parseOpType(opName), opValue, `${prim.GetPath()}.${opName}`);
|
|
@@ -345,56 +623,177 @@ function asMatrix(v, where) {
|
|
|
345
623
|
throw new Error(`${where}: expected a matrix`);
|
|
346
624
|
}
|
|
347
625
|
|
|
348
|
-
// src/
|
|
349
|
-
var
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
626
|
+
// src/three/MaterialBinding.ts
|
|
627
|
+
var DIFFUSE_INPUTS = [
|
|
628
|
+
"inputs:diffuseColor",
|
|
629
|
+
// UsdPreviewSurface
|
|
630
|
+
"inputs:diffuse_color_constant",
|
|
631
|
+
// OmniPBR
|
|
632
|
+
"inputs:diffuse_tint",
|
|
633
|
+
"inputs:base_color",
|
|
634
|
+
"inputs:baseColor"
|
|
635
|
+
];
|
|
636
|
+
var OPACITY_INPUTS = ["inputs:opacity", "inputs:opacity_constant"];
|
|
637
|
+
var OPACITY_THRESHOLD_INPUTS = ["inputs:opacityThreshold", "inputs:opacity_threshold"];
|
|
638
|
+
var METALLIC_INPUTS = ["inputs:metallic", "inputs:metallic_constant"];
|
|
639
|
+
var ROUGHNESS_INPUTS = ["inputs:roughness", "inputs:reflection_roughness_constant"];
|
|
640
|
+
var EMISSIVE_INPUTS = ["inputs:emissiveColor", "inputs:emissive_color"];
|
|
641
|
+
var SURFACE_OUTPUTS = ["outputs:surface", "outputs:mdl:surface"];
|
|
642
|
+
var TEXTURE_LOOKUPS = {
|
|
643
|
+
color: {
|
|
644
|
+
surface: ["inputs:diffuseColor"],
|
|
645
|
+
direct: ["inputs:diffuse_texture", "inputs:diffuse_color_texture"]
|
|
646
|
+
},
|
|
647
|
+
opacity: {
|
|
648
|
+
surface: ["inputs:opacity"],
|
|
649
|
+
direct: ["inputs:opacity_texture", "inputs:opacity_color_texture"]
|
|
650
|
+
},
|
|
651
|
+
normal: {
|
|
652
|
+
surface: ["inputs:normal"],
|
|
653
|
+
direct: ["inputs:normalmap_texture", "inputs:normal_texture"]
|
|
654
|
+
},
|
|
655
|
+
roughness: {
|
|
656
|
+
surface: ["inputs:roughness"],
|
|
657
|
+
direct: ["inputs:reflectionroughness_texture", "inputs:roughness_texture"]
|
|
658
|
+
},
|
|
659
|
+
metalness: {
|
|
660
|
+
surface: ["inputs:metallic"],
|
|
661
|
+
direct: ["inputs:metallic_texture"]
|
|
662
|
+
},
|
|
663
|
+
occlusion: {
|
|
664
|
+
surface: ["inputs:occlusion"],
|
|
665
|
+
direct: ["inputs:ao_texture", "inputs:occlusion_texture"]
|
|
666
|
+
},
|
|
667
|
+
emissive: {
|
|
668
|
+
surface: ["inputs:emissiveColor"],
|
|
669
|
+
direct: ["inputs:emissive_color_texture", "inputs:emissive_mask_texture"]
|
|
353
670
|
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
671
|
+
};
|
|
672
|
+
function resolveBoundMaterial(stage, prim) {
|
|
673
|
+
const materialPath = findBinding(prim);
|
|
674
|
+
if (!materialPath) return void 0;
|
|
675
|
+
const material = stage.GetPrimAtPath(materialPath);
|
|
676
|
+
if (!material) return void 0;
|
|
677
|
+
const shader = findSurfaceShader(material);
|
|
678
|
+
if (!shader) return void 0;
|
|
679
|
+
const result = { name: material.GetName() };
|
|
680
|
+
const color = firstColor(shader, DIFFUSE_INPUTS);
|
|
681
|
+
if (color) result.color = color;
|
|
682
|
+
const opacity = firstNumber(shader, OPACITY_INPUTS);
|
|
683
|
+
if (opacity !== void 0) result.opacity = opacity;
|
|
684
|
+
const opacityThreshold = firstNumber(shader, OPACITY_THRESHOLD_INPUTS);
|
|
685
|
+
if (opacityThreshold !== void 0) result.opacityThreshold = opacityThreshold;
|
|
686
|
+
const metalness = firstNumber(shader, METALLIC_INPUTS);
|
|
687
|
+
if (metalness !== void 0) result.metalness = metalness;
|
|
688
|
+
const roughness = firstNumber(shader, ROUGHNESS_INPUTS);
|
|
689
|
+
if (roughness !== void 0) result.roughness = roughness;
|
|
690
|
+
const emissive = firstColor(shader, EMISSIVE_INPUTS);
|
|
691
|
+
if (emissive && shader.GetAttribute("inputs:enable_emission").Get() !== false) {
|
|
692
|
+
result.emissiveColor = emissive;
|
|
693
|
+
}
|
|
694
|
+
const colorTex = findTexture(shader, TEXTURE_LOOKUPS.color);
|
|
695
|
+
if (colorTex !== void 0) result.colorTexture = colorTex;
|
|
696
|
+
const opacityTex = findTexture(shader, TEXTURE_LOOKUPS.opacity);
|
|
697
|
+
if (opacityTex !== void 0) result.opacityTexture = opacityTex;
|
|
698
|
+
const normal = findTexture(shader, TEXTURE_LOOKUPS.normal);
|
|
699
|
+
if (normal !== void 0) result.normalTexture = normal;
|
|
700
|
+
const roughTex = findTexture(shader, TEXTURE_LOOKUPS.roughness);
|
|
701
|
+
if (roughTex !== void 0) result.roughnessTexture = roughTex;
|
|
702
|
+
const metalTex = findTexture(shader, TEXTURE_LOOKUPS.metalness);
|
|
703
|
+
if (metalTex !== void 0) result.metalnessTexture = metalTex;
|
|
704
|
+
const aoTex = findTexture(shader, TEXTURE_LOOKUPS.occlusion);
|
|
705
|
+
if (aoTex !== void 0) result.occlusionTexture = aoTex;
|
|
706
|
+
const emissiveTex = findTexture(shader, TEXTURE_LOOKUPS.emissive);
|
|
707
|
+
if (emissiveTex !== void 0) result.emissiveTexture = emissiveTex;
|
|
708
|
+
return result;
|
|
709
|
+
}
|
|
710
|
+
function findTexture(shader, lookup) {
|
|
711
|
+
for (const name of lookup.direct) {
|
|
712
|
+
const v = shader.GetAttribute(name).Get();
|
|
713
|
+
if (v instanceof AssetPath && v.path) return { path: v.path };
|
|
714
|
+
}
|
|
715
|
+
for (const name of lookup.surface) {
|
|
716
|
+
const conn = shader.GetAttribute(name).GetConnections()[0];
|
|
717
|
+
if (!conn) continue;
|
|
718
|
+
const texPrim = shader.GetStage().GetPrimAtPath(conn.split(".")[0]);
|
|
719
|
+
if (!texPrim) continue;
|
|
720
|
+
const file = texPrim.GetAttribute("inputs:file").Get();
|
|
721
|
+
if (file instanceof AssetPath && file.path) return readUvTexture(texPrim, file.path);
|
|
722
|
+
}
|
|
723
|
+
return void 0;
|
|
724
|
+
}
|
|
725
|
+
var WRAP_VALUES = /* @__PURE__ */ new Set(["repeat", "clamp", "mirror", "black"]);
|
|
726
|
+
function readUvTexture(texPrim, path) {
|
|
727
|
+
const tex = { path };
|
|
728
|
+
const wrapS = texPrim.GetAttribute("inputs:wrapS").Get();
|
|
729
|
+
if (typeof wrapS === "string" && WRAP_VALUES.has(wrapS)) tex.wrapS = wrapS;
|
|
730
|
+
const wrapT = texPrim.GetAttribute("inputs:wrapT").Get();
|
|
731
|
+
if (typeof wrapT === "string" && WRAP_VALUES.has(wrapT)) tex.wrapT = wrapT;
|
|
732
|
+
const scale = numArray(texPrim, "inputs:scale", 4);
|
|
733
|
+
if (scale) tex.scale = scale;
|
|
734
|
+
const bias = numArray(texPrim, "inputs:bias", 4);
|
|
735
|
+
if (bias) tex.bias = bias;
|
|
736
|
+
const transform = readTransform2d(texPrim);
|
|
737
|
+
if (transform) tex.transform = transform;
|
|
738
|
+
return tex;
|
|
739
|
+
}
|
|
740
|
+
function readTransform2d(texPrim) {
|
|
741
|
+
const conn = texPrim.GetAttribute("inputs:st").GetConnections()[0];
|
|
742
|
+
if (!conn) return void 0;
|
|
743
|
+
const node = texPrim.GetStage().GetPrimAtPath(conn.split(".")[0]);
|
|
744
|
+
if (!node || node.GetAttribute("info:id").Get() !== "UsdTransform2d") return void 0;
|
|
745
|
+
const transform = {};
|
|
746
|
+
const translation = numArray(node, "inputs:translation", 2);
|
|
747
|
+
if (translation) transform.translation = translation;
|
|
748
|
+
const scale = numArray(node, "inputs:scale", 2);
|
|
749
|
+
if (scale) transform.scale = scale;
|
|
750
|
+
const rotation = node.GetAttribute("inputs:rotation").Get();
|
|
751
|
+
if (typeof rotation === "number") transform.rotation = rotation;
|
|
752
|
+
return Object.keys(transform).length > 0 ? transform : void 0;
|
|
753
|
+
}
|
|
754
|
+
function numArray(prim, name, length) {
|
|
755
|
+
const v = prim.GetAttribute(name).Get();
|
|
756
|
+
if (Array.isArray(v) && v.length >= length && v.every((n) => typeof n === "number")) {
|
|
757
|
+
return v.slice(0, length);
|
|
359
758
|
}
|
|
360
|
-
|
|
361
|
-
|
|
759
|
+
return void 0;
|
|
760
|
+
}
|
|
761
|
+
function findBinding(prim) {
|
|
762
|
+
let p = prim;
|
|
763
|
+
while (p) {
|
|
764
|
+
const targets = p.GetRelationship("material:binding").GetTargets();
|
|
765
|
+
if (targets.length > 0) return targets[0];
|
|
766
|
+
p = p.GetParent();
|
|
362
767
|
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
768
|
+
return void 0;
|
|
769
|
+
}
|
|
770
|
+
function findSurfaceShader(material) {
|
|
771
|
+
for (const out of SURFACE_OUTPUTS) {
|
|
772
|
+
const conn = material.GetAttribute(out).GetConnections()[0];
|
|
773
|
+
if (conn) {
|
|
774
|
+
const shaderPath = conn.split(".")[0];
|
|
775
|
+
const shader = material.GetStage().GetPrimAtPath(shaderPath);
|
|
776
|
+
if (shader) return shader;
|
|
777
|
+
}
|
|
368
778
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
0,
|
|
376
|
-
|
|
377
|
-
0,
|
|
378
|
-
1,
|
|
379
|
-
0,
|
|
380
|
-
0,
|
|
381
|
-
0,
|
|
382
|
-
0,
|
|
383
|
-
1,
|
|
384
|
-
0,
|
|
385
|
-
0,
|
|
386
|
-
0,
|
|
387
|
-
0,
|
|
388
|
-
1
|
|
389
|
-
], 4);
|
|
779
|
+
return material.GetChildren().find((c) => c.GetTypeName() === "Shader") ?? void 0;
|
|
780
|
+
}
|
|
781
|
+
function firstColor(shader, names) {
|
|
782
|
+
for (const name of names) {
|
|
783
|
+
const v = shader.GetAttribute(name).Get();
|
|
784
|
+
if (Array.isArray(v) && v.length >= 3 && v.every((n) => typeof n === "number")) {
|
|
785
|
+
return [v[0], v[1], v[2]];
|
|
786
|
+
}
|
|
390
787
|
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
788
|
+
return void 0;
|
|
789
|
+
}
|
|
790
|
+
function firstNumber(shader, names) {
|
|
791
|
+
for (const name of names) {
|
|
792
|
+
const v = shader.GetAttribute(name).Get();
|
|
793
|
+
if (typeof v === "number") return v;
|
|
395
794
|
}
|
|
396
|
-
|
|
397
|
-
}
|
|
795
|
+
return void 0;
|
|
796
|
+
}
|
|
398
797
|
|
|
399
798
|
// src/kinematics/sampling.ts
|
|
400
799
|
function interpolate(channel, t) {
|
|
@@ -423,118 +822,6 @@ function channelFromSamples(samples) {
|
|
|
423
822
|
return { times, values };
|
|
424
823
|
}
|
|
425
824
|
|
|
426
|
-
// src/schemas/usdGeom.ts
|
|
427
|
-
function isXform(prim) {
|
|
428
|
-
return prim.GetTypeName() === "Xform";
|
|
429
|
-
}
|
|
430
|
-
function isScope(prim) {
|
|
431
|
-
return prim.GetTypeName() === "Scope";
|
|
432
|
-
}
|
|
433
|
-
function isMesh(prim) {
|
|
434
|
-
return prim.GetTypeName() === "Mesh";
|
|
435
|
-
}
|
|
436
|
-
function getPurpose(prim) {
|
|
437
|
-
const v = prim.GetAttribute("purpose").Get();
|
|
438
|
-
return typeof v === "string" ? v : "default";
|
|
439
|
-
}
|
|
440
|
-
function isNonVisualPurpose(prim) {
|
|
441
|
-
const p = getPurpose(prim);
|
|
442
|
-
return p === "guide" || p === "proxy";
|
|
443
|
-
}
|
|
444
|
-
function* iterDescendants(prim) {
|
|
445
|
-
for (const child of prim.GetChildren()) {
|
|
446
|
-
yield child;
|
|
447
|
-
yield* iterDescendants(child);
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
function gatherMeshDescendants(prim) {
|
|
451
|
-
const paths = [];
|
|
452
|
-
for (const d of iterDescendants(prim)) {
|
|
453
|
-
if (isMesh(d)) paths.push(d.GetPath());
|
|
454
|
-
}
|
|
455
|
-
return paths;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
// src/schemas/usdPhysics.ts
|
|
459
|
-
var JOINT_TYPE_BY_SCHEMA = {
|
|
460
|
-
PhysicsFixedJoint: "fixed",
|
|
461
|
-
PhysicsRevoluteJoint: "revolute",
|
|
462
|
-
PhysicsPrismaticJoint: "prismatic"
|
|
463
|
-
};
|
|
464
|
-
var ARTICULATION_ROOT_API = "PhysicsArticulationRootAPI";
|
|
465
|
-
var RIGID_BODY_API = "PhysicsRigidBodyAPI";
|
|
466
|
-
var COLLISION_API = "PhysicsCollisionAPI";
|
|
467
|
-
function getJointType(prim) {
|
|
468
|
-
return JOINT_TYPE_BY_SCHEMA[prim.GetTypeName()] ?? null;
|
|
469
|
-
}
|
|
470
|
-
function getJointBodies(prim) {
|
|
471
|
-
const body0 = prim.GetRelationship("physics:body0").GetTargets()[0];
|
|
472
|
-
const body1 = prim.GetRelationship("physics:body1").GetTargets()[0];
|
|
473
|
-
return {
|
|
474
|
-
...body0 !== void 0 ? { body0 } : {},
|
|
475
|
-
...body1 !== void 0 ? { body1 } : {}
|
|
476
|
-
};
|
|
477
|
-
}
|
|
478
|
-
function getJointAxis(prim) {
|
|
479
|
-
const v = prim.GetAttribute("physics:axis").Get();
|
|
480
|
-
return v === "Y" || v === "Z" ? v : "X";
|
|
481
|
-
}
|
|
482
|
-
function getJointLimits(prim) {
|
|
483
|
-
const lower = readNumber(prim, "physics:lowerLimit");
|
|
484
|
-
const upper = readNumber(prim, "physics:upperLimit");
|
|
485
|
-
return {
|
|
486
|
-
...lower !== void 0 ? { lower } : {},
|
|
487
|
-
...upper !== void 0 ? { upper } : {}
|
|
488
|
-
};
|
|
489
|
-
}
|
|
490
|
-
function getJointLocalFrame(prim, index) {
|
|
491
|
-
const pos = readVec3(prim, `physics:localPos${index}`, [0, 0, 0]);
|
|
492
|
-
const rot = readQuat(prim, `physics:localRot${index}`, Quat.identity());
|
|
493
|
-
return multiply(makeTranslation(pos), makeRotationFromQuat(rot));
|
|
494
|
-
}
|
|
495
|
-
function hasArticulationRootAPI(prim) {
|
|
496
|
-
return prim.HasAPI(ARTICULATION_ROOT_API);
|
|
497
|
-
}
|
|
498
|
-
function hasRigidBodyAPI(prim) {
|
|
499
|
-
return prim.HasAPI(RIGID_BODY_API);
|
|
500
|
-
}
|
|
501
|
-
function hasCollisionAPI(prim) {
|
|
502
|
-
return prim.HasAPI(COLLISION_API);
|
|
503
|
-
}
|
|
504
|
-
function driveKindFor(type) {
|
|
505
|
-
return type === "prismatic" ? "linear" : "angular";
|
|
506
|
-
}
|
|
507
|
-
function getJointDrive(prim, kind) {
|
|
508
|
-
const targetPosition = readNumber(prim, `drive:${kind}:physics:targetPosition`);
|
|
509
|
-
const stiffness = readNumber(prim, `drive:${kind}:physics:stiffness`);
|
|
510
|
-
const damping = readNumber(prim, `drive:${kind}:physics:damping`);
|
|
511
|
-
const maxForce = readNumber(prim, `drive:${kind}:physics:maxForce`);
|
|
512
|
-
return {
|
|
513
|
-
...targetPosition !== void 0 ? { targetPosition } : {},
|
|
514
|
-
...stiffness !== void 0 ? { stiffness } : {},
|
|
515
|
-
...damping !== void 0 ? { damping } : {},
|
|
516
|
-
...maxForce !== void 0 ? { maxForce } : {}
|
|
517
|
-
};
|
|
518
|
-
}
|
|
519
|
-
function getJointStatePosition(prim, kind) {
|
|
520
|
-
return readNumber(prim, `state:${kind}:physics:position`);
|
|
521
|
-
}
|
|
522
|
-
function readNumber(prim, name) {
|
|
523
|
-
const v = prim.GetAttribute(name).Get();
|
|
524
|
-
return typeof v === "number" ? v : void 0;
|
|
525
|
-
}
|
|
526
|
-
function readVec3(prim, name, def) {
|
|
527
|
-
const v = prim.GetAttribute(name).Get();
|
|
528
|
-
if (Array.isArray(v) && v.length === 3 && v.every((n) => typeof n === "number")) {
|
|
529
|
-
return v;
|
|
530
|
-
}
|
|
531
|
-
return def;
|
|
532
|
-
}
|
|
533
|
-
function readQuat(prim, name, def) {
|
|
534
|
-
const v = prim.GetAttribute(name).Get();
|
|
535
|
-
return v instanceof Quat ? v : def;
|
|
536
|
-
}
|
|
537
|
-
|
|
538
825
|
// src/robot/buildKinematicTree.ts
|
|
539
826
|
var WORLD = "";
|
|
540
827
|
function buildKinematicTree(robot, options = {}) {
|
|
@@ -654,6 +941,9 @@ function normalizeJointLimits(type, rawLower, rawUpper) {
|
|
|
654
941
|
function jointValueToSI(angular, raw) {
|
|
655
942
|
return angular ? raw * DEG2RAD : raw;
|
|
656
943
|
}
|
|
944
|
+
function jointValueFromSI(angular, si) {
|
|
945
|
+
return angular ? si * RAD2DEG : si;
|
|
946
|
+
}
|
|
657
947
|
function refineJointType(base, lower, upper) {
|
|
658
948
|
if (base === "revolute" && lower === void 0 && upper === void 0) return "continuous";
|
|
659
949
|
return base;
|
|
@@ -720,16 +1010,28 @@ function buildLink(path, prim) {
|
|
|
720
1010
|
const collisionPrims = [];
|
|
721
1011
|
for (const meshPath of gatherMeshDescendants(prim)) {
|
|
722
1012
|
const mp = prim.GetStage().GetPrimAtPath(meshPath);
|
|
723
|
-
if (mp
|
|
724
|
-
|
|
1013
|
+
if (!mp) continue;
|
|
1014
|
+
const nonVisual = isNonVisualPurpose(mp);
|
|
1015
|
+
if (!nonVisual) visualPrims.push(meshPath);
|
|
1016
|
+
if (nonVisual || hasCollisionAPI(mp)) collisionPrims.push(meshPath);
|
|
725
1017
|
}
|
|
1018
|
+
const inertial = getMassProperties(prim);
|
|
1019
|
+
const worldTransform = computeWorldTransform(prim);
|
|
726
1020
|
return {
|
|
727
1021
|
name,
|
|
728
1022
|
primPath: path,
|
|
729
1023
|
visualPrims,
|
|
730
|
-
...collisionPrims.length ? { collisionPrims } : {}
|
|
1024
|
+
...collisionPrims.length ? { collisionPrims } : {},
|
|
1025
|
+
...inertial ? { inertial } : {},
|
|
1026
|
+
...isIdentityMat4(worldTransform) ? {} : { worldTransform }
|
|
731
1027
|
};
|
|
732
1028
|
}
|
|
1029
|
+
function isIdentityMat4(m) {
|
|
1030
|
+
for (let i = 0; i < 16; i++) {
|
|
1031
|
+
if (m[i] !== (i % 5 === 0 ? 1 : 0)) return false;
|
|
1032
|
+
}
|
|
1033
|
+
return true;
|
|
1034
|
+
}
|
|
733
1035
|
function buildJoint(prim, linkKeyByPath, warn) {
|
|
734
1036
|
const base = getJointType(prim);
|
|
735
1037
|
if (!base) return null;
|
|
@@ -1347,11 +1649,11 @@ function parseVariantSet(r) {
|
|
|
1347
1649
|
const variants = {};
|
|
1348
1650
|
while (!r.is("rbrace") && !r.atEnd()) {
|
|
1349
1651
|
const variantName = r.expect("string").value;
|
|
1350
|
-
|
|
1652
|
+
const metadata = r.is("lparen") ? parseMetadataBlock(r) : {};
|
|
1351
1653
|
r.expect("lbrace");
|
|
1352
1654
|
const body = parseBody(r);
|
|
1353
1655
|
r.expect("rbrace");
|
|
1354
|
-
variants[variantName] = { properties: body.properties, children: body.children };
|
|
1656
|
+
variants[variantName] = { properties: body.properties, children: body.children, metadata };
|
|
1355
1657
|
}
|
|
1356
1658
|
r.expect("rbrace");
|
|
1357
1659
|
return { setName, variants };
|
|
@@ -1523,12 +1825,243 @@ function parseDictionary(r) {
|
|
|
1523
1825
|
return dict;
|
|
1524
1826
|
}
|
|
1525
1827
|
|
|
1828
|
+
// src/writer/writeUsda.ts
|
|
1829
|
+
var INDENT = " ";
|
|
1830
|
+
var BARE_KEY_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
1831
|
+
function serializeUsda(file) {
|
|
1832
|
+
const out = [`#usda ${file.version}`];
|
|
1833
|
+
const meta = Object.entries(file.metadata);
|
|
1834
|
+
if (meta.length > 0) {
|
|
1835
|
+
out.push("(");
|
|
1836
|
+
for (const [key, value] of meta) pushMetaEntry(out, key, value, 1);
|
|
1837
|
+
out.push(")");
|
|
1838
|
+
}
|
|
1839
|
+
for (const prim of file.prims) {
|
|
1840
|
+
out.push("");
|
|
1841
|
+
pushPrim(out, prim, 0);
|
|
1842
|
+
}
|
|
1843
|
+
return `${out.join("\n")}
|
|
1844
|
+
`;
|
|
1845
|
+
}
|
|
1846
|
+
function pushPrim(out, prim, level) {
|
|
1847
|
+
const pad = INDENT.repeat(level);
|
|
1848
|
+
const type = prim.typeName ? `${prim.typeName} ` : "";
|
|
1849
|
+
pushWithMetadata(
|
|
1850
|
+
out,
|
|
1851
|
+
`${pad}${prim.specifier} ${type}${quoteString(prim.name)}`,
|
|
1852
|
+
prim.metadata,
|
|
1853
|
+
level
|
|
1854
|
+
);
|
|
1855
|
+
out.push(`${pad}{`);
|
|
1856
|
+
pushPrimBody(out, prim.properties, prim.children, prim.variantSets, level + 1);
|
|
1857
|
+
out.push(`${pad}}`);
|
|
1858
|
+
}
|
|
1859
|
+
function pushPrimBody(out, properties, children, variantSets, level) {
|
|
1860
|
+
for (const prop of properties) pushProperty(out, prop, level);
|
|
1861
|
+
if (variantSets) {
|
|
1862
|
+
const pad = INDENT.repeat(level);
|
|
1863
|
+
for (const [setName, variants] of Object.entries(variantSets)) {
|
|
1864
|
+
out.push(`${pad}variantSet ${quoteString(setName)} = {`);
|
|
1865
|
+
for (const [variantName, content] of Object.entries(variants)) {
|
|
1866
|
+
const head = `${pad}${INDENT}${quoteString(variantName)}`;
|
|
1867
|
+
if (Object.keys(content.metadata).length > 0) {
|
|
1868
|
+
pushWithMetadata(out, head, content.metadata, level + 1);
|
|
1869
|
+
out.push(`${pad}${INDENT}{`);
|
|
1870
|
+
} else {
|
|
1871
|
+
out.push(`${head} {`);
|
|
1872
|
+
}
|
|
1873
|
+
pushPrimBody(out, content.properties, content.children, void 0, level + 2);
|
|
1874
|
+
out.push(`${pad}${INDENT}}`);
|
|
1875
|
+
}
|
|
1876
|
+
out.push(`${pad}}`);
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
for (let i = 0; i < children.length; i++) {
|
|
1880
|
+
if (i > 0 || properties.length > 0 || variantSets) out.push("");
|
|
1881
|
+
pushPrim(out, children[i], level);
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
function pushProperty(out, prop, level) {
|
|
1885
|
+
if (prop.kind === "relationship") pushRelationship(out, prop, level);
|
|
1886
|
+
else pushAttribute(out, prop, level);
|
|
1887
|
+
}
|
|
1888
|
+
function pushRelationship(out, rel, level) {
|
|
1889
|
+
const pad = INDENT.repeat(level);
|
|
1890
|
+
const custom = rel.custom ? "custom " : "";
|
|
1891
|
+
const listOp = rel.listOp !== "explicit" ? `${rel.listOp} ` : "";
|
|
1892
|
+
let head = `${pad}${custom}${listOp}rel ${rel.name}`;
|
|
1893
|
+
if (rel.targets.length > 0) head += ` = ${formatTargets(rel.targets)}`;
|
|
1894
|
+
pushWithMetadata(out, head, rel.metadata, level);
|
|
1895
|
+
}
|
|
1896
|
+
function pushAttribute(out, attr, level) {
|
|
1897
|
+
const pad = INDENT.repeat(level);
|
|
1898
|
+
const custom = attr.custom ? "custom " : "";
|
|
1899
|
+
const uniform = attr.variability === "uniform" ? "uniform " : "";
|
|
1900
|
+
const decl = `${pad}${custom}${uniform}${attr.typeName}${attr.isArray ? "[]" : ""} ${attr.name}`;
|
|
1901
|
+
let first = true;
|
|
1902
|
+
const attach = (head) => {
|
|
1903
|
+
if (first) pushWithMetadata(out, head, attr.metadata, level);
|
|
1904
|
+
else out.push(head);
|
|
1905
|
+
first = false;
|
|
1906
|
+
};
|
|
1907
|
+
if (attr.value !== void 0) {
|
|
1908
|
+
attach(`${decl} = ${formatAttrValue(attr.value, attr.isArray)}`);
|
|
1909
|
+
}
|
|
1910
|
+
if (attr.timeSamples) {
|
|
1911
|
+
out.push(`${decl}.timeSamples = {`);
|
|
1912
|
+
for (const [time, value] of attr.timeSamples) {
|
|
1913
|
+
out.push(`${pad}${INDENT}${formatNumber(time)}: ${formatAttrValue(value, attr.isArray)},`);
|
|
1914
|
+
}
|
|
1915
|
+
attach(`${pad}}`);
|
|
1916
|
+
}
|
|
1917
|
+
if (attr.connections) {
|
|
1918
|
+
attach(
|
|
1919
|
+
`${decl}.connect = ${attr.connections.length > 0 ? formatTargets(attr.connections) : "None"}`
|
|
1920
|
+
);
|
|
1921
|
+
}
|
|
1922
|
+
if (first) attach(decl);
|
|
1923
|
+
}
|
|
1924
|
+
function formatTargets(targets) {
|
|
1925
|
+
if (targets.length === 1) return `<${targets[0]}>`;
|
|
1926
|
+
return `[${targets.map((t) => `<${t}>`).join(", ")}]`;
|
|
1927
|
+
}
|
|
1928
|
+
function pushWithMetadata(out, head, meta, level) {
|
|
1929
|
+
const entries = Object.entries(meta);
|
|
1930
|
+
if (entries.length === 0) {
|
|
1931
|
+
out.push(head);
|
|
1932
|
+
return;
|
|
1933
|
+
}
|
|
1934
|
+
out.push(`${head} (`);
|
|
1935
|
+
for (const [key, value] of entries) pushMetaEntry(out, key, value, level + 1);
|
|
1936
|
+
out.push(`${INDENT.repeat(level)})`);
|
|
1937
|
+
}
|
|
1938
|
+
function pushMetaEntry(out, key, value, level) {
|
|
1939
|
+
const pad = INDENT.repeat(level);
|
|
1940
|
+
if (isDictionary(value)) {
|
|
1941
|
+
out.push(`${pad}${key} = {`);
|
|
1942
|
+
pushDictEntries(out, value, level + 1);
|
|
1943
|
+
out.push(`${pad}}`);
|
|
1944
|
+
return;
|
|
1945
|
+
}
|
|
1946
|
+
out.push(`${pad}${key} = ${formatMetaValue(value)}`);
|
|
1947
|
+
}
|
|
1948
|
+
function pushDictEntries(out, dict, level) {
|
|
1949
|
+
const pad = INDENT.repeat(level);
|
|
1950
|
+
for (const [key, value] of Object.entries(dict)) {
|
|
1951
|
+
const keyText = BARE_KEY_RE.test(key) ? key : quoteString(key);
|
|
1952
|
+
if (isDictionary(value)) {
|
|
1953
|
+
out.push(`${pad}dictionary ${keyText} = {`);
|
|
1954
|
+
pushDictEntries(out, value, level + 1);
|
|
1955
|
+
out.push(`${pad}}`);
|
|
1956
|
+
} else {
|
|
1957
|
+
out.push(`${pad}${dictEntryTypeName(value)} ${keyText} = ${formatMetaValue(value)}`);
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
function dictEntryTypeName(v) {
|
|
1962
|
+
if (typeof v === "string") return "string";
|
|
1963
|
+
if (typeof v === "boolean") return "bool";
|
|
1964
|
+
if (typeof v === "number") return isInt32(v) ? "int" : "double";
|
|
1965
|
+
if (typeof v === "bigint") return "int64";
|
|
1966
|
+
if (v instanceof AssetPath) return "asset";
|
|
1967
|
+
if (v instanceof Quat) return "quatd";
|
|
1968
|
+
if (v instanceof UsdMatrix) return v.dim === 4 ? "matrix4d" : "matrix3d";
|
|
1969
|
+
if (Array.isArray(v)) {
|
|
1970
|
+
const elems = v;
|
|
1971
|
+
if (elems.every((e) => typeof e === "boolean")) return "bool[]";
|
|
1972
|
+
let allInt = true;
|
|
1973
|
+
for (const e of elems) {
|
|
1974
|
+
if (typeof e !== "number") return "string[]";
|
|
1975
|
+
if (!isInt32(e)) allInt = false;
|
|
1976
|
+
}
|
|
1977
|
+
return allInt ? "int[]" : "double[]";
|
|
1978
|
+
}
|
|
1979
|
+
return "string";
|
|
1980
|
+
}
|
|
1981
|
+
function isInt32(v) {
|
|
1982
|
+
return Number.isInteger(v) && Math.abs(v) <= 2147483647;
|
|
1983
|
+
}
|
|
1984
|
+
function formatMetaValue(v) {
|
|
1985
|
+
if (v === null) return "None";
|
|
1986
|
+
if (typeof v === "number") return formatNumber(v);
|
|
1987
|
+
if (typeof v === "bigint") return String(v);
|
|
1988
|
+
if (typeof v === "boolean") return v ? "true" : "false";
|
|
1989
|
+
if (typeof v === "string") return quoteString(v);
|
|
1990
|
+
if (v instanceof AssetPath) return formatAsset(v.path);
|
|
1991
|
+
if (v instanceof Quat) return formatQuat(v);
|
|
1992
|
+
if (v instanceof UsdMatrix) return formatMatrix(v);
|
|
1993
|
+
if (Array.isArray(v)) return `[${v.map(formatMetaValue).join(", ")}]`;
|
|
1994
|
+
if (isCompositionArc(v)) return formatArc(v);
|
|
1995
|
+
throw new Error("cannot serialize a nested dictionary in list/value context");
|
|
1996
|
+
}
|
|
1997
|
+
function formatArc(arc) {
|
|
1998
|
+
const asset = arc.assetPath ? formatAsset(arc.assetPath.path) : "";
|
|
1999
|
+
const prim = arc.primPath !== void 0 ? `<${arc.primPath}>` : "";
|
|
2000
|
+
return `${asset}${prim}`;
|
|
2001
|
+
}
|
|
2002
|
+
function formatAttrValue(v, isArray) {
|
|
2003
|
+
if (v === null) return "None";
|
|
2004
|
+
if (isArray && Array.isArray(v)) {
|
|
2005
|
+
return `[${v.map((el) => formatAttrScalar(el)).join(", ")}]`;
|
|
2006
|
+
}
|
|
2007
|
+
return formatAttrScalar(v);
|
|
2008
|
+
}
|
|
2009
|
+
function formatAttrScalar(v) {
|
|
2010
|
+
if (v === null) return "None";
|
|
2011
|
+
if (typeof v === "number") return formatNumber(v);
|
|
2012
|
+
if (typeof v === "bigint") return String(v);
|
|
2013
|
+
if (typeof v === "boolean") return v ? "true" : "false";
|
|
2014
|
+
if (typeof v === "string") return quoteString(v);
|
|
2015
|
+
if (v instanceof Quat) return formatQuat(v);
|
|
2016
|
+
if (v instanceof UsdMatrix) return formatMatrix(v);
|
|
2017
|
+
if (v instanceof AssetPath) return formatAsset(v.path);
|
|
2018
|
+
if (Array.isArray(v)) return `(${v.map((el) => formatAttrScalar(el)).join(", ")})`;
|
|
2019
|
+
throw new Error("cannot serialize a dictionary as an attribute value");
|
|
2020
|
+
}
|
|
2021
|
+
function formatQuat(q) {
|
|
2022
|
+
const [i, j, k] = q.imaginary;
|
|
2023
|
+
return `(${formatNumber(q.real)}, ${formatNumber(i)}, ${formatNumber(j)}, ${formatNumber(k)})`;
|
|
2024
|
+
}
|
|
2025
|
+
function formatMatrix(m) {
|
|
2026
|
+
const rows = [];
|
|
2027
|
+
for (let r = 0; r < m.dim; r++) {
|
|
2028
|
+
const row = m.values.slice(r * m.dim, (r + 1) * m.dim).map(formatNumber);
|
|
2029
|
+
rows.push(`(${row.join(", ")})`);
|
|
2030
|
+
}
|
|
2031
|
+
return `( ${rows.join(", ")} )`;
|
|
2032
|
+
}
|
|
2033
|
+
function formatNumber(v) {
|
|
2034
|
+
if (Number.isNaN(v)) return "nan";
|
|
2035
|
+
if (v === Number.POSITIVE_INFINITY) return "inf";
|
|
2036
|
+
if (v === Number.NEGATIVE_INFINITY) return "-inf";
|
|
2037
|
+
if (Object.is(v, -0)) return "-0";
|
|
2038
|
+
return String(v);
|
|
2039
|
+
}
|
|
2040
|
+
function quoteString(s) {
|
|
2041
|
+
const escaped = s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
|
|
2042
|
+
return `"${escaped}"`;
|
|
2043
|
+
}
|
|
2044
|
+
function formatAsset(path) {
|
|
2045
|
+
return path.includes("@") ? `@@@${path}@@@` : `@${path}@`;
|
|
2046
|
+
}
|
|
2047
|
+
function isDictionary(v) {
|
|
2048
|
+
return typeof v === "object" && v !== null && !Array.isArray(v) && !(v instanceof Quat) && !(v instanceof UsdMatrix) && !(v instanceof AssetPath) && !isCompositionArc(v);
|
|
2049
|
+
}
|
|
2050
|
+
function isCompositionArc(v) {
|
|
2051
|
+
const keys = Object.keys(v);
|
|
2052
|
+
return keys.length > 0 && keys.every((k) => k === "assetPath" || k === "primPath");
|
|
2053
|
+
}
|
|
2054
|
+
|
|
1526
2055
|
// src/usd/Layer.ts
|
|
1527
2056
|
var Layer = class {
|
|
1528
2057
|
constructor(_file) {
|
|
1529
2058
|
this._file = _file;
|
|
1530
2059
|
}
|
|
1531
2060
|
_file;
|
|
2061
|
+
/** Serialize this layer back to USDA text (`SdfLayer::ExportToString`-like). */
|
|
2062
|
+
ExportToString() {
|
|
2063
|
+
return serializeUsda(this._file);
|
|
2064
|
+
}
|
|
1532
2065
|
GetVersion() {
|
|
1533
2066
|
return this._file.version;
|
|
1534
2067
|
}
|
|
@@ -1712,7 +2245,9 @@ var Prim = class {
|
|
|
1712
2245
|
if (!this._attributes) {
|
|
1713
2246
|
this._attributes = /* @__PURE__ */ new Map();
|
|
1714
2247
|
for (const p of this._spec?.properties ?? []) {
|
|
1715
|
-
if (p.kind
|
|
2248
|
+
if (p.kind !== "attribute") continue;
|
|
2249
|
+
const prev = this._attributes.get(p.name);
|
|
2250
|
+
this._attributes.set(p.name, prev ? mergeAttributeSpecs(prev, p) : p);
|
|
1716
2251
|
}
|
|
1717
2252
|
}
|
|
1718
2253
|
return this._attributes;
|
|
@@ -1773,6 +2308,19 @@ var Prim = class {
|
|
|
1773
2308
|
return this.GetAppliedSchemas().some((s) => s === schemaName || s.startsWith(`${schemaName}:`));
|
|
1774
2309
|
}
|
|
1775
2310
|
};
|
|
2311
|
+
function mergeAttributeSpecs(a, b) {
|
|
2312
|
+
const merged = { ...a, metadata: { ...a.metadata, ...b.metadata } };
|
|
2313
|
+
if (b.typeName) merged.typeName = b.typeName;
|
|
2314
|
+
if (b.isArray) merged.isArray = true;
|
|
2315
|
+
if (b.variability === "uniform") merged.variability = "uniform";
|
|
2316
|
+
if (b.custom) merged.custom = true;
|
|
2317
|
+
if (b.value !== void 0) merged.value = b.value;
|
|
2318
|
+
if (b.timeSamples) {
|
|
2319
|
+
merged.timeSamples = a.timeSamples ? new Map([...a.timeSamples, ...b.timeSamples]) : b.timeSamples;
|
|
2320
|
+
}
|
|
2321
|
+
if (b.connections) merged.connections = b.connections;
|
|
2322
|
+
return merged;
|
|
2323
|
+
}
|
|
1776
2324
|
|
|
1777
2325
|
// src/usd/Stage.ts
|
|
1778
2326
|
var DEFAULT_METERS_PER_UNIT = 0.01;
|
|
@@ -1804,6 +2352,14 @@ var Stage = class _Stage {
|
|
|
1804
2352
|
GetRootLayer() {
|
|
1805
2353
|
return this._layer;
|
|
1806
2354
|
}
|
|
2355
|
+
/**
|
|
2356
|
+
* Serialize the stage's backing layer to USDA text. Loader-built stages wrap
|
|
2357
|
+
* the fully composed layer, so this is a flattened (`usdcat --flatten`-like)
|
|
2358
|
+
* export of everything that was read — including binary-crate sources.
|
|
2359
|
+
*/
|
|
2360
|
+
ExportToString() {
|
|
2361
|
+
return this._layer.ExportToString();
|
|
2362
|
+
}
|
|
1807
2363
|
GetPseudoRoot() {
|
|
1808
2364
|
return this._pseudoRoot;
|
|
1809
2365
|
}
|
|
@@ -1978,6 +2534,8 @@ var CrateType = {
|
|
|
1978
2534
|
Specifier: 42,
|
|
1979
2535
|
Permission: 43,
|
|
1980
2536
|
Variability: 44,
|
|
2537
|
+
VariantSelectionMap: 45,
|
|
2538
|
+
StringVector: 50,
|
|
1981
2539
|
PayloadListOp: 55};
|
|
1982
2540
|
var ListOpBits = {
|
|
1983
2541
|
HasExplicit: 1 << 1,
|
|
@@ -2333,6 +2891,10 @@ var CrateReader = class {
|
|
|
2333
2891
|
return this.readIndexVector(off, "token").items;
|
|
2334
2892
|
case CrateType.PathVector:
|
|
2335
2893
|
return this.readIndexVector(off, "path").items;
|
|
2894
|
+
case CrateType.StringVector:
|
|
2895
|
+
return this.readIndexVector(off, "string").items;
|
|
2896
|
+
case CrateType.VariantSelectionMap:
|
|
2897
|
+
return this.readVariantSelectionMap(off);
|
|
2336
2898
|
default:
|
|
2337
2899
|
return void 0;
|
|
2338
2900
|
}
|
|
@@ -2399,6 +2961,24 @@ var CrateReader = class {
|
|
|
2399
2961
|
}
|
|
2400
2962
|
return out;
|
|
2401
2963
|
}
|
|
2964
|
+
/**
|
|
2965
|
+
* Read an `SdfVariantSelectionMap`: `[u64 count]` then `count` pairs of
|
|
2966
|
+
* string indexes (`variantSetName → variantName`). Surfaces as a dictionary
|
|
2967
|
+
* so it maps straight onto the USDA `variants = { ... }` metadatum.
|
|
2968
|
+
*/
|
|
2969
|
+
readVariantSelectionMap(off) {
|
|
2970
|
+
const count = this.u64(off);
|
|
2971
|
+
const strings = this.getStrings();
|
|
2972
|
+
const out = {};
|
|
2973
|
+
let p = off + 8;
|
|
2974
|
+
for (let i = 0; i < count; i++) {
|
|
2975
|
+
const key = this.getToken(strings[this.view.getUint32(p, true)] ?? 0);
|
|
2976
|
+
const value = this.getToken(strings[this.view.getUint32(p + 4, true)] ?? 0);
|
|
2977
|
+
if (key) out[key] = value;
|
|
2978
|
+
p += 8;
|
|
2979
|
+
}
|
|
2980
|
+
return out;
|
|
2981
|
+
}
|
|
2402
2982
|
/** Read a `[u64 count][count × uint32|int32 index]` vector → resolved strings. */
|
|
2403
2983
|
readIndexVector(off, kind) {
|
|
2404
2984
|
const count = this.u64(off);
|
|
@@ -2406,7 +2986,7 @@ var CrateReader = class {
|
|
|
2406
2986
|
const items = new Array(count);
|
|
2407
2987
|
for (let i = 0; i < count; i++) {
|
|
2408
2988
|
const idx = this.view.getInt32(p, true);
|
|
2409
|
-
items[i] = kind === "token" ? this.getToken(idx) : this.getPaths()[idx] ?? "";
|
|
2989
|
+
items[i] = kind === "token" ? this.getToken(idx) : kind === "string" ? this.getToken(this.getStrings()[idx] ?? 0) : this.getPaths()[idx] ?? "";
|
|
2410
2990
|
p += 4;
|
|
2411
2991
|
}
|
|
2412
2992
|
return { items, next: p };
|
|
@@ -2488,6 +3068,7 @@ var SPEC_PRIM = 6;
|
|
|
2488
3068
|
var SPEC_PSEUDO_ROOT = 7;
|
|
2489
3069
|
var SPEC_ATTRIBUTE = 1;
|
|
2490
3070
|
var SPEC_RELATIONSHIP = 8;
|
|
3071
|
+
var SPEC_VARIANT = 10;
|
|
2491
3072
|
var SPECIFIERS2 = ["def", "over", "class"];
|
|
2492
3073
|
function crateToUsdaFile(crate) {
|
|
2493
3074
|
const paths = crate.getPaths();
|
|
@@ -2502,8 +3083,26 @@ function crateToUsdaFile(crate) {
|
|
|
2502
3083
|
return map;
|
|
2503
3084
|
};
|
|
2504
3085
|
const primByPath = /* @__PURE__ */ new Map();
|
|
3086
|
+
const variantByPath = /* @__PURE__ */ new Map();
|
|
2505
3087
|
const rootPrims = [];
|
|
2506
3088
|
let layerMetadata = {};
|
|
3089
|
+
const containerAt = (path) => {
|
|
3090
|
+
const prim = primByPath.get(path);
|
|
3091
|
+
if (prim) return prim;
|
|
3092
|
+
const cached = variantByPath.get(path);
|
|
3093
|
+
if (cached) return cached;
|
|
3094
|
+
const selection = variantNode(path);
|
|
3095
|
+
if (!selection) return void 0;
|
|
3096
|
+
const owner = primByPath.get(selection.owner);
|
|
3097
|
+
if (!owner) return void 0;
|
|
3098
|
+
owner.variantSets ??= {};
|
|
3099
|
+
owner.variantSets[selection.setName] ??= {};
|
|
3100
|
+
const set = owner.variantSets[selection.setName];
|
|
3101
|
+
set[selection.variantName] ??= { properties: [], children: [], metadata: {} };
|
|
3102
|
+
const content = set[selection.variantName];
|
|
3103
|
+
variantByPath.set(path, content);
|
|
3104
|
+
return content;
|
|
3105
|
+
};
|
|
2507
3106
|
for (const spec of specs) {
|
|
2508
3107
|
const path = paths[spec.pathIndex] ?? "";
|
|
2509
3108
|
if (spec.specType === SPEC_PSEUDO_ROOT) {
|
|
@@ -2522,31 +3121,50 @@ function crateToUsdaFile(crate) {
|
|
|
2522
3121
|
line: 0
|
|
2523
3122
|
});
|
|
2524
3123
|
}
|
|
3124
|
+
for (const spec of specs) {
|
|
3125
|
+
if (spec.specType !== SPEC_VARIANT) continue;
|
|
3126
|
+
const content = containerAt(paths[spec.pathIndex] ?? "");
|
|
3127
|
+
if (content)
|
|
3128
|
+
Object.assign(content.metadata, buildPrimMetadata(crate, fieldsOf(spec.fieldSetIndex)));
|
|
3129
|
+
}
|
|
2525
3130
|
for (const spec of specs) {
|
|
2526
3131
|
if (spec.specType !== SPEC_ATTRIBUTE && spec.specType !== SPEC_RELATIONSHIP) continue;
|
|
2527
3132
|
const split = splitProperty(paths[spec.pathIndex] ?? "");
|
|
2528
3133
|
if (!split) continue;
|
|
2529
|
-
const
|
|
2530
|
-
if (!
|
|
3134
|
+
const owner = containerAt(split.primPath);
|
|
3135
|
+
if (!owner) continue;
|
|
2531
3136
|
const fm = fieldsOf(spec.fieldSetIndex);
|
|
2532
|
-
|
|
3137
|
+
owner.properties.push(
|
|
2533
3138
|
spec.specType === SPEC_ATTRIBUTE ? buildAttribute(crate, split.propName, fm) : buildRelationship(crate, split.propName, fm)
|
|
2534
3139
|
);
|
|
2535
3140
|
}
|
|
2536
3141
|
for (const [path, prim] of primByPath) {
|
|
2537
3142
|
const parentPath = parentOf(path);
|
|
2538
3143
|
if (parentPath === "/") rootPrims.push(prim);
|
|
2539
|
-
else
|
|
3144
|
+
else containerAt(parentPath)?.children.push(prim);
|
|
2540
3145
|
}
|
|
2541
3146
|
return { version: crate.version.join("."), metadata: layerMetadata, prims: rootPrims };
|
|
2542
3147
|
}
|
|
3148
|
+
function variantNode(path) {
|
|
3149
|
+
if (!path.endsWith("}")) return null;
|
|
3150
|
+
const open = path.lastIndexOf("{");
|
|
3151
|
+
if (open < 0) return null;
|
|
3152
|
+
const selection = path.slice(open + 1, -1);
|
|
3153
|
+
const eq = selection.indexOf("=");
|
|
3154
|
+
if (eq < 0) return null;
|
|
3155
|
+
const variantName = selection.slice(eq + 1);
|
|
3156
|
+
if (variantName === "") return null;
|
|
3157
|
+
return { owner: path.slice(0, open), setName: selection.slice(0, eq), variantName };
|
|
3158
|
+
}
|
|
2543
3159
|
function buildAttribute(crate, name, fm) {
|
|
2544
3160
|
const defaultRep = fm.get("default");
|
|
3161
|
+
const rawType = asString(crate, fm.get("typeName")) ?? "";
|
|
3162
|
+
const isArrayType = rawType.endsWith("[]");
|
|
2545
3163
|
const attr = {
|
|
2546
3164
|
kind: "attribute",
|
|
2547
3165
|
name,
|
|
2548
|
-
typeName:
|
|
2549
|
-
isArray: defaultRep !== void 0 ? decodeRepBits(defaultRep).isArray : false,
|
|
3166
|
+
typeName: isArrayType ? rawType.slice(0, -2) : rawType,
|
|
3167
|
+
isArray: isArrayType || (defaultRep !== void 0 ? decodeRepBits(defaultRep).isArray : false),
|
|
2550
3168
|
variability: asNumber2(crate, fm.get("variability")) === 1 ? "uniform" : "varying",
|
|
2551
3169
|
custom: false,
|
|
2552
3170
|
metadata: {},
|
|
@@ -2578,6 +3196,10 @@ function buildPrimMetadata(crate, fm) {
|
|
|
2578
3196
|
if (Array.isArray(apiSchemas)) meta.apiSchemas = apiSchemas;
|
|
2579
3197
|
const kind = asString(crate, fm.get("kind"));
|
|
2580
3198
|
if (kind !== void 0) meta.kind = kind;
|
|
3199
|
+
const variants = fm.has("variantSelection") ? crate.getValue(fm.get("variantSelection")) : void 0;
|
|
3200
|
+
if (variants && typeof variants === "object" && !Array.isArray(variants)) {
|
|
3201
|
+
meta.variants = variants;
|
|
3202
|
+
}
|
|
2581
3203
|
for (const key of ARC_FIELDS) {
|
|
2582
3204
|
if (!fm.has(key)) continue;
|
|
2583
3205
|
const arcs = crate.getValue(fm.get(key));
|
|
@@ -2587,6 +3209,11 @@ function buildPrimMetadata(crate, fm) {
|
|
|
2587
3209
|
}
|
|
2588
3210
|
function buildLayerMetadata(crate, fm) {
|
|
2589
3211
|
const meta = {};
|
|
3212
|
+
const subLayers = fm.has("subLayers") ? crate.getValue(fm.get("subLayers")) : void 0;
|
|
3213
|
+
if (Array.isArray(subLayers)) {
|
|
3214
|
+
const paths = subLayers.filter((s) => typeof s === "string" && s.length > 0);
|
|
3215
|
+
if (paths.length > 0) meta.subLayers = paths.map((p) => new AssetPath(p));
|
|
3216
|
+
}
|
|
2590
3217
|
const upAxis = asString(crate, fm.get("upAxis"));
|
|
2591
3218
|
if (upAxis !== void 0) meta.upAxis = upAxis;
|
|
2592
3219
|
const defaultPrim2 = asString(crate, fm.get("defaultPrim"));
|
|
@@ -2607,10 +3234,10 @@ function asNumber2(crate, rep) {
|
|
|
2607
3234
|
}
|
|
2608
3235
|
function splitProperty(path) {
|
|
2609
3236
|
const slash = path.lastIndexOf("/");
|
|
2610
|
-
const
|
|
2611
|
-
if (
|
|
3237
|
+
const dot2 = path.indexOf(".", slash < 0 ? 0 : slash);
|
|
3238
|
+
if (dot2 === -1) return null;
|
|
2612
3239
|
if (path.includes("[")) return null;
|
|
2613
|
-
return { primPath: path.slice(0,
|
|
3240
|
+
return { primPath: path.slice(0, dot2), propName: path.slice(dot2 + 1) };
|
|
2614
3241
|
}
|
|
2615
3242
|
function parentOf(path) {
|
|
2616
3243
|
const i = path.lastIndexOf("/");
|
|
@@ -2623,16 +3250,24 @@ function leaf(path) {
|
|
|
2623
3250
|
// src/usd/composition.ts
|
|
2624
3251
|
var ARC_KEYS = ["references", "payload", "payloads", "inherits", "specializes"];
|
|
2625
3252
|
var STRIP_KEYS = [...ARC_KEYS, "variants", "variantSets"];
|
|
2626
|
-
async function composeLayer(text, baseUrl, resolver, options = {}, stack = /* @__PURE__ */ new Set()) {
|
|
2627
|
-
return composeFile(parseUsda(text), baseUrl, resolver, options, stack);
|
|
3253
|
+
async function composeLayer(text, baseUrl, resolver, options = {}, stack = /* @__PURE__ */ new Set(), cache = /* @__PURE__ */ new Map()) {
|
|
3254
|
+
return composeFile(parseUsda(text), baseUrl, resolver, options, stack, cache);
|
|
2628
3255
|
}
|
|
2629
|
-
async function composeFile(file, baseUrl, resolver, options = {}, stack = /* @__PURE__ */ new Set()) {
|
|
3256
|
+
async function composeFile(file, baseUrl, resolver, options = {}, stack = /* @__PURE__ */ new Set(), cache = /* @__PURE__ */ new Map()) {
|
|
2630
3257
|
const warn = options.onWarn ?? (() => {
|
|
2631
3258
|
});
|
|
2632
3259
|
let weak = [];
|
|
2633
3260
|
const subLayers = toArcs(file.metadata.subLayers);
|
|
2634
3261
|
for (let i = subLayers.length - 1; i >= 0; i--) {
|
|
2635
|
-
const sub = await loadExternalFile(
|
|
3262
|
+
const sub = await loadExternalFile(
|
|
3263
|
+
subLayers[i],
|
|
3264
|
+
baseUrl,
|
|
3265
|
+
resolver,
|
|
3266
|
+
options,
|
|
3267
|
+
stack,
|
|
3268
|
+
warn,
|
|
3269
|
+
cache
|
|
3270
|
+
);
|
|
2636
3271
|
if (sub) weak = mergePrimLists(weak, sub.prims);
|
|
2637
3272
|
}
|
|
2638
3273
|
const ctx = {
|
|
@@ -2642,7 +3277,8 @@ async function composeFile(file, baseUrl, resolver, options = {}, stack = /* @__
|
|
|
2642
3277
|
warn,
|
|
2643
3278
|
stack,
|
|
2644
3279
|
index: buildPathIndex(file.prims),
|
|
2645
|
-
resolving: /* @__PURE__ */ new Set()
|
|
3280
|
+
resolving: /* @__PURE__ */ new Set(),
|
|
3281
|
+
cache
|
|
2646
3282
|
};
|
|
2647
3283
|
const resolved = [];
|
|
2648
3284
|
for (const prim of file.prims) resolved.push(await resolvePrim(prim, "", ctx));
|
|
@@ -2653,13 +3289,15 @@ async function resolvePrim(spec, parentPath, ctx) {
|
|
|
2653
3289
|
const path = `${parentPath}/${spec.name}`;
|
|
2654
3290
|
let properties = spec.properties;
|
|
2655
3291
|
let children = spec.children;
|
|
3292
|
+
const variantArcs = [];
|
|
2656
3293
|
const selection = spec.metadata.variants;
|
|
2657
|
-
if (spec.variantSets &&
|
|
3294
|
+
if (spec.variantSets && isDictionary2(selection)) {
|
|
2658
3295
|
for (const [setName, variantName] of Object.entries(selection)) {
|
|
2659
3296
|
const variant = spec.variantSets[setName]?.[String(variantName)];
|
|
2660
3297
|
if (!variant) continue;
|
|
2661
3298
|
properties = mergeProperties(variant.properties, properties);
|
|
2662
3299
|
children = mergePrimLists(variant.children, children);
|
|
3300
|
+
for (const key of ARC_KEYS) variantArcs.push(...toArcs(variant.metadata[key]));
|
|
2663
3301
|
}
|
|
2664
3302
|
}
|
|
2665
3303
|
const resolvedChildren = [];
|
|
@@ -2673,7 +3311,7 @@ async function resolvePrim(spec, parentPath, ctx) {
|
|
|
2673
3311
|
children: resolvedChildren,
|
|
2674
3312
|
line: spec.line
|
|
2675
3313
|
};
|
|
2676
|
-
const arcs = ARC_KEYS.flatMap((k) => toArcs(spec.metadata[k]));
|
|
3314
|
+
const arcs = [...variantArcs, ...ARC_KEYS.flatMap((k) => toArcs(spec.metadata[k]))];
|
|
2677
3315
|
let base = null;
|
|
2678
3316
|
for (const arc of arcs) {
|
|
2679
3317
|
const target = await loadReferencedPrim(arc, ctx, path);
|
|
@@ -2682,20 +3320,21 @@ async function resolvePrim(spec, parentPath, ctx) {
|
|
|
2682
3320
|
return base ? mergePrim(base, local) : local;
|
|
2683
3321
|
}
|
|
2684
3322
|
async function loadReferencedPrim(arc, ctx, destPath) {
|
|
2685
|
-
if (arc.assetPath) {
|
|
3323
|
+
if (arc.assetPath?.path) {
|
|
2686
3324
|
const composed = await loadExternalFile(
|
|
2687
3325
|
arc,
|
|
2688
3326
|
ctx.baseUrl,
|
|
2689
3327
|
ctx.resolver,
|
|
2690
3328
|
ctx.options,
|
|
2691
3329
|
ctx.stack,
|
|
2692
|
-
ctx.warn
|
|
3330
|
+
ctx.warn,
|
|
3331
|
+
ctx.cache
|
|
2693
3332
|
);
|
|
2694
3333
|
if (!composed) return null;
|
|
2695
3334
|
const target = arc.primPath ? findPrimByPath(composed, arc.primPath) : defaultPrim(composed, ctx.warn);
|
|
2696
3335
|
if (!target) {
|
|
2697
3336
|
ctx.warn(
|
|
2698
|
-
`reference target ${arc.primPath ?? "(defaultPrim)"} not found in ${arc.assetPath
|
|
3337
|
+
`reference target ${arc.primPath ?? "(defaultPrim)"} not found in ${arc.assetPath?.path}`
|
|
2699
3338
|
);
|
|
2700
3339
|
return null;
|
|
2701
3340
|
}
|
|
@@ -2721,9 +3360,10 @@ async function loadReferencedPrim(arc, ctx, destPath) {
|
|
|
2721
3360
|
}
|
|
2722
3361
|
return null;
|
|
2723
3362
|
}
|
|
2724
|
-
async function loadExternalFile(arc, baseUrl, resolver, options, stack, warn) {
|
|
2725
|
-
if (!arc.assetPath) return null;
|
|
2726
|
-
const
|
|
3363
|
+
async function loadExternalFile(arc, baseUrl, resolver, options, stack, warn, cache) {
|
|
3364
|
+
if (!arc.assetPath?.path) return null;
|
|
3365
|
+
const assetPath = arc.assetPath.path;
|
|
3366
|
+
const url = resolver.resolve(assetPath, baseUrl);
|
|
2727
3367
|
if (stack.has(url)) {
|
|
2728
3368
|
warn(`composition cycle detected at ${url}; skipping`);
|
|
2729
3369
|
return null;
|
|
@@ -2732,18 +3372,31 @@ async function loadExternalFile(arc, baseUrl, resolver, options, stack, warn) {
|
|
|
2732
3372
|
warn(`composition exceeded max depth at ${url}; skipping`);
|
|
2733
3373
|
return null;
|
|
2734
3374
|
}
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
3375
|
+
const cached = cache.get(url);
|
|
3376
|
+
if (cached) return cached;
|
|
3377
|
+
const pending = (async () => {
|
|
3378
|
+
let bytes;
|
|
3379
|
+
try {
|
|
3380
|
+
bytes = await fetchLayerBytes(resolver, url);
|
|
3381
|
+
} catch (err) {
|
|
3382
|
+
warn(`cannot resolve "${assetPath}" -> ${url}: ${err.message}`);
|
|
3383
|
+
return null;
|
|
3384
|
+
}
|
|
3385
|
+
const childStack = /* @__PURE__ */ new Set([...stack, url]);
|
|
3386
|
+
if (CrateReader.isCrate(bytes)) {
|
|
3387
|
+
return composeFile(
|
|
3388
|
+
crateToUsdaFile(new CrateReader(bytes)),
|
|
3389
|
+
url,
|
|
3390
|
+
resolver,
|
|
3391
|
+
options,
|
|
3392
|
+
childStack,
|
|
3393
|
+
cache
|
|
3394
|
+
);
|
|
3395
|
+
}
|
|
3396
|
+
return composeLayer(new TextDecoder().decode(bytes), url, resolver, options, childStack, cache);
|
|
3397
|
+
})();
|
|
3398
|
+
cache.set(url, pending);
|
|
3399
|
+
return pending;
|
|
2747
3400
|
}
|
|
2748
3401
|
async function fetchLayerBytes(resolver, url) {
|
|
2749
3402
|
if (resolver.fetchBytes) return resolver.fetchBytes(url);
|
|
@@ -2881,7 +3534,7 @@ function toArcs(value) {
|
|
|
2881
3534
|
}
|
|
2882
3535
|
return arcs;
|
|
2883
3536
|
}
|
|
2884
|
-
function
|
|
3537
|
+
function isDictionary2(v) {
|
|
2885
3538
|
return typeof v === "object" && v !== null && !Array.isArray(v) && !(v instanceof Quat) && !(v instanceof UsdMatrix) && !(v instanceof AssetPath);
|
|
2886
3539
|
}
|
|
2887
3540
|
function stripKeys(meta, keys) {
|
|
@@ -2921,6 +3574,6 @@ function openUsdz(bytes) {
|
|
|
2921
3574
|
return { rootEntry, resolver };
|
|
2922
3575
|
}
|
|
2923
3576
|
|
|
2924
|
-
export { ARTICULATION_ROOT_API, AssetPath, Attribute, COLLISION_API, CrateReader, DEFAULT_METERS_PER_UNIT, DEG2RAD, DefaultAssetResolver, Layer, ParseError, Prim, Quat, RAD2DEG, RIGID_BODY_API, Relationship, Stage, TokenizeError, UsdMatrix, 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 };
|
|
2925
|
-
//# sourceMappingURL=chunk-
|
|
2926
|
-
//# sourceMappingURL=chunk-
|
|
3577
|
+
export { ARTICULATION_ROOT_API, AssetPath, Attribute, COLLISION_API, CrateReader, DEFAULT_METERS_PER_UNIT, DEG2RAD, DefaultAssetResolver, Layer, MASS_API, MESH_COLLISION_API, PHYSICS_MATERIAL_API, ParseError, Prim, Quat, RAD2DEG, RIGID_BODY_API, Relationship, Stage, TokenizeError, UsdMatrix, buildKinematicTree, channelFromSamples, composeFile, composeLayer, computeLocalTransform, computeWorldTransform, crateToUsdaFile, createMemoryResolver, decomposeRigid, driveKindFor, extractRobotDescription, fromUsdMatrix, gatherMeshDescendants, getJointAxis, getJointBodies, getJointDrive, getJointLimits, getJointLocalFrame, getJointStatePosition, getJointType, getMassProperties, getMaterialSubsets, getTranslation, hasArticulationRootAPI, hasCollisionAPI, hasRigidBodyAPI, identity4, interpolate, invert, isMesh, isNonVisualPurpose, isScope, isXform, iterDescendants, joinPosix, jointValueFromSI, jointValueToSI, makeEuler, makeRotationFromQuat, makeRotationX, makeRotationY, makeRotationZ, makeScale, makeTranslation, multiply, multiplyAll, normalizeJointLimits, openUsdz, parseOpType, parseUsda, refineJointType, resolveBoundMaterial, serializeUsda, toUsdMatrix, tokenize };
|
|
3578
|
+
//# sourceMappingURL=chunk-4GPCBXUS.js.map
|
|
3579
|
+
//# sourceMappingURL=chunk-4GPCBXUS.js.map
|