u-space 0.0.3 → 0.0.7

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.
Files changed (74) hide show
  1. package/dist/index.cjs +1 -2074
  2. package/dist/index.js +1077 -1509
  3. package/dist/plugins/u-manager/flows/ComponentFlowParser.d.ts +8 -0
  4. package/dist/plugins/u-manager/flows/FlowParser.d.ts +48 -0
  5. package/dist/plugins/u-manager/flows/edges/index.d.ts +9 -0
  6. package/dist/plugins/u-manager/flows/index.d.ts +4 -0
  7. package/dist/plugins/u-manager/flows/nodes/ColorNode.d.ts +8 -0
  8. package/dist/plugins/u-manager/flows/nodes/ConditionNode.d.ts +9 -0
  9. package/dist/plugins/u-manager/flows/nodes/DataExtractionNode.d.ts +8 -0
  10. package/dist/plugins/u-manager/flows/nodes/DataFilterNode.d.ts +8 -0
  11. package/dist/plugins/u-manager/flows/nodes/DelayNode.d.ts +8 -0
  12. package/dist/plugins/u-manager/flows/nodes/EmissiveNode.d.ts +8 -0
  13. package/dist/plugins/u-manager/flows/nodes/FlyToNode.d.ts +8 -0
  14. package/dist/plugins/u-manager/flows/nodes/HideNode.d.ts +10 -0
  15. package/dist/plugins/u-manager/flows/nodes/HighlightNode.d.ts +8 -0
  16. package/dist/plugins/u-manager/flows/nodes/MeshNode.d.ts +8 -0
  17. package/dist/plugins/u-manager/flows/nodes/MeshesNode.d.ts +8 -0
  18. package/dist/plugins/u-manager/flows/nodes/ModelNode.d.ts +8 -0
  19. package/dist/plugins/u-manager/flows/nodes/ModelsNode.d.ts +8 -0
  20. package/dist/plugins/u-manager/flows/nodes/Node.d.ts +52 -0
  21. package/dist/plugins/u-manager/flows/nodes/NumberNode.d.ts +8 -0
  22. package/dist/plugins/u-manager/flows/nodes/OpacityNode.d.ts +8 -0
  23. package/dist/plugins/u-manager/flows/nodes/POINode.d.ts +8 -0
  24. package/dist/plugins/u-manager/flows/nodes/POISNode.d.ts +8 -0
  25. package/dist/plugins/u-manager/flows/nodes/PathNode.d.ts +8 -0
  26. package/dist/plugins/u-manager/flows/nodes/PathsNode.d.ts +8 -0
  27. package/dist/plugins/u-manager/flows/nodes/RotateNode.d.ts +8 -0
  28. package/dist/plugins/u-manager/flows/nodes/ScaleNode.d.ts +8 -0
  29. package/dist/plugins/u-manager/flows/nodes/ShowNode.d.ts +10 -0
  30. package/dist/plugins/u-manager/flows/nodes/SpaceNode.d.ts +8 -0
  31. package/dist/plugins/u-manager/flows/nodes/SpacesNode.d.ts +8 -0
  32. package/dist/plugins/u-manager/flows/nodes/StartNode.d.ts +7 -0
  33. package/dist/plugins/u-manager/flows/nodes/TranslateNode.d.ts +8 -0
  34. package/dist/plugins/u-manager/flows/nodes/UnEmissiveNode.d.ts +10 -0
  35. package/dist/plugins/u-manager/flows/nodes/UnHighlightNode.d.ts +10 -0
  36. package/dist/plugins/u-manager/flows/nodes/UnOpacityNode.d.ts +8 -0
  37. package/dist/plugins/u-manager/flows/nodes/UserDataNode.d.ts +8 -0
  38. package/dist/plugins/u-manager/flows/nodes/clip-animation/ClipAnimationNode.d.ts +8 -0
  39. package/dist/plugins/u-manager/flows/nodes/clip-animation/UnClipAnimationNode.d.ts +8 -0
  40. package/dist/plugins/u-manager/flows/nodes/clip-animation/index.d.ts +2 -0
  41. package/dist/plugins/u-manager/flows/nodes/component-tween-animation/ComponentTweenAnimationNode.d.ts +8 -0
  42. package/dist/plugins/u-manager/flows/nodes/component-tween-animation/UnComponentTweenAnimationNode.d.ts +8 -0
  43. package/dist/plugins/u-manager/flows/nodes/component-tween-animation/index.d.ts +2 -0
  44. package/dist/plugins/u-manager/flows/nodes/component-tween-animation/utils.d.ts +5 -0
  45. package/dist/plugins/u-manager/flows/nodes/index.d.ts +34 -0
  46. package/dist/plugins/u-manager/flows/nodes/tween-animation/TweenAnimationNode.d.ts +8 -0
  47. package/dist/plugins/u-manager/flows/nodes/tween-animation/UnTweenAnimationNode.d.ts +8 -0
  48. package/dist/plugins/u-manager/flows/nodes/tween-animation/index.d.ts +2 -0
  49. package/dist/plugins/u-manager/flows/nodes/tween-animation/utils.d.ts +5 -0
  50. package/dist/plugins/u-manager/flows/types.d.ts +81 -0
  51. package/dist/plugins/u-manager/flows/utils.d.ts +14 -0
  52. package/dist/plugins/u-manager/index.cjs +59 -59
  53. package/dist/plugins/u-manager/index.d.ts +1 -0
  54. package/dist/plugins/u-manager/index.js +9718 -8616
  55. package/dist/src/effects/MaterialEffects.d.ts +10 -3
  56. package/dist/src/index.d.ts +8 -0
  57. package/dist/src/objects/Model.d.ts +14 -1
  58. package/dist/src/objects/Poi.d.ts +4 -0
  59. package/dist/src/viewers/CSSRenderer.d.ts +19 -0
  60. package/dist/src/viewers/CameraControls.d.ts +7 -0
  61. package/dist/src/viewers/RenderPipeline.d.ts +30 -2
  62. package/dist/src/viewers/Viewer.d.ts +6 -0
  63. package/dist/src/viewers/index.d.ts +2 -0
  64. package/docs/api-css-renderer.md +43 -0
  65. package/docs/api-effects.md +49 -11
  66. package/docs/api-objects.md +58 -0
  67. package/docs/api-render-pipeline.md +114 -0
  68. package/docs/api-viewer.md +37 -4
  69. package/docs/examples-guide.md +40 -0
  70. package/docs/getting-started.md +12 -0
  71. package/docs/index.md +6 -0
  72. package/package.json +1 -1
  73. package/dist/index.cjs.map +0 -1
  74. package/dist/index.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,2074 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const webgpu = require("three/webgpu");
