@nebula-spatial/viewer 0.4.3 → 0.4.5
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/CHANGELOG.md +80 -24
- package/README.md +124 -28
- package/USD-VISUAL-MATERIAL-SUPPORT.md +51 -0
- package/dist/assets/types.d.ts +13 -2
- package/dist/{index-BDo6voB2.js → index-CxbZ--5C.js} +2636 -1856
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/inspection/types.d.ts +112 -0
- package/dist/mjcf-visual-6_RqDf4z.js +73 -0
- package/dist/mujoco-runtime-C29PXDOl.js +258 -0
- package/dist/plugins.d.ts +5 -1
- package/dist/{session-1duLyM88.js → session-CnlODeFp.js} +2 -2
- package/dist/session-DNyPmQOW.js +795 -0
- package/dist/{stage-BKqg5vNe.js → stage-BPiGudYP.js} +128 -98
- package/dist/types.d.ts +2 -0
- package/dist/ui/types.d.ts +2 -0
- package/dist/urdf-session-CuIZOiCF.js +3238 -0
- package/dist/usd-session-JDfuDgWv.js +1907 -0
- package/dist/xacro-DrBtv-gK.js +1537 -0
- package/package.json +5 -2
- package/dist/mjcf-visual--X39MVO9.js +0 -63
- package/dist/mujoco-runtime-s85kwjo7.js +0 -208
- package/dist/session-DhZXy40-.js +0 -653
- package/dist/urdf-session-C_LAfkkM.js +0 -439
- package/dist/usd-session-zyj46Bcg.js +0 -1192
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nebula-spatial/viewer",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"description": "Read-only Three.js viewer facade",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"engines": {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"README.md",
|
|
13
13
|
"CHANGELOG.md",
|
|
14
14
|
"FBX-MATERIAL-CONVERSION.md",
|
|
15
|
+
"USD-VISUAL-MATERIAL-SUPPORT.md",
|
|
15
16
|
"package.json"
|
|
16
17
|
],
|
|
17
18
|
"main": "./dist/index.js",
|
|
@@ -40,7 +41,9 @@
|
|
|
40
41
|
"@mujoco/mujoco": "^3.12.0",
|
|
41
42
|
"@nebula-spatial/cad-loader": "^0.3.0",
|
|
42
43
|
"@openusd-wasm/pxr": "0.0.13",
|
|
43
|
-
"@openusd-wasm/three-loader": "^0.0.13"
|
|
44
|
+
"@openusd-wasm/three-loader": "^0.0.13",
|
|
45
|
+
"three-mesh-bvh": "^0.9.5",
|
|
46
|
+
"xacro-parser": "0.3.11"
|
|
44
47
|
},
|
|
45
48
|
"peerDependencies": {
|
|
46
49
|
"three": "0.182.0"
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { Group as A, Euler as C, BoxGeometry as E, SphereGeometry as F, CylinderGeometry as x, CapsuleGeometry as J, PlaneGeometry as q, MeshStandardMaterial as G, Mesh as z } from "three";
|
|
2
|
-
import { d as S } from "./stage-BKqg5vNe.js";
|
|
3
|
-
function v(d) {
|
|
4
|
-
const f = d.extension.documents, l = new A();
|
|
5
|
-
l.name = d.name;
|
|
6
|
-
try {
|
|
7
|
-
if (f.size !== 1) throw new Error("MJCF 独立预览暂不支持 include");
|
|
8
|
-
const c = [...f.values()][0];
|
|
9
|
-
if (c.querySelector("default, include, attach, replicate, composite, flexcomp, skin, hfield, plugin")) throw new Error("MJCF 独立预览包含尚不支持的继承、组合或扩展语义");
|
|
10
|
-
const n = c.querySelector("compiler");
|
|
11
|
-
if ((n == null ? void 0 : n.getAttribute("coordinate")) === "global" || n != null && n.hasAttribute("eulerseq")) throw new Error("MJCF 独立预览不支持此坐标设置");
|
|
12
|
-
const w = (n == null ? void 0 : n.getAttribute("angle")) === "radian" ? 1 : Math.PI / 180, b = (a, u) => {
|
|
13
|
-
const e = a ? a.trim().split(/\s+/).map(Number) : u;
|
|
14
|
-
if (e.some((o) => !Number.isFinite(o))) throw new Error("MJCF 视觉坐标无效");
|
|
15
|
-
return e;
|
|
16
|
-
}, m = (a, u, e) => {
|
|
17
|
-
const o = b(a, u);
|
|
18
|
-
if (o.length !== e) throw new Error(`MJCF 视觉变换需要 ${e} 个分量`);
|
|
19
|
-
return o;
|
|
20
|
-
}, p = (a, u) => {
|
|
21
|
-
for (const e of a.children) {
|
|
22
|
-
if (!["body", "geom"].includes(e.tagName)) continue;
|
|
23
|
-
if (["class", "childclass", "fromto", "axisangle", "xyaxes", "zaxis"].some((r) => e.hasAttribute(r))) throw new Error("MJCF 独立预览不支持此变换或默认类");
|
|
24
|
-
const o = new A();
|
|
25
|
-
if (o.name = e.getAttribute("name") ?? e.tagName, o.position.fromArray(m(e.getAttribute("pos"), [0, 0, 0], 3)), e.hasAttribute("quat")) {
|
|
26
|
-
const r = m(e.getAttribute("quat"), [1, 0, 0, 0], 4);
|
|
27
|
-
if (Math.hypot(...r) === 0) throw new Error("MJCF 视觉四元数不能为零");
|
|
28
|
-
o.quaternion.set(r[1], r[2], r[3], r[0]).normalize();
|
|
29
|
-
} else {
|
|
30
|
-
const r = m(e.getAttribute("euler"), [0, 0, 0], 3);
|
|
31
|
-
o.quaternion.setFromEuler(new C(r[0] * w, r[1] * w, r[2] * w, "XYZ"));
|
|
32
|
-
}
|
|
33
|
-
if (u.add(o), e.tagName === "body") {
|
|
34
|
-
p(e, o);
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
const s = e.getAttribute("type") ?? (e.hasAttribute("mesh") ? "mesh" : "sphere"), t = b(e.getAttribute("size"), []);
|
|
38
|
-
if (e.hasAttribute("material") || t.length === 0) throw new Error("MJCF 独立预览缺少可直接解析的几何或材质");
|
|
39
|
-
const y = { box: 3, sphere: 1, cylinder: 2, capsule: 2, plane: 3 }[s];
|
|
40
|
-
if (y && (t.length < y || t.some((r) => s === "plane" ? r < 0 : r <= 0)))
|
|
41
|
-
throw new Error(`MJCF geom ${s} 的尺寸缺失或无效`);
|
|
42
|
-
let i;
|
|
43
|
-
if (s === "box") i = new E(2 * t[0], 2 * t[1], 2 * t[2]);
|
|
44
|
-
else if (s === "sphere") i = new F(t[0]);
|
|
45
|
-
else if (s === "cylinder")
|
|
46
|
-
i = new x(t[0], t[0], 2 * t[1]), i.rotateX(Math.PI / 2);
|
|
47
|
-
else if (s === "capsule")
|
|
48
|
-
i = new J(t[0], 2 * t[1]), i.rotateX(Math.PI / 2);
|
|
49
|
-
else if (s === "plane") i = new q(2 * (t[0] || 5), 2 * (t[1] || 5));
|
|
50
|
-
else throw new Error(`MJCF 独立预览暂不支持 geom ${s}`);
|
|
51
|
-
const h = m(e.getAttribute("rgba"), [0.5, 0.5, 0.5, 1], 4), M = new G({ opacity: h[3], transparent: h[3] < 1 });
|
|
52
|
-
M.color.setRGB(h[0], h[1], h[2]), o.add(new z(i, M));
|
|
53
|
-
}
|
|
54
|
-
}, g = c.querySelector("worldbody");
|
|
55
|
-
if (!g) throw new Error("MJCF 缺少 worldbody");
|
|
56
|
-
return p(g, l), l.updateMatrixWorld(!0), l;
|
|
57
|
-
} catch (c) {
|
|
58
|
-
throw S(l), c;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
export {
|
|
62
|
-
v as compileMjcfPreview
|
|
63
|
-
};
|
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
var E = Object.defineProperty;
|
|
2
|
-
var M = (r, t, i) => t in r ? E(r, t, { enumerable: !0, configurable: !0, writable: !0, value: i }) : r[t] = i;
|
|
3
|
-
var p = (r, t, i) => M(r, typeof t != "symbol" ? t + "" : t, i);
|
|
4
|
-
import T from "@mujoco/mujoco";
|
|
5
|
-
import I from "@mujoco/mujoco/mujoco.wasm?url";
|
|
6
|
-
let w = 0;
|
|
7
|
-
function F(r, t) {
|
|
8
|
-
const i = `/viewer-simulation-${++w}`;
|
|
9
|
-
r.mkdir(i);
|
|
10
|
-
const n = /* @__PURE__ */ new Set([i]), o = /* @__PURE__ */ new Set(), a = (e, s) => {
|
|
11
|
-
const c = e.replaceAll("\\", "/").split("/");
|
|
12
|
-
if (c[0] === "" || c.some((u) => u === ".." || u.includes(":"))) throw b(`Invalid package path: ${e}`, "E_SIMULATION_PATH");
|
|
13
|
-
const l = c.filter((u) => u && u !== ".");
|
|
14
|
-
if (!l.length) throw b("Package path is empty.", "E_SIMULATION_PATH");
|
|
15
|
-
let m = i;
|
|
16
|
-
for (const u of l.slice(0, -1))
|
|
17
|
-
m += `/${u}`, n.has(m) || (r.mkdir(m), n.add(m));
|
|
18
|
-
const d = `${i}/${l.join("/")}`;
|
|
19
|
-
return r.writeFile(d, s), o.add(d), d;
|
|
20
|
-
}, h = () => {
|
|
21
|
-
for (const e of o) r.unlink(e);
|
|
22
|
-
o.clear();
|
|
23
|
-
for (const e of [...n].reverse()) r.rmdir(e);
|
|
24
|
-
n.clear();
|
|
25
|
-
};
|
|
26
|
-
try {
|
|
27
|
-
for (const [e, s] of t) a(e, s);
|
|
28
|
-
return { writeEntry: (e) => a("__viewer_entry.xml", e), dispose: h };
|
|
29
|
-
} catch (e) {
|
|
30
|
-
throw h(), e;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
function b(r, t) {
|
|
34
|
-
return Object.assign(new Error(r), { code: t });
|
|
35
|
-
}
|
|
36
|
-
function O({
|
|
37
|
-
target: r,
|
|
38
|
-
point: t,
|
|
39
|
-
velocity: i,
|
|
40
|
-
stiffness: n,
|
|
41
|
-
damping: o,
|
|
42
|
-
maxForce: a,
|
|
43
|
-
strength: h
|
|
44
|
-
}) {
|
|
45
|
-
const e = [
|
|
46
|
-
n * (r[0] - t[0]) - o * i[0],
|
|
47
|
-
n * (r[1] - t[1]) - o * i[1],
|
|
48
|
-
n * (r[2] - t[2]) - o * i[2]
|
|
49
|
-
], s = Math.hypot(e[0], e[1], e[2]), c = a * h;
|
|
50
|
-
if (s > c && s > 0) {
|
|
51
|
-
const l = c / s;
|
|
52
|
-
e[0] *= l, e[1] *= l, e[2] *= l;
|
|
53
|
-
}
|
|
54
|
-
return e;
|
|
55
|
-
}
|
|
56
|
-
const f = 1 / 240, A = 0.05, v = 80, x = 1.15, g = 3.5, y = 14;
|
|
57
|
-
class C {
|
|
58
|
-
constructor() {
|
|
59
|
-
p(this, "mujoco", null);
|
|
60
|
-
p(this, "model", null);
|
|
61
|
-
p(this, "data", null);
|
|
62
|
-
p(this, "grab", null);
|
|
63
|
-
p(this, "lastGrabForce", [0, 0, 0]);
|
|
64
|
-
p(this, "velocityBuffer", new Float64Array(6));
|
|
65
|
-
p(this, "initialControls", []);
|
|
66
|
-
p(this, "accumulator", 0);
|
|
67
|
-
p(this, "initialVelocities", []);
|
|
68
|
-
}
|
|
69
|
-
async initialize(t, i) {
|
|
70
|
-
var h;
|
|
71
|
-
this.mujoco ?? (this.mujoco = await T({ locateFile: (e) => e.endsWith(".wasm") ? i ? new URL(e, i).href : I : e }));
|
|
72
|
-
const n = F(this.mujoco.FS, t.files);
|
|
73
|
-
let o = null, a = null;
|
|
74
|
-
try {
|
|
75
|
-
o = this.mujoco.MjModel.from_xml_path(n.writeEntry(t.xml));
|
|
76
|
-
for (const e of t.massOverrides ?? []) {
|
|
77
|
-
const s = this.mujoco.mj_name2id(o, this.mujoco.mjtObj.mjOBJ_BODY.value, e.body);
|
|
78
|
-
if (s <= 0 || !Number.isFinite(e.mass) || e.mass <= 0 || !(o.body_mass[s] > 0)) throw new Error(`Invalid mass override: ${e.body}`);
|
|
79
|
-
const c = e.mass / o.body_mass[s];
|
|
80
|
-
o.body_mass[s] = e.mass;
|
|
81
|
-
for (let l = 0; l < 3; l++) o.body_inertia[s * 3 + l] *= c;
|
|
82
|
-
}
|
|
83
|
-
a = new this.mujoco.MjData(o), (h = t.massOverrides) != null && h.length && this.mujoco.mj_setConst(o, a), o.opt.timestep = f, this.applyInitialControls(a, t.initialControls), this.applyInitialVelocities(o, a, t.initialVelocities), this.mujoco.mj_forward(o, a);
|
|
84
|
-
} catch (e) {
|
|
85
|
-
throw a == null || a.delete(), o == null || o.delete(), _(e, "E_MUJOCO_INITIALIZE");
|
|
86
|
-
} finally {
|
|
87
|
-
n.dispose();
|
|
88
|
-
}
|
|
89
|
-
this.disposeModel(), this.model = o, this.data = a, this.initialControls = t.initialControls ?? [], this.initialVelocities = t.initialVelocities ?? [], this.accumulator = 0;
|
|
90
|
-
}
|
|
91
|
-
beginGrab({
|
|
92
|
-
bodyId: t,
|
|
93
|
-
localPoint: i,
|
|
94
|
-
target: n,
|
|
95
|
-
stiffness: o = v,
|
|
96
|
-
damping: a,
|
|
97
|
-
maxForce: h,
|
|
98
|
-
dampingRatio: e = x,
|
|
99
|
-
maxTargetSpeed: s = g,
|
|
100
|
-
targetResponse: c = y
|
|
101
|
-
}) {
|
|
102
|
-
var j;
|
|
103
|
-
const l = Math.max(((j = this.model) == null ? void 0 : j.body_mass[t]) ?? 1, 1e-3), m = a ?? 2 * Math.sqrt(o * l) * e, d = h ?? Math.max(120, l * 60), u = [n[0], n[1], n[2]];
|
|
104
|
-
this.grab = {
|
|
105
|
-
bodyId: t,
|
|
106
|
-
localPoint: [i[0], i[1], i[2]],
|
|
107
|
-
target: [...u],
|
|
108
|
-
requestedTarget: u,
|
|
109
|
-
stiffness: o,
|
|
110
|
-
damping: m,
|
|
111
|
-
maxForce: d,
|
|
112
|
-
strength: 1,
|
|
113
|
-
maxTargetSpeed: s,
|
|
114
|
-
targetResponse: c
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
updateGrabTarget(t) {
|
|
118
|
-
this.grab && (this.grab.requestedTarget = [t[0], t[1], t[2]]);
|
|
119
|
-
}
|
|
120
|
-
updateGrabStrength(t) {
|
|
121
|
-
this.grab && (this.grab.strength = t);
|
|
122
|
-
}
|
|
123
|
-
applyGrabForce() {
|
|
124
|
-
if (!this.grab || !this.model || !this.data || !this.mujoco) return;
|
|
125
|
-
const { bodyId: t, localPoint: i, target: n, stiffness: o, damping: a, maxForce: h, strength: e } = this.grab, s = this.data.xmat.subarray(t * 9, t * 9 + 9), c = this.data.xpos.subarray(t * 3, t * 3 + 3), l = [
|
|
126
|
-
c[0] + s[0] * i[0] + s[1] * i[1] + s[2] * i[2],
|
|
127
|
-
c[1] + s[3] * i[0] + s[4] * i[1] + s[5] * i[2],
|
|
128
|
-
c[2] + s[6] * i[0] + s[7] * i[1] + s[8] * i[2]
|
|
129
|
-
];
|
|
130
|
-
this.mujoco.mj_objectVelocity(
|
|
131
|
-
this.model,
|
|
132
|
-
this.data,
|
|
133
|
-
this.mujoco.mjtObj.mjOBJ_BODY.value,
|
|
134
|
-
t,
|
|
135
|
-
this.velocityBuffer,
|
|
136
|
-
0
|
|
137
|
-
);
|
|
138
|
-
const m = this.velocityBuffer, d = [
|
|
139
|
-
l[0] - c[0],
|
|
140
|
-
l[1] - c[1],
|
|
141
|
-
l[2] - c[2]
|
|
142
|
-
], u = [
|
|
143
|
-
m[3] + m[1] * d[2] - m[2] * d[1],
|
|
144
|
-
m[4] + m[2] * d[0] - m[0] * d[2],
|
|
145
|
-
m[5] + m[0] * d[1] - m[1] * d[0]
|
|
146
|
-
], j = O({ target: n, point: l, velocity: u, stiffness: o, damping: a, maxForce: h, strength: e });
|
|
147
|
-
this.lastGrabForce = [...j], this.data.qfrc_applied.fill(0), this.mujoco.mj_applyFT(
|
|
148
|
-
this.model,
|
|
149
|
-
this.data,
|
|
150
|
-
j,
|
|
151
|
-
[0, 0, 0],
|
|
152
|
-
l,
|
|
153
|
-
t,
|
|
154
|
-
this.data.qfrc_applied
|
|
155
|
-
);
|
|
156
|
-
}
|
|
157
|
-
endGrab() {
|
|
158
|
-
this.data && this.data.qfrc_applied.fill(0), this.lastGrabForce = [0, 0, 0], this.grab = null;
|
|
159
|
-
}
|
|
160
|
-
step(t) {
|
|
161
|
-
if (!this.mujoco || !this.model || !this.data || t <= 0) return !1;
|
|
162
|
-
this.accumulator += Math.min(t, A);
|
|
163
|
-
let i = !1;
|
|
164
|
-
for (; this.accumulator >= f; )
|
|
165
|
-
this.updateGrabTargetForStep(), this.applyGrabForce(), this.mujoco.mj_step(this.model, this.data), this.accumulator -= f, i = !0;
|
|
166
|
-
return i;
|
|
167
|
-
}
|
|
168
|
-
updateGrabTargetForStep() {
|
|
169
|
-
const t = this.grab;
|
|
170
|
-
if (!t) return;
|
|
171
|
-
const i = t.requestedTarget ?? t.target, n = (t.maxTargetSpeed ?? g) * Math.max(1, Math.sqrt(t.strength)), o = t.targetResponse ?? y, a = 1 - Math.exp(-o * f), h = n * f;
|
|
172
|
-
for (let e = 0; e < 3; e++) {
|
|
173
|
-
const s = i[e] - t.target[e], c = Math.sign(s) * Math.min(Math.abs(s) * a, h);
|
|
174
|
-
t.target[e] += c;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
reset() {
|
|
178
|
-
!this.mujoco || !this.model || !this.data || (this.endGrab(), this.mujoco.mj_resetData(this.model, this.data), this.applyInitialControls(this.data, this.initialControls), this.applyInitialVelocities(this.model, this.data, this.initialVelocities), this.mujoco.mj_forward(this.model, this.data), this.accumulator = 0);
|
|
179
|
-
}
|
|
180
|
-
dispose() {
|
|
181
|
-
this.disposeModel(), this.mujoco = null;
|
|
182
|
-
}
|
|
183
|
-
applyInitialControls(t, i) {
|
|
184
|
-
if (i != null && i.length) {
|
|
185
|
-
if (i.length !== t.ctrl.length) throw _(new Error(`Initial control count ${i.length} does not match MuJoCo actuator count ${t.ctrl.length}.`), "E_MUJOCO_INITIALIZE");
|
|
186
|
-
t.ctrl.set(i);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
applyInitialVelocities(t, i, n) {
|
|
190
|
-
for (const o of n ?? []) {
|
|
191
|
-
const a = this.mujoco.mj_name2id(t, this.mujoco.mjtObj.mjOBJ_BODY.value, o.body), h = a >= 0 ? t.body_jntadr[a] : -1;
|
|
192
|
-
if (h < 0 || t.jnt_type[h] !== this.mujoco.mjtJoint.mjJNT_FREE.value || o.velocity.length !== 6 || !o.velocity.every(Number.isFinite))
|
|
193
|
-
throw _(new Error(`Invalid free-body initial velocity: ${o.body}`), "E_MUJOCO_INITIALIZE");
|
|
194
|
-
i.qvel.set(o.velocity, t.jnt_dofadr[h]);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
disposeModel() {
|
|
198
|
-
var t, i;
|
|
199
|
-
this.endGrab(), (t = this.data) == null || t.delete(), (i = this.model) == null || i.delete(), this.data = null, this.model = null, this.initialControls = [], this.initialVelocities = [], this.accumulator = 0;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
function _(r, t) {
|
|
203
|
-
const i = r instanceof Error ? r : new Error(String(r));
|
|
204
|
-
return Object.assign(i, { code: t });
|
|
205
|
-
}
|
|
206
|
-
export {
|
|
207
|
-
C as MujocoRuntime
|
|
208
|
-
};
|