three-usd-robot 0.11.0 → 0.13.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 +32 -280
- package/dist/MeshBinding-B_8RhuQE.d.ts +288 -0
- package/dist/{ThreeUsdRobot-BxnCluuK.d.ts → ThreeUsdRobot-X1zbpRZo.d.ts} +38 -8
- package/dist/{ThreeUsdRobotLoader-C-E9uwEe.d.ts → ThreeUsdRobotLoader-u3d1yoLM.d.ts} +11 -3
- package/dist/{buildKinematicTree-BCySuZZn.d.ts → buildKinematicTree-Q9JOjAjM.d.ts} +17 -3
- package/dist/bytes-CxGRGry_.d.ts +14 -0
- package/dist/{chunk-BCRRXGNB.js → chunk-5ZPHZ5ZH.js} +81 -6
- package/dist/chunk-5ZPHZ5ZH.js.map +1 -0
- package/dist/{chunk-AXPMXEQC.js → chunk-FUVHAORT.js} +77 -717
- package/dist/chunk-FUVHAORT.js.map +1 -0
- package/dist/{chunk-5SVRTKS4.js → chunk-GRJGPHLW.js} +18 -11
- package/dist/chunk-GRJGPHLW.js.map +1 -0
- package/dist/chunk-JGIVJXBU.js +54 -0
- package/dist/chunk-JGIVJXBU.js.map +1 -0
- package/dist/{chunk-ENWFOYHU.js → chunk-JN2QPDB3.js} +101 -14
- package/dist/chunk-JN2QPDB3.js.map +1 -0
- package/dist/chunk-PPPRB6KE.js +963 -0
- package/dist/chunk-PPPRB6KE.js.map +1 -0
- package/dist/{chunk-LDO5FKQS.js → chunk-YGJ23CG3.js} +4 -53
- package/dist/chunk-YGJ23CG3.js.map +1 -0
- package/dist/core.d.ts +8 -65
- package/dist/core.js +5 -3
- package/dist/extras.d.ts +2 -2
- package/dist/helpers.d.ts +2 -2
- package/dist/helpers.js +3 -2
- package/dist/helpers.js.map +1 -1
- package/dist/index.d.ts +22 -263
- package/dist/index.js +35 -9
- package/dist/index.js.map +1 -1
- package/dist/nodes.d.ts +49 -0
- package/dist/nodes.js +439 -0
- package/dist/nodes.js.map +1 -0
- package/dist/parseMdl-vfzBGoMr.d.ts +87 -0
- package/dist/react.d.ts +6 -4
- package/dist/react.js +6 -4
- package/dist/react.js.map +1 -1
- package/package.json +6 -2
- package/dist/bytes-MOJ2oN-u.d.ts +0 -42
- package/dist/chunk-5SVRTKS4.js.map +0 -1
- package/dist/chunk-AXPMXEQC.js.map +0 -1
- package/dist/chunk-BCRRXGNB.js.map +0 -1
- package/dist/chunk-ENWFOYHU.js.map +0 -1
- package/dist/chunk-LDO5FKQS.js.map +0 -1
package/README.md
CHANGED
|
@@ -22,14 +22,12 @@ exported back to `.usda` / `.usdz` in the browser.
|
|
|
22
22
|
Multi-file assets (references / payloads / sublayers), variant selections and
|
|
23
23
|
instanceable prims are composed for you.
|
|
24
24
|
- **Robots** — links, joints (fixed / revolute / continuous / prismatic), limits,
|
|
25
|
-
drives and the initial pose become
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
and units normalized automatically. Articulation-free stages load as
|
|
32
|
-
static scenes.
|
|
25
|
+
drives, mimic couplings (gripper finger linkages) and the initial pose become
|
|
26
|
+
a `setJointValue`-able hierarchy.
|
|
27
|
+
- **Rendering** — meshes, solid gprims, point clouds and curves with `UsdShade`
|
|
28
|
+
materials (UsdPreviewSurface / Omniverse MDL / MaterialX, plus optional TSL
|
|
29
|
+
graph execution on WebGPU) and textures; up-axis and units normalized
|
|
30
|
+
automatically. Articulation-free stages load as static scenes.
|
|
33
31
|
- **Animation** — plays back time-sampled joint trajectories, and replays
|
|
34
32
|
baked body-transform recordings through `setLinkTransforms` with
|
|
35
33
|
constraint diagnostics.
|
|
@@ -55,31 +53,6 @@ The CDN is public and CORS-enabled, so this works in the browser too. Try
|
|
|
55
53
|
FK check, and a re-export to one self-contained file), or open the Vite example
|
|
56
54
|
and pick a robot from the preset list.
|
|
57
55
|
|
|
58
|
-
Materials target **UsdPreviewSurface fidelity plus an Omniverse MDL mapping**:
|
|
59
|
-
constant and textured inputs, faceVarying / indexed UVs, multiple UV sets,
|
|
60
|
-
per-vertex display colors, physical extensions (`ior` / `clearcoat` /
|
|
61
|
-
specular workflow → `MeshPhysicalMaterial`), packed ORM maps,
|
|
62
|
-
`sourceColorSpace`, and purpose/strength-aware bindings. MDL shaders are
|
|
63
|
-
identified by `info:mdl:sourceAsset` and mapped **by family** — no shader
|
|
64
|
-
execution — and referenced `.mdl` modules are fetched and parsed for their
|
|
65
|
-
declaration values, so wrapper materials
|
|
66
|
-
(`export material X(*) = OmniPBR(…)`) render correctly even when the USD
|
|
67
|
-
shader authors no inputs at all. Value priority: authored USD inputs >
|
|
68
|
-
wrapper arguments > declaration defaults.
|
|
69
|
-
|
|
70
|
-
| MDL family | three.js mapping |
|
|
71
|
-
| --- | --- |
|
|
72
|
-
| `OmniPBR` (and derivatives, e.g. `OmniPBR_Opacity`) | color / metalness / roughness / emissive (`emissive_intensity`), per-channel texture maps and packed `ORM_texture`, opacity, normal map, `texture_translate/rotate/scale` |
|
|
73
|
-
| `OmniPBR_ClearCoat` | the OmniPBR mapping plus `clearcoat` / `clearcoatRoughness` / `clearcoatNormalMap` |
|
|
74
|
-
| `OmniGlass` | `MeshPhysicalMaterial` with `transmission` / `ior` (default 1.491) / `roughness` / `thickness`, glass color + texture |
|
|
75
|
-
| `OmniSurface(Lite)` | constants subset: diffuse color / metalness / roughness / IOR / coat / emission / opacity |
|
|
76
|
-
|
|
77
|
-
Executing MDL or MaterialX shader graphs is out of scope; unknown MDL
|
|
78
|
-
materials fall back to the OmniPBR mapping with a warning. Not yet
|
|
79
|
-
supported: collection-based material bindings, and the exotic curve schemas
|
|
80
|
-
(`NurbsCurves`, `HermiteCurves`, `NurbsPatch`) which load with a warning and
|
|
81
|
-
are skipped.
|
|
82
|
-
|
|
83
56
|
## Install
|
|
84
57
|
|
|
85
58
|
```sh
|
|
@@ -104,221 +77,33 @@ robot.setJointValues({ joint1: 0.4, joint2: -0.2 });
|
|
|
104
77
|
const handMatrix = robot.getLinkWorldMatrix("tool0"); // THREE.Matrix4
|
|
105
78
|
const handPos = robot.getLinkWorldPosition("tool0"); // THREE.Vector3
|
|
106
79
|
|
|
107
|
-
robot.getJointNames(); //
|
|
80
|
+
robot.getJointNames(); // commandable joints
|
|
108
81
|
robot.getKinematicTree(); // root, ordering, loop joints, ...
|
|
109
82
|
```
|
|
110
83
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const loader = new ThreeUsdRobotLoader();
|
|
117
|
-
await loader.parse(usdaText); // USDA source string
|
|
118
|
-
await loader.parse(file); // File / Blob from drag & drop or <input type="file">
|
|
119
|
-
await loader.parse(await res.arrayBuffer()); // a fetch you did yourself
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
`parseUsdz(data)` / `parseCrate(data, baseUrl)` stay as explicit-format entries,
|
|
123
|
-
and `parseRobotDescription(data)` returns the Three.js-independent IR. Pass a
|
|
124
|
-
`baseUrl` as the second `parse` argument if the layer has relative references
|
|
125
|
-
or texture paths to resolve.
|
|
126
|
-
|
|
127
|
-
### World up-axis & units
|
|
128
|
-
|
|
129
|
-
Stages load normalized: `metersPerUnit` scales the root, and the authored
|
|
130
|
-
`upAxis` (`"Y"` or `"Z"`) is rotated into your world convention via `worldUp`:
|
|
131
|
-
|
|
132
|
-
```ts
|
|
133
|
-
new ThreeUsdRobotLoader(); // default: "Y" — upright in a stock three.js scene
|
|
134
|
-
new ThreeUsdRobotLoader({ worldUp: "Z" }); // robotics-style Z-up world
|
|
135
|
-
new ThreeUsdRobotLoader({ worldUp: "keep" }); // leave the authored orientation
|
|
136
|
-
|
|
137
|
-
robot.upAxis; // authored stage value ("Y" | "Z"), independent of normalization
|
|
138
|
-
robot.metersPerUnit; // authored stage scale (already applied to the root)
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
Isaac Sim assets are Z-up, so the default makes them stand upright in a plain
|
|
142
|
-
three.js scene; a Z-up app (ROS-style) passes `worldUp: "Z"` once instead of
|
|
143
|
-
counter-rotating per asset. The M9 option `upAxisConversion` remains as a
|
|
144
|
-
deprecated alias (`"auto"` ≡ `worldUp: "Y"`, `"none"` ≡ `"keep"`).
|
|
145
|
-
|
|
146
|
-
### Stable addressing (naming contract)
|
|
147
|
-
|
|
148
|
-
Joints and links are keyed by their prim's **leaf name** while it is unique
|
|
149
|
-
across the robot; on a collision (say, two arms each with a `seg` link) the
|
|
150
|
-
colliding entries are keyed by their **full prim path** instead —
|
|
151
|
-
deterministically. Every accessor also takes the full prim path directly, so
|
|
152
|
-
tooling can pin exact prims no matter how the asset is named:
|
|
153
|
-
|
|
154
|
-
```ts
|
|
155
|
-
robot.setJointValue("/World/armL/j1", 0.4); // same joint as its key
|
|
156
|
-
robot.getLinkWorldMatrix("/World/armL/seg");
|
|
157
|
-
robot.getLinkObjectsByPath(); // Map<primPath, LinkObject>
|
|
158
|
-
robot.getJointObjectsByPath(); // Map<primPath, JointObject>
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
`LinkObject.primPath` / `JointObject.primPath` carry the reverse direction.
|
|
162
|
-
|
|
163
|
-
### Viewer toggles & helpers
|
|
164
|
-
|
|
165
|
-
```ts
|
|
166
|
-
robot.showVisual = true;
|
|
167
|
-
robot.showCollision = false;
|
|
168
|
-
robot.showJointAxes = true; // built-in axes gizmos on each joint
|
|
169
|
-
robot.showLinkFrames = false;
|
|
170
|
-
|
|
171
|
-
import { addJointLimitHelpers } from "three-usd-robot/helpers";
|
|
172
|
-
addJointLimitHelpers(robot); // arc (revolute) / segment (prismatic) per joint
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### Link highlighting & ghosts
|
|
176
|
-
|
|
177
|
-
Per-link appearance helpers cover the common viewer chores — flagging
|
|
178
|
-
colliding links, material swaps, and translucent "ghost" pose previews:
|
|
179
|
-
|
|
180
|
-
```ts
|
|
181
|
-
import {
|
|
182
|
-
createGhostRobot,
|
|
183
|
-
highlightLink,
|
|
184
|
-
restoreLinkMaterials,
|
|
185
|
-
setLinkMaterial,
|
|
186
|
-
} from "three-usd-robot/helpers";
|
|
187
|
-
|
|
188
|
-
highlightLink(robot, "link1"); // emissive red tint; maps/colors kept
|
|
189
|
-
highlightLink(robot, "/World/armL/seg", { color: 0xffaa00, opacity: 0.6 });
|
|
190
|
-
setLinkMaterial(robot, "link2", new THREE.MeshBasicMaterial({ wireframe: true }));
|
|
191
|
-
restoreLinkMaterials(robot, "link1"); // exact original materials back
|
|
192
|
-
|
|
193
|
-
const ghost = createGhostRobot(robot, { jointValues: { joint1: 1.2 } });
|
|
194
|
-
scene.add(ghost); // translucent copy previewing the target pose
|
|
195
|
-
ghost.setJointValues(ikSolution); // a full ThreeUsdRobot, driveable like the source
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
Highlights never stack (each call re-tints from the originals), and ghosts
|
|
199
|
-
share the source's geometry — cloning is cheap enough for onion-skinning.
|
|
200
|
-
|
|
201
|
-
Loading a whole cell rather than a bare robot? Pass
|
|
202
|
-
`{ loadSceneGeometry: true }` to the loader to draw the static environment
|
|
203
|
-
(floor, guarding, racking, …) around the machines. A stage with **no
|
|
204
|
-
articulation at all** — a plain static USD scene — is detected and rendered as
|
|
205
|
-
scene geometry automatically, with the same unit / up-axis normalization; pass
|
|
206
|
-
`loadSceneGeometry: false` to opt out.
|
|
207
|
-
|
|
208
|
-
### Joint slider panel (lil-gui)
|
|
209
|
-
|
|
210
|
-
```ts
|
|
211
|
-
import GUI from "lil-gui";
|
|
212
|
-
import { createJointSliderPanel } from "three-usd-robot/extras";
|
|
213
|
-
|
|
214
|
-
createJointSliderPanel(robot, new GUI()); // one slider per articulated joint
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
The panel takes the GUI instance from you, so the library never bundles
|
|
218
|
-
`lil-gui`.
|
|
219
|
-
|
|
220
|
-
### Animation playback
|
|
221
|
-
|
|
222
|
-
If the asset has time-sampled joint trajectories, the robot plays them back:
|
|
223
|
-
|
|
224
|
-
```ts
|
|
225
|
-
const range = robot.getTimeRange();
|
|
226
|
-
if (range) {
|
|
227
|
-
// in your render loop, advance a time code between range.start and range.end:
|
|
228
|
-
robot.setTime(t); // interpolates every animated joint and updates FK
|
|
229
|
-
}
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
### Baked link transforms (recorded playback)
|
|
233
|
-
|
|
234
|
-
Recordings baked as **body transforms** (Isaac Sim stage-recorder output,
|
|
235
|
-
maximal-coordinate solver playback) can drive link poses directly, bypassing
|
|
236
|
-
the joints — usdview-style display semantics:
|
|
237
|
-
|
|
238
|
-
```ts
|
|
239
|
-
// A world-pose track keyed by prim path (or link key), quaternion in [x, y, z, w]:
|
|
240
|
-
robot.setLinkTransforms({
|
|
241
|
-
"/World/link1": { position: [0, 0, 1], quaternion: [0, 0, 0, 1] },
|
|
242
|
-
"/World/link2": { position: [0.3, 0, 2], quaternion: [0, 0, 0, 1] },
|
|
243
|
-
}); // batched — one matrix update; unlisted links keep their current world pose
|
|
244
|
-
|
|
245
|
-
robot.displayMode; // "baked": joint values are untouched and no longer place links
|
|
246
|
-
robot.setJointValues(liveValues); // recompute all links from joint values → "fk"
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
Poses are read in the **three.js scene world after `worldUp` normalization** —
|
|
250
|
-
pair a Z-up meter track (Isaac / ROS convention) with `worldUp: "Z"`; feeding
|
|
251
|
-
it into the default Y-up normalization lays the robot on its side. Transforms
|
|
252
|
-
on the `robot` object itself (placement, uniform scaling) are accounted for,
|
|
253
|
-
and `{ space: "stage" }` reads authored stage coordinates instead.
|
|
254
|
-
|
|
255
|
-
Constraint deviations — a recording from a different model version, solver
|
|
256
|
-
drift, a coordinate-convention bug — are shown, never silently corrected.
|
|
257
|
-
Measure them, or project onto the joints instead:
|
|
258
|
-
|
|
259
|
-
```ts
|
|
260
|
-
robot.validateLinkTransforms(poses);
|
|
261
|
-
// { "/World/joint1": { anchorError /* m */, axisError /* rad */, q, limitExceeded }, … }
|
|
262
|
-
// covers every joint: fixed joints, loop joints dropped from the FK tree,
|
|
263
|
-
// and the world-fixed root attachment
|
|
264
|
-
|
|
265
|
-
const { values, residuals } = robot.jointValuesFromLinkTransforms(poses, {
|
|
266
|
-
previous: lastValues, // ±π branch continuity, frame to frame
|
|
267
|
-
});
|
|
268
|
-
robot.setJointValues(values); // constraint-respecting playback of the same track
|
|
269
|
-
```
|
|
84
|
+
`parse` also takes in-memory content (USDA text, an `ArrayBuffer` / typed
|
|
85
|
+
array / `Blob` — the format is sniffed, so a dropped `File` works as-is), and
|
|
86
|
+
the loader normalizes units and up-axis for you: Isaac's Z-up assets stand
|
|
87
|
+
upright in a Y-up three.js scene by default, or pass `worldUp: "Z"` for a
|
|
88
|
+
robotics-style Z-up world. Details in the [runtime guide](./docs/runtime.md).
|
|
270
89
|
|
|
271
|
-
|
|
272
|
-
session when poses deviate beyond 1 mm / 0.01 rad.
|
|
273
|
-
|
|
274
|
-
### React Three Fiber
|
|
275
|
-
|
|
276
|
-
`three-usd-robot/react` provides a declarative `<UsdRobot>` (`react` and
|
|
277
|
-
`@react-three/fiber` are **optional** peer deps):
|
|
278
|
-
|
|
279
|
-
```tsx
|
|
280
|
-
import { Canvas } from "@react-three/fiber";
|
|
281
|
-
import { Suspense } from "react";
|
|
282
|
-
import { UsdRobot } from "three-usd-robot/react";
|
|
283
|
-
|
|
284
|
-
<Canvas camera={{ position: [2, 2, 2] }}>
|
|
285
|
-
<Suspense fallback={null}>
|
|
286
|
-
<UsdRobot
|
|
287
|
-
url="/robot.usda"
|
|
288
|
-
jointValues={{ joint1: 0.4 }} // controlled
|
|
289
|
-
showJointAxes
|
|
290
|
-
animate // play time-sampled trajectories
|
|
291
|
-
onLoad={(robot) => console.log(robot.getJointNames())}
|
|
292
|
-
/>
|
|
293
|
-
</Suspense>
|
|
294
|
-
<ambientLight />
|
|
295
|
-
</Canvas>;
|
|
296
|
-
```
|
|
90
|
+
## Documentation
|
|
297
91
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
92
|
+
| Doc | Contents |
|
|
93
|
+
| --- | --- |
|
|
94
|
+
| [Runtime guide](./docs/runtime.md) | Input sources, up-axis & units, naming contract, mimic joints, viewer helpers & ghosts, static scenes, joint sliders, React Three Fiber, using the core without Three.js |
|
|
95
|
+
| [Materials](./docs/materials.md) | UsdPreviewSurface fidelity, Omniverse MDL family mappings, MaterialX, optional TSL graph execution (WebGPU) |
|
|
96
|
+
| [Animation & recorded playback](./docs/recorded-playback.md) | Time-sampled trajectories, baked body-transform recordings, constraint diagnostics & joint projection |
|
|
97
|
+
| [Exporting USD](./docs/export.md) | Re-export, `RobotBuilder` authoring, simulation-ready assets (mass / collision / Isaac Robot Schema), USDZ packaging |
|
|
301
98
|
|
|
302
99
|
## Export USD
|
|
303
100
|
|
|
304
|
-
The loader's inverse
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-

|
|
101
|
+
The loader's inverse — author a robot from Three.js meshes and open it in
|
|
102
|
+
Isaac Sim:
|
|
308
103
|
|
|
309
104
|
```ts
|
|
310
|
-
import {
|
|
311
|
-
|
|
312
|
-
RobotBuilder,
|
|
313
|
-
serializeUsda,
|
|
314
|
-
writeUsdz,
|
|
315
|
-
} from "three-usd-robot";
|
|
316
|
-
|
|
317
|
-
// Re-export a loaded robot (meshes harvested from the Three.js scene):
|
|
318
|
-
const usda = serializeUsda(exportThreeUsdRobot(robot));
|
|
319
|
-
|
|
320
|
-
// …or build one from Three.js meshes. Z-up and metres by default; each joint
|
|
321
|
-
// takes ONE world-space frame, and the build-time arrangement is the zero pose.
|
|
105
|
+
import { RobotBuilder, serializeUsda } from "three-usd-robot";
|
|
106
|
+
|
|
322
107
|
const builder = new RobotBuilder({ name: "my_robot" });
|
|
323
108
|
builder.addLink({ name: "base", visuals: [baseMesh] });
|
|
324
109
|
builder.addLink({ name: "arm", frame: armFrame, visuals: [armMesh] });
|
|
@@ -327,46 +112,11 @@ builder.addRevoluteJoint({
|
|
|
327
112
|
name: "j1", parent: "base", child: "arm",
|
|
328
113
|
frame: jointFrame, axis: "Z", lower: -Math.PI, upper: Math.PI,
|
|
329
114
|
});
|
|
330
|
-
|
|
331
|
-
const file = builder.toUsda();
|
|
332
|
-
writeFileSync("robot.usda", serializeUsda(file));
|
|
333
|
-
writeFileSync("robot.usdz", writeUsdz({ "robot.usda": serializeUsda(file) }));
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
Joints export as `UsdPhysics` prims with their limits, drives and initial pose.
|
|
337
|
-
For a simulation-ready asset, links also take mass properties, and collision
|
|
338
|
-
meshes take physics materials and a collision approximation:
|
|
339
|
-
|
|
340
|
-
```ts
|
|
341
|
-
builder.addLink({
|
|
342
|
-
name: "arm",
|
|
343
|
-
visuals: [armMesh],
|
|
344
|
-
collisions: [armCollisionMesh],
|
|
345
|
-
inertial: { mass: 2.5, centerOfMass: [0, 0, 0.2], diagonalInertia: [0.02, 0.02, 0.004] },
|
|
346
|
-
collisionApproximation: "convexHull",
|
|
347
|
-
physicsMaterial: { name: "steel", staticFriction: 0.6, dynamicFriction: 0.5 },
|
|
348
|
-
});
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
Both screenshots above come from `npx tsx scripts/demo-factory.ts`, which
|
|
352
|
-
authors a complete robot cell — a 7-DOF arm with a gripper, a conveyor, a
|
|
353
|
-
turntable and the surrounding scenery — and exports it to
|
|
354
|
-
`out/factory.usda` / `.usdz`.
|
|
355
|
-
|
|
356
|
-
## Use it without Three.js
|
|
357
|
-
|
|
358
|
-
`three-usd-robot/core` is a standalone USD parser, writer and robot IR — handy
|
|
359
|
-
for server-side validation or asset tooling:
|
|
360
|
-
|
|
361
|
-
```ts
|
|
362
|
-
import { parseUsda, Stage, extractRobotDescription } from "three-usd-robot/core";
|
|
363
|
-
|
|
364
|
-
const desc = extractRobotDescription(Stage.OpenFromString(usdaText));
|
|
365
|
-
console.log(desc.rootLink, Object.keys(desc.joints));
|
|
115
|
+
writeFileSync("robot.usda", serializeUsda(builder.toUsda()));
|
|
366
116
|
```
|
|
367
117
|
|
|
368
|
-
|
|
369
|
-
|
|
118
|
+
Limits, drives, mimic couplings, the initial pose, mass properties and
|
|
119
|
+
collision setup all serialize — see [Exporting USD](./docs/export.md).
|
|
370
120
|
|
|
371
121
|
## Examples
|
|
372
122
|
|
|
@@ -377,10 +127,11 @@ and `.usdz` packages to ASCII USDA.
|
|
|
377
127
|
(prim tree + attribute inspector), a transform gizmo, joint sliders,
|
|
378
128
|
animation playback and USD export.
|
|
379
129
|
- **`vite-basic-viewer`** — the same thing through React Three Fiber.
|
|
130
|
+
- **`vite-webgpu-nodes`** — MaterialX graph execution (TSL) on `WebGPURenderer`.
|
|
380
131
|
|
|
381
|
-
|
|
382
|
-
one straight from NVIDIA's CDN. `npm run demo:build` generates the
|
|
383
|
-
and builds the deployable site.
|
|
132
|
+
The viewers take `?asset=<url>` for any asset, or `?isaac=<path under Isaac/>`
|
|
133
|
+
to pull one straight from NVIDIA's CDN. `npm run demo:build` generates the
|
|
134
|
+
factory cell and builds the deployable site.
|
|
384
135
|
|
|
385
136
|
## Package entry points
|
|
386
137
|
|
|
@@ -388,8 +139,9 @@ and builds the deployable site.
|
|
|
388
139
|
| --- | --- |
|
|
389
140
|
| `three-usd-robot` | Three.js runtime — `ThreeUsdRobotLoader`, `ThreeUsdRobot`, `RobotBuilder`, export helpers |
|
|
390
141
|
| `three-usd-robot/core` | Three.js-independent USD parser & writer, robot IR, forward-kinematics math |
|
|
391
|
-
| `three-usd-robot/helpers` | Viewer helpers (joint axes, link frames, joint limits) |
|
|
142
|
+
| `three-usd-robot/helpers` | Viewer helpers (joint axes, link frames, joint limits, highlights, ghosts) |
|
|
392
143
|
| `three-usd-robot/extras` | Joint slider panel (bring your own `lil-gui`) |
|
|
144
|
+
| `three-usd-robot/nodes` | Optional MaterialX → TSL execution (`three/webgpu`) — `createMaterialXNodeFactory`, `loadMaterialXDocument` |
|
|
393
145
|
| `three-usd-robot/react` | React Three Fiber `<UsdRobot>` component + hooks |
|
|
394
146
|
|
|
395
147
|
## Development
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { y as Vec2, z as Vec3, S as Stage, P as Prim, R as RobotDescription } from './buildKinematicTree-Q9JOjAjM.js';
|
|
3
|
+
import { b as MdlModuleProvider, A as AssetResolver } from './parseMdl-vfzBGoMr.js';
|
|
4
|
+
import { T as ThreeUsdRobot } from './ThreeUsdRobot-X1zbpRZo.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Resolves `UsdShade` material bindings to flat PBR parameters.
|
|
8
|
+
*
|
|
9
|
+
* Follows a prim's (or an ancestor's) `material:binding` to a `Material`, finds
|
|
10
|
+
* its surface `Shader`, and reads constant color/metalness/roughness/opacity/
|
|
11
|
+
* emissive inputs plus the **texture** asset paths for the diffuse, normal,
|
|
12
|
+
* roughness, metallic, occlusion and emissive channels. Handles both
|
|
13
|
+
* `UsdPreviewSurface` (constant inputs or a connected `UsdUVTexture` network)
|
|
14
|
+
* and the Omniverse MDL material families (M20): `OmniPBR` (and derivatives
|
|
15
|
+
* such as `OmniPBR_Opacity`), `OmniPBR_ClearCoat`, `OmniGlass`, and an
|
|
16
|
+
* `OmniSurface(Lite)` constants subset. MDL shaders are identified by
|
|
17
|
+
* `info:mdl:sourceAsset` / `:subIdentifier`; when the referenced `.mdl` module
|
|
18
|
+
* text is available (see `loadMdlModules`), parameter values fall back from
|
|
19
|
+
* authored USD inputs to the module's wrapper arguments and declaration
|
|
20
|
+
* defaults. Executing MDL remains out of scope.
|
|
21
|
+
*
|
|
22
|
+
* MaterialX networks authored natively in UsdShade (M21) resolve here too:
|
|
23
|
+
* `ND_standard_surface_surfaceshader` has a dedicated reader (see
|
|
24
|
+
* `MaterialXBinding.ts`), while the `ND_Usd*` compatibility nodes share
|
|
25
|
+
* `UsdPreviewSurface` input names and reuse the generic reads.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/** `UsdUVTexture` wrap mode for one axis (`black` ≈ clamp; three has no border). */
|
|
29
|
+
type TextureWrap = "repeat" | "clamp" | "mirror" | "black";
|
|
30
|
+
/** `UsdTransform2d` applied to the `st` coords feeding a texture. */
|
|
31
|
+
type TextureTransform = {
|
|
32
|
+
/** `inputs:translation` (UV offset). */
|
|
33
|
+
translation?: Vec2;
|
|
34
|
+
/** `inputs:rotation` in degrees (CCW about the origin). */
|
|
35
|
+
rotation?: number;
|
|
36
|
+
/** `inputs:scale` (UV tiling). */
|
|
37
|
+
scale?: Vec2;
|
|
38
|
+
};
|
|
39
|
+
/** A resolved texture reference plus its `UsdUVTexture` sampler/transform state. */
|
|
40
|
+
type ResolvedTexture = {
|
|
41
|
+
/** Authored asset path of the image. */
|
|
42
|
+
path: string;
|
|
43
|
+
wrapS?: TextureWrap;
|
|
44
|
+
wrapT?: TextureWrap;
|
|
45
|
+
/** `UsdTransform2d` on the `st` input, if any. */
|
|
46
|
+
transform?: TextureTransform;
|
|
47
|
+
/** `inputs:scale` — multiplies the sampled value (folded into material factors). */
|
|
48
|
+
scale?: [number, number, number, number];
|
|
49
|
+
/** `inputs:bias` — added to the sampled value. */
|
|
50
|
+
bias?: [number, number, number, number];
|
|
51
|
+
/**
|
|
52
|
+
* UV-set (primvar) name the texture reads, resolved through the `inputs:st`
|
|
53
|
+
* connection to a `UsdPrimvarReader_float2.inputs:varname`. Absent ⇒ `"st"`.
|
|
54
|
+
*/
|
|
55
|
+
uvSet?: string;
|
|
56
|
+
/**
|
|
57
|
+
* Direct UV channel index (MaterialX `ND_texcoord_*.inputs:index`, M21).
|
|
58
|
+
* Beats `uvSet`; channel N is the mesh's N-th UV set in `meshUvSetNames`
|
|
59
|
+
* order (`st` first, extras sorted).
|
|
60
|
+
*/
|
|
61
|
+
uvChannel?: number;
|
|
62
|
+
/** `inputs:sourceColorSpace` — overrides the per-channel colorspace default. */
|
|
63
|
+
sourceColorSpace?: "raw" | "sRGB" | "auto";
|
|
64
|
+
/**
|
|
65
|
+
* Which output the consuming input connects to (`outputs:r` → `"r"`, …).
|
|
66
|
+
* three.js samples fixed channels (roughness = G, metalness = B, ao = R);
|
|
67
|
+
* a mismatch is surfaced as a load warning.
|
|
68
|
+
*/
|
|
69
|
+
outputChannel?: "r" | "g" | "b" | "a" | "rgb";
|
|
70
|
+
};
|
|
71
|
+
type ResolvedMaterial = {
|
|
72
|
+
/** Name of the bound `Material` prim, for round-tripping and debugging. */
|
|
73
|
+
name?: string;
|
|
74
|
+
color?: Vec3;
|
|
75
|
+
opacity?: number;
|
|
76
|
+
metalness?: number;
|
|
77
|
+
roughness?: number;
|
|
78
|
+
emissiveColor?: Vec3;
|
|
79
|
+
/**
|
|
80
|
+
* `inputs:opacityThreshold`. When `> 0`, opacity is a binary mask (alpha
|
|
81
|
+
* clip / cutout); when `0`/absent, sub-unit opacity blends translucently.
|
|
82
|
+
*/
|
|
83
|
+
opacityThreshold?: number;
|
|
84
|
+
/** `inputs:ior` — promotes the three material to `MeshPhysicalMaterial`. */
|
|
85
|
+
ior?: number;
|
|
86
|
+
/** `inputs:clearcoat` (physical promotion). */
|
|
87
|
+
clearcoat?: number;
|
|
88
|
+
/** `inputs:clearcoatRoughness` (physical promotion). */
|
|
89
|
+
clearcoatRoughness?: number;
|
|
90
|
+
/** `inputs:specularColor`, only when `inputs:useSpecularWorkflow = 1`. */
|
|
91
|
+
specularColor?: Vec3;
|
|
92
|
+
/** OmniPBR `inputs:emissive_intensity` — multiplies the emissive color. */
|
|
93
|
+
emissiveIntensity?: number;
|
|
94
|
+
/** OmniGlass — `1` marks a transmissive dielectric (physical promotion, M20). */
|
|
95
|
+
transmission?: number;
|
|
96
|
+
/** OmniGlass `inputs:depth` — refraction volume thickness (scene units, M20). */
|
|
97
|
+
thickness?: number;
|
|
98
|
+
/** Diffuse/albedo texture, if any. */
|
|
99
|
+
colorTexture?: ResolvedTexture;
|
|
100
|
+
/** Opacity / alpha texture (may be the same image as `colorTexture`). */
|
|
101
|
+
opacityTexture?: ResolvedTexture;
|
|
102
|
+
/** Tangent-space normal map, if any. */
|
|
103
|
+
normalTexture?: ResolvedTexture;
|
|
104
|
+
/** Roughness map, if any. */
|
|
105
|
+
roughnessTexture?: ResolvedTexture;
|
|
106
|
+
/** Metallic map, if any. */
|
|
107
|
+
metalnessTexture?: ResolvedTexture;
|
|
108
|
+
/** Ambient-occlusion map, if any. */
|
|
109
|
+
occlusionTexture?: ResolvedTexture;
|
|
110
|
+
/** Emissive map, if any. */
|
|
111
|
+
emissiveTexture?: ResolvedTexture;
|
|
112
|
+
/** OmniPBR_ClearCoat `clearcoat_normalmap_texture` (physical promotion, M20). */
|
|
113
|
+
clearcoatNormalTexture?: ResolvedTexture;
|
|
114
|
+
};
|
|
115
|
+
type ResolveMaterialOptions = {
|
|
116
|
+
/** Parsed `.mdl` modules for MDL family detection and value fallback (M20). */
|
|
117
|
+
mdl?: MdlModuleProvider;
|
|
118
|
+
/** Receives diagnostics (unknown MDL material families). */
|
|
119
|
+
onWarn?: (message: string) => void;
|
|
120
|
+
};
|
|
121
|
+
/** Resolve the bound material's flat parameters for `prim`, or `undefined`. */
|
|
122
|
+
declare function resolveBoundMaterial(stage: Stage, prim: Prim, options?: ResolveMaterialOptions): ResolvedMaterial | undefined;
|
|
123
|
+
/**
|
|
124
|
+
* The `Shader` prim driving `prim`'s bound material surface, or `undefined`.
|
|
125
|
+
* Follows the same binding/surface-output resolution as
|
|
126
|
+
* {@link resolveBoundMaterial} — exposed for custom material factories (M22)
|
|
127
|
+
* that need the raw shader network rather than the flattened parameters.
|
|
128
|
+
*/
|
|
129
|
+
declare function findBoundSurfaceShader(stage: Stage, prim: Prim): Prim | undefined;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Loads texture image assets referenced by `UsdShade` materials.
|
|
133
|
+
*
|
|
134
|
+
* A {@link TextureProvider} maps an authored asset path (plus sampler/transform
|
|
135
|
+
* options) to a `THREE.Texture`. The default provider fetches the image **bytes**
|
|
136
|
+
* through the {@link AssetResolver} and decodes them via a blob URL — so it works
|
|
137
|
+
* uniformly for textures served over HTTP and for images embedded inside a
|
|
138
|
+
* `.usdz` package (whose resolver serves zip entries, not real URLs). Decoded
|
|
139
|
+
* images are cached per resolved URL and shared across every texture that uses
|
|
140
|
+
* them; each `THREE.Texture` carries its own color space / wrap / transform.
|
|
141
|
+
*/
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Color space to interpret a texture in. Color/albedo and emissive maps are
|
|
145
|
+
* `"srgb"`; data maps (normal, roughness, metalness, occlusion) are `"linear"`.
|
|
146
|
+
*/
|
|
147
|
+
type TextureColorSpace = "srgb" | "linear";
|
|
148
|
+
/** Per-use sampler state applied to the returned `THREE.Texture`. */
|
|
149
|
+
type TextureOptions = {
|
|
150
|
+
/** Defaults to `"srgb"`. */
|
|
151
|
+
colorSpace?: TextureColorSpace;
|
|
152
|
+
wrapS?: TextureWrap;
|
|
153
|
+
wrapT?: TextureWrap;
|
|
154
|
+
transform?: TextureTransform;
|
|
155
|
+
/** UV channel index (0 = `uv`, 1 = `uv1`, …) for multi-UV-set meshes. */
|
|
156
|
+
channel?: number;
|
|
157
|
+
};
|
|
158
|
+
/** Resolve an authored texture asset path to a `THREE.Texture` (or `null`). */
|
|
159
|
+
type TextureProvider = (assetPath: string, options?: TextureOptions) => THREE.Texture | null;
|
|
160
|
+
/**
|
|
161
|
+
* A {@link TextureProvider} backed by the {@link AssetResolver}, resolving paths
|
|
162
|
+
* against `baseUrl`. Image bytes are fetched once per URL (works for HTTP and
|
|
163
|
+
* `.usdz` entries alike) and the decoded image is shared; each call returns a
|
|
164
|
+
* distinct `THREE.Texture` carrying the requested color space / wrap / transform.
|
|
165
|
+
*/
|
|
166
|
+
declare function createTextureProvider(resolver: AssetResolver, baseUrl: string): TextureProvider;
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Binds renderable gprims — `UsdGeom.Mesh` plus the parametric solids (`Cube` /
|
|
170
|
+
* `Sphere` / `Cylinder` / `Capsule` / `Cone`) — to Three.js geometry and
|
|
171
|
+
* attaches them under the robot's link objects.
|
|
172
|
+
*
|
|
173
|
+
* Meshes are triangulated with a simple fan. Primvars (`st` UV sets, `normals`,
|
|
174
|
+
* `displayColor`) resolve with USD interpolation semantics — `:indices`
|
|
175
|
+
* de-referencing, vertex vs faceVarying (de-indexed) layouts, multiple UV
|
|
176
|
+
* channels. Solids tessellate from their schema attributes. Geometry is left
|
|
177
|
+
* in stage units; the global `metersPerUnit` scale is applied at the root in M9.
|
|
178
|
+
*/
|
|
179
|
+
|
|
180
|
+
type MeshKind = "visual" | "collision";
|
|
181
|
+
/**
|
|
182
|
+
* Replaces material creation for mesh-like gprims (`Mesh` and the parametric
|
|
183
|
+
* solids). Return `null` to fall back to the default `UsdShade` resolution —
|
|
184
|
+
* the hook that lets the optional `three-usd-robot/nodes` entry build TSL
|
|
185
|
+
* `NodeMaterial`s without the core depending on `three/webgpu` (M22).
|
|
186
|
+
*/
|
|
187
|
+
type MaterialFactory = (prim: Prim, stage: Stage) => THREE.Material | null;
|
|
188
|
+
type BindMeshesOptions = {
|
|
189
|
+
loadVisuals?: boolean;
|
|
190
|
+
loadCollisions?: boolean;
|
|
191
|
+
/** Resolves diffuse texture asset paths to `THREE.Texture` (M-tex). */
|
|
192
|
+
textureProvider?: TextureProvider;
|
|
193
|
+
/** Render `BasisCurves` with authored `widths` as tube meshes (M18). */
|
|
194
|
+
curveTubes?: boolean;
|
|
195
|
+
/** Receives fidelity diagnostics (channel-packing mismatches, M19). */
|
|
196
|
+
onWarn?: (message: string) => void;
|
|
197
|
+
/** Parsed `.mdl` modules for MDL material family/value resolution (M20). */
|
|
198
|
+
mdl?: MdlModuleProvider;
|
|
199
|
+
/** Overrides material creation for mesh-like gprims (M22). */
|
|
200
|
+
materialFactory?: MaterialFactory;
|
|
201
|
+
};
|
|
202
|
+
/**
|
|
203
|
+
* Build a `BufferGeometry` from a Mesh prim, or `null` if it has no points.
|
|
204
|
+
*
|
|
205
|
+
* Primvars resolve with full interpolation semantics (M19): `:indices` arrays
|
|
206
|
+
* are de-referenced, vertex-interpolated `st` sets / `normals` /
|
|
207
|
+
* `displayColor` bind onto the shared vertices, and any faceVarying primvar
|
|
208
|
+
* (or per-face color) switches the mesh to a de-indexed layout where every
|
|
209
|
+
* face corner owns its vertex. Extra UV sets become `uv1`, `uv2`, … in
|
|
210
|
+
* {@link meshUvSetNames} order.
|
|
211
|
+
*
|
|
212
|
+
* When the mesh carries `materialBind` face subsets, the triangles are ordered
|
|
213
|
+
* subset by subset and a geometry group is added for each — so the mesh can be
|
|
214
|
+
* drawn with one material per subset (see {@link buildMeshMaterials}). Group
|
|
215
|
+
* order matches {@link getMaterialSubsets}, with any unassigned faces last.
|
|
216
|
+
*/
|
|
217
|
+
declare function buildMeshGeometry(meshPrim: Prim): THREE.BufferGeometry | null;
|
|
218
|
+
/**
|
|
219
|
+
* Build geometry for any renderable gprim: `Mesh` via {@link buildMeshGeometry},
|
|
220
|
+
* parametric solids from their schema attributes. Solids follow UsdGeom
|
|
221
|
+
* semantics — sizes in stage units, centered at the origin, `axis` (default
|
|
222
|
+
* `"Z"`) along the spine, and a capsule's `height` spans only its cylindrical
|
|
223
|
+
* section. Returns `null` for unsupported prim types.
|
|
224
|
+
*/
|
|
225
|
+
declare function buildGprimGeometry(prim: Prim): THREE.BufferGeometry | null;
|
|
226
|
+
type BuildGprimOptions = {
|
|
227
|
+
/** Resolves texture asset paths for mesh materials. */
|
|
228
|
+
textureProvider?: TextureProvider;
|
|
229
|
+
/**
|
|
230
|
+
* Render `BasisCurves` that author `widths` as tube meshes instead of
|
|
231
|
+
* 1-px lines (default `false`).
|
|
232
|
+
*/
|
|
233
|
+
curveTubes?: boolean;
|
|
234
|
+
/** Receives fidelity diagnostics (channel-packing mismatches, M19). */
|
|
235
|
+
onWarn?: (message: string) => void;
|
|
236
|
+
/** Parsed `.mdl` modules for MDL material family/value resolution (M20). */
|
|
237
|
+
mdl?: MdlModuleProvider;
|
|
238
|
+
/** Overrides material creation for mesh-like gprims (M22). */
|
|
239
|
+
materialFactory?: MaterialFactory;
|
|
240
|
+
};
|
|
241
|
+
/**
|
|
242
|
+
* Build a renderable `THREE.Object3D` for any supported gprim (M18):
|
|
243
|
+
* `Mesh` and the parametric solids become a `THREE.Mesh` (via
|
|
244
|
+
* {@link buildGprimGeometry} + {@link buildMeshMaterials}), `Points` a
|
|
245
|
+
* `THREE.Points`, and `BasisCurves` a `THREE.Group` holding one line — or,
|
|
246
|
+
* with {@link BuildGprimOptions.curveTubes}, one tube mesh — per curve.
|
|
247
|
+
* Returns `null` for unsupported prim types and degenerate geometry.
|
|
248
|
+
*/
|
|
249
|
+
declare function buildGprimObject(prim: Prim, stage?: Stage, options?: BuildGprimOptions): THREE.Object3D | null;
|
|
250
|
+
/**
|
|
251
|
+
* Build a material for a gprim. Color priority: bound `UsdShade` material
|
|
252
|
+
* (when `stage` is given) → `primvars:displayColor` → default gray. Textures
|
|
253
|
+
* (via `textures`) become the matching `MeshStandardMaterial` maps — diffuse →
|
|
254
|
+
* `map` (sRGB), plus `normalMap` / `roughnessMap` / `metalnessMap` / `aoMap`
|
|
255
|
+
* (linear data) and emissive `emissiveMap`. Metalness / roughness / opacity /
|
|
256
|
+
* emissive constants come from the bound material when present.
|
|
257
|
+
*/
|
|
258
|
+
declare function buildMeshMaterial(meshPrim: Prim, stage?: Stage, textures?: TextureProvider,
|
|
259
|
+
/** Resolve the material binding from here instead (a `GeomSubset`). */
|
|
260
|
+
bindingPrim?: Prim,
|
|
261
|
+
/** Receives fidelity diagnostics (channel-packing mismatches, M19). */
|
|
262
|
+
onWarn?: (message: string) => void,
|
|
263
|
+
/** Parsed `.mdl` modules for MDL material family/value resolution (M20). */
|
|
264
|
+
mdl?: MdlModuleProvider): THREE.Material;
|
|
265
|
+
/**
|
|
266
|
+
* Attach visual (and optionally collision) meshes to every link of a built
|
|
267
|
+
* {@link ThreeUsdRobot}. Each mesh is positioned by its transform relative to
|
|
268
|
+
* the owning link prim.
|
|
269
|
+
*/
|
|
270
|
+
declare function bindRobotMeshes(stage: Stage, robot3d: ThreeUsdRobot, desc: RobotDescription, options?: BindMeshesOptions): void;
|
|
271
|
+
/**
|
|
272
|
+
* Attach the gprims that belong to no link — the static scenery of a cell that
|
|
273
|
+
* also contains robots. The authored prim hierarchy is mirrored with
|
|
274
|
+
* `THREE.Group` nodes (each carrying `userData.primPath` and its prim's local
|
|
275
|
+
* transform), so grouped scenery — a pallet and its cartons, a fence and its
|
|
276
|
+
* wires — stays one movable subtree. World placements are unchanged, and the
|
|
277
|
+
* loader's up-axis and unit normalization still applies at the robot root.
|
|
278
|
+
* Collision-only and guide/proxy prims are skipped.
|
|
279
|
+
*/
|
|
280
|
+
declare function bindSceneMeshes(stage: Stage, robot3d: ThreeUsdRobot, desc: RobotDescription, options?: {
|
|
281
|
+
textureProvider?: TextureProvider;
|
|
282
|
+
curveTubes?: boolean;
|
|
283
|
+
onWarn?: (message: string) => void;
|
|
284
|
+
mdl?: MdlModuleProvider;
|
|
285
|
+
materialFactory?: MaterialFactory;
|
|
286
|
+
}): number;
|
|
287
|
+
|
|
288
|
+
export { type BindMeshesOptions as B, type MaterialFactory as M, type ResolveMaterialOptions as R, type TextureProvider as T, type BuildGprimOptions as a, type MeshKind as b, type ResolvedMaterial as c, type ResolvedTexture as d, type TextureColorSpace as e, type TextureOptions as f, type TextureTransform as g, type TextureWrap as h, bindRobotMeshes as i, bindSceneMeshes as j, buildGprimGeometry as k, buildGprimObject as l, buildMeshGeometry as m, buildMeshMaterial as n, createTextureProvider as o, findBoundSurfaceShader as p, resolveBoundMaterial as r };
|