4
- const tsl = require("three/tsl");
5
- const CameraControlsBase = require("camera-controls");
6
- const RoomEnvironment_js = require("three/addons/environments/RoomEnvironment.js");
7
- const ViewHelper_js = require("three/addons/helpers/ViewHelper.js");
8
- const GLTFLoader_js = require("three/addons/loaders/GLTFLoader.js");
9
- const FBXLoader_js = require("three/addons/loaders/FBXLoader.js");
10
- const OBJLoader_js = require("three/addons/loaders/OBJLoader.js");
11
- const STLLoader_js = require("three/addons/loaders/STLLoader.js");
12
- const DRACOLoader_js = require("three/addons/loaders/DRACOLoader.js");
13
- const KTX2Loader_js = require("three/addons/loaders/KTX2Loader.js");
14
- const meshopt_decoder_module_js = require("three/addons/libs/meshopt_decoder.module.js");
15
- const HDRLoader_js = require("three/addons/loaders/HDRLoader.js");
16
- const SkeletonUtils_js = require("three/addons/utils/SkeletonUtils.js");
17
- const three = require("three");
18
- const tween_module_js = require("three/addons/libs/tween.module.js");
19
- class InteractionEvent {
20
- /** The type of event (e.g., 'click', 'pointerdown'). */
21
- type;
22
- /** The original 3D object that triggered the event. */
23
- target;
24
- /** The current 3D object during the bubbling phase. */
25
- currentTarget;
26
- /** The intersection data from raycasting, or null if not applicable. */
27
- intersect;
28
- /** The original DOM event, or undefined if not applicable. */
29
- originalEvent;
30
- _propagationStopped = false;
31
- constructor(init) {
32
- this.type = init.type;
33
- this.target = init.target;
34
- this.currentTarget = init.target;
35
- this.intersect = init.intersect;
36
- this.originalEvent = init.originalEvent;
37
- }
38
- /**
39
- * Stops the event from bubbling up the parent chain.
40
- */
41
- stopPropagation() {
42
- this._propagationStopped = true;
43
- }
44
- /**
45
- * Returns true if `stopPropagation()` has been called.
46
- */
47
- get propagationStopped() {
48
- return this._propagationStopped;
49
- }
50
- }
51
- class InteractionManager {
52
- domElement;
53
- scene;
54
- camera;
55
- raycaster = new webgpu.Raycaster();
56
- pointer = new webgpu.Vector2();
57
- hoveredObject = null;
58
- pointerDownTime = 0;
59
- pointerDownPos = new webgpu.Vector2();
60
- clickTimer = null;
61
- longPressThreshold = 500;
62
- moveThreshold = 0.01;
63
- /**
64
- * The objects to check for intersections. default to all children of the scene (including nested).
65
- */
66
- targetObjects;
67
- /**
68
- * Whether to enable pointer move events (pointermove, pointerenter, pointerleave).
69
- * Disabled by default for performance optimization.
70
- */
71
- pointerMoveEventsEnabled = false;
72
- constructor(domElement, scene, camera) {
73
- this.domElement = domElement;
74
- this.scene = scene;
75
- this.camera = camera;
76
- this.raycaster.params.Points.threshold = 0.1;
77
- this.raycaster.params.Line.threshold = 0.1;
78
- this.targetObjects = this.scene.children;
79
- this._bindEvents();
80
- }
81
- /**
82
- * Updates the camera reference (useful when switching cameras).
83
- */
84
- setCamera(camera) {
85
- this.camera = camera;
86
- }
87
- _bindEvents() {
88
- this.domElement.addEventListener("click", this._onClick);
89
- this.domElement.addEventListener("dblclick", this._onDblClick);
90
- this.domElement.addEventListener("contextmenu", this._onContextMenu);
91
- this.domElement.addEventListener("pointerdown", this._onPointerDown);
92
- this.domElement.addEventListener("pointerup", this._onPointerUp);
93
- this.domElement.addEventListener("pointermove", this._onPointerMove);
94
- }
95
- _updatePointer(event) {
96
- const rect = this.domElement.getBoundingClientRect();
97
- this.pointer.x = (event.clientX - rect.left) / rect.width * 2 - 1;
98
- this.pointer.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
99
- }
100
- _getIntersects() {
101
- this.raycaster.setFromCamera(this.pointer, this.camera);
102
- return this.raycaster.intersectObjects(this.targetObjects, true);
103
- }
104
- /**
105
- * Dispatches an event to the target object and bubbles up the parent chain.
106
- */
107
- _dispatchToTarget(type, target, intersect, originalEvent) {
108
- const event3d = new InteractionEvent({
109
- type,
110
- target,
111
- intersect,
112
- originalEvent
113
- });
114
- let current = target;
115
- while (current && !event3d.propagationStopped) {
116
- event3d.currentTarget = current;
117
- current.dispatchEvent({ type, event: event3d });
118
- current = current.parent;
119
- }
120
- }
121
- /**
122
- * Handles a DOM event by raycasting and dispatching to the first intersected object.
123
- */
124
- _handleEvent(type, originalEvent) {
125
- this._updatePointer(originalEvent);
126
- const intersects = this._getIntersects();
127
- if (intersects.length === 0) return;
128
- const hit = intersects[0];
129
- this._dispatchToTarget(type, hit.object, hit, originalEvent);
130
- }
131
- _onClick = (e) => {
132
- const duration = Date.now() - this.pointerDownTime;
133
- const moveDistance = this.pointer.distanceTo(this.pointerDownPos);
134
- if (duration > this.longPressThreshold || moveDistance > this.moveThreshold) {
135
- return;
136
- }
137
- if (this.clickTimer) {
138
- clearTimeout(this.clickTimer);
139
- this.clickTimer = null;
140
- return;
141
- }
142
- this.clickTimer = setTimeout(() => {
143
- this._handleEvent("click", e);
144
- this.clickTimer = null;
145
- }, 200);
146
- };
147
- _onDblClick = (e) => {
148
- if (this.clickTimer) {
149
- clearTimeout(this.clickTimer);
150
- this.clickTimer = null;
151
- }
152
- this._handleEvent("dblclick", e);
153
- };
154
- _onContextMenu = (e) => {
155
- e.preventDefault();
156
- };
157
- _onPointerDown = (e) => {
158
- this.pointerDownTime = Date.now();
159
- this._updatePointer(e);
160
- this.pointerDownPos.copy(this.pointer);
161
- this._handleEvent("pointerdown", e);
162
- };
163
- _onPointerUp = (e) => {
164
- this._updatePointer(e);
165
- if (e.button === 2) {
166
- const duration = Date.now() - this.pointerDownTime;
167
- const moveDistance = this.pointer.distanceTo(this.pointerDownPos);
168
- if (duration <= this.longPressThreshold && moveDistance <= this.moveThreshold) {
169
- this._handleEvent("rightclick", e);
170
- }
171
- }
172
- this._handleEvent("pointerup", e);
173
- };
174
- _onPointerMove = (e) => {
175
- if (!this.pointerMoveEventsEnabled) return;
176
- this._updatePointer(e);
177
- const intersects = this._getIntersects();
178
- const hitObject = intersects.length > 0 ? intersects[0].object : null;
179
- const intersect = intersects.length > 0 ? intersects[0] : null;
180
- if (this.hoveredObject !== hitObject) {
181
- if (this.hoveredObject) {
182
- this._dispatchToTarget("pointerleave", this.hoveredObject, null, e);
183
- }
184
- this.hoveredObject = hitObject;
185
- if (hitObject && intersect) {
186
- this._dispatchToTarget("pointerenter", hitObject, intersect, e);
187
- }
188
- }
189
- if (hitObject && intersect) {
190
- this._dispatchToTarget("pointermove", hitObject, intersect, e);
191
- }
192
- };
193
- /**
194
- * Cleans up event listeners.
195
- */
196
- dispose() {
197
- this.domElement.removeEventListener("click", this._onClick);
198
- this.domElement.removeEventListener("dblclick", this._onDblClick);
199
- this.domElement.removeEventListener("contextmenu", this._onContextMenu);
200
- this.domElement.removeEventListener("pointerdown", this._onPointerDown);
201
- this.domElement.removeEventListener("pointerup", this._onPointerUp);
202
- this.domElement.removeEventListener("pointermove", this._onPointerMove);
203
- this.hoveredObject = null;
204
- }
205
- }
206
- class ObjectManager {
207
- idMap = /* @__PURE__ */ new Map();
208
- nameMap = /* @__PURE__ */ new Map();
209
- typeMap = /* @__PURE__ */ new Map();
210
- objectIds = /* @__PURE__ */ new Map();
211
- allObjects = /* @__PURE__ */ new Set();
212
- /**
213
- * Add an object with a custom id.
214
- * One object can have multiple ids.
215
- */
216
- add(id, object) {
217
- if (this.idMap.has(id)) {
218
- console.warn(`ObjectManager: Object with id ${id} already exists.`);
219
- return;
220
- }
221
- this.idMap.set(id, object);
222
- this.allObjects.add(object);
223
- if (!this.objectIds.has(object)) {
224
- this.objectIds.set(object, /* @__PURE__ */ new Set());
225
- }
226
- this.objectIds.get(object).add(id);
227
- if (object.name) {
228
- if (!this.nameMap.has(object.name)) {
229
- this.nameMap.set(object.name, /* @__PURE__ */ new Set());
230
- }
231
- this.nameMap.get(object.name).add(object);
232
- }
233
- if (object.type) {
234
- if (!this.typeMap.has(object.type)) {
235
- this.typeMap.set(object.type, /* @__PURE__ */ new Set());
236
- }
237
- this.typeMap.get(object.type).add(object);
238
- }
239
- }
240
- /**
241
- * Get an object by its custom id.
242
- */
243
- getById(id) {
244
- return this.idMap.get(id);
245
- }
246
- /**
247
- * Get all objects with a given name.
248
- */
249
- getByName(name) {
250
- return this.nameMap.get(name) || /* @__PURE__ */ new Set();
251
- }
252
- /**
253
- * Get all objects with a given type.
254
- */
255
- getByType(type) {
256
- return this.typeMap.get(type) || /* @__PURE__ */ new Set();
257
- }
258
- /**
259
- * Get all ids associated with an object.
260
- */
261
- getObjectIds(object) {
262
- return this.objectIds.get(object) || /* @__PURE__ */ new Set();
263
- }
264
- /**
265
- * Remove an object and all its associated ids.
266
- */
267
- remove(object) {
268
- const ids = this.objectIds.get(object);
269
- if (ids) {
270
- for (const id of ids) {
271
- this.idMap.delete(id);
272
- }
273
- this.objectIds.delete(object);
274
- }
275
- if (object.name && this.nameMap.has(object.name)) {
276
- const set = this.nameMap.get(object.name);
277
- set.delete(object);
278
- if (set.size === 0) {
279
- this.nameMap.delete(object.name);
280
- }
281
- }
282
- if (object.type && this.typeMap.has(object.type)) {
283
- const set = this.typeMap.get(object.type);
284
- set.delete(object);
285
- if (set.size === 0) {
286
- this.typeMap.delete(object.type);
287
- }
288
- }
289
- this.allObjects.delete(object);
290
- }
291
- /**
292
- * Remove an object by its id.
293
- */
294
- removeById(id) {
295
- const object = this.idMap.get(id);
296
- if (object) {
297
- this.remove(object);
298
- }
299
- }
300
- /**
301
- * Remove all objects with a given name.
302
- */
303
- removeByName(name) {
304
- const objects = this.getByName(name);
305
- for (const object of objects) {
306
- this.remove(object);
307
- }
308
- }
309
- /**
310
- * Remove all objects with a given type.
311
- */
312
- removeByType(type) {
313
- const objects = this.getByType(type);
314
- for (const object of objects) {
315
- this.remove(object);
316
- }
317
- }
318
- /**
319
- * Clear all cached objects.
320
- */
321
- clear() {
322
- this.idMap.clear();
323
- this.nameMap.clear();
324
- this.typeMap.clear();
325
- this.objectIds.clear();
326
- this.allObjects.clear();
327
- }
328
- /**
329
- * Get all cached objects as a Set.
330
- */
331
- getAll() {
332
- return this.allObjects;
333
- }
334
- /**
335
- * Get the number of unique cached objects.
336
- */
337
- get size() {
338
- return this.allObjects.size;
339
- }
340
- }
341
- class RenderPipeline extends webgpu.RenderPipeline {
342
- scene;
343
- camera;
344
- currentOutputNode;
345
- needsUpdateOutputNode;
346
- #overlayPasses;
347
- constructor(...args) {
348
- const [renderer, scene, camera] = args;
349
- super(renderer);
350
- this.scene = scene;
351
- this.camera = camera;
352
- this.currentOutputNode = tsl.pass(scene, camera);
353
- this.needsUpdateOutputNode = true;
354
- this.#overlayPasses = /* @__PURE__ */ new Set();
355
- }
356
- addOverlayPass(pass2) {
357
- this.#overlayPasses.add(pass2);
358
- this.needsUpdateOutputNode = true;
359
- }
360
- removeOverlayPass(pass2) {
361
- this.#overlayPasses.delete(pass2);
362
- this.needsUpdateOutputNode = true;
363
- }
364
- setCamera(camera) {
365
- this.camera = camera;
366
- this.needsUpdateOutputNode = true;
367
- }
368
- setCurrentOutputNode(node) {
369
- this.currentOutputNode.dispose();
370
- this.currentOutputNode = node;
371
- this.needsUpdateOutputNode = true;
372
- }
373
- resetCurrentOutputNode() {
374
- this.currentOutputNode.dispose();
375
- this.currentOutputNode = tsl.pass(this.scene, this.camera);
376
- this.needsUpdateOutputNode = true;
377
- }
378
- #updateOutputNode() {
379
- let currentNode = this.currentOutputNode;
380
- if (this.#overlayPasses.size > 0) {
381
- this.#overlayPasses.forEach((overlayPass) => {
382
- currentNode = tsl.blendColor(currentNode, overlayPass);
383
- });
384
- }
385
- this.outputNode = currentNode;
386
- this.needsUpdate = true;
387
- }
388
- render() {
389
- if (this.needsUpdateOutputNode) {
390
- this.#updateOutputNode();
391
- this.needsUpdateOutputNode = false;
392
- }
393
- super.render();
394
- }
395
- }
396
- const subsetOfTHREE = {
397
- Vector2: webgpu.Vector2,
398
- Vector3: webgpu.Vector3,
399
- Vector4: webgpu.Vector4,
400
- Quaternion: webgpu.Quaternion,
401
- Matrix4: webgpu.Matrix4,
402
- Spherical: webgpu.Spherical,
403
- Box3: webgpu.Box3,
404
- Sphere: webgpu.Sphere,
405
- Raycaster: webgpu.Raycaster
406
- };
407
- CameraControlsBase.install({ THREE: subsetOfTHREE });
408
- class CameraControls extends CameraControlsBase {
409
- constructor(...args) {
410
- super(...args);
411
- this.minDistance = 0.2;
412
- this.smoothTime = 0.2;
413
- this.dollySpeed = 0.2;
414
- }
415
- /**
416
- * Set absolute angle for azimuth to avoid spinning
417
- */
418
- absoluteRotations() {
419
- this.azimuthAngle = absoluteAngle(this.azimuthAngle, 0);
420
- }
421
- async flyToBox(box, options = {}) {
422
- if (box.isEmpty()) {
423
- console.warn("CameraControls.flyToBox: The provided Box3 is empty.");
424
- return false;
425
- }
426
- this.absoluteRotations();
427
- const { viewpoint = "frontTop", enableTransition = true, padding = 0.1, cover = false } = options;
428
- const promises = [];
429
- if (viewpoint !== "current") {
430
- const spherical = viewpointsSpherical[viewpoint.toUpperCase()] ?? viewpointsSpherical.FRONTTOP;
431
- const azimuthAngle = spherical.theta, polarAngle = spherical.phi;
432
- promises.push(
433
- this.fitToBox(box, enableTransition, {
434
- paddingLeft: padding,
435
- paddingRight: padding,
436
- paddingTop: padding,
437
- paddingBottom: padding,
438
- cover
439
- })
440
- );
441
- promises.push(this.rotateTo(azimuthAngle, polarAngle, enableTransition));
442
- } else {
443
- const sphere = new webgpu.Sphere();
444
- box.getBoundingSphere(sphere);
445
- sphere.radius += padding;
446
- promises.push(this.fitToSphere(sphere, enableTransition));
447
- }
448
- await Promise.all(promises);
449
- return true;
450
- }
451
- async flyToObject(object, options = {}) {
452
- const box = new webgpu.Box3().setFromObject(object);
453
- return this.flyToBox(box, options);
454
- }
455
- }
456
- const viewpointsSpherical = {
457
- LEFT: new webgpu.Spherical(0, Math.PI / 2, -Math.PI / 2),
458
- RIGHT: new webgpu.Spherical(0, Math.PI / 2, Math.PI / 2),
459
- FRONT: new webgpu.Spherical(0, Math.PI / 2, 0),
460
- BACK: new webgpu.Spherical(0, Math.PI / 2, Math.PI),
461
- TOP: new webgpu.Spherical(0, 0, 0),
462
- BOTTOM: new webgpu.Spherical(0, Math.PI, 0),
463
- FRONTTOP: new webgpu.Spherical(0, Math.PI / 4, 0),
464
- BACKTOP: new webgpu.Spherical(0, Math.PI / 4, Math.PI),
465
- LEFTTOP: new webgpu.Spherical(0, Math.PI / 4, -Math.PI / 2),
466
- RIGHTTOP: new webgpu.Spherical(0, Math.PI / 4, Math.PI / 2),
467
- LEFTFRONTTOP: new webgpu.Spherical(0, Math.PI / 4, -Math.PI / 4),
468
- RIGHTFRONTTOP: new webgpu.Spherical(0, Math.PI / 4, Math.PI / 4),
469
- LEFTBACKTOP: new webgpu.Spherical(0, Math.PI / 4, -Math.PI / 4 * 3),
470
- RIGHTBACKTOP: new webgpu.Spherical(0, Math.PI / 4, Math.PI / 4 * 3)
471
- };
472
- function absoluteAngle(targetAngle, sourceAngle) {
473
- const angle = targetAngle - sourceAngle;
474
- return webgpu.MathUtils.euclideanModulo(angle + Math.PI, Math.PI * 2) - Math.PI;
475
- }
476
- class RoomEnvironment {
477
- environment = new RoomEnvironment_js.RoomEnvironment();
478
- renderer;
479
- pmremGenerator;
480
- envMap = null;
481
- constructor(renderer) {
482
- this.renderer = renderer;
483
- this.pmremGenerator = new webgpu.PMREMGenerator(renderer);
484
- }
485
- update() {
486
- if (!this.envMap) {
487
- this.envMap = this.pmremGenerator.fromScene(this.environment).texture;
488
- }
489
- }
490
- dispose() {
491
- this.pmremGenerator.dispose();
492
- this.envMap?.dispose();
493
- }
494
- }
495
- const dim = 128;
496
- class ViewerHelper extends ViewHelper_js.ViewHelper {
497
- viewer;
498
- overlayPass;
499
- constructor(viewer) {
500
- super(viewer.camera, viewer.el);
501
- this.viewer = viewer;
502
- const orthoCamera = new webgpu.OrthographicCamera(-2, 2, 2, -2, 0, 4);
503
- orthoCamera.position.set(0, 0, 2);
504
- this.overlayPass = tsl.pass(this, orthoCamera);
505
- this.setLabels("x", "y", "z");
506
- }
507
- _update = () => {
508
- this.quaternion.copy(this.viewer.camera.quaternion).invert();
509
- const location = this.location;
510
- let x, y;
511
- if (location.left !== null) {
512
- x = location.left;
513
- } else {
514
- x = this.viewer.el.offsetWidth - dim - location.right;
515
- }
516
- if (location.top !== null) {
517
- y = location.top;
518
- } else {
519
- y = this.viewer.el.offsetHeight - dim - location.bottom;
520
- }
521
- this.overlayPass.setViewport(x, y, dim, dim);
522
- };
523
- enable() {
524
- this.viewer.renderPipeline.addOverlayPass(this.overlayPass);
525
- this.viewer.addEventListener("beforeRender", this._update);
526
- this.viewer.render();
527
- return this;
528
- }
529
- disable() {
530
- this.viewer.renderPipeline.removeOverlayPass(this.overlayPass);
531
- this.viewer.removeEventListener("beforeRender", this._update);
532
- this.viewer.render();
533
- return this;
534
- }
535
- }
536
- class Info {
537
- el;
538
- renderer;
539
- container;
540
- drawCallsText;
541
- frameCallsText;
542
- trianglesText;
543
- pointsText;
544
- linesText;
545
- timestampText;
546
- _enabled = false;
547
- constructor(el, renderer) {
548
- this.el = el;
549
- this.renderer = renderer;
550
- const container = document.createElement("div");
551
- container.style.position = "absolute";
552
- container.style.left = "12px";
553
- container.style.bottom = "12px";
554
- container.style.fontSize = "12px";
555
- container.style.color = "#fff";
556
- container.style.pointerEvents = "none";
557
- this.container = container;
558
- function createTextEl(text, isMarginLeft = true) {
559
- const el2 = document.createElement("span");
560
- if (isMarginLeft) el2.style.marginLeft = "6px";
561
- el2.innerText = text;
562
- return el2;
563
- }
564
- function createBr() {
565
- return document.createElement("br");
566
- }
567
- this.drawCallsText = createTextEl("0");
568
- this.frameCallsText = createTextEl("0");
569
- this.trianglesText = createTextEl("0");
570
- this.linesText = createTextEl("0");
571
- this.pointsText = createTextEl("0");
572
- this.timestampText = createTextEl("0");
573
- this.container.appendChild(createTextEl("draw calls", false));
574
- this.container.appendChild(this.drawCallsText);
575
- this.container.appendChild(createBr());
576
- this.container.appendChild(createTextEl("frame calls", false));
577
- this.container.appendChild(this.frameCallsText);
578
- this.container.appendChild(createBr());
579
- this.container.appendChild(createTextEl("triangles", false));
580
- this.container.appendChild(this.trianglesText);
581
- this.container.appendChild(createBr());
582
- this.container.appendChild(createTextEl("points", false));
583
- this.container.appendChild(this.pointsText);
584
- this.container.appendChild(createBr());
585
- this.container.appendChild(createTextEl("lines", false));
586
- this.container.appendChild(this.linesText);
587
- this.container.appendChild(createBr());
588
- this.container.appendChild(createTextEl("timestamp", false));
589
- this.container.appendChild(this.timestampText);
590
- this.container.appendChild(createBr());
591
- }
592
- update() {
593
- if (this._enabled) {
594
- const { render } = this.renderer.info;
595
- this.drawCallsText.innerText = render.drawCalls.toString();
596
- this.frameCallsText.innerText = render.frameCalls.toString();
597
- this.trianglesText.innerText = render.triangles.toString();
598
- this.pointsText.innerText = render.points.toString();
599
- this.linesText.innerText = render.lines.toString();
600
- this.renderer.resolveTimestampsAsync(webgpu.TimestampQuery.RENDER).then((timestamps) => {
601
- this.timestampText.innerText = timestamps?.toFixed(2) ?? "0";
602
- });
603
- }
604
- }
605
- enable() {
606
- this._enabled = true;
607
- this.el.appendChild(this.container);
608
- }
609
- disable() {
610
- this._enabled = false;
611
- this.container.remove();
612
- }
613
- dispose() {
614
- this.disable();
615
- }
616
- }
617
- webgpu.Cache.enabled = true;
618
- class Viewer extends webgpu.EventDispatcher {
619
- el;
620
- renderer;
621
- scene;
622
- camera;
623
- info;
624
- controls;
625
- renderPipeline;
626
- timer;
627
- roomEnvironment;
628
- interactionManager;
629
- objectManager;
630
- viewerHelper;
631
- frameCount = 1;
632
- frameloop = "demand";
633
- constructor({ el, rendererOptions }) {
634
- super();
635
- this.el = el;
636
- this.renderer = this._initRenderer(rendererOptions);
637
- this.scene = this.createScene();
638
- this.camera = this.createPerspectiveCamera();
639
- this.info = new Info(this.el, this.renderer);
640
- this.controls = new CameraControls(this.camera, this.renderer.domElement);
641
- this.renderPipeline = new RenderPipeline(this.renderer, this.scene, this.camera);
642
- this.timer = new webgpu.Timer();
643
- this.roomEnvironment = new RoomEnvironment(this.renderer);
644
- this.interactionManager = new InteractionManager(this.renderer.domElement, this.scene, this.camera);
645
- this.objectManager = new ObjectManager();
646
- this.viewerHelper = new ViewerHelper(this);
647
- window.addEventListener("resize", this.onWindowResize);
648
- }
649
- onWindowResize = () => {
650
- const width = this.el.clientWidth;
651
- const height = this.el.clientHeight;
652
- if (this.camera instanceof webgpu.PerspectiveCamera) {
653
- this.camera.aspect = width / height;
654
- this.camera.updateProjectionMatrix();
655
- } else if (this.camera instanceof webgpu.OrthographicCamera) {
656
- this.camera.left = -width / 2;
657
- this.camera.right = width / 2;
658
- this.camera.top = height / 2;
659
- this.camera.bottom = -height / 2;
660
- this.camera.updateProjectionMatrix();
661
- }
662
- this.renderer.setSize(width, height);
663
- this.render();
664
- };
665
- async init() {
666
- await this.renderer.init();
667
- this.roomEnvironment.update();
668
- this.scene.environment = this.roomEnvironment.envMap;
669
- }
670
- setCamera(camera) {
671
- this.camera = camera;
672
- this.controls.camera = camera;
673
- this.interactionManager.setCamera(camera);
674
- this.renderPipeline.setCamera(camera);
675
- this.onWindowResize();
676
- this.dispatchEvent({ type: "cameraChange", camera });
677
- }
678
- setCameraByType(type) {
679
- if (type === "perspective" && !(this.camera instanceof webgpu.PerspectiveCamera)) {
680
- this.setCamera(this.createPerspectiveCamera());
681
- } else if (type === "orthographic" && !(this.camera instanceof webgpu.OrthographicCamera)) {
682
- this.setCamera(this.createOrthographicCamera());
683
- }
684
- }
685
- render(frame = 1) {
686
- this.frameCount += frame;
687
- return new Promise((resolve) => {
688
- const fn = () => {
689
- this.removeEventListener("afterRender", fn);
690
- resolve();
691
- };
692
- this.addEventListener("afterRender", fn);
693
- });
694
- }
695
- animate = (time) => {
696
- this.timer.update(time);
697
- this.dispatchEvent({ type: "beforeControlsUpdate", time });
698
- let needsRender = this.controls.update(this.timer.getDelta());
699
- this.dispatchEvent({ type: "afterControlsUpdate", time });
700
- if (this.frameCount > 0) {
701
- this.frameCount--;
702
- needsRender = true;
703
- }
704
- if (this.frameloop === "always") {
705
- needsRender = true;
706
- }
707
- if (needsRender) {
708
- this.dispatchEvent({ type: "beforeRender", time });
709
- this.renderer.info.reset();
710
- this.renderPipeline.render();
711
- this.info.update();
712
- this.dispatchEvent({ type: "afterRender", time });
713
- }
714
- };
715
- _initRenderer(rendererOptions) {
716
- const renderer = new webgpu.WebGPURenderer({
717
- logarithmicDepthBuffer: true,
718
- antialias: false,
719
- depth: false,
720
- trackTimestamp: true,
721
- ...rendererOptions
722
- });
723
- renderer.setSize(this.el.clientWidth, this.el.clientHeight);
724
- renderer.shadowMap.enabled = true;
725
- renderer.shadowMap.type = webgpu.PCFShadowMap;
726
- renderer.toneMapping = webgpu.AgXToneMapping;
727
- renderer.toneMappingExposure = 1;
728
- renderer.info.autoReset = false;
729
- renderer.setPixelRatio(window.devicePixelRatio);
730
- renderer.setAnimationLoop(this.animate);
731
- this.el.appendChild(renderer.domElement);
732
- return renderer;
733
- }
734
- createScene() {
735
- const scene = new webgpu.Scene();
736
- scene.background = new webgpu.Color(0);
737
- return scene;
738
- }
739
- createPerspectiveCamera() {
740
- const camera = new webgpu.PerspectiveCamera(50, this.el.clientWidth / this.el.clientHeight, 0.1, 1e5);
741
- camera.position.setScalar(5);
742
- return camera;
743
- }
744
- createOrthographicCamera() {
745
- const camera = new webgpu.OrthographicCamera(
746
- -this.el.clientWidth / 2,
747
- this.el.clientWidth / 2,
748
- this.el.clientHeight / 2,
749
- -this.el.clientHeight / 2,
750
- 0.1,
751
- 1e5
752
- );
753
- camera.position.setScalar(5);
754
- return camera;
755
- }
756
- dispose() {
757
- this.el.removeChild(this.renderer.domElement);
758
- window.removeEventListener("resize", this.onWindowResize);
759
- this.info.dispose();
760
- this.interactionManager.dispose();
761
- this.roomEnvironment.dispose();
762
- this.renderPipeline.dispose();
763
- this.renderer.dispose();
764
- }
765
- }
766
- class SBMXLoader extends GLTFLoader_js.GLTFLoader {
767
- constructor(manager) {
768
- super(manager);
769
- }
770
- parse(data, path, onLoad, onError) {
771
- const formatName = getAsciiString(data.slice(0, 8));
772
- switch (formatName) {
773
- case "SBMG----": {
774
- const swappedBuffer = swapBytes(data.slice(8));
775
- return super.parse(swappedBuffer, path, onLoad, onError);
776
- }
777
- default: {
778
- return super.parse(data, path, onLoad, onError);
779
- }
780
- }
781
- }
782
- }
783
- function getAsciiString(buf) {
784
- const decoder = new TextDecoder();
785
- return decoder.decode(new Uint8Array(buf));
786
- }
787
- function swapBytes(buffer) {
788
- const view = new DataView(buffer);
789
- for (let i = 0; i < view.byteLength; i++) {
790
- const byte = view.getUint8(i);
791
- const swappedByte = (byte >> 4 & 15) + (byte << 4 & 240);
792
- view.setUint8(i, swappedByte);
793
- }
794
- return view.buffer;
795
- }
796
- const BYTE_LENGTH_MAGIC = 8;
797
- const BYTE_LENGTH_HEAD = 130;
798
- const BYTE_LENGTH_ATTACH = 66;
799
- const MAGIC_SBK = "SBK-----";
800
- const MAGIC_SBM = "SBM-----";
801
- const textDecoder = new TextDecoder();
802
- const textEncoder = new TextEncoder();
803
- function decodeSbk(buffer) {
804
- let read = BYTE_LENGTH_MAGIC;
805
- const magicBytes = new Uint8Array(buffer, 0, read);
806
- const magic = textDecoder.decode(magicBytes);
807
- if (magic !== MAGIC_SBK) {
808
- return buffer;
809
- }
810
- read += BYTE_LENGTH_HEAD;
811
- const headBytes = new Uint8Array(buffer, 0, read);
812
- const version = headBytes[40];
813
- if (version === 1) {
814
- const magicBuf = textEncoder.encode(MAGIC_SBM);
815
- const versionBuf = new Uint8Array([headBytes[41]]);
816
- const sbmKey = getSbmKey(headBytes);
817
- const encodeKey = getLeftKey(sbmKey);
818
- let j = BYTE_LENGTH_ATTACH % encodeKey.length;
819
- const offset = read + BYTE_LENGTH_ATTACH;
820
- const bodyBytes = new Uint8Array(buffer, offset);
821
- const bodyBuf = new Uint8Array(bodyBytes.length);
822
- for (let i = 0; i < bodyBytes.length; i++) {
823
- bodyBuf[i] = bodyBytes[i] ^ encodeKey[j];
824
- j = (j + 1) % encodeKey.length;
825
- }
826
- const buf = new Uint8Array(magicBuf.length + versionBuf.length + bodyBuf.length);
827
- buf.set(magicBuf);
828
- buf.set(versionBuf, magicBuf.length);
829
- buf.set(bodyBuf, magicBuf.length + versionBuf.length);
830
- return buf.buffer;
831
- }
832
- }
833
- function getSbmKey(headBuffer) {
834
- const bytes = new Uint8Array(128);
835
- bytes.set(headBuffer.slice(42, 42 + 32), 0);
836
- bytes.set(headBuffer.slice(74, 74 + 64), 32);
837
- bytes.set(headBuffer.slice(8, 8 + 32), 96);
838
- return bytes;
839
- }
840
- function getLeftKey(sbmKey) {
841
- const bytes = new Uint8Array(64);
842
- bytes.set(sbmKey.slice(0, 8), 0);
843
- bytes.set(sbmKey.slice(24, 24 + 8), 8);
844
- bytes.set(sbmKey.slice(40, 40 + 16), 16);
845
- bytes.set(sbmKey.slice(64, 64 + 24), 32);
846
- bytes.set(sbmKey.slice(96, 96 + 8), 56);
847
- return bytes;
848
- }
849
- const getTextureName = (dataView, texnamelen, offset) => {
850
- const temp = dataView.buffer.slice(offset, offset + texnamelen);
851
- let textureName = textDecoder.decode(temp);
852
- textureName = textureName.replace("\\", "/");
853
- if (!textureName.startsWith("Maps/")) {
854
- textureName = `Maps/${textureName}`;
855
- }
856
- return textureName;
857
- };
858
- const generateSbmMaterial = (materialId, arr, png) => {
859
- const [d0, d1, d2, d3, side] = arr;
860
- const trans = png || d3 < 1;
861
- const material = new webgpu.MeshStandardNodeMaterial({
862
- name: materialId,
863
- color: new webgpu.Color(d0, d1, d2),
864
- opacity: d3,
865
- transparent: trans,
866
- alphaTest: 0.01,
867
- side
868
- });
869
- return material;
870
- };
871
- const isPNG = (textureUrl) => {
872
- return textureUrl?.toLowerCase().endsWith(".png") ?? false;
873
- };
874
- class SBMParser {
875
- data;
876
- options;
877
- textureLoader;
878
- littleEndian = true;
879
- materials = /* @__PURE__ */ new Map();
880
- constructor(data, options) {
881
- this.data = data;
882
- this.options = options;
883
- this.textureLoader = new webgpu.TextureLoader(options.manager);
884
- this.textureLoader.setCrossOrigin(options.crossOrigin);
885
- this.textureLoader.setRequestHeader(options.requestHeader);
886
- }
887
- parse(onLoad, onError) {
888
- let buffer = this.data;
889
- const decodeBuffer = decodeSbk(this.data);
890
- if (decodeBuffer) {
891
- buffer = decodeBuffer;
892
- }
893
- const dataView = new DataView(buffer);
894
- let offset = 8;
895
- const version = dataView.getUint8(offset);
896
- offset += 1;
897
- if (version === 1) {
898
- this._parseV2(dataView, offset, onLoad);
899
- } else if (version === 2) {
900
- this._parseV2(dataView, offset, onLoad);
901
- } else if (version === 3) {
902
- this._parseV3(dataView, offset, onLoad);
903
- } else {
904
- onError?.(new Error(`SBMLoader: Unsupported SBM version: ${version}`));
905
- }
906
- }
907
- _parseV2(dataView, offset, onLoad) {
908
- const sbm = new webgpu.Group();
909
- const materialCount = dataView.getUint16(offset, this.littleEndian);
910
- offset += 2;
911
- const meshCount = dataView.getUint16(offset, this.littleEndian);
912
- offset += 2;
913
- for (let i = 0; i < materialCount; ++i) {
914
- const materialId = dataView.getUint16(offset, this.littleEndian).toString();
915
- offset += 2;
916
- offset += 4;
917
- offset += 4;
918
- offset += 4;
919
- offset += 4;
920
- const d0 = dataView.getFloat32(offset, this.littleEndian);
921
- offset += 4;
922
- const d1 = dataView.getFloat32(offset, this.littleEndian);
923
- offset += 4;
924
- const d2 = dataView.getFloat32(offset, this.littleEndian);
925
- offset += 4;
926
- const d3 = dataView.getFloat32(offset, this.littleEndian);
927
- offset += 4;
928
- offset += 4;
929
- offset += 4;
930
- offset += 4;
931
- offset += 4;
932
- let side = dataView.getUint8(offset);
933
- offset += 1;
934
- if (side === 0) side = webgpu.FrontSide;
935
- else if (side === 1) side = webgpu.BackSide;
936
- else if (side === 2) side = webgpu.DoubleSide;
937
- const textureNameLength = dataView.getUint16(offset, this.littleEndian);
938
- offset += 2;
939
- const textureName = textureNameLength > 0 ? getTextureName(dataView, textureNameLength, offset) : "";
940
- offset += textureNameLength;
941
- if (!this.materials.has(materialId)) {
942
- const materialInfo = [d0, d1, d2, d3, side];
943
- const material = generateSbmMaterial(materialId, materialInfo, isPNG(textureName));
944
- this.materials.set(materialId, material);
945
- if (textureName && this.options.path) {
946
- this.textureLoader.load(webgpu.LoaderUtils.resolveURL(textureName, this.options.path), (texture) => {
947
- texture.colorSpace = webgpu.SRGBColorSpace;
948
- texture.wrapS = webgpu.RepeatWrapping;
949
- texture.wrapT = webgpu.RepeatWrapping;
950
- texture.flipY = false;
951
- texture.anisotropy = 16;
952
- material.map = texture;
953
- });
954
- }
955
- }
956
- }
957
- for (let i = 0; i < meshCount; ++i) {
958
- const meshId = dataView.getUint16(offset, this.littleEndian).toString();
959
- offset += 2;
960
- const materialId = dataView.getUint16(offset, this.littleEndian).toString();
961
- offset += 2;
962
- const vertices = [];
963
- const texcoords = [];
964
- const faces = [];
965
- const faceVertexUvs = [];
966
- const verticesCount = dataView.getUint16(offset, this.littleEndian);
967
- offset += 2;
968
- if (verticesCount > 0) {
969
- for (let j = 0; j < verticesCount; j++) {
970
- const vector3 = new webgpu.Vector3();
971
- vector3.setX(dataView.getFloat32(offset, this.littleEndian));
972
- offset += 4;
973
- vector3.setY(dataView.getFloat32(offset, this.littleEndian));
974
- offset += 4;
975
- vector3.setZ(dataView.getFloat32(offset, this.littleEndian));
976
- offset += 4;
977
- vertices.push(vector3);
978
- }
979
- }
980
- const normalsCount = dataView.getUint16(offset, this.littleEndian);
981
- offset += 2;
982
- if (normalsCount > 0) {
983
- for (let j = 0; j < normalsCount; j++) {
984
- offset += 4;
985
- offset += 4;
986
- offset += 4;
987
- }
988
- }
989
- const texcoordCount = dataView.getUint16(offset, this.littleEndian);
990
- offset += 2;
991
- if (texcoordCount > 0) {
992
- for (let j = 0; j < texcoordCount; j++) {
993
- const texcoord = new webgpu.Vector2();
994
- texcoord.setX(dataView.getFloat32(offset, this.littleEndian));
995
- offset += 4;
996
- texcoord.setY(dataView.getFloat32(offset, this.littleEndian));
997
- offset += 4;
998
- texcoords.push(texcoord);
999
- }
1000
- }
1001
- const idxCount = dataView.getUint16(offset, this.littleEndian);
1002
- offset += 2;
1003
- if (idxCount > 0) {
1004
- for (let j = 0; j < idxCount; j++) {
1005
- const a = dataView.getUint16(offset, this.littleEndian);
1006
- offset += 2;
1007
- const b = dataView.getUint16(offset, this.littleEndian);
1008
- offset += 2;
1009
- const c = dataView.getUint16(offset, this.littleEndian);
1010
- offset += 2;
1011
- const face = [a, b, c];
1012
- faces.push(face);
1013
- if (texcoords.length > 0) {
1014
- faceVertexUvs.push([texcoords[face[0]], texcoords[face[1]], texcoords[face[2]]]);
1015
- }
1016
- }
1017
- }
1018
- const positions = [], uvs = [];
1019
- for (let i2 = 0; i2 < faces.length; i2++) {
1020
- const face = faces[i2];
1021
- const vertex = vertices[face[0]], vertex2 = vertices[face[1]], vertex3 = vertices[face[2]];
1022
- positions.push(...vertex.toArray(), ...vertex2.toArray(), ...vertex3.toArray());
1023
- let uv = new webgpu.Vector2(), uv2 = new webgpu.Vector2(), uv3 = new webgpu.Vector2();
1024
- const vertexUvs = faceVertexUvs[i2];
1025
- if (vertexUvs !== void 0) {
1026
- uv = vertexUvs[0];
1027
- uv2 = vertexUvs[1];
1028
- uv3 = vertexUvs[2];
1029
- }
1030
- uvs.push(...uv.toArray(), ...uv2.toArray(), ...uv3.toArray());
1031
- }
1032
- const positionArray = new Float32Array(positions), uvArray = new Float32Array(uvs);
1033
- const bufferGeometry = new webgpu.BufferGeometry();
1034
- if (positionArray.length > 0) {
1035
- bufferGeometry.setAttribute("position", new webgpu.BufferAttribute(positionArray, 3));
1036
- }
1037
- if (uvArray.length > 0) {
1038
- bufferGeometry.setAttribute("uv", new webgpu.BufferAttribute(uvArray, 2));
1039
- }
1040
- bufferGeometry.computeVertexNormals();
1041
- if (this.materials.has(materialId)) {
1042
- const sbmChild = new webgpu.Mesh(bufferGeometry, this.materials.get(materialId));
1043
- sbmChild.name = meshId;
1044
- sbmChild.castShadow = true;
1045
- sbmChild.receiveShadow = true;
1046
- sbm.add(sbmChild);
1047
- }
1048
- }
1049
- onLoad(sbm);
1050
- }
1051
- _parseV3(_dataView, _offset, onLoad) {
1052
- const sbm = new webgpu.Group();
1053
- console.warn("SBMLoader: SBM version 3 is not supported yet.");
1054
- onLoad(sbm);
1055
- }
1056
- }
1057
- class SBMLoader extends webgpu.Loader {
1058
- load(url, onLoad, onProgress, onError) {
1059
- let resourcePath;
1060
- if (this.resourcePath !== "") {
1061
- resourcePath = this.resourcePath;
1062
- } else if (this.path !== "") {
1063
- const relativeUrl = webgpu.LoaderUtils.extractUrlBase(url);
1064
- resourcePath = webgpu.LoaderUtils.resolveURL(relativeUrl, this.path);
1065
- } else {
1066
- resourcePath = webgpu.LoaderUtils.extractUrlBase(url);
1067
- }
1068
- this.manager.itemStart(url);
1069
- const _onError = (e) => {
1070
- if (onError) {
1071
- onError(e);
1072
- } else {
1073
- console.error(e);
1074
- }
1075
- this.manager.itemError(url);
1076
- this.manager.itemEnd(url);
1077
- };
1078
- const loader = new webgpu.FileLoader(this.manager);
1079
- loader.setPath(this.path);
1080
- loader.setResponseType("arraybuffer");
1081
- loader.setRequestHeader(this.requestHeader);
1082
- loader.setWithCredentials(this.withCredentials);
1083
- loader.load(
1084
- url,
1085
- (data) => {
1086
- try {
1087
- this.parse(
1088
- data,
1089
- resourcePath,
1090
- (sbm) => {
1091
- onLoad(sbm);
1092
- this.manager.itemEnd(url);
1093
- },
1094
- _onError
1095
- );
1096
- } catch (e) {
1097
- _onError(e);
1098
- }
1099
- },
1100
- onProgress,
1101
- _onError
1102
- );
1103
- }
1104
- parse(data, path, onLoad, onError) {
1105
- const formatName = new TextDecoder().decode(data.slice(0, 8));
1106
- if (formatName !== "SBK-----" && formatName !== "SBM-----") {
1107
- onError?.(new Error(`SBMLoader: Invalid SBM format: ${formatName}`));
1108
- return;
1109
- }
1110
- const parser = new SBMParser(data, {
1111
- path,
1112
- crossOrigin: this.crossOrigin,
1113
- requestHeader: this.requestHeader,
1114
- manager: this.manager
1115
- });
1116
- parser.parse(onLoad, onError);
1117
- }
1118
- parseAsync(data, path) {
1119
- return new Promise((resolve, reject) => {
1120
- this.parse(
1121
- data,
1122
- path,
1123
- (sbm) => {
1124
- resolve(sbm);
1125
- },
1126
- (err) => {
1127
- reject(err);
1128
- }
1129
- );
1130
- });
1131
- }
1132
- }
1133
- class ModelLoaderManager {
1134
- static CACHE_NAME = "u-space-model-loader-cache";
1135
- static fileLoader = new webgpu.FileLoader().setResponseType("arraybuffer");
1136
- static dracoLoader = new DRACOLoader_js.DRACOLoader().setDecoderPath(
1137
- `https://cdn.jsdelivr.net/npm/three@0.${webgpu.REVISION}.0/examples/jsm/libs/draco/`
1138
- );
1139
- static ktx2Loader = new KTX2Loader_js.KTX2Loader().setTranscoderPath(
1140
- `https://cdn.jsdelivr.net/npm/three@0.${webgpu.REVISION}.0/examples/jsm/libs/basis/`
1141
- );
1142
- static gltfLoader = new GLTFLoader_js.GLTFLoader().setDRACOLoader(ModelLoaderManager.dracoLoader).setKTX2Loader(ModelLoaderManager.ktx2Loader).setMeshoptDecoder(meshopt_decoder_module_js.MeshoptDecoder);
1143
- static sbmxLoader = new SBMXLoader().setDRACOLoader(ModelLoaderManager.dracoLoader).setKTX2Loader(ModelLoaderManager.ktx2Loader).setMeshoptDecoder(meshopt_decoder_module_js.MeshoptDecoder);
1144
- static sbmLoader = new SBMLoader();
1145
- static fbxLoader = new FBXLoader_js.FBXLoader();
1146
- static objLoader = new OBJLoader_js.OBJLoader();
1147
- static stlLoader = new STLLoader_js.STLLoader();
1148
- static setLoadingManager(loadingManager) {
1149
- this.fileLoader.manager = loadingManager;
1150
- this.dracoLoader.manager = loadingManager;
1151
- this.ktx2Loader.manager = loadingManager;
1152
- this.gltfLoader.manager = loadingManager;
1153
- this.sbmxLoader.manager = loadingManager;
1154
- this.sbmLoader.manager = loadingManager;
1155
- this.fbxLoader.manager = loadingManager;
1156
- this.objLoader.manager = loadingManager;
1157
- this.stlLoader.manager = loadingManager;
1158
- }
1159
- /**
1160
- * Set the renderer to enable KTX2 support and other renderer-dependent features.
1161
- */
1162
- static async setRenderer(renderer) {
1163
- await renderer.init();
1164
- this.ktx2Loader.detectSupport(renderer);
1165
- }
1166
- /**
1167
- * Configure Draco decoder path.
1168
- */
1169
- static setDracoPath(path) {
1170
- this.dracoLoader.setDecoderPath(path);
1171
- }
1172
- /**
1173
- * Configure KTX2 transcoder path.
1174
- */
1175
- static setKTX2Path(path) {
1176
- this.ktx2Loader.setTranscoderPath(path);
1177
- }
1178
- static async loadAsync(url, parameters = { persistent: true }) {
1179
- const extension = url.split(".").pop()?.split("?")[0].toLowerCase();
1180
- let buffer;
1181
- if (parameters.persistent && typeof caches !== "undefined") {
1182
- buffer = await this.getPersistentData(url);
1183
- } else {
1184
- buffer = await this.fileLoader.loadAsync(url);
1185
- }
1186
- switch (extension) {
1187
- case "gltf":
1188
- case "glb":
1189
- const gltf = await this.gltfLoader.parseAsync(buffer, webgpu.LoaderUtils.extractUrlBase(url));
1190
- return gltf.scene;
1191
- case "sbmx":
1192
- const sbmx = await this.sbmxLoader.parseAsync(buffer, webgpu.LoaderUtils.extractUrlBase(url));
1193
- return sbmx.scene;
1194
- case "sbm":
1195
- const sbm = await this.sbmLoader.parseAsync(buffer, webgpu.LoaderUtils.extractUrlBase(url));
1196
- return sbm;
1197
- case "fbx":
1198
- const fbx = this.fbxLoader.parse(buffer, webgpu.LoaderUtils.extractUrlBase(url));
1199
- return fbx;
1200
- case "obj":
1201
- const text = new TextDecoder().decode(buffer);
1202
- const obj = this.objLoader.parse(text);
1203
- return obj;
1204
- case "stl":
1205
- const geometry = this.stlLoader.parse(buffer);
1206
- const mesh = new webgpu.Mesh(geometry, new webgpu.MeshStandardNodeMaterial());
1207
- return mesh;
1208
- default:
1209
- throw new Error(`Unsupported model format: ${extension}`);
1210
- }
1211
- }
1212
- static async getPersistentData(url) {
1213
- try {
1214
- const cache = await caches.open(this.CACHE_NAME);
1215
- const cachedResponse = await cache.match(url);
1216
- if (cachedResponse) {
1217
- return await cachedResponse.arrayBuffer();
1218
- }
1219
- const buffer = await this.fileLoader.loadAsync(url);
1220
- const response = new Response(buffer);
1221
- await cache.put(url, response);
1222
- return buffer;
1223
- } catch (error) {
1224
- console.warn(`[LoaderManager] Failed to use Cache API for ${url}:`, error);
1225
- return await this.fileLoader.loadAsync(url);
1226
- }
1227
- }
1228
- }
1229
- class TextureLoaderManager {
1230
- static textureLoader = new webgpu.TextureLoader();
1231
- static hdrLoader = new HDRLoader_js.HDRLoader();
1232
- static cubeTextureLoader = new webgpu.CubeTextureLoader();
1233
- static setLoadingManager(loadingManager) {
1234
- this.textureLoader.manager = loadingManager;
1235
- this.hdrLoader.manager = loadingManager;
1236
- this.cubeTextureLoader.manager = loadingManager;
1237
- }
1238
- static async loadAsyncTexture(url) {
1239
- const texture = await this.textureLoader.loadAsync(url);
1240
- return texture;
1241
- }
1242
- static async loadAsyncHDR(url) {
1243
- const dataTexture = await this.hdrLoader.loadAsync(url);
1244
- dataTexture.mapping = webgpu.EquirectangularReflectionMapping;
1245
- return dataTexture;
1246
- }
1247
- static async loadAsyncCubeTexture(path, urls) {
1248
- this.cubeTextureLoader.setPath(path);
1249
- const cubeTexture = await this.cubeTextureLoader.loadAsync(urls);
1250
- return cubeTexture;
1251
- }
1252
- }
1253
- class BaseMesh extends webgpu.Mesh {
1254
- isBaseMesh = true;
1255
- type = "BaseMesh";
1256
- ignoreInvisibleWhenRaycast = true;
1257
- constructor(...args) {
1258
- super(...args);
1259
- }
1260
- raycast(raycaster, intersects) {
1261
- if (this.visible === false && this.ignoreInvisibleWhenRaycast === true) {
1262
- return false;
1263
- }
1264
- return super.raycast(raycaster, intersects);
1265
- }
1266
- }
1267
- class BaseGroup extends webgpu.Group {
1268
- isBaseGroup = true;
1269
- type = "BaseGroup";
1270
- ignoreInvisibleWhenRaycast = true;
1271
- constructor(...args) {
1272
- super(...args);
1273
- }
1274
- raycast(raycaster, intersects) {
1275
- if (this.visible === false && this.ignoreInvisibleWhenRaycast === true) {
1276
- return false;
1277
- }
1278
- return super.raycast(raycaster, intersects);
1279
- }
1280
- }
1281
- class BaseSprite extends webgpu.Sprite {
1282
- isBaseSprite = true;
1283
- type = "BaseSprite";
1284
- ignoreInvisibleWhenRaycast = true;
1285
- constructor(...args) {
1286
- super(...args);
1287
- }
1288
- raycast(raycaster, intersects) {
1289
- if (this.visible === false && this.ignoreInvisibleWhenRaycast === true) {
1290
- return false;
1291
- }
1292
- return super.raycast(raycaster, intersects);
1293
- }
1294
- }
1295
- class Model extends BaseGroup {
1296
- isModel = true;
1297
- type = "Model";
1298
- static memoryCache = /* @__PURE__ */ new Map();
1299
- constructor() {
1300
- super();
1301
- }
1302
- async loadAsync(parameters) {
1303
- const { url, cache = true, persistent = true } = parameters;
1304
- try {
1305
- let objectPromise;
1306
- if (cache) {
1307
- if (Model.memoryCache.has(url)) {
1308
- objectPromise = Model.memoryCache.get(url);
1309
- } else {
1310
- objectPromise = ModelLoaderManager.loadAsync(url, { persistent });
1311
- Model.memoryCache.set(url, objectPromise);
1312
- }
1313
- } else {
1314
- objectPromise = ModelLoaderManager.loadAsync(url, { persistent });
1315
- }
1316
- const object = await objectPromise;
1317
- const clonedObject = SkeletonUtils_js.clone(object);
1318
- this.add(clonedObject);
1319
- return clonedObject;
1320
- } catch (error) {
1321
- console.error(`[Model] Failed to load model from ${url}:`, error);
1322
- return null;
1323
- }
1324
- }
1325
- static clearMemoryCache() {
1326
- this.memoryCache.clear();
1327
- }
1328
- static async clearPersistentCache() {
1329
- if (typeof caches !== "undefined") {
1330
- await caches.delete("u-space-loader-cache");
1331
- }
1332
- }
1333
- }
1334
- class SphereMesh extends BaseMesh {
1335
- isSphereMesh = true;
1336
- type = "SphereMesh";
1337
- constructor({ geometryParameters, materialParameters } = {}) {
1338
- super();
1339
- this.geometry = new webgpu.SphereGeometry(
1340
- geometryParameters?.radius,
1341
- geometryParameters?.widthSegments,
1342
- geometryParameters?.heightSegments,
1343
- geometryParameters?.phiStart,
1344
- geometryParameters?.phiLength,
1345
- geometryParameters?.thetaStart,
1346
- geometryParameters?.thetaLength
1347
- );
1348
- this.material = new webgpu.MeshStandardNodeMaterial(materialParameters);
1349
- }
1350
- }
1351
- class TubeMesh extends BaseMesh {
1352
- isTubeMesh = true;
1353
- type = "TubeMesh";
1354
- constructor({ geometryParameters, materialParameters } = {}) {
1355
- super();
1356
- this.geometry = new webgpu.TubeGeometry(
1357
- geometryParameters?.path,
1358
- geometryParameters?.tubularSegments,
1359
- geometryParameters?.radius,
1360
- geometryParameters?.radialSegments,
1361
- geometryParameters?.closed
1362
- );
1363
- this.material = new webgpu.MeshStandardNodeMaterial(materialParameters);
1364
- }
1365
- }
1366
- class Topology extends BaseGroup {
1367
- isTopology = true;
1368
- type = "Topology";
1369
- // Visuals
1370
- parameters = {
1371
- nodeColor: 255,
1372
- nodeRadius: 0.5,
1373
- edgeColor: 65280,
1374
- edgeRadius: 0.1,
1375
- pathColor: 16711935,
1376
- pathRadius: 0.2
1377
- };
1378
- nodes = /* @__PURE__ */ new Map();
1379
- adjacencyMap = /* @__PURE__ */ new Map();
1380
- graphGroup = null;
1381
- pathMeshes = [];
1382
- constructor(parameters) {
1383
- super();
1384
- if (parameters) {
1385
- Object.assign(this.parameters, parameters);
1386
- }
1387
- }
1388
- /**
1389
- * Add a node to the topology graph.
1390
- * @param id Unique identifier for the node
1391
- * @param position 3D position of the node
1392
- */
1393
- addNode(id, position) {
1394
- if (this.nodes.has(id)) {
1395
- console.warn(`[Topology] Node ${id} already exists. Overwriting.`);
1396
- }
1397
- this.nodes.set(id, position);
1398
- if (!this.adjacencyMap.has(id)) {
1399
- this.adjacencyMap.set(id, /* @__PURE__ */ new Map());
1400
- }
1401
- }
1402
- /**
1403
- * Remove a node from the topology graph.
1404
- * @param id Unique identifier for the node
1405
- */
1406
- removeNode(id) {
1407
- if (!this.nodes.has(id)) {
1408
- console.warn(`[Topology] Node ${id} does not exist.`);
1409
- return;
1410
- }
1411
- this.nodes.delete(id);
1412
- this.adjacencyMap.delete(id);
1413
- }
1414
- /**
1415
- * Add an edge between two nodes.
1416
- * @param from Node ID
1417
- * @param to Node ID
1418
- * @param weight Cost of the edge. Defaults to Euclidean distance.
1419
- * @param bidirectional If true, adds the reverse edge as well. Default true.
1420
- */
1421
- addEdge(from, to, weight, bidirectional = true) {
1422
- const fromPos = this.nodes.get(from);
1423
- const toPos = this.nodes.get(to);
1424
- if (!fromPos || !toPos) {
1425
- console.error(`[Topology] Cannot add edge. One or both nodes not found: ${from}, ${to}`);
1426
- return;
1427
- }
1428
- const dist = weight ?? fromPos.distanceTo(toPos);
1429
- this.getNeighbors(from)?.set(to, dist);
1430
- if (bidirectional) {
1431
- this.getNeighbors(to)?.set(from, dist);
1432
- }
1433
- }
1434
- /**
1435
- * Remove an edge between two nodes.
1436
- * @param from Node ID
1437
- * @param to Node ID
1438
- * @param bidirectional If true, removes the reverse edge as well. Default true.
1439
- */
1440
- removeEdge(from, to, bidirectional = true) {
1441
- const fromNeighbors = this.getNeighbors(from);
1442
- fromNeighbors?.delete(to);
1443
- if (bidirectional) {
1444
- const toNeighbors = this.getNeighbors(to);
1445
- toNeighbors?.delete(from);
1446
- }
1447
- }
1448
- /**
1449
- * Find the shortest path between start and end nodes using Dijkstra's algorithm.
1450
- */
1451
- getShortestPath(startId, endId) {
1452
- if (!this.nodes.has(startId) || !this.nodes.has(endId)) {
1453
- console.warn(`[Topology] Start or End node not found.`);
1454
- return [];
1455
- }
1456
- const distances = /* @__PURE__ */ new Map();
1457
- const previous = /* @__PURE__ */ new Map();
1458
- const unvisited = /* @__PURE__ */ new Set();
1459
- for (const [id] of this.nodes) {
1460
- distances.set(id, Infinity);
1461
- previous.set(id, null);
1462
- unvisited.add(id);
1463
- }
1464
- distances.set(startId, 0);
1465
- while (unvisited.size > 0) {
1466
- let currentId = null;
1467
- let minDist = Infinity;
1468
- for (const id of unvisited) {
1469
- const d = distances.get(id);
1470
- if (d < minDist) {
1471
- minDist = d;
1472
- currentId = id;
1473
- }
1474
- }
1475
- if (currentId === null || currentId === endId) {
1476
- break;
1477
- }
1478
- if (minDist === Infinity) {
1479
- break;
1480
- }
1481
- unvisited.delete(currentId);
1482
- const neighbors = this.adjacencyMap?.get(currentId);
1483
- if (!neighbors) {
1484
- continue;
1485
- }
1486
- for (const [to, weight] of neighbors) {
1487
- if (!unvisited.has(to)) continue;
1488
- const alt = distances.get(currentId) + weight;
1489
- if (alt < distances.get(to)) {
1490
- distances.set(to, alt);
1491
- previous.set(to, currentId);
1492
- }
1493
- }
1494
- }
1495
- const path = [];
1496
- let curr = endId;
1497
- if (previous.get(endId) === null && startId !== endId) {
1498
- return [];
1499
- }
1500
- while (curr !== null) {
1501
- const pos = this.nodes.get(curr);
1502
- if (pos) path.unshift(pos);
1503
- curr = previous.get(curr) || null;
1504
- }
1505
- return path;
1506
- }
1507
- /**
1508
- * Renders the entire topology graph structure using TubeGeometry and Spheres.
1509
- */
1510
- renderGraph() {
1511
- this.clearGraph();
1512
- this.graphGroup = new webgpu.Group();
1513
- const _dummySphere = new SphereMesh({
1514
- geometryParameters: {
1515
- radius: this.parameters.nodeRadius,
1516
- widthSegments: 16,
1517
- heightSegments: 16
1518
- },
1519
- materialParameters: {
1520
- color: this.parameters.nodeColor
1521
- }
1522
- });
1523
- this.nodes.forEach((pos, id) => {
1524
- const nodeMesh = _dummySphere.clone();
1525
- nodeMesh.position.copy(pos);
1526
- Object.assign(nodeMesh.userData, { id, type: "node" });
1527
- this.graphGroup.add(nodeMesh);
1528
- });
1529
- const processedEdges = /* @__PURE__ */ new Set();
1530
- this.adjacencyMap.forEach((edges, from) => {
1531
- edges.forEach((weight, to) => {
1532
- const key = [from, to].sort().join("-");
1533
- if (processedEdges.has(key)) return;
1534
- processedEdges.add(key);
1535
- const p1 = this.nodes.get(from);
1536
- const p2 = this.nodes.get(to);
1537
- if (p1 && p2) {
1538
- const path = new webgpu.LineCurve3(p1, p2);
1539
- const tubeMesh = new TubeMesh({
1540
- geometryParameters: {
1541
- path,
1542
- tubularSegments: 1,
1543
- radius: this.parameters.edgeRadius,
1544
- radialSegments: 8,
1545
- closed: false
1546
- },
1547
- materialParameters: {
1548
- color: this.parameters.edgeColor
1549
- }
1550
- });
1551
- Object.assign(tubeMesh.userData, { from, to, weight, type: "edge" });
1552
- this.graphGroup.add(tubeMesh);
1553
- }
1554
- });
1555
- });
1556
- this.add(this.graphGroup);
1557
- }
1558
- clearGraph() {
1559
- if (this.graphGroup) {
1560
- this.remove(this.graphGroup);
1561
- this.graphGroup.traverse((child) => {
1562
- if (child instanceof webgpu.Mesh) {
1563
- child.geometry.dispose();
1564
- child.material.dispose();
1565
- }
1566
- });
1567
- this.graphGroup = null;
1568
- }
1569
- }
1570
- /**
1571
- * Visualizes a path using TubeGeometry (CatmullRomCurve3).
1572
- */
1573
- renderPath(points, color = this.parameters.pathColor) {
1574
- if (points.length < 2) return;
1575
- const curve = new webgpu.CatmullRomCurve3(points, false, "catmullrom", 0);
1576
- const mesh = new TubeMesh({
1577
- geometryParameters: {
1578
- path: curve,
1579
- tubularSegments: points.length * 10,
1580
- radius: this.parameters.pathRadius,
1581
- closed: false
1582
- },
1583
- materialParameters: {
1584
- color
1585
- }
1586
- });
1587
- this.add(mesh);
1588
- this.pathMeshes.push(mesh);
1589
- return mesh;
1590
- }
1591
- clearPaths() {
1592
- this.pathMeshes.forEach((m) => {
1593
- this.remove(m);
1594
- m.geometry.dispose();
1595
- m.material.dispose();
1596
- });
1597
- this.pathMeshes = [];
1598
- }
1599
- /** Export nodes and edges as a JSON-serializable object. */
1600
- exportData() {
1601
- const nodes = {};
1602
- this.nodes.forEach((pos, id) => {
1603
- nodes[id] = { x: pos.x, y: pos.y, z: pos.z };
1604
- });
1605
- const edges = [];
1606
- const processed = /* @__PURE__ */ new Set();
1607
- this.adjacencyMap.forEach((neighbors, from) => {
1608
- neighbors.forEach((weight, to) => {
1609
- const key = [from, to].sort().join("-");
1610
- if (!processed.has(key)) {
1611
- processed.add(key);
1612
- edges.push({ from, to, weight });
1613
- }
1614
- });
1615
- });
1616
- return { nodes, edges };
1617
- }
1618
- /**
1619
- * Load topology from a previously exported data object.
1620
- * Replaces all current nodes, edges, and path meshes, then re-renders the graph.
1621
- */
1622
- importData(data) {
1623
- this.clearGraph();
1624
- this.clearPaths();
1625
- this.nodes.clear();
1626
- this.adjacencyMap.clear();
1627
- Object.entries(data.nodes).forEach(([id, pos]) => {
1628
- this.addNode(id, new webgpu.Vector3(pos.x, pos.y, pos.z));
1629
- });
1630
- data.edges.forEach(({ from, to, weight }) => {
1631
- this.addEdge(from, to, weight);
1632
- });
1633
- this.renderGraph();
1634
- }
1635
- dispose() {
1636
- this.clearGraph();
1637
- this.clearPaths();
1638
- }
1639
- getNeighbors(id) {
1640
- return this.adjacencyMap.get(id);
1641
- }
1642
- }
1643
- class Poi extends BaseSprite {
1644
- isPoi = true;
1645
- type = "Poi";
1646
- parameters = {
1647
- img: "",
1648
- text: "",
1649
- fontSize: 32,
1650
- fontFamily: "Arial",
1651
- color: "#ffffff",
1652
- iconSize: 64,
1653
- padding: 10,
1654
- backgroundColor: "rgba(0, 0, 0, 0)",
1655
- borderRadius: 8,
1656
- textPosition: "right",
1657
- scaleFactor: 0.01
1658
- };
1659
- _canvas = document.createElement("canvas");
1660
- _lastParametersJSON = "";
1661
- constructor(parameters = {}) {
1662
- super(new webgpu.SpriteNodeMaterial());
1663
- Object.assign(this.parameters, parameters);
1664
- this.updateAsync();
1665
- }
1666
- /**
1667
- * Update the POI with new parameters
1668
- * @param parameters Partial POI parameters
1669
- */
1670
- async updateAsync(parameters = {}) {
1671
- Object.assign(this.parameters, parameters);
1672
- const json = JSON.stringify(this.parameters);
1673
- if (json === this._lastParametersJSON) return;
1674
- this._lastParametersJSON = json;
1675
- const canvas = this._canvas;
1676
- const ctx = canvas.getContext("2d");
1677
- if (!ctx) return;
1678
- ctx.font = `${this.parameters.fontSize}px ${this.parameters.fontFamily}`;
1679
- let image = null;
1680
- if (this.parameters.img) {
1681
- image = await this._loadImage(this.parameters.img);
1682
- }
1683
- const { text, fontSize, color, iconSize, padding, backgroundColor, borderRadius, textPosition, scaleFactor } = this.parameters;
1684
- const textMetrics = ctx.measureText(text);
1685
- const textWidth = text ? textMetrics.width : 0;
1686
- const textHeight = text ? fontSize : 0;
1687
- let contentWidth = 0;
1688
- let contentHeight = 0;
1689
- let iconX = 0, iconY = 0;
1690
- let textX = 0, textY = 0;
1691
- const hasImage = !!image;
1692
- const hasText = !!text;
1693
- if (hasImage && hasText) {
1694
- switch (textPosition) {
1695
- case "top":
1696
- contentWidth = Math.max(iconSize, textWidth);
1697
- contentHeight = iconSize + padding + textHeight;
1698
- textX = (contentWidth - textWidth) / 2;
1699
- textY = textHeight / 2;
1700
- iconX = (contentWidth - iconSize) / 2;
1701
- iconY = textHeight + padding;
1702
- break;
1703
- case "bottom":
1704
- contentWidth = Math.max(iconSize, textWidth);
1705
- contentHeight = iconSize + padding + textHeight;
1706
- iconX = (contentWidth - iconSize) / 2;
1707
- iconY = 0;
1708
- textX = (contentWidth - textWidth) / 2;
1709
- textY = iconSize + padding + textHeight / 2;
1710
- break;
1711
- case "left":
1712
- contentWidth = iconSize + padding + textWidth;
1713
- contentHeight = Math.max(iconSize, textHeight);
1714
- textX = 0;
1715
- textY = contentHeight / 2;
1716
- iconX = textWidth + padding;
1717
- iconY = (contentHeight - iconSize) / 2;
1718
- break;
1719
- case "right":
1720
- default:
1721
- contentWidth = iconSize + padding + textWidth;
1722
- contentHeight = Math.max(iconSize, textHeight);
1723
- iconX = 0;
1724
- iconY = (contentHeight - iconSize) / 2;
1725
- textX = iconSize + padding;
1726
- textY = contentHeight / 2;
1727
- break;
1728
- }
1729
- } else if (hasImage) {
1730
- contentWidth = iconSize;
1731
- contentHeight = iconSize;
1732
- iconX = 0;
1733
- iconY = 0;
1734
- } else if (hasText) {
1735
- contentWidth = textWidth;
1736
- contentHeight = textHeight;
1737
- textX = 0;
1738
- textY = textHeight / 2;
1739
- }
1740
- const canvasWidth = contentWidth + padding * 2;
1741
- const canvasHeight = contentHeight + padding * 2;
1742
- canvas.width = canvasWidth;
1743
- canvas.height = canvasHeight;
1744
- ctx.font = `${fontSize}px ${this.parameters.fontFamily}`;
1745
- if (backgroundColor) {
1746
- ctx.fillStyle = backgroundColor;
1747
- this._drawRoundedRect(ctx, 0, 0, canvasWidth, canvasHeight, borderRadius);
1748
- ctx.fill();
1749
- }
1750
- if (hasImage) {
1751
- ctx.drawImage(image, iconX + padding, iconY + padding, iconSize, iconSize);
1752
- }
1753
- if (hasText) {
1754
- ctx.fillStyle = color;
1755
- const metrics = ctx.measureText(text);
1756
- const actualTextHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
1757
- const baselineOffset = metrics.actualBoundingBoxAscent - actualTextHeight / 2;
1758
- ctx.textBaseline = "alphabetic";
1759
- ctx.fillText(text, textX + padding, textY + padding + baselineOffset);
1760
- }
1761
- const oldTexture = this.material.map;
1762
- const texture = new webgpu.CanvasTexture(canvas);
1763
- texture.colorSpace = webgpu.SRGBColorSpace;
1764
- this.material.map = texture;
1765
- oldTexture?.dispose();
1766
- this.scale.set(canvasWidth * scaleFactor, canvasHeight * scaleFactor, 1);
1767
- }
1768
- _loadImage(img) {
1769
- return new Promise((resolve, reject) => {
1770
- if (typeof img === "string") {
1771
- const _img = new Image();
1772
- _img.crossOrigin = "Anonymous";
1773
- _img.onload = () => resolve(_img);
1774
- _img.onerror = () => reject(new Error(`Failed to load image: ${img}`));
1775
- _img.src = img;
1776
- } else {
1777
- resolve(img);
1778
- }
1779
- });
1780
- }
1781
- _drawRoundedRect(ctx, x, y, width, height, radius) {
1782
- ctx.beginPath();
1783
- ctx.moveTo(x + radius, y);
1784
- ctx.lineTo(x + width - radius, y);
1785
- ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
1786
- ctx.lineTo(x + width, y + height - radius);
1787
- ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
1788
- ctx.lineTo(x + radius, y + height);
1789
- ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
1790
- ctx.lineTo(x, y + radius);
1791
- ctx.quadraticCurveTo(x, y, x + radius, y);
1792
- ctx.closePath();
1793
- }
1794
- dispose() {
1795
- this.material.map?.dispose();
1796
- this.material.dispose();
1797
- }
1798
- }
1799
- class ShapeMesh extends BaseMesh {
1800
- isShapeMesh = true;
1801
- type = "ShapeMesh";
1802
- constructor({ geometryParameters, materialParameters } = {}) {
1803
- super();
1804
- this.geometry = new webgpu.ShapeGeometry(geometryParameters?.shape, geometryParameters?.curveSegments);
1805
- this.material = new webgpu.MeshStandardNodeMaterial(materialParameters);
1806
- this.geometry.rotateX(-Math.PI / 2);
1807
- }
1808
- static createFromPoints(points, parameters = {}) {
1809
- return new ShapeMesh({
1810
- ...parameters,
1811
- geometryParameters: {
1812
- ...parameters.geometryParameters,
1813
- shape: new webgpu.Shape(points.map((point) => new webgpu.Vector2(point.x, -point.z)))
1814
- }
1815
- });
1816
- }
1817
- }
1818
- class ExtrudeMesh extends BaseMesh {
1819
- isExtrudeMesh = true;
1820
- type = "ExtrudeMesh";
1821
- constructor({ geometryParameters, materialParameters } = {}) {
1822
- super();
1823
- this.geometry = new webgpu.ExtrudeGeometry(geometryParameters?.shape, geometryParameters?.options);
1824
- this.material = new webgpu.MeshStandardNodeMaterial(materialParameters);
1825
- this.geometry.rotateX(-Math.PI / 2);
1826
- }
1827
- static createFromPoints(points, parameters = {}) {
1828
- return new ExtrudeMesh({
1829
- ...parameters,
1830
- geometryParameters: {
1831
- ...parameters.geometryParameters,
1832
- shape: new webgpu.Shape(points.map((point) => new webgpu.Vector2(point.x, -point.z)))
1833
- }
1834
- });
1835
- }
1836
- }
1837
- class PlaneMesh extends BaseMesh {
1838
- isPlaneMesh = true;
1839
- type = "PlaneMesh";
1840
- constructor({ geometryParameters, materialParameters } = {}) {
1841
- super();
1842
- this.geometry = new webgpu.PlaneGeometry(
1843
- geometryParameters?.width,
1844
- geometryParameters?.height,
1845
- geometryParameters?.widthSegments,
1846
- geometryParameters?.heightSegments
1847
- );
1848
- this.material = new webgpu.MeshStandardNodeMaterial(materialParameters);
1849
- }
1850
- }
1851
- class CircleMesh extends BaseMesh {
1852
- isCircleMesh = true;
1853
- type = "CircleMesh";
1854
- constructor({ geometryParameters, materialParameters } = {}) {
1855
- super(
1856
- new webgpu.CircleGeometry(
1857
- geometryParameters?.radius,
1858
- geometryParameters?.segments,
1859
- geometryParameters?.thetaStart,
1860
- geometryParameters?.thetaLength
1861
- ),
1862
- new webgpu.MeshStandardNodeMaterial(materialParameters)
1863
- );
1864
- this.geometry.rotateX(-Math.PI / 2);
1865
- }
1866
- }
1867
- class ObjectUtils {
1868
- static traverseMeshes(object, callback) {
1869
- object.traverse((child) => {
1870
- if (child instanceof webgpu.Mesh) {
1871
- callback(child);
1872
- }
1873
- });
1874
- }
1875
- }
1876
- class TSLEffects {
1877
- static flow(parameters = {}) {
1878
- const { baseColor = 16777215, flowColor = 65280, speed = 1, scale = 3, intensity = 4 } = parameters;
1879
- const baseColorNode = tsl.color(new three.Color(baseColor));
1880
- const flowColorNode = tsl.color(new three.Color(flowColor));
1881
- const flow = tsl.uv().x.mul(scale).sub(tsl.time.mul(speed));
1882
- const pattern = tsl.pow(tsl.sin(flow).add(1).mul(0.5), intensity);
1883
- return tsl.mix(baseColorNode, flowColorNode, pattern);
1884
- }
1885
- static breathe(parameters = {}) {
1886
- const { baseColor = 16777215, breathColor = 65280, speed = 1, intensity = 2 } = parameters;
1887
- const baseColorNode = tsl.color(new three.Color(baseColor));
1888
- const breathColorNode = tsl.color(new three.Color(breathColor));
1889
- const osc = tsl.sin(tsl.time.mul(speed)).add(1).mul(0.5);
1890
- const pattern = tsl.pow(osc, intensity);
1891
- return tsl.mix(baseColorNode, breathColorNode, pattern);
1892
- }
1893
- static fluid(parameters = {}) {
1894
- const {
1895
- baseColor = 16777215,
1896
- flowColor = 255,
1897
- speed = 1,
1898
- scale = 1,
1899
- intensity = 1,
1900
- distortion = 0.5
1901
- } = parameters;
1902
- const baseColorNode = tsl.color(new three.Color(baseColor));
1903
- const flowColorNode = tsl.color(new three.Color(flowColor));
1904
- const uvNode = tsl.uv().mul(scale);
1905
- const timeNode = tsl.time.mul(speed);
1906
- const noiseNode = tsl.mx_noise_float(uvNode.add(timeNode), 1, 0);
1907
- const distortedUV = uvNode.add(noiseNode.mul(distortion));
1908
- const pattern = tsl.mx_noise_float(distortedUV, 1, 0).add(1).mul(0.5);
1909
- const fluidPattern = tsl.pow(pattern, intensity);
1910
- return tsl.mix(baseColorNode, flowColorNode, fluidPattern);
1911
- }
1912
- }
1913
- function reinterpretType(_value) {
1914
- }
1915
- const _highlightKey = "uSpaceHighlight";
1916
- const _highlightEnabledKey = `${_highlightKey}/enabled`;
1917
- const _highlightOpacityKey = `${_highlightKey}/opacity`;
1918
- const _highlightColorKey = `${_highlightKey}/color`;
1919
- const _highlightOverwriteKey = `${_highlightKey}/overwrite`;
1920
- const _highlightColorNode = tsl.Fn(() => {
1921
- const enabled = tsl.userData(_highlightEnabledKey, "uint");
1922
- const colorUint = tsl.userData(_highlightColorKey, "uint");
1923
- const overwrite = tsl.userData(_highlightOverwriteKey, "uint");
1924
- const hlColorRaw = uintToColor(colorUint);
1925
- const tintedColor = tsl.materialColor.mul(hlColorRaw);
1926
- const finalHlColor = tsl.select(overwrite.greaterThan(0), hlColorRaw, tintedColor);
1927
- const hlColor = tsl.select(enabled.greaterThan(0), finalHlColor, tsl.materialColor);
1928
- return hlColor;
1929
- })();
1930
- const _highlightOpacityNode = tsl.Fn(() => {
1931
- const enabled = tsl.userData(_highlightEnabledKey, "uint");
1932
- const opacity = tsl.userData(_highlightOpacityKey, "float");
1933
- const hlOpacity = tsl.select(enabled.greaterThan(0), opacity, tsl.materialOpacity);
1934
- return hlOpacity;
1935
- })();
1936
- class MaterialEffects {
1937
- static highlight(object, options = {}) {
1938
- const highlightOptions = Object.assign(
1939
- {
1940
- enabled: true,
1941
- opacity: 0.5,
1942
- color: 16711680,
1943
- overwrite: false
1944
- },
1945
- options
1946
- );
1947
- highlightOptions.color = new webgpu.Color(highlightOptions.color).getHex();
1948
- ObjectUtils.traverseMeshes(object, (mesh) => {
1949
- mesh.userData[_highlightEnabledKey] = highlightOptions.enabled ? 1 : 0;
1950
- mesh.userData[_highlightOpacityKey] = highlightOptions.opacity;
1951
- mesh.userData[_highlightColorKey] = highlightOptions.color;
1952
- mesh.userData[_highlightOverwriteKey] = highlightOptions.overwrite ? 1 : 0;
1953
- const material = mesh.material;
1954
- if (material && !Array.isArray(material)) {
1955
- material.transparent = true;
1956
- material.colorNode = _highlightColorNode;
1957
- material.opacityNode = _highlightOpacityNode;
1958
- material.needsUpdate = true;
1959
- }
1960
- });
1961
- }
1962
- }
1963
- const uintToColor = (colorUint) => {
1964
- const r = colorUint.shiftRight(16).bitAnd(255).toFloat().div(255);
1965
- const g = colorUint.shiftRight(8).bitAnd(255).toFloat().div(255);
1966
- const b = colorUint.bitAnd(255).toFloat().div(255);
1967
- return tsl.vec3(r, g, b);
1968
- };
1969
- class Tween extends tween_module_js.Tween {
1970
- viewer;
1971
- constructor(viewer, source) {
1972
- super(source);
1973
- this.viewer = viewer;
1974
- }
1975
- _update = ({ time }) => {
1976
- const needsRender = this.update(time);
1977
- if (needsRender) {
1978
- this.viewer.render();
1979
- }
1980
- };
1981
- easingByMode(mode) {
1982
- const tweenModeFunc = animationModeEnum[mode];
1983
- return super.easing(tweenModeFunc);
1984
- }
1985
- start(time, overrideStartingValues) {
1986
- this.viewer.addEventListener("afterControlsUpdate", this._update);
1987
- return super.start(time, overrideStartingValues);
1988
- }
1989
- stop() {
1990
- this.viewer.removeEventListener("afterControlsUpdate", this._update);
1991
- return super.stop();
1992
- }
1993
- }
1994
- function tweenAnimation(viewer, source, target, options = {}, onUpdate, onStart) {
1995
- return new Promise((resolve, reject) => {
1996
- const { duration = 1e3, delay = 0, repeat = false, mode = "Linear.None", yoyo = false } = options;
1997
- const tween = new Tween(viewer, source).to(target, duration).easingByMode(mode).delay(delay).onUpdate((e) => {
1998
- onUpdate?.(e, tween);
1999
- }).onComplete(() => {
2000
- resolve();
2001
- }).onStop(() => {
2002
- reject("animation stop");
2003
- }).onStart(() => {
2004
- onStart?.(tween);
2005
- });
2006
- if (typeof repeat === "number") tween.repeat(repeat);
2007
- else if (typeof repeat === "boolean" && repeat) tween.repeat(Infinity);
2008
- if (yoyo) tween.repeatDelay(20);
2009
- tween.yoyo(yoyo);
2010
- tween.start();
2011
- });
2012
- }
2013
- const animationModeEnum = {
2014
- "Linear.None": tween_module_js.Easing.Linear.None,
2015
- "Quadratic.In": tween_module_js.Easing.Quadratic.In,
2016
- "Quadratic.Out": tween_module_js.Easing.Quadratic.Out,
2017
- "Quadratic.InOut": tween_module_js.Easing.Quadratic.InOut,
2018
- "Cubic.In": tween_module_js.Easing.Cubic.In,
2019
- "Cubic.Out": tween_module_js.Easing.Cubic.Out,
2020
- "Cubic.InOut": tween_module_js.Easing.Cubic.InOut,
2021
- "Quartic.In": tween_module_js.Easing.Quartic.In,
2022
- "Quartic.Out": tween_module_js.Easing.Quartic.Out,
2023
- "Quartic.InOut": tween_module_js.Easing.Quartic.InOut,
2024
- "Quintic.In": tween_module_js.Easing.Quintic.In,
2025
- "Quintic.Out": tween_module_js.Easing.Quintic.Out,
2026
- "Quintic.InOut": tween_module_js.Easing.Quintic.InOut,
2027
- "Sinusoidal.In": tween_module_js.Easing.Sinusoidal.In,
2028
- "Sinusoidal.Out": tween_module_js.Easing.Sinusoidal.Out,
2029
- "Sinusoidal.InOut": tween_module_js.Easing.Sinusoidal.InOut,
2030
- "Exponential.In": tween_module_js.Easing.Exponential.In,
2031
- "Exponential.Out": tween_module_js.Easing.Exponential.Out,
2032
- "Exponential.InOut": tween_module_js.Easing.Exponential.InOut,
2033
- "Circular.In": tween_module_js.Easing.Circular.In,
2034
- "Circular.Out": tween_module_js.Easing.Circular.Out,
2035
- "Circular.InOut": tween_module_js.Easing.Circular.InOut,
2036
- "Elastic.In": tween_module_js.Easing.Elastic.In,
2037
- "Elastic.Out": tween_module_js.Easing.Elastic.Out,
2038
- "Elastic.InOut": tween_module_js.Easing.Elastic.InOut,
2039
- "Back.In": tween_module_js.Easing.Back.In,
2040
- "Back.Out": tween_module_js.Easing.Back.Out,
2041
- "Back.InOut": tween_module_js.Easing.Back.InOut,
2042
- "Bounce.In": tween_module_js.Easing.Bounce.In,
2043
- "Bounce.Out": tween_module_js.Easing.Bounce.Out,
2044
- "Bounce.InOut": tween_module_js.Easing.Bounce.InOut
2045
- };
2046
- exports.BaseGroup = BaseGroup;
2047
- exports.BaseMesh = BaseMesh;
2048
- exports.BaseSprite = BaseSprite;
2049
- exports.CameraControls = CameraControls;
2050
- exports.CircleMesh = CircleMesh;
2051
- exports.ExtrudeMesh = ExtrudeMesh;
2052
- exports.InteractionEvent = InteractionEvent;
2053
- exports.InteractionManager = InteractionManager;
2054
- exports.MaterialEffects = MaterialEffects;
2055
- exports.Model = Model;
2056
- exports.ModelLoaderManager = ModelLoaderManager;
2057
- exports.ObjectManager = ObjectManager;
2058
- exports.ObjectUtils = ObjectUtils;
2059
- exports.PlaneMesh = PlaneMesh;
2060
- exports.Poi = Poi;
2061
- exports.RoomEnvironment = RoomEnvironment;
2062
- exports.SBMLoader = SBMLoader;
2063
- exports.SBMXLoader = SBMXLoader;
2064
- exports.ShapeMesh = ShapeMesh;
2065
- exports.SphereMesh = SphereMesh;
2066
- exports.TSLEffects = TSLEffects;
2067
- exports.TextureLoaderManager = TextureLoaderManager;
2068
- exports.Topology = Topology;
2069
- exports.TubeMesh = TubeMesh;
2070
- exports.Tween = Tween;
2071
- exports.Viewer = Viewer;
2072
- exports.reinterpretType = reinterpretType;
2073
- exports.tweenAnimation = tweenAnimation;
2074
- //# sourceMappingURL=index.cjs.map
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("three/webgpu"),d=require("three/tsl"),Oe=require("three/addons/tsl/display/BloomNode.js"),Le=require("three/addons/tsl/display/SSGINode.js"),Re=require("three/addons/tsl/display/TRAANode.js"),ne=require("camera-controls"),Ie=require("three/addons/environments/RoomEnvironment.js"),_e=require("three/addons/helpers/ViewHelper.js"),K=require("three/addons/renderers/CSS2DRenderer.js"),U=require("three/addons/renderers/CSS3DRenderer.js"),re=require("three/addons/loaders/GLTFLoader.js"),Be=require("three/addons/loaders/FBXLoader.js"),Ne=require("three/addons/loaders/OBJLoader.js"),Ae=require("three/addons/loaders/STLLoader.js"),De=require("three/addons/loaders/DRACOLoader.js"),je=require("three/addons/loaders/KTX2Loader.js"),J=require("three/addons/libs/meshopt_decoder.module.js"),Ue=require("three/addons/loaders/HDRLoader.js"),Ge=require("three/addons/utils/SkeletonUtils.js"),A=require("three"),u=require("three/addons/libs/tween.module.js");class ae{type;target;currentTarget;intersect;originalEvent;_propagationStopped=!1;constructor(e){this.type=e.type,this.target=e.target,this.currentTarget=e.target,this.intersect=e.intersect,this.originalEvent=e.originalEvent}stopPropagation(){this._propagationStopped=!0}get propagationStopped(){return this._propagationStopped}}class oe{domElement;scene;camera;raycaster=new n.Raycaster;pointer=new n.Vector2;hoveredObject=null;pointerDownTime=0;pointerDownPos=new n.Vector2;clickTimer=null;longPressThreshold=500;moveThreshold=.01;targetObjects;pointerMoveEventsEnabled=!1;constructor(e,t,s){this.domElement=e,this.scene=t,this.camera=s,this.raycaster.params.Points.threshold=.1,this.raycaster.params.Line.threshold=.1,this.targetObjects=this.scene.children,this._bindEvents()}setCamera(e){this.camera=e}_bindEvents(){this.domElement.addEventListener("click",this._onClick),this.domElement.addEventListener("dblclick",this._onDblClick),this.domElement.addEventListener("contextmenu",this._onContextMenu),this.domElement.addEventListener("pointerdown",this._onPointerDown),this.domElement.addEventListener("pointerup",this._onPointerUp),this.domElement.addEventListener("pointermove",this._onPointerMove)}_updatePointer(e){const t=this.domElement.getBoundingClientRect();this.pointer.x=(e.clientX-t.left)/t.width*2-1,this.pointer.y=-((e.clientY-t.top)/t.height)*2+1}_getIntersects(){return this.raycaster.setFromCamera(this.pointer,this.camera),this.raycaster.intersectObjects(this.targetObjects,!0)}_dispatchToTarget(e,t,s,i){const r=new ae({type:e,target:t,intersect:s,originalEvent:i});let a=t;for(;a&&!r.propagationStopped;)r.currentTarget=a,a.dispatchEvent({type:e,event:r}),a=a.parent}_handleEvent(e,t){this._updatePointer(t);const s=this._getIntersects();if(s.length===0)return;const i=s[0];this._dispatchToTarget(e,i.object,i,t)}_onClick=e=>{const t=Date.now()-this.pointerDownTime,s=this.pointer.distanceTo(this.pointerDownPos);if(!(t>this.longPressThreshold||s>this.moveThreshold)){if(this.clickTimer){clearTimeout(this.clickTimer),this.clickTimer=null;return}this.clickTimer=setTimeout(()=>{this._handleEvent("click",e),this.clickTimer=null},200)}};_onDblClick=e=>{this.clickTimer&&(clearTimeout(this.clickTimer),this.clickTimer=null),this._handleEvent("dblclick",e)};_onContextMenu=e=>{e.preventDefault()};_onPointerDown=e=>{this.pointerDownTime=Date.now(),this._updatePointer(e),this.pointerDownPos.copy(this.pointer),this._handleEvent("pointerdown",e)};_onPointerUp=e=>{if(this._updatePointer(e),e.button===2){const t=Date.now()-this.pointerDownTime,s=this.pointer.distanceTo(this.pointerDownPos);t<=this.longPressThreshold&&s<=this.moveThreshold&&this._handleEvent("rightclick",e)}this._handleEvent("pointerup",e)};_onPointerMove=e=>{if(!this.pointerMoveEventsEnabled)return;this._updatePointer(e);const t=this._getIntersects(),s=t.length>0?t[0].object:null,i=t.length>0?t[0]:null;this.hoveredObject!==s&&(this.hoveredObject&&this._dispatchToTarget("pointerleave",this.hoveredObject,null,e),this.hoveredObject=s,s&&i&&this._dispatchToTarget("pointerenter",s,i,e)),s&&i&&this._dispatchToTarget("pointermove",s,i,e)};dispose(){this.domElement.removeEventListener("click",this._onClick),this.domElement.removeEventListener("dblclick",this._onDblClick),this.domElement.removeEventListener("contextmenu",this._onContextMenu),this.domElement.removeEventListener("pointerdown",this._onPointerDown),this.domElement.removeEventListener("pointerup",this._onPointerUp),this.domElement.removeEventListener("pointermove",this._onPointerMove),this.hoveredObject=null}}class ce{idMap=new Map;nameMap=new Map;typeMap=new Map;objectIds=new Map;allObjects=new Set;add(e,t){if(this.idMap.has(e)){console.warn(`ObjectManager: Object with id ${e} already exists.`);return}this.idMap.set(e,t),this.allObjects.add(t),this.objectIds.has(t)||this.objectIds.set(t,new Set),this.objectIds.get(t).add(e),t.name&&(this.nameMap.has(t.name)||this.nameMap.set(t.name,new Set),this.nameMap.get(t.name).add(t)),t.type&&(this.typeMap.has(t.type)||this.typeMap.set(t.type,new Set),this.typeMap.get(t.type).add(t))}getById(e){return this.idMap.get(e)}getByName(e){return this.nameMap.get(e)||new Set}getByType(e){return this.typeMap.get(e)||new Set}getObjectIds(e){return this.objectIds.get(e)||new Set}remove(e){const t=this.objectIds.get(e);if(t){for(const s of t)this.idMap.delete(s);this.objectIds.delete(e)}if(e.name&&this.nameMap.has(e.name)){const s=this.nameMap.get(e.name);s.delete(e),s.size===0&&this.nameMap.delete(e.name)}if(e.type&&this.typeMap.has(e.type)){const s=this.typeMap.get(e.type);s.delete(e),s.size===0&&this.typeMap.delete(e.type)}this.allObjects.delete(e)}removeById(e){const t=this.idMap.get(e);t&&this.remove(t)}removeByName(e){const t=this.getByName(e);for(const s of t)this.remove(s)}removeByType(e){const t=this.getByType(e);for(const s of t)this.remove(s)}clear(){this.idMap.clear(),this.nameMap.clear(),this.typeMap.clear(),this.objectIds.clear(),this.allObjects.clear()}getAll(){return this.allObjects}get size(){return this.allObjects.size}}class he extends n.RenderPipeline{scene;camera;scenePass;needsUpdateOutputNode;#r;#t;#s=!1;#a={strength:1,radius:0,threshold:0};#c=null;#n=!1;#e={sliceCount:1,stepCount:12,aoIntensity:1,giIntensity:10,radius:12,thickness:1};#h=null;#o=!1;#l=null;#d=null;constructor(...e){const[t,s,i]=e;super(t),this.scene=s,this.camera=i,this.scenePass=d.pass(s,i),this.needsUpdateOutputNode=!0,this.#r=new Set,this.#t=[],this.#p()}get currentOutputNode(){return this.scenePass}addOverlayPass(e){this.#r.add(e),this.needsUpdateOutputNode=!0}removeOverlayPass(e){this.#r.delete(e),this.needsUpdateOutputNode=!0}setCamera(e){this.camera=e,this.#i()}setCurrentOutputNode(e){this.setOutputComposer(()=>e)}resetCurrentOutputNode(){this.setOutputComposer(null)}setOutputComposer(e){this.#d=e,this.needsUpdateOutputNode=!0}enableBloom(e){e&&Object.assign(this.#a,e),this.#s=!0,this.#i()}disableBloom(){this.#s=!1,this.#c=null,this.#i()}updateBloom(e){Object.assign(this.#a,e),this.#s&&(this.needsUpdateOutputNode=!0)}enableSSGI(e){e&&Object.assign(this.#e,e),this.#n=!0,this.#i()}disableSSGI(){this.#n=!1,this.#h=null,this.#i()}updateSSGI(e){if(Object.assign(this.#e,e),this.#h){const t=this.#h;e.sliceCount!==void 0&&(t.sliceCount.value=e.sliceCount),e.stepCount!==void 0&&(t.stepCount.value=e.stepCount),e.aoIntensity!==void 0&&(t.aoIntensity.value=e.aoIntensity),e.giIntensity!==void 0&&(t.giIntensity.value=e.giIntensity),e.radius!==void 0&&(t.radius.value=e.radius),e.thickness!==void 0&&(t.thickness.value=e.thickness)}}enableTRAA(){this.#o=!0,this.#i()}disableTRAA(){this.#o=!1,this.#l=null,this.#i()}#i(){const e=this.scenePass;this.scenePass=d.pass(this.scene,this.camera),this.#p(),this.needsUpdateOutputNode=!0,e.dispose()}#p(){if(this.#s||this.#n||this.#o){const t={output:d.output};this.#s&&(t.emissive=d.emissive),this.#n&&(t.normal=d.normalView),this.#o&&(t.velocity=d.velocity),this.scenePass.setMRT(d.mrt(t))}}#u(){for(const e of this.#t)e.dispose();this.#t=[]}#m(){let e=this.scenePass.getTextureNode();if(this.#n)if(!(this.camera instanceof n.PerspectiveCamera))console.warn("RenderPipeline: SSGI requires a PerspectiveCamera, skipping.");else{const t=this.scenePass.getTextureNode(),s=this.scenePass.getTextureNode("depth"),i=this.scenePass.getTextureNode("normal"),r=Le.ssgi(t,s,i,this.camera);r.sliceCount.value=this.#e.sliceCount,r.stepCount.value=this.#e.stepCount,r.aoIntensity.value=this.#e.aoIntensity,r.giIntensity.value=this.#e.giIntensity,r.radius.value=this.#e.radius,r.thickness.value=this.#e.thickness,this.#h=r,e=d.add(e,r),this.#t.push(r)}if(this.#s){const t=this.scenePass.getTextureNode("emissive");this.#c=Oe.bloom(t,this.#a.strength,this.#a.radius,this.#a.threshold),e=d.add(e,this.#c),this.#t.push(this.#c)}return e}#g(){this.#u();let e;if(this.#d?e=this.#d(this.scenePass):this.#s||this.#n?e=this.#m():e=this.scenePass,this.#o){const t=this.scenePass.getTextureNode("depth"),s=this.scenePass.getTextureNode("velocity");this.#l=Re.traa(e,t,s,this.camera),this.#t.push(this.#l),e=this.#l}this.#r.size>0&&this.#r.forEach(t=>{const s=d.blendColor(e,t);this.#t.push(s),e=s}),this.outputNode=e,this.needsUpdate=!0}render(){this.needsUpdateOutputNode&&(this.#g(),this.needsUpdateOutputNode=!1),super.render()}dispose(){this.#u(),this.scenePass.dispose(),super.dispose()}}const ke={Vector2:n.Vector2,Vector3:n.Vector3,Vector4:n.Vector4,Quaternion:n.Quaternion,Matrix4:n.Matrix4,Spherical:n.Spherical,Box3:n.Box3,Sphere:n.Sphere,Raycaster:n.Raycaster};ne.install({THREE:ke});class le extends ne{constructor(...e){super(...e),this.minDistance=.2,this.smoothTime=.2,this.dollySpeed=.2}absoluteRotations(){this.azimuthAngle=Fe(this.azimuthAngle,0)}async flyToBox(e,t={}){if(e.isEmpty())return console.warn("CameraControls.flyToBox: The provided Box3 is empty."),!1;this.absoluteRotations();const{viewpoint:s="frontTop",enableTransition:i=!0,padding:r=.1,cover:a=!1}=t,c=[];if(s!=="current"){const h=Z[s.toUpperCase()]??Z.FRONTTOP,l=h.theta,p=h.phi;c.push(this.fitToBox(e,i,{paddingLeft:r,paddingRight:r,paddingTop:r,paddingBottom:r,cover:a})),c.push(this.rotateTo(l,p,i))}else{const h=new n.Sphere;e.getBoundingSphere(h),h.radius+=r,c.push(this.fitToSphere(h,i))}return await Promise.all(c),!0}async flyToObject(e,t={}){const s=new n.Box3().setFromObject(e);return this.flyToBox(s,t)}async setCameraViewpoint(e,t=!0){const{position:s,target:i,zoom:r=this.camera.zoom}=e;return Promise.all([this.zoomTo(r,t),this.setLookAt(s.x,s.y,s.z,i.x,i.y,i.z,t)])}}const Z={LEFT:new n.Spherical(0,Math.PI/2,-Math.PI/2),RIGHT:new n.Spherical(0,Math.PI/2,Math.PI/2),FRONT:new n.Spherical(0,Math.PI/2,0),BACK:new n.Spherical(0,Math.PI/2,Math.PI),TOP:new n.Spherical(0,0,0),BOTTOM:new n.Spherical(0,Math.PI,0),FRONTTOP:new n.Spherical(0,Math.PI/4,0),BACKTOP:new n.Spherical(0,Math.PI/4,Math.PI),LEFTTOP:new n.Spherical(0,Math.PI/4,-Math.PI/2),RIGHTTOP:new n.Spherical(0,Math.PI/4,Math.PI/2),LEFTFRONTTOP:new n.Spherical(0,Math.PI/4,-Math.PI/4),RIGHTFRONTTOP:new n.Spherical(0,Math.PI/4,Math.PI/4),LEFTBACKTOP:new n.Spherical(0,Math.PI/4,-Math.PI/4*3),RIGHTBACKTOP:new n.Spherical(0,Math.PI/4,Math.PI/4*3)};function Fe(o,e){const t=o-e;return n.MathUtils.euclideanModulo(t+Math.PI,Math.PI*2)-Math.PI}class de{environment=new Ie.RoomEnvironment;renderer;pmremGenerator;envMap=null;constructor(e){this.renderer=e,this.pmremGenerator=new n.PMREMGenerator(e)}update(){this.envMap||(this.envMap=this.pmremGenerator.fromScene(this.environment).texture)}dispose(){this.pmremGenerator.dispose(),this.envMap?.dispose()}}const H=128;class He extends _e.ViewHelper{viewer;overlayPass;constructor(e){super(e.camera,e.el),this.viewer=e;const t=new n.OrthographicCamera(-2,2,2,-2,0,4);t.position.set(0,0,2),this.overlayPass=d.pass(this,t),this.setLabels("x","y","z")}_update=()=>{this.quaternion.copy(this.viewer.camera.quaternion).invert();const e=this.location;let t,s;e.left!==null?t=e.left:t=this.viewer.el.offsetWidth-H-e.right,e.top!==null?s=e.top:s=this.viewer.el.offsetHeight-H-e.bottom,this.overlayPass.setViewport(t,s,H,H)};enable(){return this.viewer.renderPipeline.addOverlayPass(this.overlayPass),this.viewer.addEventListener("beforeRender",this._update),this.viewer.render(),this}disable(){return this.viewer.renderPipeline.removeOverlayPass(this.overlayPass),this.viewer.removeEventListener("beforeRender",this._update),this.viewer.render(),this}}const pe="position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;overflow:hidden;",ze=pe+"z-index:0;",qe=pe+"z-index:1;";class ue{el;css2dRenderer=null;css3dRenderer=null;constructor(e){this.el=e,getComputedStyle(e).position==="static"&&(e.style.position="relative")}initCSS2DRenderer(){const e=new K.CSS2DRenderer;return e.setSize(this.el.clientWidth,this.el.clientHeight),e.domElement.style.cssText=qe,this.el.appendChild(e.domElement),this.css2dRenderer=e,e}initCSS3DRenderer(){const e=new U.CSS3DRenderer;return e.setSize(this.el.clientWidth,this.el.clientHeight),e.domElement.style.cssText=ze,this.el.appendChild(e.domElement),this.css3dRenderer=e,e}createCSS2DObject(e){return this.css2dRenderer||this.initCSS2DRenderer(),new K.CSS2DObject(e)}createCSS25DObject(e){return this.css3dRenderer||this.initCSS3DRenderer(),new U.CSS3DSprite(e)}createCSS3DObject(e){return this.css3dRenderer||this.initCSS3DRenderer(),new U.CSS3DObject(e)}render(e,t){this.css2dRenderer&&this.css2dRenderer.render(e,t),this.css3dRenderer&&this.css3dRenderer.render(e,t)}resize(e,t){this.css2dRenderer&&this.css2dRenderer.setSize(e,t),this.css3dRenderer&&this.css3dRenderer.setSize(e,t)}dispose(){this.css2dRenderer&&(this.el.removeChild(this.css2dRenderer.domElement),this.css2dRenderer=null),this.css3dRenderer&&(this.el.removeChild(this.css3dRenderer.domElement),this.css3dRenderer=null)}}class We{el;renderer;container;drawCallsText;frameCallsText;trianglesText;pointsText;linesText;timestampText;_enabled=!1;constructor(e,t){this.el=e,this.renderer=t;const s=document.createElement("div");s.style.position="absolute",s.style.left="12px",s.style.bottom="12px",s.style.fontSize="12px",s.style.color="#fff",s.style.pointerEvents="none",this.container=s;function i(a,c=!0){const h=document.createElement("span");return c&&(h.style.marginLeft="6px"),h.innerText=a,h}function r(){return document.createElement("br")}this.drawCallsText=i("0"),this.frameCallsText=i("0"),this.trianglesText=i("0"),this.linesText=i("0"),this.pointsText=i("0"),this.timestampText=i("0"),this.container.appendChild(i("draw calls",!1)),this.container.appendChild(this.drawCallsText),this.container.appendChild(r()),this.container.appendChild(i("frame calls",!1)),this.container.appendChild(this.frameCallsText),this.container.appendChild(r()),this.container.appendChild(i("triangles",!1)),this.container.appendChild(this.trianglesText),this.container.appendChild(r()),this.container.appendChild(i("points",!1)),this.container.appendChild(this.pointsText),this.container.appendChild(r()),this.container.appendChild(i("lines",!1)),this.container.appendChild(this.linesText),this.container.appendChild(r()),this.container.appendChild(i("timestamp",!1)),this.container.appendChild(this.timestampText),this.container.appendChild(r())}update(){if(this._enabled){const{render:e}=this.renderer.info;this.drawCallsText.innerText=e.drawCalls.toString(),this.frameCallsText.innerText=e.frameCalls.toString(),this.trianglesText.innerText=e.triangles.toString(),this.pointsText.innerText=e.points.toString(),this.linesText.innerText=e.lines.toString(),this.renderer.resolveTimestampsAsync(n.TimestampQuery.RENDER).then(t=>{this.timestampText.innerText=t?.toFixed(2)??"0"})}}enable(){this._enabled=!0,this.el.appendChild(this.container)}disable(){this._enabled=!1,this.container.remove()}dispose(){this.disable()}}n.Cache.enabled=!0;class $e extends n.EventDispatcher{el;renderer;scene;camera;info;controls;renderPipeline;timer;roomEnvironment;interactionManager;objectManager;viewerHelper;cssRenderer;frameCount=1;frameloop="demand";constructor({el:e,rendererOptions:t}){super(),this.el=e,this.renderer=this._initRenderer(t),this.scene=this.createScene(),this.camera=this.createPerspectiveCamera(),this.info=new We(this.el,this.renderer),this.controls=new le(this.camera,this.renderer.domElement),this.renderPipeline=new he(this.renderer,this.scene,this.camera),this.timer=new n.Timer,this.roomEnvironment=new de(this.renderer),this.interactionManager=new oe(this.renderer.domElement,this.scene,this.camera),this.objectManager=new ce,this.viewerHelper=new He(this),this.cssRenderer=new ue(this.el),window.addEventListener("resize",this.onWindowResize)}onWindowResize=()=>{const e=this.el.clientWidth,t=this.el.clientHeight;this.camera instanceof n.PerspectiveCamera?(this.camera.aspect=e/t,this.camera.updateProjectionMatrix()):this.camera instanceof n.OrthographicCamera&&(this.camera.left=-e/2,this.camera.right=e/2,this.camera.top=t/2,this.camera.bottom=-t/2,this.camera.updateProjectionMatrix()),this.renderer.setSize(e,t),this.cssRenderer.resize(e,t),this.render()};async init(){await this.renderer.init(),this.roomEnvironment.update(),this.scene.environment=this.roomEnvironment.envMap}setCamera(e){this.camera=e,this.controls.camera=e,this.interactionManager.setCamera(e),this.renderPipeline.setCamera(e),this.onWindowResize(),this.dispatchEvent({type:"cameraChange",camera:e})}setCameraByType(e){e==="perspective"&&!(this.camera instanceof n.PerspectiveCamera)?this.setCamera(this.createPerspectiveCamera()):e==="orthographic"&&!(this.camera instanceof n.OrthographicCamera)&&this.setCamera(this.createOrthographicCamera())}render(e=1){return this.frameCount+=e,new Promise(t=>{const s=()=>{this.removeEventListener("afterRender",s),t()};this.addEventListener("afterRender",s)})}animate=e=>{this.timer.update(e);const t=this.timer.getDelta();this.dispatchEvent({type:"beforeControlsUpdate",time:e,delta:t});let s=this.controls.update(t);this.dispatchEvent({type:"afterControlsUpdate",time:e,delta:t}),this.frameCount>0&&(this.frameCount--,s=!0),this.frameloop==="always"&&(s=!0),s&&(this.dispatchEvent({type:"beforeRender",time:e,delta:t}),this.renderer.info.reset(),this.renderPipeline.render(),this.cssRenderer.render(this.scene,this.camera),this.info.update(),this.dispatchEvent({type:"afterRender",time:e,delta:t}))};_initRenderer(e){const t=new n.WebGPURenderer({logarithmicDepthBuffer:!0,antialias:!1,depth:!1,trackTimestamp:!0,...e});return t.setSize(this.el.clientWidth,this.el.clientHeight),t.shadowMap.enabled=!0,t.shadowMap.type=n.PCFShadowMap,t.toneMapping=n.AgXToneMapping,t.toneMappingExposure=1,t.info.autoReset=!1,t.setPixelRatio(window.devicePixelRatio),t.setAnimationLoop(this.animate),this.el.appendChild(t.domElement),t}createScene(){const e=new n.Scene;return e.background=new n.Color(0),e}createPerspectiveCamera(){const e=new n.PerspectiveCamera(50,this.el.clientWidth/this.el.clientHeight,.1,1e5);return e.position.setScalar(5),e}createOrthographicCamera(){const e=new n.OrthographicCamera(-this.el.clientWidth/2,this.el.clientWidth/2,this.el.clientHeight/2,-this.el.clientHeight/2,.1,1e5);return e.position.setScalar(5),e}dispose(){this.el.removeChild(this.renderer.domElement),window.removeEventListener("resize",this.onWindowResize),this.info.dispose(),this.interactionManager.dispose(),this.roomEnvironment.dispose(),this.cssRenderer.dispose(),this.renderPipeline.dispose(),this.renderer.dispose()}}class me extends re.GLTFLoader{constructor(e){super(e)}parse(e,t,s,i){if(Ke(e.slice(0,8))==="SBMG----"){const a=Qe(e.slice(8));return super.parse(a,t,s,i)}else return super.parse(e,t,s,i)}}function Ke(o){return new TextDecoder().decode(new Uint8Array(o))}function Qe(o){const e=new DataView(o);for(let t=0;t<e.byteLength;t++){const s=e.getUint8(t),i=(s>>4&15)+(s<<4&240);e.setUint8(t,i)}return e.buffer}const Xe=8,Ve=130,ee=66,Ye="SBK-----",Je="SBM-----",ge=new TextDecoder,Ze=new TextEncoder;function et(o){let e=Xe;const t=new Uint8Array(o,0,e);if(ge.decode(t)!==Ye)return o;e+=Ve;const i=new Uint8Array(o,0,e);if(i[40]===1){const a=Ze.encode(Je),c=new Uint8Array([i[41]]),h=tt(i),l=st(h);let p=ee%l.length;const m=e+ee,y=new Uint8Array(o,m),g=new Uint8Array(y.length);for(let C=0;C<y.length;C++)g[C]=y[C]^l[p],p=(p+1)%l.length;const v=new Uint8Array(a.length+c.length+g.length);return v.set(a),v.set(c,a.length),v.set(g,a.length+c.length),v.buffer}}function tt(o){const e=new Uint8Array(128);return e.set(o.slice(42,74),0),e.set(o.slice(74,138),32),e.set(o.slice(8,40),96),e}function st(o){const e=new Uint8Array(64);return e.set(o.slice(0,8),0),e.set(o.slice(24,32),8),e.set(o.slice(40,56),16),e.set(o.slice(64,88),32),e.set(o.slice(96,104),56),e}const it=(o,e,t)=>{const s=o.buffer.slice(t,t+e);let i=ge.decode(s);return i=i.replace("\\","/"),i.startsWith("Maps/")||(i=`Maps/${i}`),i},nt=(o,e,t)=>{const[s,i,r,a,c]=e,h=t||a<1;return new n.MeshStandardNodeMaterial({name:o,color:new n.Color(s,i,r),opacity:a,transparent:h,alphaTest:.01,side:c})},rt=o=>o?.toLowerCase().endsWith(".png")??!1;class at{data;options;textureLoader;littleEndian=!0;materials=new Map;constructor(e,t){this.data=e,this.options=t,this.textureLoader=new n.TextureLoader(t.manager),this.textureLoader.setCrossOrigin(t.crossOrigin),this.textureLoader.setRequestHeader(t.requestHeader)}parse(e,t){let s=this.data;const i=et(this.data);i&&(s=i);const r=new DataView(s);let a=8;const c=r.getUint8(a);a+=1,c===1?this._parseV2(r,a,e):c===2?this._parseV2(r,a,e):c===3?this._parseV3(r,a,e):t?.(new Error(`SBMLoader: Unsupported SBM version: ${c}`))}_parseV2(e,t,s){const i=new n.Group,r=e.getUint16(t,this.littleEndian);t+=2;const a=e.getUint16(t,this.littleEndian);t+=2;for(let c=0;c<r;++c){const h=e.getUint16(t,this.littleEndian).toString();t+=2,t+=4,t+=4,t+=4,t+=4;const l=e.getFloat32(t,this.littleEndian);t+=4;const p=e.getFloat32(t,this.littleEndian);t+=4;const m=e.getFloat32(t,this.littleEndian);t+=4;const y=e.getFloat32(t,this.littleEndian);t+=4,t+=4,t+=4,t+=4,t+=4;let g=e.getUint8(t);t+=1,g===0?g=n.FrontSide:g===1?g=n.BackSide:g===2&&(g=n.DoubleSide);const v=e.getUint16(t,this.littleEndian);t+=2;const C=v>0?it(e,v,t):"";if(t+=v,!this.materials.has(h)){const S=nt(h,[l,p,m,y,g],rt(C));this.materials.set(h,S),C&&this.options.path&&this.textureLoader.load(n.LoaderUtils.resolveURL(C,this.options.path),w=>{w.colorSpace=n.SRGBColorSpace,w.wrapS=n.RepeatWrapping,w.wrapT=n.RepeatWrapping,w.flipY=!1,w.anisotropy=16,S.map=w})}}for(let c=0;c<a;++c){const h=e.getUint16(t,this.littleEndian).toString();t+=2;const l=e.getUint16(t,this.littleEndian).toString();t+=2;const p=[],m=[],y=[],g=[],v=e.getUint16(t,this.littleEndian);if(t+=2,v>0)for(let f=0;f<v;f++){const b=new n.Vector3;b.setX(e.getFloat32(t,this.littleEndian)),t+=4,b.setY(e.getFloat32(t,this.littleEndian)),t+=4,b.setZ(e.getFloat32(t,this.littleEndian)),t+=4,p.push(b)}const C=e.getUint16(t,this.littleEndian);if(t+=2,C>0)for(let f=0;f<C;f++)t+=4,t+=4,t+=4;const T=e.getUint16(t,this.littleEndian);if(t+=2,T>0)for(let f=0;f<T;f++){const b=new n.Vector2;b.setX(e.getFloat32(t,this.littleEndian)),t+=4,b.setY(e.getFloat32(t,this.littleEndian)),t+=4,m.push(b)}const S=e.getUint16(t,this.littleEndian);if(t+=2,S>0)for(let f=0;f<S;f++){const b=e.getUint16(t,this.littleEndian);t+=2;const R=e.getUint16(t,this.littleEndian);t+=2;const I=e.getUint16(t,this.littleEndian);t+=2;const x=[b,R,I];y.push(x),m.length>0&&g.push([m[x[0]],m[x[1]],m[x[2]]])}const w=[],E=[];for(let f=0;f<y.length;f++){const b=y[f],R=p[b[0]],I=p[b[1]],x=p[b[2]];w.push(...R.toArray(),...I.toArray(),...x.toArray());let F=new n.Vector2,D=new n.Vector2,B=new n.Vector2;const N=g[f];N!==void 0&&(F=N[0],D=N[1],B=N[2]),E.push(...F.toArray(),...D.toArray(),...B.toArray())}const P=new Float32Array(w),O=new Float32Array(E),M=new n.BufferGeometry;if(P.length>0&&M.setAttribute("position",new n.BufferAttribute(P,3)),O.length>0&&M.setAttribute("uv",new n.BufferAttribute(O,2)),M.computeVertexNormals(),this.materials.has(l)){const f=new n.Mesh(M,this.materials.get(l));f.name=h,f.castShadow=!0,f.receiveShadow=!0,i.add(f)}}s(i)}_parseV3(e,t,s){const i=new n.Group;console.warn("SBMLoader: SBM version 3 is not supported yet."),s(i)}}class fe extends n.Loader{load(e,t,s,i){let r;if(this.resourcePath!=="")r=this.resourcePath;else if(this.path!==""){const h=n.LoaderUtils.extractUrlBase(e);r=n.LoaderUtils.resolveURL(h,this.path)}else r=n.LoaderUtils.extractUrlBase(e);this.manager.itemStart(e);const a=h=>{i?i(h):console.error(h),this.manager.itemError(e),this.manager.itemEnd(e)},c=new n.FileLoader(this.manager);c.setPath(this.path),c.setResponseType("arraybuffer"),c.setRequestHeader(this.requestHeader),c.setWithCredentials(this.withCredentials),c.load(e,h=>{try{this.parse(h,r,l=>{t(l),this.manager.itemEnd(e)},a)}catch(l){a(l)}},s,a)}parse(e,t,s,i){const r=new TextDecoder().decode(e.slice(0,8));if(r!=="SBK-----"&&r!=="SBM-----"){i?.(new Error(`SBMLoader: Invalid SBM format: ${r}`));return}new at(e,{path:t,crossOrigin:this.crossOrigin,requestHeader:this.requestHeader,manager:this.manager}).parse(s,i)}parseAsync(e,t){return new Promise((s,i)=>{this.parse(e,t,r=>{s(r)},r=>{i(r)})})}}class L{static CACHE_NAME="u-space-model-loader-cache";static fileLoader=new n.FileLoader().setResponseType("arraybuffer");static dracoLoader=new De.DRACOLoader().setDecoderPath(`https://cdn.jsdelivr.net/npm/three@0.${n.REVISION}.0/examples/jsm/libs/draco/`);static ktx2Loader=new je.KTX2Loader().setTranscoderPath(`https://cdn.jsdelivr.net/npm/three@0.${n.REVISION}.0/examples/jsm/libs/basis/`);static gltfLoader=new re.GLTFLoader().setDRACOLoader(L.dracoLoader).setKTX2Loader(L.ktx2Loader).setMeshoptDecoder(J.MeshoptDecoder);static sbmxLoader=new me().setDRACOLoader(L.dracoLoader).setKTX2Loader(L.ktx2Loader).setMeshoptDecoder(J.MeshoptDecoder);static sbmLoader=new fe;static fbxLoader=new Be.FBXLoader;static objLoader=new Ne.OBJLoader;static stlLoader=new Ae.STLLoader;static setLoadingManager(e){this.fileLoader.manager=e,this.dracoLoader.manager=e,this.ktx2Loader.manager=e,this.gltfLoader.manager=e,this.sbmxLoader.manager=e,this.sbmLoader.manager=e,this.fbxLoader.manager=e,this.objLoader.manager=e,this.stlLoader.manager=e}static async setRenderer(e){await e.init(),this.ktx2Loader.detectSupport(e)}static setDracoPath(e){this.dracoLoader.setDecoderPath(e)}static setKTX2Path(e){this.ktx2Loader.setTranscoderPath(e)}static async loadAsync(e,t={persistent:!0}){const s=e.split(".").pop()?.split("?")[0].toLowerCase();let i;switch(t.persistent&&typeof caches<"u"?i=await this.getPersistentData(e):i=await this.fileLoader.loadAsync(e),s){case"gltf":case"glb":const r=await this.gltfLoader.parseAsync(i,n.LoaderUtils.extractUrlBase(e));return r.scene.animations=r.animations,r.scene;case"sbmx":const a=await this.sbmxLoader.parseAsync(i,n.LoaderUtils.extractUrlBase(e));return a.scene.animations=a.animations,a.scene;case"sbm":return await this.sbmLoader.parseAsync(i,n.LoaderUtils.extractUrlBase(e));case"fbx":return this.fbxLoader.parse(i,n.LoaderUtils.extractUrlBase(e));case"obj":const l=new TextDecoder().decode(i);return this.objLoader.parse(l);case"stl":const m=this.stlLoader.parse(i);return new n.Mesh(m,new n.MeshStandardNodeMaterial);default:throw new Error(`Unsupported model format: ${s}`)}}static async getPersistentData(e){try{const t=await caches.open(this.CACHE_NAME),s=await t.match(e);if(s)return await s.arrayBuffer();const i=await this.fileLoader.loadAsync(e),r=new Response(i);return await t.put(e,r),i}catch(t){return console.warn(`[LoaderManager] Failed to use Cache API for ${e}:`,t),await this.fileLoader.loadAsync(e)}}}class ot{static textureLoader=new n.TextureLoader;static hdrLoader=new Ue.HDRLoader;static cubeTextureLoader=new n.CubeTextureLoader;static setLoadingManager(e){this.textureLoader.manager=e,this.hdrLoader.manager=e,this.cubeTextureLoader.manager=e}static async loadAsyncTexture(e){return await this.textureLoader.loadAsync(e)}static async loadAsyncHDR(e){const t=await this.hdrLoader.loadAsync(e);return t.mapping=n.EquirectangularReflectionMapping,t}static async loadAsyncCubeTexture(e,t){return this.cubeTextureLoader.setPath(e),await this.cubeTextureLoader.loadAsync(t)}}class _ extends n.Mesh{isBaseMesh=!0;type="BaseMesh";ignoreInvisibleWhenRaycast=!0;constructor(...e){super(...e)}raycast(e,t){return this.visible===!1&&this.ignoreInvisibleWhenRaycast===!0?!1:super.raycast(e,t)}}class X extends n.Group{isBaseGroup=!0;type="BaseGroup";ignoreInvisibleWhenRaycast=!0;constructor(...e){super(...e)}raycast(e,t){return this.visible===!1&&this.ignoreInvisibleWhenRaycast===!0?!1:super.raycast(e,t)}}class ye extends n.Sprite{isBaseSprite=!0;type="BaseSprite";ignoreInvisibleWhenRaycast=!0;constructor(...e){super(...e)}raycast(e,t){return this.visible===!1&&this.ignoreInvisibleWhenRaycast===!0?!1:super.raycast(e,t)}}class G extends X{isModel=!0;type="Model";static memoryCache=new Map;mixer=null;animations=[];actions=new Map;constructor(){super()}async loadAsync(e){const{url:t,cache:s=!0,persistent:i=!0}=e;try{let r;s?G.memoryCache.has(t)?r=G.memoryCache.get(t):(r=L.loadAsync(t,{persistent:i}),G.memoryCache.set(t,r)):r=L.loadAsync(t,{persistent:i});const a=await r,c=Ge.clone(a);return this.add(c),c.animations&&c.animations.length>0&&(this.animations=c.animations,this.mixer=new n.AnimationMixer(c)),c}catch(r){return console.error(`[Model] Failed to load model from ${t}:`,r),null}}playAnimation(e,t={}){if(!this.mixer||this.animations.length===0)return null;const{loop:s=!0,repetitions:i=1/0,timeScale:r=1,clampWhenFinished:a=!1}=t;let c;if(e===void 0?c=this.animations[0]:typeof e=="number"?c=this.animations[e]:c=this.animations.find(l=>l.name===e),!c)return console.warn(`[Model] Animation not found: ${e}`),null;let h=this.actions.get(c.name);return h||(h=this.mixer.clipAction(c),this.actions.set(c.name,h)),h.setLoop(s?n.LoopRepeat:n.LoopOnce,i),h.clampWhenFinished=a,h.timeScale=r,h.reset().play(),h}playAllAnimations(e={}){return this.animations.map((t,s)=>this.playAnimation(s,e)).filter(t=>t!==null)}stopAnimation(e){if(!this.mixer)return;if(e===void 0){this.mixer.stopAllAction();return}let t;typeof e=="number"?t=this.animations[e]?.name:t=e,t&&this.actions.get(t)?.stop()}updateAnimation(e){this.mixer?.update(e)}static clearMemoryCache(){this.memoryCache.clear()}static async clearPersistentCache(){typeof caches<"u"&&await caches.delete("u-space-loader-cache")}}class we extends _{isSphereMesh=!0;type="SphereMesh";constructor({geometryParameters:e,materialParameters:t}={}){super(),this.geometry=new n.SphereGeometry(e?.radius,e?.widthSegments,e?.heightSegments,e?.phiStart,e?.phiLength,e?.thetaStart,e?.thetaLength),this.material=new n.MeshStandardNodeMaterial(t)}}class Q extends _{isTubeMesh=!0;type="TubeMesh";constructor({geometryParameters:e,materialParameters:t}={}){super(),this.geometry=new n.TubeGeometry(e?.path,e?.tubularSegments,e?.radius,e?.radialSegments,e?.closed),this.material=new n.MeshStandardNodeMaterial(t)}}class ct extends X{isTopology=!0;type="Topology";parameters={nodeColor:255,nodeRadius:.5,edgeColor:65280,edgeRadius:.1,pathColor:16711935,pathRadius:.2};nodes=new Map;adjacencyMap=new Map;graphGroup=null;pathMeshes=[];constructor(e){super(),e&&Object.assign(this.parameters,e)}addNode(e,t){this.nodes.has(e)&&console.warn(`[Topology] Node ${e} already exists. Overwriting.`),this.nodes.set(e,t),this.adjacencyMap.has(e)||this.adjacencyMap.set(e,new Map)}removeNode(e){if(!this.nodes.has(e)){console.warn(`[Topology] Node ${e} does not exist.`);return}this.nodes.delete(e),this.adjacencyMap.delete(e)}addEdge(e,t,s,i=!0){const r=this.nodes.get(e),a=this.nodes.get(t);if(!r||!a){console.error(`[Topology] Cannot add edge. One or both nodes not found: ${e}, ${t}`);return}const c=s??r.distanceTo(a);this.getNeighbors(e)?.set(t,c),i&&this.getNeighbors(t)?.set(e,c)}removeEdge(e,t,s=!0){this.getNeighbors(e)?.delete(t),s&&this.getNeighbors(t)?.delete(e)}getShortestPath(e,t){if(!this.nodes.has(e)||!this.nodes.has(t))return console.warn("[Topology] Start or End node not found."),[];const s=new Map,i=new Map,r=new Set;for(const[h]of this.nodes)s.set(h,1/0),i.set(h,null),r.add(h);for(s.set(e,0);r.size>0;){let h=null,l=1/0;for(const m of r){const y=s.get(m);y<l&&(l=y,h=m)}if(h===null||h===t||l===1/0)break;r.delete(h);const p=this.adjacencyMap?.get(h);if(p)for(const[m,y]of p){if(!r.has(m))continue;const g=s.get(h)+y;g<s.get(m)&&(s.set(m,g),i.set(m,h))}}const a=[];let c=t;if(i.get(t)===null&&e!==t)return[];for(;c!==null;){const h=this.nodes.get(c);h&&a.unshift(h),c=i.get(c)||null}return a}renderGraph(){this.clearGraph(),this.graphGroup=new n.Group;const e=new we({geometryParameters:{radius:this.parameters.nodeRadius,widthSegments:16,heightSegments:16},materialParameters:{color:this.parameters.nodeColor}});this.nodes.forEach((s,i)=>{const r=e.clone();r.position.copy(s),Object.assign(r.userData,{id:i,type:"node"}),this.graphGroup.add(r)});const t=new Set;this.adjacencyMap.forEach((s,i)=>{s.forEach((r,a)=>{const c=[i,a].sort().join("-");if(t.has(c))return;t.add(c);const h=this.nodes.get(i),l=this.nodes.get(a);if(h&&l){const p=new n.LineCurve3(h,l),m=new Q({geometryParameters:{path:p,tubularSegments:1,radius:this.parameters.edgeRadius,radialSegments:8,closed:!1},materialParameters:{color:this.parameters.edgeColor}});Object.assign(m.userData,{from:i,to:a,weight:r,type:"edge"}),this.graphGroup.add(m)}})}),this.add(this.graphGroup)}clearGraph(){this.graphGroup&&(this.remove(this.graphGroup),this.graphGroup.traverse(e=>{e instanceof n.Mesh&&(e.geometry.dispose(),e.material.dispose())}),this.graphGroup=null)}renderPath(e,t=this.parameters.pathColor){if(e.length<2)return;const s=new n.CatmullRomCurve3(e,!1,"catmullrom",0),i=new Q({geometryParameters:{path:s,tubularSegments:e.length*10,radius:this.parameters.pathRadius,closed:!1},materialParameters:{color:t}});return this.add(i),this.pathMeshes.push(i),i}clearPaths(){this.pathMeshes.forEach(e=>{this.remove(e),e.geometry.dispose(),e.material.dispose()}),this.pathMeshes=[]}exportData(){const e={};this.nodes.forEach((i,r)=>{e[r]={x:i.x,y:i.y,z:i.z}});const t=[],s=new Set;return this.adjacencyMap.forEach((i,r)=>{i.forEach((a,c)=>{const h=[r,c].sort().join("-");s.has(h)||(s.add(h),t.push({from:r,to:c,weight:a}))})}),{nodes:e,edges:t}}importData(e){this.clearGraph(),this.clearPaths(),this.nodes.clear(),this.adjacencyMap.clear(),Object.entries(e.nodes).forEach(([t,s])=>{this.addNode(t,new n.Vector3(s.x,s.y,s.z))}),e.edges.forEach(({from:t,to:s,weight:i})=>{this.addEdge(t,s,i)}),this.renderGraph()}dispose(){this.clearGraph(),this.clearPaths()}getNeighbors(e){return this.adjacencyMap.get(e)}}class ht extends ye{isPoi=!0;type="Poi";parameters={img:"",text:"",fontSize:32,fontFamily:"Arial",color:"#ffffff",iconSize:64,padding:10,backgroundColor:"rgba(0, 0, 0, 0)",borderRadius:8,textPosition:"right",scaleFactor:.01};_canvas=document.createElement("canvas");_lastParametersJSON="";constructor(e={}){super(new n.SpriteNodeMaterial),Object.assign(this.parameters,e),this.updateAsync()}async updateAsync(e={}){Object.assign(this.parameters,e);const t=JSON.stringify(this.parameters);if(t===this._lastParametersJSON)return;this._lastParametersJSON=t;const s=this._canvas,i=s.getContext("2d");if(!i)return;i.font=`${this.parameters.fontSize}px ${this.parameters.fontFamily}`;let r=null;this.parameters.img&&(r=await this._loadImage(this.parameters.img));const{text:a,fontSize:c,color:h,iconSize:l,padding:p,backgroundColor:m,borderRadius:y,textPosition:g,scaleFactor:v}=this.parameters,C=i.measureText(a),T=a?C.width:0,S=a?c:0;let w=0,E=0,P=0,O=0,M=0,f=0;const b=!!r,R=!!a;if(b&&R)switch(g){case"top":w=Math.max(l,T),E=l+p+S,M=(w-T)/2,f=S/2,P=(w-l)/2,O=S+p;break;case"bottom":w=Math.max(l,T),E=l+p+S,P=(w-l)/2,O=0,M=(w-T)/2,f=l+p+S/2;break;case"left":w=l+p+T,E=Math.max(l,S),M=0,f=E/2,P=T+p,O=(E-l)/2;break;default:w=l+p+T,E=Math.max(l,S),P=0,O=(E-l)/2,M=l+p,f=E/2;break}else b?(w=l,E=l,P=0,O=0):R&&(w=T,E=S,M=0,f=S/2);const I=w+p*2,x=E+p*2;if(s.width=I,s.height=x,i.font=`${c}px ${this.parameters.fontFamily}`,m&&(i.fillStyle=m,this._drawRoundedRect(i,0,0,I,x,y),i.fill()),b&&i.drawImage(r,P+p,O+p,l,l),R){i.fillStyle=h;const B=i.measureText(a),N=B.actualBoundingBoxAscent+B.actualBoundingBoxDescent,Pe=B.actualBoundingBoxAscent-N/2;i.textBaseline="alphabetic",i.fillText(a,M+p,f+p+Pe)}const F=this.material.map,D=new n.CanvasTexture(s);D.colorSpace=n.SRGBColorSpace,this.material.map=D,F?.dispose(),this.scale.set(I*v,x*v,1)}_loadImage(e){return new Promise((t,s)=>{if(typeof e=="string"){const i=new Image;i.crossOrigin="Anonymous",i.onload=()=>t(i),i.onerror=()=>s(new Error(`Failed to load image: ${e}`)),i.src=e}else t(e)})}_drawRoundedRect(e,t,s,i,r,a){e.beginPath(),e.moveTo(t+a,s),e.lineTo(t+i-a,s),e.quadraticCurveTo(t+i,s,t+i,s+a),e.lineTo(t+i,s+r-a),e.quadraticCurveTo(t+i,s+r,t+i-a,s+r),e.lineTo(t+a,s+r),e.quadraticCurveTo(t,s+r,t,s+r-a),e.lineTo(t,s+a),e.quadraticCurveTo(t,s,t+a,s),e.closePath()}dispose(){this.material.map?.dispose(),this.material.dispose()}}class V extends _{isShapeMesh=!0;type="ShapeMesh";constructor({geometryParameters:e,materialParameters:t}={}){super(),this.geometry=new n.ShapeGeometry(e?.shape,e?.curveSegments),this.material=new n.MeshStandardNodeMaterial(t),this.geometry.rotateX(-Math.PI/2)}static createFromPoints(e,t={}){return new V({...t,geometryParameters:{...t.geometryParameters,shape:new n.Shape(e.map(s=>new n.Vector2(s.x,-s.z)))}})}}class Y extends _{isExtrudeMesh=!0;type="ExtrudeMesh";constructor({geometryParameters:e,materialParameters:t}={}){super(),this.geometry=new n.ExtrudeGeometry(e?.shape,e?.options),this.material=new n.MeshStandardNodeMaterial(t),this.geometry.rotateX(-Math.PI/2)}static createFromPoints(e,t={}){return new Y({...t,geometryParameters:{...t.geometryParameters,shape:new n.Shape(e.map(s=>new n.Vector2(s.x,-s.z)))}})}}class lt extends _{isPlaneMesh=!0;type="PlaneMesh";constructor({geometryParameters:e,materialParameters:t}={}){super(),this.geometry=new n.PlaneGeometry(e?.width,e?.height,e?.widthSegments,e?.heightSegments),this.material=new n.MeshStandardNodeMaterial(t)}}class dt extends _{isCircleMesh=!0;type="CircleMesh";constructor({geometryParameters:e,materialParameters:t}={}){super(new n.CircleGeometry(e?.radius,e?.segments,e?.thetaStart,e?.thetaLength),new n.MeshStandardNodeMaterial(t)),this.geometry.rotateX(-Math.PI/2)}}class j{static traverseMeshes(e,t){e.traverse(s=>{s instanceof n.Mesh&&t(s)})}}class pt{static flow(e={}){const{baseColor:t=16777215,flowColor:s=65280,speed:i=1,scale:r=3,intensity:a=4}=e,c=d.color(new A.Color(t)),h=d.color(new A.Color(s)),l=d.uv().x.mul(r).sub(d.time.mul(i)),p=d.pow(d.sin(l).add(1).mul(.5),a);return d.mix(c,h,p)}static breathe(e={}){const{baseColor:t=16777215,breathColor:s=65280,speed:i=1,intensity:r=2}=e,a=d.color(new A.Color(t)),c=d.color(new A.Color(s)),h=d.sin(d.time.mul(i)).add(1).mul(.5),l=d.pow(h,r);return d.mix(a,c,l)}static fluid(e={}){const{baseColor:t=16777215,flowColor:s=255,speed:i=1,scale:r=1,intensity:a=1,distortion:c=.5}=e,h=d.color(new A.Color(t)),l=d.color(new A.Color(s)),p=d.uv().mul(r),m=d.time.mul(i),y=d.mx_noise_float(p.add(m),1,0),g=p.add(y.mul(c)),v=d.mx_noise_float(g,1,0).add(1).mul(.5),C=d.pow(v,a);return d.mix(h,l,C)}}function ut(o){}const W="uSpaceHighlight",k=`${W}/enabled`,ve=`${W}/opacity`,be=`${W}/color`,Ce=`${W}/overwrite`,$="uSpaceBreathe",z=`${$}/enabled`,Se=`${$}/color`,Ee=`${$}/speed`,Te=`${$}/intensity`,q=new WeakMap,mt=d.Fn(()=>{const o=d.userData(k,"uint"),e=d.userData(be,"uint"),t=d.userData(Ce,"uint"),s=ie(e),i=d.materialColor.mul(s),r=d.select(t.greaterThan(0),s,i),a=d.select(o.greaterThan(0),r,d.materialColor),c=d.userData(z,"uint"),h=d.userData(Se,"uint"),l=d.userData(Ee,"float"),p=d.userData(Te,"float"),m=ie(h),y=d.sin(d.time.mul(l)).add(1).mul(.5),g=d.pow(y,p),v=d.mix(a,m,g);return d.select(c.greaterThan(0),v,a)})(),gt=d.Fn(()=>{const o=d.userData(k,"uint"),e=d.userData(ve,"float");return d.select(o.greaterThan(0),e,d.materialOpacity)})();function te(o){const e=o.material;if(!e||Array.isArray(e))return;let t=q.get(e);t||(t={colorNode:e.colorNode,opacityNode:e.opacityNode,transparent:e.transparent,activeMeshes:new Set},q.set(e,t)),t.activeMeshes.add(o),e.transparent=!0,e.colorNode=mt,e.opacityNode=gt,e.needsUpdate=!0}function se(o){const e=o.userData[k],t=o.userData[z];if(e||t)return;const s=o.material;if(!s||Array.isArray(s))return;const i=q.get(s);i&&(i.activeMeshes.delete(o),!(i.activeMeshes.size>0)&&(s.colorNode=i.colorNode,s.opacityNode=i.opacityNode,s.transparent=i.transparent,s.needsUpdate=!0,q.delete(s)))}class ft{static highlightColor(e,t={}){const s=Array.isArray(e)?e:[e],i=Object.assign({opacity:.5,color:16711680,overwrite:!1},t);i.color=new n.Color(i.color).getHex();for(const r of s)j.traverseMeshes(r,a=>{a.userData[k]=1,a.userData[ve]=i.opacity,a.userData[be]=i.color,a.userData[Ce]=i.overwrite?1:0,te(a)})}static removeHighlightColor(e){const t=Array.isArray(e)?e:[e];for(const s of t)j.traverseMeshes(s,i=>{i.userData[k]=0,se(i)})}static breatheColor(e,t={}){const s=Array.isArray(e)?e:[e],i=Object.assign({color:65280,speed:1,intensity:2},t);i.color=new n.Color(i.color).getHex();for(const r of s)j.traverseMeshes(r,a=>{a.userData[z]=1,a.userData[Se]=i.color,a.userData[Ee]=i.speed,a.userData[Te]=i.intensity,te(a)})}static removeBreatheColor(e){const t=Array.isArray(e)?e:[e];for(const s of t)j.traverseMeshes(s,i=>{i.userData[z]=0,se(i)})}}const ie=o=>{const e=o.shiftRight(16).bitAnd(255).toFloat().div(255),t=o.shiftRight(8).bitAnd(255).toFloat().div(255),s=o.bitAnd(255).toFloat().div(255);return d.vec3(e,t,s)};class Me extends u.Tween{viewer;constructor(e,t){super(t),this.viewer=e}_update=({time:e})=>{this.update(e)&&this.viewer.render()};easingByMode(e){const t=wt[e];return super.easing(t)}start(e,t){return this.viewer.addEventListener("afterControlsUpdate",this._update),super.start(e,t)}stop(){return this.viewer.removeEventListener("afterControlsUpdate",this._update),super.stop()}}function yt(o,e,t,s={},i,r){return new Promise((a,c)=>{const{duration:h=1e3,delay:l=0,repeat:p=!1,mode:m="Linear.None",yoyo:y=!1}=s,g=new Me(o,e).to(t,h).easingByMode(m).delay(l).onUpdate(v=>{i?.(v,g)}).onComplete(()=>{a()}).onStop(()=>{c("animation stop")}).onStart(()=>{r?.(g)});typeof p=="number"?g.repeat(p):typeof p=="boolean"&&p&&g.repeat(1/0),y&&g.repeatDelay(20),g.yoyo(y),g.start()})}const wt={"Linear.None":u.Easing.Linear.None,"Quadratic.In":u.Easing.Quadratic.In,"Quadratic.Out":u.Easing.Quadratic.Out,"Quadratic.InOut":u.Easing.Quadratic.InOut,"Cubic.In":u.Easing.Cubic.In,"Cubic.Out":u.Easing.Cubic.Out,"Cubic.InOut":u.Easing.Cubic.InOut,"Quartic.In":u.Easing.Quartic.In,"Quartic.Out":u.Easing.Quartic.Out,"Quartic.InOut":u.Easing.Quartic.InOut,"Quintic.In":u.Easing.Quintic.In,"Quintic.Out":u.Easing.Quintic.Out,"Quintic.InOut":u.Easing.Quintic.InOut,"Sinusoidal.In":u.Easing.Sinusoidal.In,"Sinusoidal.Out":u.Easing.Sinusoidal.Out,"Sinusoidal.InOut":u.Easing.Sinusoidal.InOut,"Exponential.In":u.Easing.Exponential.In,"Exponential.Out":u.Easing.Exponential.Out,"Exponential.InOut":u.Easing.Exponential.InOut,"Circular.In":u.Easing.Circular.In,"Circular.Out":u.Easing.Circular.Out,"Circular.InOut":u.Easing.Circular.InOut,"Elastic.In":u.Easing.Elastic.In,"Elastic.Out":u.Easing.Elastic.Out,"Elastic.InOut":u.Easing.Elastic.InOut,"Back.In":u.Easing.Back.In,"Back.Out":u.Easing.Back.Out,"Back.InOut":u.Easing.Back.InOut,"Bounce.In":u.Easing.Bounce.In,"Bounce.Out":u.Easing.Bounce.Out,"Bounce.InOut":u.Easing.Bounce.InOut},xe="0.0.5";window.__USPACE__={version:xe};Object.defineProperty(exports,"CSS2DObject",{enumerable:!0,get:()=>K.CSS2DObject});Object.defineProperty(exports,"CSS3DObject",{enumerable:!0,get:()=>U.CSS3DObject});Object.defineProperty(exports,"CSS3DSprite",{enumerable:!0,get:()=>U.CSS3DSprite});exports.BaseGroup=X;exports.BaseMesh=_;exports.BaseSprite=ye;exports.CSSRenderer=ue;exports.CameraControls=le;exports.CircleMesh=dt;exports.ExtrudeMesh=Y;exports.InteractionEvent=ae;exports.InteractionManager=oe;exports.MaterialEffects=ft;exports.Model=G;exports.ModelLoaderManager=L;exports.ObjectManager=ce;exports.ObjectUtils=j;exports.PlaneMesh=lt;exports.Poi=ht;exports.RenderPipeline=he;exports.RoomEnvironment=de;exports.SBMLoader=fe;exports.SBMXLoader=me;exports.ShapeMesh=V;exports.SphereMesh=we;exports.TSLEffects=pt;exports.TextureLoaderManager=ot;exports.Topology=ct;exports.TubeMesh=Q;exports.Tween=Me;exports.Viewer=$e;exports.reinterpretType=ut;exports.tweenAnimation=yt;exports.version=xe;