@nebula-spatial/viewer 0.2.4 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +93 -37
- package/README.md +593 -119
- package/dist/assets/types.d.ts +234 -0
- package/dist/cad/types.d.ts +132 -24
- package/dist/index-Lsk3kHNe.js +6718 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +4 -3971
- package/dist/mujoco-runtime-s85kwjo7.js +208 -0
- package/dist/plugins.d.ts +175 -0
- package/dist/session-B_UiRctl.js +762 -0
- package/dist/session-CGaj14lM.js +93 -0
- package/dist/stage-BxROW_dP.js +421 -0
- package/dist/types.d.ts +82 -3
- package/dist/ui/types.d.ts +45 -0
- package/dist/usd-session-Dcd20Z6G.js +522 -0
- package/package.json +7 -4
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { Quaternion as y, Vector3 as M, Group as P, Box3 as T } from "three";
|
|
2
|
+
import { DRACOLoader as x } from "three/examples/jsm/loaders/DRACOLoader.js";
|
|
3
|
+
import { GLTFLoader as D } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
4
|
+
import { S as E, d as w } from "./stage-BxROW_dP.js";
|
|
5
|
+
const G = new y().setFromAxisAngle(new M(1, 0, 0), Math.PI / 2), R = new y();
|
|
6
|
+
function S(r) {
|
|
7
|
+
return r === "y" ? G : R;
|
|
8
|
+
}
|
|
9
|
+
function b(r, n) {
|
|
10
|
+
const t = S(n);
|
|
11
|
+
return t.equals(r.quaternion) ? !1 : (r.quaternion.copy(t), r.updateMatrixWorld(!0), !0);
|
|
12
|
+
}
|
|
13
|
+
function z(r, n) {
|
|
14
|
+
let t = !1, i = null, e = null, d = "z", f;
|
|
15
|
+
const l = new x(), p = new D(), m = () => {
|
|
16
|
+
t = !0;
|
|
17
|
+
}, a = (async () => {
|
|
18
|
+
d = n.options.upAxis ?? "z", n.options.dracoDecoderPath && l.setDecoderPath(n.options.dracoDecoderPath), p.setDRACOLoader(l);
|
|
19
|
+
let o = null;
|
|
20
|
+
try {
|
|
21
|
+
if (t || n.signal.aborted) throw h();
|
|
22
|
+
const s = await p.loadAsync(r.url ?? await r.resolve(r.entryPath ?? ""));
|
|
23
|
+
o = new P(), o.name = "viewer-model-root";
|
|
24
|
+
const u = s.scenes.filter((c) => c !== s.scene);
|
|
25
|
+
if (o.add(s.scene), t || n.signal.aborted) {
|
|
26
|
+
for (const c of u) o.add(c);
|
|
27
|
+
throw h();
|
|
28
|
+
}
|
|
29
|
+
b(o, d), g(o);
|
|
30
|
+
const A = new E(o, n.options.simulationTheme, void 0, "model");
|
|
31
|
+
i = o, e = A, o = null;
|
|
32
|
+
} finally {
|
|
33
|
+
o && w(o), l.dispose();
|
|
34
|
+
}
|
|
35
|
+
})();
|
|
36
|
+
return a.catch(() => {
|
|
37
|
+
}), {
|
|
38
|
+
id: `model-${Math.random().toString(36).slice(2)}`,
|
|
39
|
+
opened: a,
|
|
40
|
+
get root() {
|
|
41
|
+
return (e == null ? void 0 : e.root) ?? null;
|
|
42
|
+
},
|
|
43
|
+
getFitBounds() {
|
|
44
|
+
return (e == null ? void 0 : e.getModelBounds()) ?? null;
|
|
45
|
+
},
|
|
46
|
+
beforeRender(o, s, u) {
|
|
47
|
+
return e == null ? void 0 : e.beforeRender(o, s, u);
|
|
48
|
+
},
|
|
49
|
+
capabilities: { canPlay: !1, canPause: !1, canReset: !1, hasPhysics: !1, canReorientUpAxis: !0, canToggleGround: !0 },
|
|
50
|
+
// Session presentation overrides are only consulted for `interactionMode`
|
|
51
|
+
// and `fitPolicy`; the UI group comes from the loader descriptor. Keep the
|
|
52
|
+
// two in sync so the override never reads as a contradictory value.
|
|
53
|
+
presentation: { preferredViewMode: "3d", interactionMode: "object", uiProfile: "model", fitPolicy: "fit-on-ready" },
|
|
54
|
+
getUpAxis() {
|
|
55
|
+
return i ? d : null;
|
|
56
|
+
},
|
|
57
|
+
setTheme(o) {
|
|
58
|
+
e == null || e.setTheme(o);
|
|
59
|
+
},
|
|
60
|
+
setGroundVisible(o) {
|
|
61
|
+
e == null || e.setGroundVisible(o);
|
|
62
|
+
},
|
|
63
|
+
getGroundVisible() {
|
|
64
|
+
return (e == null ? void 0 : e.getGroundVisible()) ?? !0;
|
|
65
|
+
},
|
|
66
|
+
setUpAxis(o) {
|
|
67
|
+
if (t || !i || !e || !b(i, o)) return;
|
|
68
|
+
d = o, e.reseatGround();
|
|
69
|
+
const s = e.getModelBounds();
|
|
70
|
+
n.requestRender(), n.fit(s, { padding: 1.15 });
|
|
71
|
+
},
|
|
72
|
+
beginDispose: m,
|
|
73
|
+
dispose() {
|
|
74
|
+
return m(), f ?? (f = a.catch(() => {
|
|
75
|
+
}).then(() => {
|
|
76
|
+
e == null || e.dispose(), e = null, i && w(i), i = null;
|
|
77
|
+
})), f;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function g(r) {
|
|
82
|
+
r.updateMatrixWorld(!0);
|
|
83
|
+
const n = new T().setFromObject(r);
|
|
84
|
+
if (n.isEmpty()) throw new Error("模型不包含可显示的几何内容。");
|
|
85
|
+
const t = n.getSize(new M()), i = Math.max(t.x, t.y, t.z);
|
|
86
|
+
if (!Number.isFinite(i) || i <= 0) throw new Error("模型尺寸无效。");
|
|
87
|
+
}
|
|
88
|
+
function h() {
|
|
89
|
+
return Object.assign(new Error("Model load aborted."), { name: "AbortError", code: "E_ABORTED" });
|
|
90
|
+
}
|
|
91
|
+
export {
|
|
92
|
+
z as createModelSession
|
|
93
|
+
};
|
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
var v = Object.defineProperty;
|
|
2
|
+
var y = (c, e, t) => e in c ? v(c, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : c[e] = t;
|
|
3
|
+
var a = (c, e, t) => y(c, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
+
import * as o from "three";
|
|
5
|
+
import { V as p } from "./index-Lsk3kHNe.js";
|
|
6
|
+
const x = 1, b = (
|
|
7
|
+
/* glsl */
|
|
8
|
+
`
|
|
9
|
+
uniform mat4 textureMatrix;
|
|
10
|
+
varying vec4 vReflectionUv;
|
|
11
|
+
varying vec3 vWorldPosition;
|
|
12
|
+
|
|
13
|
+
void main() {
|
|
14
|
+
vec4 worldPosition = modelMatrix * vec4(position, 1.0);
|
|
15
|
+
vWorldPosition = worldPosition.xyz;
|
|
16
|
+
vReflectionUv = textureMatrix * vec4(position, 1.0);
|
|
17
|
+
// Match Three.js built-in materials: transform to view space before projection.
|
|
18
|
+
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
|
|
19
|
+
gl_Position = projectionMatrix * mvPosition;
|
|
20
|
+
}
|
|
21
|
+
`
|
|
22
|
+
), M = (
|
|
23
|
+
/* glsl */
|
|
24
|
+
`
|
|
25
|
+
uniform sampler2D tDiffuse;
|
|
26
|
+
uniform vec2 resolution;
|
|
27
|
+
uniform vec3 fineGridColor;
|
|
28
|
+
uniform vec3 coarseGridColor;
|
|
29
|
+
uniform float blurIntensity;
|
|
30
|
+
uniform float reflectionMix;
|
|
31
|
+
uniform float gridOpacity;
|
|
32
|
+
uniform float gridScale;
|
|
33
|
+
uniform vec2 groundCenter;
|
|
34
|
+
uniform float maxRadius;
|
|
35
|
+
uniform float fadeSoftness;
|
|
36
|
+
|
|
37
|
+
varying vec4 vReflectionUv;
|
|
38
|
+
varying vec3 vWorldPosition;
|
|
39
|
+
|
|
40
|
+
vec4 blur9(sampler2D image, vec2 uv, vec2 res, float radius) {
|
|
41
|
+
vec4 color = vec4(0.0);
|
|
42
|
+
vec2 stepSize = radius / res;
|
|
43
|
+
color += texture2D(image, uv + vec2(-stepSize.x, -stepSize.y)) * 0.0625;
|
|
44
|
+
color += texture2D(image, uv + vec2(0.0, -stepSize.y)) * 0.125;
|
|
45
|
+
color += texture2D(image, uv + vec2(stepSize.x, -stepSize.y)) * 0.0625;
|
|
46
|
+
color += texture2D(image, uv + vec2(-stepSize.x, 0.0)) * 0.125;
|
|
47
|
+
color += texture2D(image, uv) * 0.25;
|
|
48
|
+
color += texture2D(image, uv + vec2(stepSize.x, 0.0)) * 0.125;
|
|
49
|
+
color += texture2D(image, uv + vec2(-stepSize.x, stepSize.y)) * 0.0625;
|
|
50
|
+
color += texture2D(image, uv + vec2(0.0, stepSize.y)) * 0.125;
|
|
51
|
+
color += texture2D(image, uv + vec2(stepSize.x, stepSize.y)) * 0.0625;
|
|
52
|
+
return color;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
float gridLine(vec2 position, float scale) {
|
|
56
|
+
vec2 coordinate = position / scale;
|
|
57
|
+
vec2 width = max(fwidth(coordinate), vec2(0.0001));
|
|
58
|
+
vec2 distanceToLine = abs(fract(coordinate - 0.5) - 0.5) / width;
|
|
59
|
+
return 1.0 - min(min(distanceToLine.x, distanceToLine.y), 1.0);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
void main() {
|
|
63
|
+
vec2 groundPosition = vWorldPosition.xy;
|
|
64
|
+
float edgeDistance = length(groundPosition - groundCenter);
|
|
65
|
+
float edgeFade = 1.0 - smoothstep(maxRadius - fadeSoftness, maxRadius, edgeDistance);
|
|
66
|
+
|
|
67
|
+
float fineLine = gridLine(groundPosition, gridScale);
|
|
68
|
+
float coarseLine = gridLine(groundPosition, gridScale * 10.0);
|
|
69
|
+
float gridAlpha = max(fineLine * 0.16, coarseLine * 0.42) * gridOpacity * edgeFade;
|
|
70
|
+
vec3 gridColor = mix(fineGridColor, coarseGridColor, coarseLine);
|
|
71
|
+
|
|
72
|
+
vec2 reflectionUv = vReflectionUv.xy / vReflectionUv.w;
|
|
73
|
+
bool validReflection = reflectionUv.x >= 0.0 && reflectionUv.x <= 1.0
|
|
74
|
+
&& reflectionUv.y >= 0.0 && reflectionUv.y <= 1.0;
|
|
75
|
+
vec4 reflection = validReflection
|
|
76
|
+
? blur9(tDiffuse, reflectionUv, resolution, blurIntensity)
|
|
77
|
+
: vec4(0.0);
|
|
78
|
+
float reflectionAlpha = reflectionMix * edgeFade * (validReflection ? 1.0 : 0.0);
|
|
79
|
+
|
|
80
|
+
float alpha = reflectionAlpha + gridAlpha * (1.0 - reflectionAlpha);
|
|
81
|
+
if (alpha <= 0.001) discard;
|
|
82
|
+
vec3 color = mix(reflection.rgb, gridColor, gridAlpha / max(alpha, 0.001));
|
|
83
|
+
gl_FragColor = vec4(color, alpha);
|
|
84
|
+
#include <tonemapping_fragment>
|
|
85
|
+
#include <colorspace_fragment>
|
|
86
|
+
}
|
|
87
|
+
`
|
|
88
|
+
);
|
|
89
|
+
class w extends o.Mesh {
|
|
90
|
+
constructor({ size: t = 20, textureWidth: i = 512, textureHeight: r = 512 } = {}) {
|
|
91
|
+
const s = new o.Matrix4(), n = new o.WebGLRenderTarget(i, r, {
|
|
92
|
+
type: o.HalfFloatType,
|
|
93
|
+
minFilter: o.LinearFilter,
|
|
94
|
+
magFilter: o.LinearFilter,
|
|
95
|
+
format: o.RGBAFormat,
|
|
96
|
+
depthBuffer: !0,
|
|
97
|
+
samples: 0
|
|
98
|
+
}), l = new o.ShaderMaterial({
|
|
99
|
+
uniforms: {
|
|
100
|
+
tDiffuse: { value: n.texture },
|
|
101
|
+
textureMatrix: { value: s },
|
|
102
|
+
resolution: { value: new o.Vector2(i, r) },
|
|
103
|
+
fineGridColor: { value: new o.Color(2502702) },
|
|
104
|
+
coarseGridColor: { value: new o.Color(7897726) },
|
|
105
|
+
blurIntensity: { value: 1.7 },
|
|
106
|
+
reflectionMix: { value: 0.07 },
|
|
107
|
+
gridOpacity: { value: 1 },
|
|
108
|
+
gridScale: { value: 0.2 },
|
|
109
|
+
groundCenter: { value: new o.Vector2() },
|
|
110
|
+
maxRadius: { value: t * 0.5 },
|
|
111
|
+
fadeSoftness: { value: t * 0.325 }
|
|
112
|
+
},
|
|
113
|
+
vertexShader: b,
|
|
114
|
+
fragmentShader: M,
|
|
115
|
+
transparent: !0,
|
|
116
|
+
depthWrite: !1,
|
|
117
|
+
toneMapped: !0,
|
|
118
|
+
fog: !1
|
|
119
|
+
});
|
|
120
|
+
super(new o.PlaneGeometry(t, t), l);
|
|
121
|
+
a(this, "renderTarget");
|
|
122
|
+
a(this, "textureMatrix");
|
|
123
|
+
a(this, "virtualCamera");
|
|
124
|
+
a(this, "clipBias");
|
|
125
|
+
a(this, "reflectorPlane");
|
|
126
|
+
a(this, "normal");
|
|
127
|
+
a(this, "reflectorWorldPosition");
|
|
128
|
+
a(this, "cameraWorldPosition");
|
|
129
|
+
a(this, "rotationMatrix");
|
|
130
|
+
a(this, "lookAtPosition");
|
|
131
|
+
a(this, "clipPlane");
|
|
132
|
+
a(this, "view");
|
|
133
|
+
a(this, "target");
|
|
134
|
+
a(this, "q");
|
|
135
|
+
this.renderTarget = n, this.textureMatrix = s, this.virtualCamera = new o.PerspectiveCamera(), this.virtualCamera.layers.set(x), this.clipBias = 3e-3, this.frustumCulled = !1, this.renderOrder = 1, this.position.z = 2e-3, this.reflectorPlane = new o.Plane(), this.normal = new o.Vector3(), this.reflectorWorldPosition = new o.Vector3(), this.cameraWorldPosition = new o.Vector3(), this.rotationMatrix = new o.Matrix4(), this.lookAtPosition = new o.Vector3(0, 0, -1), this.clipPlane = new o.Vector4(), this.view = new o.Vector3(), this.target = new o.Vector3(), this.q = new o.Vector4();
|
|
136
|
+
}
|
|
137
|
+
renderReflection(t, i, r) {
|
|
138
|
+
if (this.reflectorWorldPosition.setFromMatrixPosition(this.matrixWorld), this.cameraWorldPosition.setFromMatrixPosition(r.matrixWorld), this.rotationMatrix.extractRotation(this.matrixWorld), this.normal.set(0, 0, 1).applyMatrix4(this.rotationMatrix), this.view.subVectors(this.reflectorWorldPosition, this.cameraWorldPosition), this.view.dot(this.normal) > 0) return;
|
|
139
|
+
this.view.reflect(this.normal).negate().add(this.reflectorWorldPosition), this.rotationMatrix.extractRotation(r.matrixWorld), this.lookAtPosition.set(0, 0, -1).applyMatrix4(this.rotationMatrix).add(this.cameraWorldPosition), this.target.subVectors(this.reflectorWorldPosition, this.lookAtPosition).reflect(this.normal).negate().add(this.reflectorWorldPosition), this.virtualCamera.position.copy(this.view), this.virtualCamera.up.set(0, 1, 0).applyMatrix4(this.rotationMatrix).reflect(this.normal), this.virtualCamera.lookAt(this.target), this.virtualCamera.near = r.near, this.virtualCamera.far = r.far, this.virtualCamera.updateMatrixWorld(), this.virtualCamera.projectionMatrix.copy(r.projectionMatrix), this.textureMatrix.set(
|
|
140
|
+
0.5,
|
|
141
|
+
0,
|
|
142
|
+
0,
|
|
143
|
+
0.5,
|
|
144
|
+
0,
|
|
145
|
+
0.5,
|
|
146
|
+
0,
|
|
147
|
+
0.5,
|
|
148
|
+
0,
|
|
149
|
+
0,
|
|
150
|
+
0.5,
|
|
151
|
+
0.5,
|
|
152
|
+
0,
|
|
153
|
+
0,
|
|
154
|
+
0,
|
|
155
|
+
1
|
|
156
|
+
).multiply(this.virtualCamera.projectionMatrix).multiply(this.virtualCamera.matrixWorldInverse).multiply(this.matrixWorld), this.reflectorPlane.setFromNormalAndCoplanarPoint(this.normal, this.reflectorWorldPosition).applyMatrix4(this.virtualCamera.matrixWorldInverse), this.clipPlane.set(
|
|
157
|
+
this.reflectorPlane.normal.x,
|
|
158
|
+
this.reflectorPlane.normal.y,
|
|
159
|
+
this.reflectorPlane.normal.z,
|
|
160
|
+
this.reflectorPlane.constant
|
|
161
|
+
);
|
|
162
|
+
const s = this.virtualCamera.projectionMatrix;
|
|
163
|
+
this.q.set(
|
|
164
|
+
(Math.sign(this.clipPlane.x) + s.elements[8]) / s.elements[0],
|
|
165
|
+
(Math.sign(this.clipPlane.y) + s.elements[9]) / s.elements[5],
|
|
166
|
+
-1,
|
|
167
|
+
(1 + s.elements[10]) / s.elements[14]
|
|
168
|
+
), this.clipPlane.multiplyScalar(2 / this.clipPlane.dot(this.q)), s.elements[2] = this.clipPlane.x, s.elements[6] = this.clipPlane.y, s.elements[10] = this.clipPlane.z + 1 - this.clipBias, s.elements[14] = this.clipPlane.w, this.virtualCamera.projectionMatrixInverse.copy(s).invert();
|
|
169
|
+
const n = t.getRenderTarget(), l = t.xr.enabled, u = t.shadowMap.autoUpdate, d = t.shadowMap.enabled;
|
|
170
|
+
try {
|
|
171
|
+
t.xr.enabled = !1, t.shadowMap.enabled = !1, t.shadowMap.autoUpdate = !1, t.setRenderTarget(this.renderTarget), t.state.buffers.depth.setMask(!0), t.clear(), t.render(i, this.virtualCamera);
|
|
172
|
+
} finally {
|
|
173
|
+
t.setRenderTarget(n), t.xr.enabled = l, t.shadowMap.enabled = d, t.shadowMap.autoUpdate = u;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
setRenderSize(t, i) {
|
|
177
|
+
this.renderTarget.setSize(t, i), this.material.uniforms.resolution.value.set(t, i);
|
|
178
|
+
}
|
|
179
|
+
// Radius is in world units; the outer 65% fades before the square mesh edge.
|
|
180
|
+
setRadius(t, i, r = this.material.uniforms.groundCenter.value) {
|
|
181
|
+
this.scale.setScalar(t * 2 / this.geometry.parameters.width), this.position.x = r.x, this.position.y = r.y, this.material.uniforms.groundCenter.value.set(r.x, r.y), this.material.uniforms.gridScale.value = i, this.material.uniforms.maxRadius.value = t, this.material.uniforms.fadeSoftness.value = t * 0.65;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const g = {
|
|
185
|
+
light: {
|
|
186
|
+
background: p.light,
|
|
187
|
+
fineGrid: 5859168,
|
|
188
|
+
coarseGrid: 3427136,
|
|
189
|
+
gridOpacity: 0.85,
|
|
190
|
+
reflectionMix: 0.06
|
|
191
|
+
},
|
|
192
|
+
dark: {
|
|
193
|
+
background: p.dark,
|
|
194
|
+
fineGrid: 7375236,
|
|
195
|
+
coarseGrid: 5552554,
|
|
196
|
+
gridOpacity: 0.9,
|
|
197
|
+
reflectionMix: 0.06
|
|
198
|
+
}
|
|
199
|
+
}, P = {
|
|
200
|
+
simulation: 0.68,
|
|
201
|
+
model: 1.4
|
|
202
|
+
};
|
|
203
|
+
function C(c) {
|
|
204
|
+
const e = /* @__PURE__ */ new Set(), t = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set();
|
|
205
|
+
c.traverse((s) => {
|
|
206
|
+
var l;
|
|
207
|
+
const n = s;
|
|
208
|
+
n.geometry && e.add(n.geometry);
|
|
209
|
+
for (const u of Array.isArray(n.material) ? n.material : [n.material])
|
|
210
|
+
if (u) {
|
|
211
|
+
t.add(u);
|
|
212
|
+
for (const d of Object.values(u)) {
|
|
213
|
+
if (!S(d)) continue;
|
|
214
|
+
i.add(d);
|
|
215
|
+
const h = (l = d.source) == null ? void 0 : l.data;
|
|
216
|
+
h && typeof h.close == "function" && r.add(h);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
for (const s of e) s.dispose();
|
|
221
|
+
for (const s of t) s.dispose();
|
|
222
|
+
for (const s of i) s.dispose();
|
|
223
|
+
for (const s of r) s.close();
|
|
224
|
+
}
|
|
225
|
+
function S(c) {
|
|
226
|
+
return !!(c && typeof c == "object" && c.isTexture);
|
|
227
|
+
}
|
|
228
|
+
const f = 2213822, G = 6000111, R = 6;
|
|
229
|
+
function L(c, e, t) {
|
|
230
|
+
e.updateMatrixWorld();
|
|
231
|
+
const i = new o.Vector3();
|
|
232
|
+
return e.getWorldDirection(i).normalize(), c.setFromNormalAndCoplanarPoint(i, t);
|
|
233
|
+
}
|
|
234
|
+
class F {
|
|
235
|
+
constructor(e, t = "dark", i, r = "simulation") {
|
|
236
|
+
a(this, "root", new o.Group());
|
|
237
|
+
a(this, "reflector", new w({ size: 100, textureWidth: 256, textureHeight: 256 }));
|
|
238
|
+
a(this, "values");
|
|
239
|
+
a(this, "fog");
|
|
240
|
+
a(this, "raycaster", new o.Raycaster());
|
|
241
|
+
a(this, "pointer", new o.Vector2());
|
|
242
|
+
a(this, "dragPlane", new o.Plane());
|
|
243
|
+
a(this, "dragTarget", new o.Vector3());
|
|
244
|
+
a(this, "dragIntersection", new o.Vector3());
|
|
245
|
+
a(this, "dragOffset", new o.Vector3());
|
|
246
|
+
a(this, "bodyGroups", /* @__PURE__ */ new Map());
|
|
247
|
+
a(this, "auxiliaries", /* @__PURE__ */ new Set());
|
|
248
|
+
a(this, "forceLine");
|
|
249
|
+
a(this, "forceBoosted", !1);
|
|
250
|
+
a(this, "grabCanvas", null);
|
|
251
|
+
a(this, "previousCursor", "");
|
|
252
|
+
a(this, "size", "");
|
|
253
|
+
a(this, "groundVisible");
|
|
254
|
+
a(this, "disposed", !1);
|
|
255
|
+
this.model = e, this.runtime = i, this.presentation = r, this.values = g[t];
|
|
256
|
+
const s = this.values, n = new o.Box3().setFromObject(e), l = Math.max(...n.getSize(new o.Vector3()).toArray());
|
|
257
|
+
if (!Number.isFinite(l) || l <= 0) throw new Error("Empty simulation geometry.");
|
|
258
|
+
this.root.add(e), this.forceLine = this.createForceLine(), this.root.add(this.forceLine), e.traverse((m) => {
|
|
259
|
+
m instanceof o.Mesh && m.layers.enable(x);
|
|
260
|
+
}), this.root.add(this.reflector);
|
|
261
|
+
const u = Math.max(n.getSize(new o.Vector3()).length() * 0.5, 0.02), d = this.reflector.material.uniforms;
|
|
262
|
+
d.fineGridColor.value.setHex(s.fineGrid), d.coarseGridColor.value.setHex(s.coarseGrid), d.gridOpacity.value = s.gridOpacity, d.reflectionMix.value = s.reflectionMix, this.layoutGround(n, u), this.groundVisible = r === "simulation", this.setGroundVisible(this.groundVisible);
|
|
263
|
+
const h = u / Math.sin(o.MathUtils.degToRad(38) / 2) * 1.25;
|
|
264
|
+
this.fog = new o.Fog(s.background, h * 2.5, h * 8);
|
|
265
|
+
}
|
|
266
|
+
setTheme(e) {
|
|
267
|
+
if (this.disposed) return;
|
|
268
|
+
const t = this.values = g[e], i = this.reflector.material.uniforms;
|
|
269
|
+
i.fineGridColor.value.setHex(t.fineGrid), i.coarseGridColor.value.setHex(t.coarseGrid), i.gridOpacity.value = t.gridOpacity, i.reflectionMix.value = t.reflectionMix, this.fog.color.setHex(t.background);
|
|
270
|
+
}
|
|
271
|
+
layoutGround(e, t) {
|
|
272
|
+
this.reflector.setRadius(t * 8, Math.pow(10, Math.floor(Math.log10(Math.max(t, 0.01)))), e.getCenter(new o.Vector3()));
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Re-fits the ground disc and reflection to the model's current world bounds.
|
|
276
|
+
* Model previews call this after re-orienting the asset's authored up axis:
|
|
277
|
+
* an axis-aligned bounding box is not rotation invariant, so the floor that
|
|
278
|
+
* was sized to a wide-flat footprint can end up clipping an upright model.
|
|
279
|
+
*/
|
|
280
|
+
reseatGround() {
|
|
281
|
+
if (this.disposed) return;
|
|
282
|
+
this.root.updateMatrixWorld(!0);
|
|
283
|
+
const e = new o.Box3().setFromObject(this.model);
|
|
284
|
+
e.isEmpty() || this.layoutGround(e, Math.max(e.getSize(new o.Vector3()).length() * 0.5, 0.02));
|
|
285
|
+
}
|
|
286
|
+
createForceLine() {
|
|
287
|
+
const e = new o.BufferGeometry().setFromPoints([
|
|
288
|
+
new o.Vector3(),
|
|
289
|
+
new o.Vector3()
|
|
290
|
+
]), t = new o.LineBasicMaterial({
|
|
291
|
+
color: f,
|
|
292
|
+
depthTest: !1,
|
|
293
|
+
transparent: !0
|
|
294
|
+
}), i = new o.Line(e, t);
|
|
295
|
+
return i.renderOrder = 1e3, i.visible = !1, i;
|
|
296
|
+
}
|
|
297
|
+
findBodyGroup(e) {
|
|
298
|
+
var i;
|
|
299
|
+
let t = e;
|
|
300
|
+
for (; t && t !== this.model && t !== this.root; ) {
|
|
301
|
+
if (typeof ((i = t.userData) == null ? void 0 : i.bodyId) == "number") return t;
|
|
302
|
+
t = t.parent;
|
|
303
|
+
}
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
getBodyGroup(e) {
|
|
307
|
+
let t = this.bodyGroups.get(e);
|
|
308
|
+
return t || this.model.traverse((i) => {
|
|
309
|
+
var r;
|
|
310
|
+
((r = i.userData) == null ? void 0 : r.bodyId) === e && (t = i, this.bodyGroups.set(e, i));
|
|
311
|
+
}), t;
|
|
312
|
+
}
|
|
313
|
+
pointerRay(e, t, i) {
|
|
314
|
+
const r = i.getBoundingClientRect();
|
|
315
|
+
this.pointer.set(
|
|
316
|
+
(e.clientX - r.left) / r.width * 2 - 1,
|
|
317
|
+
-((e.clientY - r.top) / r.height) * 2 + 1
|
|
318
|
+
), this.raycaster.setFromCamera(this.pointer, t);
|
|
319
|
+
}
|
|
320
|
+
setForceBoost(e) {
|
|
321
|
+
var t;
|
|
322
|
+
!((t = this.runtime) != null && t.grab) || e === this.forceBoosted || (this.forceBoosted = e, this.runtime.updateGrabStrength(e ? R : 1), this.forceLine.material.color.setHex(e ? G : f));
|
|
323
|
+
}
|
|
324
|
+
beginGrab(e, t, i) {
|
|
325
|
+
if (!this.runtime || this.disposed) return !1;
|
|
326
|
+
this.pointerRay(e, t, i);
|
|
327
|
+
const r = this.raycaster.intersectObject(this.model, !0).find((u) => u.object.isMesh);
|
|
328
|
+
if (!r) return !1;
|
|
329
|
+
const s = this.findBodyGroup(r.object);
|
|
330
|
+
if (!s) return !1;
|
|
331
|
+
const n = s.worldToLocal(r.point.clone());
|
|
332
|
+
this.dragTarget.copy(r.point), L(this.dragPlane, t, r.point), this.dragOffset.set(0, 0, 0);
|
|
333
|
+
const l = this.root.worldToLocal(r.point.clone());
|
|
334
|
+
return this.bodyGroups.set(s.userData.bodyId, s), this.runtime.beginGrab({
|
|
335
|
+
bodyId: s.userData.bodyId,
|
|
336
|
+
localPoint: [n.x, n.y, n.z],
|
|
337
|
+
target: [l.x, l.y, l.z]
|
|
338
|
+
}), this.forceBoosted = !1, this.setForceBoost(e.shiftKey), this.forceLine.visible = !0, this.updateForceLine(), this.grabCanvas = i, i != null && i.style && (this.previousCursor = i.style.cursor, i.style.cursor = "grabbing"), !0;
|
|
339
|
+
}
|
|
340
|
+
moveGrab(e, t, i) {
|
|
341
|
+
var s;
|
|
342
|
+
if (!((s = this.runtime) != null && s.grab)) return;
|
|
343
|
+
if (this.pointerRay(e, t, i), this.setForceBoost(e.shiftKey), i != null && i.style && i.style.cursor !== "grabbing" && (i.style.cursor = "grabbing"), this.raycaster.ray.intersectPlane(this.dragPlane, this.dragIntersection))
|
|
344
|
+
this.dragTarget.copy(this.dragIntersection).add(this.dragOffset);
|
|
345
|
+
else
|
|
346
|
+
return;
|
|
347
|
+
const r = this.root.worldToLocal(this.dragTarget.clone());
|
|
348
|
+
this.runtime.updateGrabTarget([r.x, r.y, r.z]), this.updateForceLine();
|
|
349
|
+
}
|
|
350
|
+
endGrab() {
|
|
351
|
+
var e;
|
|
352
|
+
this.runtime && (this.runtime.endGrab(), this.forceBoosted = !1, this.forceLine.visible = !1, this.forceLine.material.color.setHex(f), (e = this.grabCanvas) != null && e.style && (this.grabCanvas.style.cursor = this.previousCursor), this.grabCanvas = null);
|
|
353
|
+
}
|
|
354
|
+
updateForceLine() {
|
|
355
|
+
var l;
|
|
356
|
+
const e = (l = this.runtime) == null ? void 0 : l.grab;
|
|
357
|
+
if (!e) return;
|
|
358
|
+
const t = this.getBodyGroup(e.bodyId);
|
|
359
|
+
if (!t) return;
|
|
360
|
+
const i = new o.Vector3().fromArray(e.localPoint), r = t.localToWorld(i), s = this.root.worldToLocal(r), n = this.forceLine.geometry.attributes.position;
|
|
361
|
+
n.setXYZ(0, s.x, s.y, s.z), n.setXYZ(1, e.target[0], e.target[1], e.target[2]), n.needsUpdate = !0;
|
|
362
|
+
}
|
|
363
|
+
beforeRender(e, t, i) {
|
|
364
|
+
var n;
|
|
365
|
+
const r = {
|
|
366
|
+
tone: e.toneMapping,
|
|
367
|
+
exposure: e.toneMappingExposure,
|
|
368
|
+
color: e.outputColorSpace,
|
|
369
|
+
environment: t.environment,
|
|
370
|
+
fog: t.fog,
|
|
371
|
+
background: t.background
|
|
372
|
+
}, s = () => {
|
|
373
|
+
e.toneMapping = r.tone, e.toneMappingExposure = r.exposure, e.outputColorSpace = r.color, t.environment = r.environment, t.fog = r.fog, t.background = r.background;
|
|
374
|
+
};
|
|
375
|
+
if (this.disposed) return s;
|
|
376
|
+
try {
|
|
377
|
+
(n = this.runtime) != null && n.grab && this.updateForceLine(), e.toneMapping = o.ACESFilmicToneMapping, e.toneMappingExposure = P[this.presentation], e.outputColorSpace = o.SRGBColorSpace, t.background = new o.Color(this.values.background), t.fog = this.fog;
|
|
378
|
+
const l = e.getSize(new o.Vector2()), u = `${l.x}:${l.y}`;
|
|
379
|
+
return u !== this.size && (this.size = u, this.reflector.setRenderSize(Math.max(1, Math.floor(l.x * 0.35)), Math.max(1, Math.floor(l.y * 0.35)))), t.updateMatrixWorld(!0), i.updateMatrixWorld(!0), this.groundVisible && i instanceof o.PerspectiveCamera && this.reflector.renderReflection(e, t, i), s;
|
|
380
|
+
} catch (l) {
|
|
381
|
+
throw s(), l;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* The reflector mesh carries both the grid lines and the reflection. Hiding
|
|
386
|
+
* it also skips the reflection render pass, which only feeds its shader.
|
|
387
|
+
*/
|
|
388
|
+
setGroundVisible(e) {
|
|
389
|
+
this.groundVisible = e, this.reflector.visible = e;
|
|
390
|
+
}
|
|
391
|
+
getGroundVisible() {
|
|
392
|
+
return this.groundVisible;
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Adds a debug/auxiliary object next to the model rather than inside it.
|
|
396
|
+
* The model subtree is what the reflector pass and `getModelBounds` measure,
|
|
397
|
+
* so nesting hidden aids (collision meshes, which are far larger than the
|
|
398
|
+
* visual shell) would inflate both the reflection extent and the camera fit.
|
|
399
|
+
*/
|
|
400
|
+
attachAuxiliary(e) {
|
|
401
|
+
this.auxiliaries.add(e), this.root.add(e);
|
|
402
|
+
}
|
|
403
|
+
getModelBounds() {
|
|
404
|
+
this.root.updateMatrixWorld(!0);
|
|
405
|
+
const e = new o.Box3().setFromObject(this.model);
|
|
406
|
+
if (!e.isEmpty()) return e;
|
|
407
|
+
const t = new o.Box3();
|
|
408
|
+
return t.min.set(-5e3, -5e3, -5e3), t.max.set(5e3, 5e3, 5e3), t;
|
|
409
|
+
}
|
|
410
|
+
dispose() {
|
|
411
|
+
if (!this.disposed) {
|
|
412
|
+
this.disposed = !0, this.endGrab(), this.model.removeFromParent();
|
|
413
|
+
for (const e of this.auxiliaries) e.removeFromParent();
|
|
414
|
+
this.auxiliaries.clear(), this.root.removeFromParent(), this.reflector.renderTarget.dispose(), C(this.root);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
export {
|
|
419
|
+
F as S,
|
|
420
|
+
C as d
|
|
421
|
+
};
|
package/dist/types.d.ts
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import type { Box3, ColorRepresentation, Object3D, Vector3 } from 'three';
|
|
2
|
-
import type { CadViewerCapability, CameraStateStore, ViewerUiOptions } from './cad/types';
|
|
3
|
-
|
|
2
|
+
import type { CadViewerCapability, CameraStateStore, ViewerUiOptions, ViewerUiTheme } from './cad/types';
|
|
3
|
+
import type { AssetChangeEvent, AssetControlChangeEvent, AssetErrorEvent, AssetPreview, AssetSource, OpenAssetOptions, ViewerAssetOptions } from './assets/types';
|
|
4
|
+
export type { CadBlockModel, CadDocumentHandle, CadDocumentUnits, CadFontResolver, CadFontRequest, CadResolvedFont, CadResolvedTextFont, CadTextWarmupOptions, CadHudModel, CadHudSnapshot, CadInspectorModel, CadInspectorSnapshot, CadLayerModel, CadLayerRow, CadBlockUsageRow, CadSessionPhase, CadWorldBounds, CadScaleRulerState, CadInsertDetails, CadInsertSelection, CadInsertSelectionId, CadTextDetails, CadTextSelection, CadTextSelectionId, CadSelection, CadHit, CadViewerSnapshot, CadLoadProgress, CadViewerErrorCode, CadViewerErrorEvent, CadLoadSource, CadOpenOptions, CadSessionLoadTiming, RenderDebugBreakdownEntry, SplitBlockLayerDetail, CadViewerCapability, ResolveTextFont, CadViewerEventMap, CameraStateStore, ViewerCadUiKeyboardOptions, ViewerUiOptions, ViewerCadUiParts, ViewerCadUiOptions, ViewerUiPreset, ViewerCadUiStateStore, ViewerUiTheme, ViewerUiTokens, } from './cad/types';
|
|
4
5
|
export type ViewerViewMode = '2d' | '3d';
|
|
6
|
+
export type CadInteractionMode = 'managed' | 'manual' | 'disabled';
|
|
7
|
+
/**
|
|
8
|
+
* Which 3D navigation implementation the runtime drives.
|
|
9
|
+
* `viewer` is the CAD path; `preview` is the model/simulation particle viewer
|
|
10
|
+
* matching sim-studio. Kept as its own union so the viewer's public surface
|
|
11
|
+
* does not re-export the runtime package's type.
|
|
12
|
+
*/
|
|
13
|
+
export type ViewerNavigationPolicy = 'legacy' | 'viewer' | 'preview';
|
|
14
|
+
export type CameraChangeReason = 'pointer' | 'wheel' | 'fit' | 'restore' | 'api' | 'view-mode';
|
|
5
15
|
export type ViewerEnvironment = 'room' | {
|
|
6
16
|
/** Load an external equirectangular HDR texture for image-based lighting. */
|
|
7
17
|
readonly type: 'hdr';
|
|
@@ -50,10 +60,28 @@ export interface ViewerOptions {
|
|
|
50
60
|
environment?: ViewerEnvironment;
|
|
51
61
|
autoSelectOnPick?: boolean;
|
|
52
62
|
pointerPick?: boolean;
|
|
63
|
+
/** CAD click policy. Defaults to managed. */
|
|
64
|
+
cadInteraction?: CadInteractionMode;
|
|
65
|
+
cadInteractionStyle?: {
|
|
66
|
+
hover?: {
|
|
67
|
+
color?: ColorRepresentation;
|
|
68
|
+
fillOpacity?: number;
|
|
69
|
+
edgeOpacity?: number;
|
|
70
|
+
enabled?: boolean;
|
|
71
|
+
};
|
|
72
|
+
selected?: {
|
|
73
|
+
color?: ColorRepresentation;
|
|
74
|
+
fillOpacity?: number;
|
|
75
|
+
edgeOpacity?: number;
|
|
76
|
+
enabled?: boolean;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
53
79
|
cameraStateStore?: CameraStateStore | false;
|
|
54
80
|
/** Max delay for merged viewport demands while the interaction is active. Default 160ms. */
|
|
55
81
|
viewportDemandCoalesceMs?: number;
|
|
56
82
|
ui?: ViewerUiOptions;
|
|
83
|
+
assets?: ViewerAssetOptions;
|
|
84
|
+
onCleanupError?: (event: AssetErrorEvent) => void;
|
|
57
85
|
}
|
|
58
86
|
export interface ViewerFitViewOptions {
|
|
59
87
|
padding?: number;
|
|
@@ -75,6 +103,10 @@ export interface ViewerPickResult {
|
|
|
75
103
|
export interface ViewerHighlightOptions {
|
|
76
104
|
color?: ColorRepresentation;
|
|
77
105
|
}
|
|
106
|
+
export interface ViewerObjectOptions {
|
|
107
|
+
/** Viewer only mounts the object; the caller retains responsibility for GPU resource disposal. */
|
|
108
|
+
readonly ownership?: 'borrowed';
|
|
109
|
+
}
|
|
78
110
|
export interface ViewerRenderStats {
|
|
79
111
|
readonly drawCalls: number;
|
|
80
112
|
readonly submittedVertexRefs: number;
|
|
@@ -104,6 +136,9 @@ export interface ViewerEventMap {
|
|
|
104
136
|
'view-mode-change': {
|
|
105
137
|
viewMode: ViewerViewMode;
|
|
106
138
|
};
|
|
139
|
+
'theme-change': {
|
|
140
|
+
theme: ViewerUiTheme;
|
|
141
|
+
};
|
|
107
142
|
resize: {
|
|
108
143
|
resized: boolean;
|
|
109
144
|
};
|
|
@@ -121,7 +156,22 @@ export interface ViewerEventMap {
|
|
|
121
156
|
};
|
|
122
157
|
'camera-change': {
|
|
123
158
|
viewMode: ViewerViewMode;
|
|
159
|
+
reason: CameraChangeReason;
|
|
160
|
+
interaction: 'active' | 'idle';
|
|
161
|
+
};
|
|
162
|
+
'ui-layout-change': {
|
|
163
|
+
contentInsets: {
|
|
164
|
+
readonly top: number;
|
|
165
|
+
readonly right: number;
|
|
166
|
+
readonly bottom: number;
|
|
167
|
+
readonly left: number;
|
|
168
|
+
};
|
|
169
|
+
layerPanelOpen: boolean;
|
|
170
|
+
propertyPanelOpen: boolean;
|
|
124
171
|
};
|
|
172
|
+
'asset-change': AssetChangeEvent;
|
|
173
|
+
'asset-error': AssetErrorEvent;
|
|
174
|
+
'asset-control-change': AssetControlChangeEvent;
|
|
125
175
|
}
|
|
126
176
|
export interface Viewer {
|
|
127
177
|
readonly viewport: HTMLElement;
|
|
@@ -131,13 +181,37 @@ export interface Viewer {
|
|
|
131
181
|
readonly highlightedObject: Object3D | null;
|
|
132
182
|
readonly isDisposed: boolean;
|
|
133
183
|
readonly cad: CadViewerCapability;
|
|
134
|
-
|
|
184
|
+
readonly overlays: {
|
|
185
|
+
set(key: string, object: Object3D, options?: {
|
|
186
|
+
owned?: boolean;
|
|
187
|
+
}): void;
|
|
188
|
+
remove(key: string, options?: {
|
|
189
|
+
dispose?: boolean;
|
|
190
|
+
}): Object3D | null;
|
|
191
|
+
};
|
|
192
|
+
readonly camera: {
|
|
193
|
+
getState(): ViewerCameraSnapshot | null;
|
|
194
|
+
/** Applies a validated snapshot immediately. Animated transitions are not part of the current contract. */
|
|
195
|
+
setState(snapshot: ViewerCameraSnapshot): boolean;
|
|
196
|
+
reset(): boolean;
|
|
197
|
+
};
|
|
198
|
+
readonly plugins: import('./plugins').ViewerPluginRegistry;
|
|
199
|
+
readonly commands: {
|
|
200
|
+
execute(id: string, args?: unknown): boolean;
|
|
201
|
+
has(id: string): boolean;
|
|
202
|
+
};
|
|
203
|
+
openAsset(source: AssetSource, options?: OpenAssetOptions): AssetPreview;
|
|
204
|
+
closeAsset(): Promise<void>;
|
|
205
|
+
addObject(object: Object3D, options?: ViewerObjectOptions): void;
|
|
135
206
|
removeObject(object: Object3D): boolean;
|
|
136
207
|
setVisible(object: Object3D, visible: boolean): void;
|
|
137
208
|
setViewMode(mode: ViewerViewMode, options?: {
|
|
138
209
|
preserveOrbit?: boolean;
|
|
139
210
|
}): void;
|
|
211
|
+
/** Switches the UI and active preview stage theme at runtime. */
|
|
212
|
+
setTheme(theme: ViewerUiTheme): boolean;
|
|
140
213
|
fitView(target?: Object3D | Box3, options?: ViewerFitViewOptions): boolean;
|
|
214
|
+
fitAll(options?: ViewerFitViewOptions): boolean;
|
|
141
215
|
screenToWorldOnPlane(clientX: number, clientY: number, planeZ?: number): Vector3 | null;
|
|
142
216
|
pick(clientX: number, clientY: number, options?: ViewerPickOptions): ViewerPickResult | null;
|
|
143
217
|
setSelection(object: Object3D | null): void;
|
|
@@ -145,5 +219,10 @@ export interface Viewer {
|
|
|
145
219
|
on<K extends keyof ViewerEventMap>(type: K, listener: (event: ViewerEventMap[K]) => void): () => void;
|
|
146
220
|
resize(): boolean;
|
|
147
221
|
requestRender(): void;
|
|
222
|
+
getActiveCamera(): import('three').Camera;
|
|
223
|
+
setNavigationEnabled(enabled: boolean): void;
|
|
148
224
|
dispose(): void;
|
|
225
|
+
use(plugins: readonly import('./plugins').ViewerPlugin[], options?: {
|
|
226
|
+
replace?: boolean;
|
|
227
|
+
}): void;
|
|
149
228
|
}
|