@displayxr/inline3d 1.43.1 → 1.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +129 -0
- package/THIRD_PARTY_NOTICES.md +26 -2
- package/camera.d.ts +7 -0
- package/cursor-depth.d.ts +275 -1
- package/dist/call.js +18 -4
- package/js/camera/pair-cursor.js +129 -26
- package/js/inline3d-cursor-bvh.js +147 -0
- package/js/inline3d-cursor-depth-playcanvas.js +507 -61
- package/js/inline3d-cursor-depth.js +497 -43
- package/js/inline3d-cursor-option.js +140 -6
- package/js/inline3d-cursor-perf.js +199 -0
- package/js/inline3d-cursor-shape.js +962 -0
- package/js/inline3d-model.js +30 -1
- package/js/inline3d-playcanvas-engine.js +2 -0
- package/js/inline3d-splat-layer-rig.js +3 -0
- package/js/inline3d-three.js +263 -30
- package/js/vendor/three-mesh-bvh.js +3 -0
- package/model.d.ts +1 -1
- package/package.json +7 -1
- package/splat.d.ts +1 -1
- package/three.d.ts +43 -4
package/js/inline3d-model.js
CHANGED
|
@@ -42,11 +42,38 @@ import { guardedAttach } from './inline3d-splat-shared.js';
|
|
|
42
42
|
import * as THREE from 'three';
|
|
43
43
|
import { EyeCamera, EdgeFeather, DepthCursor, raycastHitTest } from './inline3d-three.js';
|
|
44
44
|
import { resolveCursorOption } from './inline3d-cursor-depth.js';
|
|
45
|
+
import { CURSOR_MODEL_RAYS_PER_FRAME } from './inline3d-cursor-perf.js';
|
|
45
46
|
import { SceneViewer } from './inline3d-viewer.js';
|
|
46
47
|
// Procedural — built in memory, no asset to serve. Imported eagerly rather than lazily because it
|
|
47
48
|
// is the default lighting path, so deferring it would only add a frame of unlit content.
|
|
48
49
|
import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';
|
|
49
50
|
|
|
51
|
+
/**
|
|
52
|
+
* `cursor: 'depth'`'s hit test over the model: three's plain raycast at once, then the
|
|
53
|
+
* BVH-accelerated one (./inline3d-cursor-bvh.js, with its vendored three-mesh-bvh slice) as soon as
|
|
54
|
+
* that module arrives. Called on opt-in ONLY — the one place the module is imported, dynamically,
|
|
55
|
+
* so a page without the cursor never downloads it (ADR-046 §0). If it cannot load, the plain
|
|
56
|
+
* raycast simply stays.
|
|
57
|
+
*/
|
|
58
|
+
function cursorHitTest(content) {
|
|
59
|
+
const plain = raycastHitTest(THREE, [content]);
|
|
60
|
+
let fast = null;
|
|
61
|
+
let failed = false;
|
|
62
|
+
import('./inline3d-cursor-bvh.js').then(
|
|
63
|
+
(m) => {
|
|
64
|
+
fast = m.bvhHitTest(THREE, [content]);
|
|
65
|
+
},
|
|
66
|
+
(err) => {
|
|
67
|
+
failed = true;
|
|
68
|
+
console.warn('[inline3d/model] cursor: depth: the BVH pick could not load; using the plain raycast.', err);
|
|
69
|
+
},
|
|
70
|
+
);
|
|
71
|
+
const hitTest = (origin, direction) => (fast ? fast(origin, direction) : plain(origin, direction));
|
|
72
|
+
/** Diagnostics (`cursor: { debug }`): which pick is answering. */
|
|
73
|
+
hitTest.info = () => (fast ? fast.info() : { mode: failed ? 'plain (bvh failed to load)' : 'plain (bvh loading)' });
|
|
74
|
+
return hitTest;
|
|
75
|
+
}
|
|
76
|
+
|
|
50
77
|
/** Cached across calls so a grid of models resolves the loader module once. */
|
|
51
78
|
let _GLTFLoader = null;
|
|
52
79
|
|
|
@@ -391,7 +418,9 @@ function addModelUnguarded(wall, canvas, src, opts = {}) {
|
|
|
391
418
|
viewerEase: opts.viewerEase,
|
|
392
419
|
}).useEyeCamera(EyeCamera, EdgeFeather);
|
|
393
420
|
const cursorOpts = resolveCursorOption(opts.cursor, '@displayxr/inline3d/model');
|
|
394
|
-
|
|
421
|
+
// Amortised pick (a few rays a frame): the sprite follows the newest pointer position every
|
|
422
|
+
// frame and the pick only refreshes its depth, so a heavy mesh never stretches the frame.
|
|
423
|
+
if (cursorOpts) viewer.useDepthCursor(DepthCursor, cursorHitTest, { raysPerFrame: CURSOR_MODEL_RAYS_PER_FRAME, ...cursorOpts });
|
|
395
424
|
|
|
396
425
|
if (envMap) viewer.scene.environment = envMap;
|
|
397
426
|
else if (environment === 'room') addRoomEnvironment(viewer);
|
|
@@ -58,10 +58,12 @@ export {
|
|
|
58
58
|
SEMANTIC_COLOR,
|
|
59
59
|
ShaderChunks,
|
|
60
60
|
SHADERLANGUAGE_GLSL,
|
|
61
|
+
SHADERLANGUAGE_WGSL,
|
|
61
62
|
SHADER_FORWARD,
|
|
62
63
|
CHUNKAPI_2_8,
|
|
63
64
|
// setSource's frame snapshot
|
|
64
65
|
RenderTarget,
|
|
66
|
+
FILTER_LINEAR,
|
|
65
67
|
FILTER_NEAREST,
|
|
66
68
|
// setSource's live outgoing asset (./inline3d-splat-live.js)
|
|
67
69
|
Layer,
|
|
@@ -570,6 +570,9 @@ export class LayerRigCameras {
|
|
|
570
570
|
L.planeM = plane;
|
|
571
571
|
L.photoConvergenceM = frame ? frame.D : null;
|
|
572
572
|
const round = hasRun && frame ? roundViews(entries, frame, k, this._round, plane) : null;
|
|
573
|
+
// cursor: 'depth' picks the display run through these exact views (./inline3d-cursor-depth-playcanvas.js).
|
|
574
|
+
this.lastEntries = hasRun ? entries : null;
|
|
575
|
+
this.lastRound = round;
|
|
573
576
|
let reason = null;
|
|
574
577
|
if (!hasRun) reason = this._syncReason;
|
|
575
578
|
else if (entries.length < 2) reason = 'mono (one view): nothing to round — identical to the photo rig';
|
package/js/inline3d-three.js
CHANGED
|
@@ -55,14 +55,24 @@
|
|
|
55
55
|
import {
|
|
56
56
|
CursorDepthPlacer,
|
|
57
57
|
CursorPointer,
|
|
58
|
-
cursorArrowMesh,
|
|
59
58
|
cursorArrowFootprint,
|
|
60
59
|
cursorDefaultHeight,
|
|
61
60
|
cursorModelMatrix,
|
|
61
|
+
cursorPlacementSoften,
|
|
62
|
+
cursorArrowMesh,
|
|
63
|
+
cursorSoftArrowBox,
|
|
64
|
+
cursorSoftArrowGLSL,
|
|
65
|
+
CursorShapeSelector,
|
|
66
|
+
cursorShapeTexture,
|
|
67
|
+
cursorSpriteBox,
|
|
68
|
+
cursorSpriteGLSL,
|
|
69
|
+
cursorSpriteRect,
|
|
62
70
|
cursorViewRay,
|
|
71
|
+
resolveCursorSoften,
|
|
63
72
|
CURSOR_DEFAULT_TUNING,
|
|
64
73
|
CURSOR_OUTLINE_COLOR,
|
|
65
74
|
} from './inline3d-cursor-depth.js';
|
|
75
|
+
import { CursorAmortisedPick, CursorDebugStats, cursorDebugMode } from './inline3d-cursor-perf.js';
|
|
66
76
|
|
|
67
77
|
/**
|
|
68
78
|
* A reusable three.js camera driven directly by an XRView's matrices. Construct once with
|
|
@@ -496,33 +506,73 @@ export class DepthCursor {
|
|
|
496
506
|
* content) while it is still; 'screen' never parallaxes; 'world' always does.
|
|
497
507
|
* @param {'canvas'|'window'} [opts.pointerScope='canvas'] 'window' keeps the cursor over DOM
|
|
498
508
|
* layered on the canvas (overlay buttons) and hides the CSS cursor page-wide meanwhile.
|
|
509
|
+
* @param {'both'|'off'|'alpha'|'blur'|object} [opts.soften='both'] crosstalk softening of the
|
|
510
|
+
* LIFTED arrow (runtime ADR-046 Amendment 2 §B.7): an edge blur of 0.1 × its ghost offset
|
|
511
|
+
* (capped at 6% of its height, 8 px) and an opacity easing to 0.5 over 0.03 baselines of
|
|
512
|
+
* lift, both zero on the glass. A preset, or `{ mode, blurK, blurMaxPx, blurMaxFrac,
|
|
513
|
+
* alphaMin, fullD }` over the defaults. Drawn in the arrow's own shader.
|
|
514
|
+
* @param {string} [opts.shape='auto'] the sprite: 'auto' mirrors the page's CSS cursor under the
|
|
515
|
+
* pointer — every standard keyword has a sprite (`grab` the open hand, `text` the I-beam,
|
|
516
|
+
* the resize arrows, …), `url(…)` images are drawn as images, `none` draws nothing; a
|
|
517
|
+
* CURSOR_SHAPES name (or 'none') fixes it. (`color` tints the arrow only.)
|
|
518
|
+
* @param {(hit: {u: number, v: number, point: number[]|null, css: string|null, cssValue: string|null}) => string|null|undefined} [opts.shapeFor]
|
|
519
|
+
* per-frame override while the sprite draws: return a shape name, or nothing for `shape`'s.
|
|
499
520
|
* @param {object} [opts.viewSpace] Object3D whose world matrix maps view transforms to world.
|
|
500
|
-
* @param {number} [opts.raysPerFrame=0] 0 = the whole footprint every frame (two eyes ×
|
|
501
|
-
* points). N > 0 =
|
|
502
|
-
*
|
|
503
|
-
*
|
|
521
|
+
* @param {number} [opts.raysPerFrame=0] 0 = the whole footprint every frame (two eyes × 10
|
|
522
|
+
* points), synchronously. N > 0 = amortised: N rays a frame, cycling the footprint
|
|
523
|
+
* (alternating eyes), each point's last hit kept until the pointer moves away from where it
|
|
524
|
+
* was cast. The sprite still follows the NEWEST pointer position every frame, at the depth
|
|
525
|
+
* the pick has so far; the depth filter absorbs the cadence. ./model passes 3, ./splat 1
|
|
526
|
+
* (a gaussian-splat raycast costs ~8 ms a ray).
|
|
527
|
+
* @param {boolean|'both'} [opts.debug=false] true: log update() cost, rays a frame and the frame
|
|
528
|
+
* interval (rolling stats, at most once a second; `cursor.debugStats.last` holds the newest).
|
|
529
|
+
* 'both': that, and the OS cursor stays visible beside the sprite (the latency check).
|
|
504
530
|
*/
|
|
505
531
|
constructor(
|
|
506
532
|
THREE,
|
|
507
|
-
{ canvas, hitTest, height = null, color = 0xffffff, viewSpace = null, raysPerFrame = 0, margin, anchor = 'hybrid', pointerScope = 'canvas' },
|
|
533
|
+
{ canvas, hitTest, height = null, color = 0xffffff, viewSpace = null, raysPerFrame = 0, margin, anchor = 'hybrid', pointerScope = 'canvas', debug = false, soften, shape = 'auto', shapeFor = null },
|
|
508
534
|
) {
|
|
509
535
|
this._THREE = THREE;
|
|
510
536
|
this.canvas = canvas;
|
|
511
537
|
this.hitTest = hitTest;
|
|
538
|
+
const debugMode = cursorDebugMode(debug);
|
|
539
|
+
/** `cursor: { debug }` only: the rolling stats (null otherwise — nothing is measured). */
|
|
540
|
+
this.debugStats = null;
|
|
541
|
+
if (debugMode) {
|
|
542
|
+
this.debugStats = new CursorDebugStats({ info: typeof hitTest.info === 'function' ? hitTest.info : null });
|
|
543
|
+
this._rays = 0;
|
|
544
|
+
this._seenSamples = 0;
|
|
545
|
+
this._seenTime = 0;
|
|
546
|
+
const inner = hitTest;
|
|
547
|
+
this.hitTest = (o, d) => {
|
|
548
|
+
this._rays++;
|
|
549
|
+
return inner(o, d);
|
|
550
|
+
};
|
|
551
|
+
}
|
|
512
552
|
/** Sprite height (canvas heights) when set; null = the OS arrow's size, from the canvas's on-page height. */
|
|
513
553
|
this.height = height > 0 && Number.isFinite(height) ? height : null;
|
|
514
554
|
this.viewSpace = viewSpace;
|
|
515
555
|
this.raysPerFrame = raysPerFrame;
|
|
516
|
-
this.
|
|
517
|
-
this._next = 0;
|
|
556
|
+
this._pick = null; // amortised mode (raysPerFrame > 0): a CursorAmortisedPick, built on first use
|
|
518
557
|
const tuning = margin > 0 && Number.isFinite(margin) ? { ...CURSOR_DEFAULT_TUNING, margin } : CURSOR_DEFAULT_TUNING;
|
|
519
558
|
this.placer = new CursorDepthPlacer(tuning, { anchor });
|
|
520
|
-
this.pointer = new CursorPointer(canvas, { scope: pointerScope });
|
|
559
|
+
this.pointer = new CursorPointer(canvas, { scope: pointerScope, keepCss: debugMode === 'both' });
|
|
560
|
+
if (this.debugStats) this.debugStats.source = this.pointer.source;
|
|
521
561
|
/** The last placement (diagnostics): `{active, position, height, disparity, targetDisparity, anchored}`. */
|
|
522
562
|
this.placement = { active: false };
|
|
563
|
+
/** Crosstalk softening parameters (resolveCursorSoften). */
|
|
564
|
+
this.soften = resolveCursorSoften(soften, '@displayxr/inline3d/three DepthCursor');
|
|
565
|
+
/** The last frame's softening (diagnostics): `{blurPx, alpha, ghostPx, spritePx, radius, aa, soft}`. */
|
|
566
|
+
this.softening = null;
|
|
567
|
+
this._soft = null; // { geometry, material } — built on the first softened frame
|
|
568
|
+
/** Which sprite (the page's CSS cursor / fixed / shapeFor); `.shape` = the one drawn last. */
|
|
569
|
+
this.shapes = new CursorShapeSelector(this.pointer, { shape, shapeFor });
|
|
570
|
+
this._tex = null; // { geometry, material } — the textured quad, built on the first non-arrow sprite
|
|
571
|
+
this._textures = new Map(); // sprite key → THREE texture
|
|
523
572
|
|
|
524
573
|
// The arrow: a dark outline polygon, the fill inset over it; tip at the origin (the hotspot).
|
|
525
574
|
const fill = [((color >> 16) & 255) / 255, ((color >> 8) & 255) / 255, (color & 255) / 255, 1];
|
|
575
|
+
this._fill = fill;
|
|
526
576
|
const m = cursorArrowMesh(fill, CURSOR_OUTLINE_COLOR);
|
|
527
577
|
const geom = new THREE.BufferGeometry();
|
|
528
578
|
geom.setAttribute('position', new THREE.Float32BufferAttribute(m.positions, 3));
|
|
@@ -541,6 +591,12 @@ export class DepthCursor {
|
|
|
541
591
|
this.object.frustumCulled = false;
|
|
542
592
|
this.object.renderOrder = 1e9; // last: never occluded, it is in front by construction
|
|
543
593
|
this.object.visible = false;
|
|
594
|
+
this._crisp = { geometry: geom, material: mat };
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/** The sprite drawn last: a CURSOR_SHAPES name, 'none' or 'image'. */
|
|
598
|
+
get shape() {
|
|
599
|
+
return this.shapes.current;
|
|
544
600
|
}
|
|
545
601
|
|
|
546
602
|
/** Set the pointer position directly (canvas-normalised, v down), or null — for scripted input. */
|
|
@@ -554,31 +610,210 @@ export class DepthCursor {
|
|
|
554
610
|
* @param {number} [nowMs=performance.now()]
|
|
555
611
|
*/
|
|
556
612
|
update(views, nowMs = globalThis.performance ? globalThis.performance.now() : Date.now()) {
|
|
613
|
+
if (this.debugStats) return this._updateMeasured(views, nowMs);
|
|
614
|
+
return this._update(views, nowMs);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// `cursor: { debug }`: the same update, timed. Off, update() never reaches this.
|
|
618
|
+
_updateMeasured(views, nowMs) {
|
|
619
|
+
const clock = () => (globalThis.performance ? globalThis.performance.now() : Date.now());
|
|
620
|
+
this._rays = 0;
|
|
621
|
+
const t0 = clock();
|
|
622
|
+
const p = this._update(views, nowMs);
|
|
623
|
+
const t1 = clock();
|
|
624
|
+
const ptr = this.pointer;
|
|
625
|
+
const fresh = ptr.samples !== this._seenSamples && ptr.sampleTime > 0 && ptr.sampleTime !== this._seenTime;
|
|
626
|
+
const samples = ptr.samples - this._seenSamples;
|
|
627
|
+
this._seenSamples = ptr.samples;
|
|
628
|
+
this._seenTime = ptr.sampleTime;
|
|
629
|
+
this.debugStats.frame(t1 - t0, this._rays, t0, fresh ? t0 - ptr.sampleTime : null, samples);
|
|
630
|
+
return p;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
_update(views, nowMs) {
|
|
557
634
|
const vs = this._worldViews(views);
|
|
558
635
|
const uv = this.pointer.uv;
|
|
559
636
|
let p = { active: false };
|
|
637
|
+
let h = 0;
|
|
638
|
+
let nearestPoint = null;
|
|
560
639
|
if (uv && vs.length >= 2) {
|
|
561
640
|
const [u, v] = uv;
|
|
562
|
-
|
|
563
|
-
|
|
641
|
+
h = this.height ?? cursorDefaultHeight(this.pointer.cssHeight());
|
|
642
|
+
nearestPoint = this._footprintHit(vs, u, v, h);
|
|
564
643
|
p = this.placer.update(vs, { u, v, nearestPoint, cursorHeight: h, canvasPx: this.pointer.panelPx() }, nowMs / 1000);
|
|
565
644
|
}
|
|
566
645
|
this.placement = p;
|
|
567
|
-
|
|
646
|
+
let visible = !!p.active;
|
|
568
647
|
if (p.active) {
|
|
569
648
|
this.object.matrix.fromArray(cursorModelMatrix(p));
|
|
570
649
|
this.object.matrixWorldNeedsUpdate = true;
|
|
650
|
+
const [pw, ph] = this.pointer.panelSize();
|
|
651
|
+
const s = (this.softening = cursorPlacementSoften(p, vs, pw, ph, h, this.soften));
|
|
652
|
+
const sprite = this.shapes.pick({ u: uv[0], v: uv[1], point: nearestPoint }, nowMs);
|
|
653
|
+
if (sprite.kind === 'none') visible = false; // the page hides its cursor: so do we (and the OS one stays hidden)
|
|
654
|
+
else if (sprite.kind === 'shape' && sprite.name === 'arrow') this._useSoft(s);
|
|
655
|
+
else this._useSprite(s, sprite);
|
|
656
|
+
} else {
|
|
657
|
+
this.softening = null;
|
|
571
658
|
}
|
|
659
|
+
this.object.visible = visible;
|
|
572
660
|
this.pointer.hideCss(!!p.active);
|
|
573
661
|
return p;
|
|
574
662
|
}
|
|
575
663
|
|
|
664
|
+
// Crisp frames draw the arrow mesh exactly as without softening; softened ones swap in a quad
|
|
665
|
+
// whose shader evaluates the arrow at the runtime's 13 blur taps, times the opacity.
|
|
666
|
+
_useSoft(s) {
|
|
667
|
+
if (!s.soft) {
|
|
668
|
+
this.object.geometry = this._crisp.geometry;
|
|
669
|
+
this.object.material = this._crisp.material;
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
const soft = this._soft || (this._soft = this._makeSoft());
|
|
673
|
+
const u = soft.material.uniforms;
|
|
674
|
+
const [x0, y0, x1, y1] = cursorSoftArrowBox(s.radius, s.aa);
|
|
675
|
+
u.inline3dCursorBox.value.set(x0, y0, x1, y1);
|
|
676
|
+
u.inline3dCursorSoft.value.set(s.radius, s.alpha, s.aa, 0);
|
|
677
|
+
this.object.geometry = soft.geometry;
|
|
678
|
+
this.object.material = soft.material;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
_makeSoft() {
|
|
682
|
+
const THREE = this._THREE;
|
|
683
|
+
const geometry = new THREE.BufferGeometry();
|
|
684
|
+
// A unit quad; the vertex shader spreads it over the padded arrow box (arrow units, y down).
|
|
685
|
+
geometry.setAttribute('position', new THREE.Float32BufferAttribute([0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0], 3));
|
|
686
|
+
// three >= 0.154 names the output-transform chunk colorspace_fragment; 0.150-0.153 encodings_fragment.
|
|
687
|
+
const chunk = THREE.ShaderChunk && THREE.ShaderChunk.colorspace_fragment !== undefined ? 'colorspace_fragment' : 'encodings_fragment';
|
|
688
|
+
const material = new THREE.ShaderMaterial({
|
|
689
|
+
uniforms: {
|
|
690
|
+
inline3dCursorBox: { value: new THREE.Vector4() },
|
|
691
|
+
inline3dCursorSoft: { value: new THREE.Vector4(0, 1, 0, 0) },
|
|
692
|
+
inline3dCursorFill: { value: new THREE.Vector3(this._fill[0], this._fill[1], this._fill[2]) },
|
|
693
|
+
inline3dCursorOutline: { value: new THREE.Vector3(CURSOR_OUTLINE_COLOR[0], CURSOR_OUTLINE_COLOR[1], CURSOR_OUTLINE_COLOR[2]) },
|
|
694
|
+
},
|
|
695
|
+
vertexShader: `
|
|
696
|
+
uniform vec4 inline3dCursorBox;
|
|
697
|
+
varying vec2 vArrow;
|
|
698
|
+
void main() {
|
|
699
|
+
vArrow = vec2(mix(inline3dCursorBox.x, inline3dCursorBox.z, position.x), mix(inline3dCursorBox.y, inline3dCursorBox.w, position.y));
|
|
700
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(vArrow.x, -vArrow.y, 0.0, 1.0);
|
|
701
|
+
}`,
|
|
702
|
+
fragmentShader: `
|
|
703
|
+
uniform vec4 inline3dCursorSoft; // radius, opacity, aa (arrow units)
|
|
704
|
+
uniform vec3 inline3dCursorFill;
|
|
705
|
+
uniform vec3 inline3dCursorOutline;
|
|
706
|
+
varying vec2 vArrow;
|
|
707
|
+
${cursorSoftArrowGLSL()}
|
|
708
|
+
void main() {
|
|
709
|
+
vec4 c = inline3dSoftArrow(vArrow, inline3dCursorSoft.x, inline3dCursorSoft.z, inline3dCursorFill, inline3dCursorOutline);
|
|
710
|
+
gl_FragColor = vec4(c.rgb, c.a * inline3dCursorSoft.y);
|
|
711
|
+
#include <${chunk}>
|
|
712
|
+
}`,
|
|
713
|
+
transparent: true,
|
|
714
|
+
depthTest: false,
|
|
715
|
+
depthWrite: false,
|
|
716
|
+
side: THREE.DoubleSide,
|
|
717
|
+
toneMapped: false,
|
|
718
|
+
});
|
|
719
|
+
return { geometry, material };
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
// Every sprite but the arrow: a texture (a keyword shape rasterised once, or a url() image) on
|
|
723
|
+
// one soft quad — the same 13-tap blur and opacity, crisp at radius 0. One program for all.
|
|
724
|
+
_useSprite(s, sprite) {
|
|
725
|
+
const tex = this._texture(sprite);
|
|
726
|
+
const q = this._tex || (this._tex = this._makeTex());
|
|
727
|
+
const u = q.material.uniforms;
|
|
728
|
+
const radius = s.soft ? s.radius : 0;
|
|
729
|
+
const [x0, y0, x1, y1] = cursorSpriteBox(sprite, radius, s.aa);
|
|
730
|
+
const r = cursorSpriteRect(sprite);
|
|
731
|
+
u.inline3dCursorBox.value.set(x0, y0, x1, y1);
|
|
732
|
+
u.inline3dCursorRect.value.set(r[0], r[1], r[2], r[3]);
|
|
733
|
+
u.inline3dCursorSoft.value.set(radius, s.soft ? s.alpha : 1, 0, 0);
|
|
734
|
+
u.inline3dCursorTex.value = tex;
|
|
735
|
+
this.object.geometry = q.geometry;
|
|
736
|
+
this.object.material = q.material;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
_texture(sprite) {
|
|
740
|
+
let t = this._textures.get(sprite.key);
|
|
741
|
+
if (t) return t;
|
|
742
|
+
const THREE = this._THREE;
|
|
743
|
+
if (sprite.kind === 'image') {
|
|
744
|
+
t = new THREE.Texture(sprite.entry.image);
|
|
745
|
+
} else {
|
|
746
|
+
const d = cursorShapeTexture(sprite.name);
|
|
747
|
+
t = new THREE.DataTexture(d.data, d.width, d.height, THREE.RGBAFormat);
|
|
748
|
+
}
|
|
749
|
+
t.flipY = false; // row 0 = the sprite's top, as the shader reads it
|
|
750
|
+
t.generateMipmaps = false;
|
|
751
|
+
t.minFilter = THREE.LinearFilter;
|
|
752
|
+
t.magFilter = THREE.LinearFilter;
|
|
753
|
+
if (THREE.ClampToEdgeWrapping !== undefined) t.wrapS = t.wrapT = THREE.ClampToEdgeWrapping;
|
|
754
|
+
// The bytes are sRGB: decode on sampling, so the output transform does not encode them twice.
|
|
755
|
+
if ('colorSpace' in t && THREE.SRGBColorSpace) t.colorSpace = THREE.SRGBColorSpace;
|
|
756
|
+
else if (THREE.sRGBEncoding !== undefined) t.encoding = THREE.sRGBEncoding;
|
|
757
|
+
t.needsUpdate = true;
|
|
758
|
+
if (this._textures.size > 32) {
|
|
759
|
+
for (const old of this._textures.values()) old.dispose?.();
|
|
760
|
+
this._textures.clear();
|
|
761
|
+
}
|
|
762
|
+
this._textures.set(sprite.key, t);
|
|
763
|
+
return t;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
_makeTex() {
|
|
767
|
+
const THREE = this._THREE;
|
|
768
|
+
const geometry = new THREE.BufferGeometry();
|
|
769
|
+
geometry.setAttribute('position', new THREE.Float32BufferAttribute([0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0], 3));
|
|
770
|
+
const chunk = THREE.ShaderChunk && THREE.ShaderChunk.colorspace_fragment !== undefined ? 'colorspace_fragment' : 'encodings_fragment';
|
|
771
|
+
const material = new THREE.ShaderMaterial({
|
|
772
|
+
uniforms: {
|
|
773
|
+
inline3dCursorBox: { value: new THREE.Vector4() },
|
|
774
|
+
inline3dCursorRect: { value: new THREE.Vector4(0, 0, 1, 1) },
|
|
775
|
+
inline3dCursorSoft: { value: new THREE.Vector4(0, 1, 0, 0) },
|
|
776
|
+
inline3dCursorTex: { value: null },
|
|
777
|
+
},
|
|
778
|
+
vertexShader: `
|
|
779
|
+
uniform vec4 inline3dCursorBox;
|
|
780
|
+
varying vec2 vSprite;
|
|
781
|
+
void main() {
|
|
782
|
+
vSprite = vec2(mix(inline3dCursorBox.x, inline3dCursorBox.z, position.x), mix(inline3dCursorBox.y, inline3dCursorBox.w, position.y));
|
|
783
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(vSprite.x, -vSprite.y, 0.0, 1.0);
|
|
784
|
+
}`,
|
|
785
|
+
fragmentShader: `
|
|
786
|
+
uniform vec4 inline3dCursorRect; // the area the texture covers (sprite units, y down)
|
|
787
|
+
uniform vec4 inline3dCursorSoft; // radius (sprite units), opacity
|
|
788
|
+
uniform sampler2D inline3dCursorTex;
|
|
789
|
+
varying vec2 vSprite;
|
|
790
|
+
${cursorSpriteGLSL()}
|
|
791
|
+
void main() {
|
|
792
|
+
vec4 c = inline3dSoftSprite(inline3dCursorTex, vSprite, inline3dCursorRect, inline3dCursorSoft.x);
|
|
793
|
+
gl_FragColor = vec4(c.rgb, c.a * inline3dCursorSoft.y);
|
|
794
|
+
#include <${chunk}>
|
|
795
|
+
}`,
|
|
796
|
+
transparent: true,
|
|
797
|
+
depthTest: false,
|
|
798
|
+
depthWrite: false,
|
|
799
|
+
side: THREE.DoubleSide,
|
|
800
|
+
toneMapped: false,
|
|
801
|
+
});
|
|
802
|
+
return { geometry, material };
|
|
803
|
+
}
|
|
804
|
+
|
|
576
805
|
/** Remove listeners, give the CSS cursor back, free the sprite's GPU resources. */
|
|
577
806
|
dispose() {
|
|
578
807
|
this.pointer.dispose();
|
|
808
|
+
this.shapes.dispose();
|
|
579
809
|
this.object.visible = false;
|
|
580
|
-
this.
|
|
581
|
-
|
|
810
|
+
for (const r of [this._crisp, this._soft, this._tex]) {
|
|
811
|
+
if (!r) continue;
|
|
812
|
+
r.geometry.dispose();
|
|
813
|
+
r.material.dispose();
|
|
814
|
+
}
|
|
815
|
+
for (const t of this._textures.values()) t.dispose?.();
|
|
816
|
+
this._textures.clear();
|
|
582
817
|
}
|
|
583
818
|
|
|
584
819
|
// Nearest content point under the footprint, from the two outer views (or, amortised, from
|
|
@@ -589,23 +824,21 @@ export class DepthCursor {
|
|
|
589
824
|
const fl = Math.hypot(m[8], m[9], m[10]) || 1;
|
|
590
825
|
const f = [-m[8] / fl, -m[9] / fl, -m[10] / fl];
|
|
591
826
|
const fp = cursorArrowFootprint(u, v, height, this.pointer.aspect());
|
|
592
|
-
let candidates;
|
|
593
827
|
if (this.raysPerFrame > 0) {
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
}
|
|
828
|
+
// Amortised: N rays a frame over the (point, eye) slots; the newest pointer position is
|
|
829
|
+
// placed this frame regardless, with the depth the pick has so far (CursorAmortisedPick).
|
|
830
|
+
const pick = (this._pick ||= new CursorAmortisedPick(this.raysPerFrame));
|
|
831
|
+
const eyes = [a, b];
|
|
832
|
+
return pick.step(fp, 2, (e, su, sv) => {
|
|
833
|
+
const ray = cursorViewRay(eyes[e], su, sv);
|
|
834
|
+
return this.hitTest(ray.origin, ray.direction);
|
|
835
|
+
}, f, this.pointer.aspect(), height);
|
|
836
|
+
}
|
|
837
|
+
const candidates = [];
|
|
838
|
+
for (const [su, sv] of fp) {
|
|
839
|
+
for (const view of [a, b]) {
|
|
840
|
+
const ray = cursorViewRay(view, su, sv);
|
|
841
|
+
candidates.push(this.hitTest(ray.origin, ray.direction));
|
|
609
842
|
}
|
|
610
843
|
}
|
|
611
844
|
let best = Infinity, nearest = null;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/* three-mesh-bvh 0.9.15 (MeshBVH only) — MIT License, Copyright (c) 2018 Garrett Johnson — https://github.com/gkjohnson/three-mesh-bvh
|
|
2
|
+
* Vendored by @displayxr/inline3d for the depth cursor's pick; rebuilt by tools/vendor/three-mesh-bvh.mjs. Do not edit. */
|
|
3
|
+
import{Box3 as je}from"three";var ut=Math.pow(2,-24),Et=Symbol("SKIP_GENERATION"),Ht={strategy:0,maxDepth:40,targetLeafSize:10,useSharedArrayBuffer:!1,setBoundingBox:!0,onProgress:null,indirect:!1,verbose:!0,range:null,[Et]:!1};function C(i,t,n){return n.min.x=t[i],n.min.y=t[i+1],n.min.z=t[i+2],n.max.x=t[i+3],n.max.y=t[i+4],n.max.z=t[i+5],n}function bt(i){let t=-1,n=-1/0;for(let e=0;e<3;e++){let s=i[e+3]-i[e];s>n&&(n=s,t=e)}return t}function xn(i,t){t.set(i)}function hn(i,t,n){let e,s;for(let o=0;o<3;o++){let r=o+3;e=i[o],s=t[o],n[o]=e<s?e:s,e=i[r],s=t[r],n[r]=e>s?e:s}}function It(i,t,n){for(let e=0;e<3;e++){let s=t[i+2*e],o=t[i+2*e+1],r=s-o,l=s+o;r<n[e]&&(n[e]=r),l>n[e+3]&&(n[e+3]=l)}}function pt(i){let t=i[3]-i[0],n=i[4]-i[1],e=i[5]-i[2];return 2*(t*n+n*e+e*t)}function L(i,t){return t[i+15]===65535}function U(i,t){return t[i+6]}function O(i,t){return t[i+14]}function v(i){return i+8}function R(i,t){let n=t[i+6];return i+n*8}function mt(i,t){return t[i+7]}function qt(i,t,n,e,s){let o=1/0,r=1/0,l=1/0,c=-1/0,p=-1/0,u=-1/0,a=1/0,f=1/0,m=1/0,T=-1/0,w=-1/0,A=-1/0,g=i.offset||0;for(let y=(t-g)*6,x=(t+n-g)*6;y<x;y+=6){let d=i[y+0],h=i[y+1],_=d-h,B=d+h;_<o&&(o=_),B>c&&(c=B),d<a&&(a=d),d>T&&(T=d);let E=i[y+2],b=i[y+3],P=E-b,I=E+b;P<r&&(r=P),I>p&&(p=I),E<f&&(f=E),E>w&&(w=E);let S=i[y+4],N=i[y+5],F=S-N,D=S+N;F<l&&(l=F),D>u&&(u=D),S<m&&(m=S),S>A&&(A=S)}e[0]=o,e[1]=r,e[2]=l,e[3]=c,e[4]=p,e[5]=u,s[0]=a,s[1]=f,s[2]=m,s[3]=T,s[4]=w,s[5]=A}var J=32,Ge=(i,t)=>i.candidate-t.candidate,tt=new Array(J).fill().map(()=>({count:0,bounds:new Float32Array(6),rightCacheBounds:new Float32Array(6),leftCacheBounds:new Float32Array(6),candidate:0})),kt=new Float32Array(6);function Yn(i,t,n,e,s,o){let r=-1,l=0;if(o===0)r=bt(t),r!==-1&&(l=(t[r]+t[r+3])/2);else if(o===1)r=bt(i),r!==-1&&(l=Ze(n,e,s,r));else if(o===2){let c=pt(i),p=1.25*s,u=n.offset||0,a=(e-u)*6,f=(e+s-u)*6;for(let m=0;m<3;m++){let T=t[m],g=(t[m+3]-T)/J;if(s<J/4){let y=[...tt];y.length=s;let x=0;for(let h=a;h<f;h+=6,x++){let _=y[x];_.candidate=n[h+2*m],_.count=0;let{bounds:B,leftCacheBounds:E,rightCacheBounds:b}=_;for(let P=0;P<3;P++)b[P]=1/0,b[P+3]=-1/0,E[P]=1/0,E[P+3]=-1/0,B[P]=1/0,B[P+3]=-1/0;It(h,n,B)}y.sort(Ge);let d=s;for(let h=0;h<d;h++){let _=y[h];for(;h+1<d&&y[h+1].candidate===_.candidate;)y.splice(h+1,1),d--}for(let h=a;h<f;h+=6){let _=n[h+2*m];for(let B=0;B<d;B++){let E=y[B];_>=E.candidate?It(h,n,E.rightCacheBounds):(It(h,n,E.leftCacheBounds),E.count++)}}for(let h=0;h<d;h++){let _=y[h],B=_.count,E=s-_.count,b=_.leftCacheBounds,P=_.rightCacheBounds,I=0;B!==0&&(I=pt(b)/c);let S=0;E!==0&&(S=pt(P)/c);let N=1+1.25*(I*B+S*E);N<p&&(r=m,p=N,l=_.candidate)}}else{for(let d=0;d<J;d++){let h=tt[d];h.count=0,h.candidate=T+g+d*g;let _=h.bounds;for(let B=0;B<3;B++)_[B]=1/0,_[B+3]=-1/0}for(let d=a;d<f;d+=6){let B=~~((n[d+2*m]-T)/g);B>=J&&(B=J-1);let E=tt[B];E.count++,It(d,n,E.bounds)}let y=tt[J-1];xn(y.bounds,y.rightCacheBounds);for(let d=J-2;d>=0;d--){let h=tt[d],_=tt[d+1];hn(h.bounds,_.rightCacheBounds,h.rightCacheBounds)}let x=0;for(let d=0;d<J-1;d++){let h=tt[d],_=h.count,B=h.bounds,b=tt[d+1].rightCacheBounds;_!==0&&(x===0?xn(B,kt):hn(B,kt,kt)),x+=_;let P=0,I=0;x!==0&&(P=pt(kt)/c);let S=s-x;S!==0&&(I=pt(b)/c);let N=1+1.25*(P*x+I*S);N<p&&(r=m,p=N,l=h.candidate)}}}}else console.warn(`BVH: Invalid build strategy value ${o} used.`);return{axis:r,pos:l}}function Ze(i,t,n,e){let s=0,o=i.offset;for(let r=t,l=t+n;r<l;r++)s+=i[(r-o)*6+e*2];return s/n}var yt=class{constructor(){this.boundingData=new Float32Array(6)}};function Gn(i,t,n,e,s,o){let r=e,l=e+s-1,c=o.pos,p=o.axis*2,u=n.offset||0;for(;;){for(;r<=l&&n[(r-u)*6+p]<c;)r++;for(;r<=l&&n[(l-u)*6+p]>=c;)l--;if(r<l){for(let a=0;a<t;a++){let f=i[r*t+a];i[r*t+a]=i[l*t+a],i[l*t+a]=f}for(let a=0;a<6;a++){let f=r-u,m=l-u,T=n[f*6+a];n[f*6+a]=n[m*6+a],n[m*6+a]=T}r++,l--}else return r}}var Zn,Xt,Tn,Kn,Ke=Math.pow(2,32);function Yt(i){return"count"in i?1:1+Yt(i.left)+Yt(i.right)}function Wn(i,t,n){return Zn=new Float32Array(n),Xt=new Uint32Array(n),Tn=new Uint16Array(n),Kn=new Uint8Array(n),An(i,t)}function An(i,t){let n=i/4,e=i/2,s="count"in t,o=t.boundingData;for(let r=0;r<6;r++)Zn[n+r]=o[r];if(s)return t.buffer?(Kn.set(new Uint8Array(t.buffer),i),i+t.buffer.byteLength):(Xt[n+6]=t.offset,Tn[e+14]=t.count,Tn[e+15]=65535,i+32);{let{left:r,right:l,splitAxis:c}=t,p=i+32,u=An(p,r),a=i/32,m=u/32-a;if(m>Ke)throw new Error("MeshBVH: Cannot store relative child node offset greater than 32 bits.");return Xt[n+6]=m,Xt[n+7]=c,An(u,l)}}function We(i,t,n,e,s,o){let{maxDepth:r,verbose:l,targetLeafSize:c,_strictLeafSize:p=1/0,strategy:u,onProgress:a}=s,f=i.primitiveBuffer,m=i.primitiveBufferStride,T=new Float32Array(6),w=!1,A=new yt;return qt(t,n,e,A.boundingData,T),y(A,n,e,T),A;function g(x){a&&a((x-o.offset)/o.count)}function y(x,d,h,_=null,B=0){!w&&B>=r&&(w=!0,l&&console.warn(`BVH: Max depth of ${r} reached when generating BVH. Consider increasing maxDepth.`));let E=h>p;if(h<=c&&!E||B>=r)return g(d+h),x.offset=d,x.count=h,x;let b=Yn(x.boundingData,_,t,d,h,u),P=b.axis===-1?-1:Gn(f,m,t,d,h,b);if(b.axis===-1||P===d||P===d+h){if(!E)return g(d+h),x.offset=d,x.count=h,x;b.axis=Math.max(0,bt(x.boundingData)),P=d+Math.max(1,Math.floor(h/2))}x.splitAxis=b.axis;let I=new yt,S=d,N=P-d;x.left=I,qt(t,S,N,I.boundingData,T),y(I,S,N,T,B+1);let F=new yt,D=P,z=h-N;return x.right=F,qt(t,D,z,F.boundingData,T),y(F,D,z,T,B+1),x}}function $n(i,t){let n=t.useSharedArrayBuffer?SharedArrayBuffer:ArrayBuffer,e=i.getRootRanges(t.range),s=e[0],o=e[e.length-1],r={offset:s.offset,count:o.offset+o.count-s.offset},l=new Float32Array(6*r.count);l.offset=r.offset,i.computePrimitiveBounds(r.offset,r.count,l),i._roots=e.map(c=>{let p=We(i,l,c.offset,c.count,t,r),u=Yt(p),a=new n(32*u);return Wn(0,p,a),a})}import{Box3 as Qe}from"three";var nt=class{constructor(t){this._getNewPrimitive=t,this._primitives=[]}getPrimitive(){let t=this._primitives;return t.length===0?this._getNewPrimitive():t.pop()}releasePrimitive(t){this._primitives.push(t)}};var wn=class{constructor(){this.float32Array=null,this.uint16Array=null,this.uint32Array=null;let t=[],n=null;this.setBuffer=e=>{n&&t.push(n),n=e,this.float32Array=new Float32Array(e),this.uint16Array=new Uint16Array(e),this.uint32Array=new Uint32Array(e)},this.clearBuffer=()=>{n=null,this.float32Array=null,this.uint16Array=null,this.uint32Array=null,t.length!==0&&this.setBuffer(t.pop())}}},M=new wn;var et,xt,dt=[],Gt=new nt(()=>new Qe);function Qn(i,t,n,e,s,o){et=Gt.getPrimitive(),xt=Gt.getPrimitive(),dt.push(et,xt),M.setBuffer(i._roots[t]);let r=gn(0,i.geometry,n,e,s,o);M.clearBuffer(),Gt.releasePrimitive(et),Gt.releasePrimitive(xt),dt.pop(),dt.pop();let l=dt.length;return l>0&&(xt=dt[l-1],et=dt[l-2]),r}function gn(i,t,n,e,s=null,o=0,r=0){let{float32Array:l,uint16Array:c,uint32Array:p}=M,u=i*2;if(L(u,c)){let f=U(i,p),m=O(u,c);return C(i,l,et),e(f,m,!1,r,o+i/8,et)}else{let P=function(S){let{uint16Array:N,uint32Array:F}=M,D=S*2;for(;!L(D,N);)S=v(S),D=S*2;return U(S,F)},I=function(S){let{uint16Array:N,uint32Array:F}=M,D=S*2;for(;!L(D,N);)S=R(S,F),D=S*2;return U(S,F)+O(D,N)},f=v(i),m=R(i,p),T=f,w=m,A,g,y,x;if(s&&(y=et,x=xt,C(T,l,y),C(w,l,x),A=s(y),g=s(x),g<A)){T=m,w=f;let S=A;A=g,g=S,y=x}y||(y=et,C(T,l,y));let d=L(T*2,c),h=n(y,d,A,r+1,o+T/8),_;if(h===2){let S=P(T),F=I(T)-S;_=e(S,F,!0,r+1,o+T/8,y)}else _=h&&gn(T,t,n,e,s,o,r+1);if(_)return!0;x=xt,C(w,l,x);let B=L(w*2,c),E=n(x,B,g,r+1,o+w/8),b;if(E===2){let S=P(w),F=I(w)-S;b=e(S,F,!0,r+1,o+w/8,x)}else b=E&&gn(w,t,n,e,s,o,r+1);return!!b}}import{Box3 as Ft,Matrix4 as Je}from"three";var Nt=new M.constructor,Zt=new M.constructor,it=new nt(()=>new Ft),ht=new Ft,Tt=new Ft,Pn=new Ft,Sn=new Ft,_n=!1;function Jn(i,t,n,e){if(_n)throw new Error("MeshBVH: Recursive calls to bvhcast not supported.");_n=!0;let s=i._roots,o=t._roots,r,l=0,c=0,p=new Je().copy(n).invert();for(let u=0,a=s.length;u<a;u++){Nt.setBuffer(s[u]),c=0;let f=it.getPrimitive();C(0,Nt.float32Array,f),f.applyMatrix4(p);for(let m=0,T=o.length;m<T&&(Zt.setBuffer(o[m]),r=W(0,0,n,p,e,l,c,0,0,f),Zt.clearBuffer(),c+=o[m].byteLength/32,!r);m++);if(it.releasePrimitive(f),Nt.clearBuffer(),l+=s[u].byteLength/32,r)break}return _n=!1,r}function W(i,t,n,e,s,o=0,r=0,l=0,c=0,p=null,u=!1){let a,f;u?(a=Zt,f=Nt):(a=Nt,f=Zt);let m=a.float32Array,T=a.uint32Array,w=a.uint16Array,A=f.float32Array,g=f.uint32Array,y=f.uint16Array,x=i*2,d=t*2,h=L(x,w),_=L(d,y),B=!1;if(_&&h)u?B=s(U(t,g),O(t*2,y),U(i,T),O(i*2,w),c,r+t/8,l,o+i/8):B=s(U(i,T),O(i*2,w),U(t,g),O(t*2,y),l,o+i/8,c,r+t/8);else if(_){let E=it.getPrimitive();C(t,A,E),E.applyMatrix4(n);let b=v(i),P=R(i,T);C(b,m,ht),C(P,m,Tt);let I=E.intersectsBox(ht),S=E.intersectsBox(Tt);B=I&&W(t,b,e,n,s,r,o,c,l+1,E,!u)||S&&W(t,P,e,n,s,r,o,c,l+1,E,!u),it.releasePrimitive(E)}else{let E=v(t),b=R(t,g);C(E,A,Pn),C(b,A,Sn);let P=p.intersectsBox(Pn),I=p.intersectsBox(Sn);if(P&&I)B=W(i,E,n,e,s,o,r,l,c+1,p,u)||W(i,b,n,e,s,o,r,l,c+1,p,u);else if(P)if(h)B=W(i,E,n,e,s,o,r,l,c+1,p,u);else{let S=it.getPrimitive();S.copy(Pn).applyMatrix4(n);let N=v(i),F=R(i,T);C(N,m,ht),C(F,m,Tt);let D=S.intersectsBox(ht),z=S.intersectsBox(Tt);B=D&&W(E,N,e,n,s,r,o,c,l+1,S,!u)||z&&W(E,F,e,n,s,r,o,c,l+1,S,!u),it.releasePrimitive(S)}else if(I)if(h)B=W(i,b,n,e,s,o,r,l,c+1,p,u);else{let S=it.getPrimitive();S.copy(Sn).applyMatrix4(n);let N=v(i),F=R(i,T);C(N,m,ht),C(F,m,Tt);let D=S.intersectsBox(ht),z=S.intersectsBox(Tt);B=D&&W(b,N,e,n,s,r,o,c,l+1,S,!u)||z&&W(b,F,e,n,s,r,o,c,l+1,S,!u),it.releasePrimitive(S)}}return B}var Kt=new class{constructor(){let i=null,t=null,n=null,e=!1;this.root=null,this.buffer=null,this.uint32Array=null,this.uint16Array=null,this.setBVH=(o,r)=>{if(e)throw new Error("BVHTraversalHelper: cannot call setBVH during an active traversal.");this.root=r,this.buffer=i=o._roots[r],this.uint16Array=n=new Uint16Array(i),this.uint32Array=t=new Uint32Array(i)},this.reset=()=>{this.root=null,this.buffer=i=null,this.uint16Array=n=null,this.uint32Array=t=null},this.getRangeStart=o=>{let r=o*2;for(;!L(r,n);)o=v(o),r=o*2;return U(o,t)},this.getRangeEnd=o=>{let r=o*2;for(;!L(r,n);)o=R(o,t),r=o*2;return U(o,t)+O(r,n)};let s=(o,r,l)=>{let c=r*2,p=L(c,n);if(!o(l,p,r)&&!p){let a=v(r),f=R(r,t);s(o,a,l+1),s(o,f,l+1)}};this.traverseBuffer=o=>{if(e)throw new Error("BVHTraversalHelper: cannot start a traversal during an active traversal.");e=!0;try{s(o,0,0)}finally{e=!1}},this.traverse=o=>{this.traverseBuffer((r,l,c)=>{if(l){let p=c*2,u=t[c+6],a=n[p+14];return o(r,l,new Float32Array(i,c*4,6),u,a)}else{let p=mt(c,t);return o(r,l,new Float32Array(i,c*4,6),p)}})}}};var jn=new je,At=new Float32Array(6),Wt=class{constructor(){this._roots=null,this.primitiveBuffer=null,this.primitiveBufferStride=null}init(t){t={...Ht,...t},"maxLeafSize"in t&&(console.warn('BVH: "maxLeafSize" option has been deprecated. Use "targetLeafSize", instead.'),t={...t,targetLeafSize:t.maxLeafSize}),$n(this,t)}getRootRanges(){throw new Error("BVH: getRootRanges() not implemented")}writePrimitiveBounds(){throw new Error("BVH: writePrimitiveBounds() not implemented")}writePrimitiveRangeBounds(t,n,e,s){let o=1/0,r=1/0,l=1/0,c=-1/0,p=-1/0,u=-1/0;for(let a=t,f=t+n;a<f;a++){this.writePrimitiveBounds(a,At,0);let[m,T,w,A,g,y]=At;m<o&&(o=m),A>c&&(c=A),T<r&&(r=T),g>p&&(p=g),w<l&&(l=w),y>u&&(u=y)}return e[s+0]=o,e[s+1]=r,e[s+2]=l,e[s+3]=c,e[s+4]=p,e[s+5]=u,e}computePrimitiveBounds(t,n,e){let s=e.offset||0;for(let o=t,r=t+n;o<r;o++){this.writePrimitiveBounds(o,At,0);let[l,c,p,u,a,f]=At,m=(l+u)/2,T=(c+a)/2,w=(p+f)/2,A=(u-l)/2,g=(a-c)/2,y=(f-p)/2,x=(o-s)*6;e[x+0]=m,e[x+1]=A+(Math.abs(m)+A)*ut,e[x+2]=T,e[x+3]=g+(Math.abs(T)+g)*ut,e[x+4]=w,e[x+5]=y+(Math.abs(w)+y)*ut}return e}shiftPrimitiveOffsets(t){let n=this._indirectBuffer;if(n)for(let e=0,s=n.length;e<s;e++)n[e]+=t;else{let e=this._roots;for(let s=0;s<e.length;s++){let o=e[s],r=new Uint32Array(o),l=new Uint16Array(o),c=o.byteLength/32;for(let p=0;p<c;p++){let u=8*p,a=2*u;L(a,l)&&(r[u+6]+=t)}}}}traverse(t,n=0){Kt.setBVH(this,n),Kt.traverse(t),Kt.reset()}refit(){let t=this._roots;for(let n=0,e=t.length;n<e;n++){let s=t[n],o=new Uint32Array(s),r=new Uint16Array(s),l=new Float32Array(s),c=s.byteLength/32;for(let p=c-1;p>=0;p--){let u=p*8,a=u*2;if(L(a,r)){let m=U(u,o),T=O(a,r);this.writePrimitiveRangeBounds(m,T,At,0),l.set(At,u)}else{let m=v(u),T=R(u,o);for(let w=0;w<3;w++){let A=l[m+w],g=l[m+w+3],y=l[T+w],x=l[T+w+3];l[u+w]=A<y?A:y,l[u+w+3]=g>x?g:x}}}}}getBoundingBox(t){return t.makeEmpty(),this._roots.forEach(e=>{C(0,new Float32Array(e),jn),t.union(jn)}),t}shapecast(t){let{boundsTraverseOrder:n,intersectsBounds:e,intersectsRange:s,intersectsPrimitive:o,scratchPrimitive:r,iterate:l}=t;if(s&&o){let a=s;s=(f,m,T,w,A)=>a(f,m,T,w,A)?!0:l(f,m,this,o,T,w,r)}else s||(o?s=(a,f,m,T)=>l(a,f,this,o,m,T,r):s=(a,f,m)=>m);let c=!1,p=0,u=this._roots;for(let a=0,f=u.length;a<f;a++){let m=u[a];if(c=Qn(this,a,e,s,n,p),c)break;p+=m.byteLength/32}return c}bvhcast(t,n,e){let{intersectsRanges:s}=e;return Jn(this,t,n,s)}};import{Box3 as si}from"three";function te(){return typeof SharedArrayBuffer<"u"}import{BufferAttribute as ti}from"three";function En(i){return i.index?i.index.count:i.attributes.position.count}function st(i){return En(i)/3}function ni(i,t=ArrayBuffer){return i>65535?new Uint32Array(new t(4*i)):new Uint16Array(new t(2*i))}function ne(i,t){if(!i.index){let n=i.attributes.position.count,e=t.useSharedArrayBuffer?SharedArrayBuffer:ArrayBuffer,s=ni(n,e);i.setIndex(new ti(s,1));for(let o=0;o<n;o++)s[o]=o}}function ei(i,t,n){let e=En(i)/n,s=t||i.drawRange,o=s.start/n,r=(s.start+s.count)/n,l=Math.max(0,o),c=Math.min(e,r)-l;return{offset:Math.floor(l),count:Math.floor(c)}}function ii(i,t){return i.groups.map(n=>({offset:n.start/t,count:n.count/t}))}function bn(i,t,n){let e=ei(i,t,n),s=ii(i,n);if(!s.length)return[e];let o=[],r=e.offset,l=e.offset+e.count,c=En(i)/n,p=[];for(let f of s){let{offset:m,count:T}=f,w=m,A=isFinite(T)?T:c-m,g=m+A;w<l&&g>r&&(p.push({pos:Math.max(r,w),isStart:!0}),p.push({pos:Math.min(l,g),isStart:!1}))}p.sort((f,m)=>f.pos!==m.pos?f.pos-m.pos:f.type==="end"?-1:1);let u=0,a=null;for(let f of p){let m=f.pos;u!==0&&m!==a&&o.push({offset:a,count:m-a}),u+=f.isStart?1:-1,a=m}return o}function ri(i,t){let n=i[i.length-1],e=n.offset+n.count>2**16,s=i.reduce((p,u)=>p+u.count,0),o=e?4:2,r=t?new SharedArrayBuffer(s*o):new ArrayBuffer(s*o),l=e?new Uint32Array(r):new Uint16Array(r),c=0;for(let p=0;p<i.length;p++){let{offset:u,count:a}=i[p];for(let f=0;f<a;f++)l[c+f]=u+f;c+=a}return l}var $t=class extends Wt{get indirect(){return!!this._indirectBuffer}get primitiveStride(){return null}get primitiveBufferStride(){return this.indirect?1:this.primitiveStride}set primitiveBufferStride(t){}get primitiveBuffer(){return this.indirect?this._indirectBuffer:this.geometry.index.array}set primitiveBuffer(t){}constructor(t,n={}){if(t.isBufferGeometry){if(t.index&&t.index.isInterleavedBufferAttribute)throw new Error("BVH: InterleavedBufferAttribute is not supported for the index attribute.")}else throw new Error("BVH: Only BufferGeometries are supported.");if(n.useSharedArrayBuffer&&!te())throw new Error("BVH: SharedArrayBuffer is not available.");super(),this.geometry=t,this.resolvePrimitiveIndex=n.indirect?e=>this._indirectBuffer[e]:e=>e,this.primitiveBuffer=null,this.primitiveBufferStride=null,this._indirectBuffer=null,n={...Ht,...n},n[Et]||this.init(n)}init(t){let{geometry:n,primitiveStride:e}=this;if(t.indirect){let s=bn(n,t.range,e),o=ri(s,t.useSharedArrayBuffer);this._indirectBuffer=o}else ne(n,t);super.init(t),!n.boundingBox&&t.setBoundingBox&&(n.boundingBox=this.getBoundingBox(new si))}getRootRanges(t){return this.indirect?[{offset:0,count:this._indirectBuffer.length}]:bn(this.geometry,t,this.primitiveStride)}raycastObject3D(){throw new Error("BVH: raycastObject3D() not implemented")}};import{BufferAttribute as vi,FrontSide as Me,Ray as Ri,Vector3 as Oe,Matrix4 as Ui}from"three";import{Vector3 as rt,Matrix4 as re,Line3 as oe}from"three";import{Vector3 as oi}from"three";var G=class{constructor(){this.min=1/0,this.max=-1/0}setFromPointsField(t,n){let e=1/0,s=-1/0;for(let o=0,r=t.length;o<r;o++){let c=t[o][n];e=c<e?c:e,s=c>s?c:s}this.min=e,this.max=s}setFromPoints(t,n){let e=1/0,s=-1/0;for(let o=0,r=n.length;o<r;o++){let l=n[o],c=t.dot(l);e=c<e?c:e,s=c>s?c:s}this.min=e,this.max=s}isSeparated(t){return this.min>t.max||t.min>this.max}};G.prototype.setFromBox=(function(){let i=new oi;return function(n,e){let s=e.min,o=e.max,r=1/0,l=-1/0;for(let c=0;c<=1;c++)for(let p=0;p<=1;p++)for(let u=0;u<=1;u++){i.x=s.x*c+o.x*(1-c),i.y=s.y*p+o.y*(1-p),i.z=s.z*u+o.z*(1-u);let a=n.dot(i);r=Math.min(a,r),l=Math.max(a,l)}this.min=r,this.max=l}})();import{Triangle as ui,Vector3 as $,Vector2 as ie,Line3 as wt,Plane as pi}from"three";import{Vector3 as ot,Vector2 as ci,Plane as li,Line3 as fi}from"three";var ai=(function(){let i=new ot,t=new ot,n=new ot;return function(s,o,r){let l=s.start,c=i,p=o.start,u=t;n.subVectors(l,p),i.subVectors(s.end,s.start),t.subVectors(o.end,o.start);let a=n.dot(u),f=u.dot(c),m=u.dot(u),T=n.dot(c),A=c.dot(c)*m-f*f,g,y;A!==0?g=(a*f-T*m)/A:g=0,y=(a+g*f)/m,r.x=g,r.y=y}})(),Dt=(function(){let i=new ci,t=new ot,n=new ot;return function(s,o,r,l){ai(s,o,i);let c=i.x,p=i.y;if(c>=0&&c<=1&&p>=0&&p<=1){s.at(c,r),o.at(p,l);return}else if(c>=0&&c<=1){p<0?o.at(0,l):o.at(1,l),s.closestPointToPoint(l,!0,r);return}else if(p>=0&&p<=1){c<0?s.at(0,r):s.at(1,r),o.closestPointToPoint(r,!0,l);return}else{let u;c<0?u=s.start:u=s.end;let a;p<0?a=o.start:a=o.end;let f=t,m=n;if(s.closestPointToPoint(a,!0,t),o.closestPointToPoint(u,!0,n),f.distanceToSquared(a)<=m.distanceToSquared(u)){r.copy(f),l.copy(a);return}else{r.copy(u),l.copy(m);return}}}})(),ee=(function(){let i=new ot,t=new ot,n=new li,e=new fi;return function(o,r){let{radius:l,center:c}=o,{a:p,b:u,c:a}=r;if(e.start=p,e.end=u,e.closestPointToPoint(c,!0,i).distanceTo(c)<=l||(e.start=p,e.end=a,e.closestPointToPoint(c,!0,i).distanceTo(c)<=l)||(e.start=u,e.end=a,e.closestPointToPoint(c,!0,i).distanceTo(c)<=l))return!0;let w=r.getPlane(n);if(Math.abs(w.distanceToPoint(c))<=l){let g=w.projectPoint(c,t);if(r.containsPoint(g))return!0}return!1}})();var mi=["x","y","z"],j=1e-15,se=j*j;function Z(i){return Math.abs(i)<j}var k=class extends ui{constructor(...t){super(...t),this.isExtendedTriangle=!0,this.satAxes=new Array(4).fill().map(()=>new $),this.satBounds=new Array(4).fill().map(()=>new G),this.points=[this.a,this.b,this.c],this.plane=new pi,this.isDegenerateIntoSegment=!1,this.isDegenerateIntoPoint=!1,this.degenerateSegment=new wt,this.needsUpdate=!0}intersectsSphere(t){return ee(t,this)}update(){let t=this.a,n=this.b,e=this.c,s=this.points,o=this.satAxes,r=this.satBounds,l=o[0],c=r[0];this.getNormal(l),c.setFromPoints(l,s);let p=o[1],u=r[1];p.subVectors(t,n),u.setFromPoints(p,s);let a=o[2],f=r[2];a.subVectors(n,e),f.setFromPoints(a,s);let m=o[3],T=r[3];m.subVectors(e,t),T.setFromPoints(m,s);let w=p.length(),A=a.length(),g=m.length();this.isDegenerateIntoPoint=!1,this.isDegenerateIntoSegment=!1,w<j?A<j||g<j?this.isDegenerateIntoPoint=!0:(this.isDegenerateIntoSegment=!0,this.degenerateSegment.start.copy(t),this.degenerateSegment.end.copy(e)):A<j?g<j?this.isDegenerateIntoPoint=!0:(this.isDegenerateIntoSegment=!0,this.degenerateSegment.start.copy(n),this.degenerateSegment.end.copy(t)):g<j&&(this.isDegenerateIntoSegment=!0,this.degenerateSegment.start.copy(e),this.degenerateSegment.end.copy(n)),this.plane.setFromNormalAndCoplanarPoint(l,t),this.needsUpdate=!1}};k.prototype.closestPointToSegment=(function(){let i=new $,t=new $,n=new wt;return function(s,o=null,r=null){let{start:l,end:c}=s,p=this.points,u,a=1/0;for(let f=0;f<3;f++){let m=(f+1)%3;n.start.copy(p[f]),n.end.copy(p[m]),Dt(n,s,i,t),u=i.distanceToSquared(t),u<a&&(a=u,o&&o.copy(i),r&&r.copy(t))}return this.closestPointToPoint(l,i),u=l.distanceToSquared(i),u<a&&(a=u,o&&o.copy(i),r&&r.copy(l)),this.closestPointToPoint(c,i),u=c.distanceToSquared(i),u<a&&(a=u,o&&o.copy(i),r&&r.copy(c)),Math.sqrt(a)}})();k.prototype.intersectsTriangle=(function(){let i=new k,t=new G,n=new G,e=new $,s=new $,o=new $,r=new $,l=new wt,c=new wt,p=new $,u=new ie,a=new ie;function f(x,d,h,_){let B=e;!x.isDegenerateIntoPoint&&!x.isDegenerateIntoSegment?B.copy(x.plane.normal):B.copy(d.plane.normal);let E=x.satBounds,b=x.satAxes;for(let S=1;S<4;S++){let N=E[S],F=b[S];if(t.setFromPoints(F,d.points),N.isSeparated(t)||(r.copy(B).cross(F),t.setFromPoints(r,x.points),n.setFromPoints(r,d.points),t.isSeparated(n)))return!1}let P=d.satBounds,I=d.satAxes;for(let S=1;S<4;S++){let N=P[S],F=I[S];if(t.setFromPoints(F,x.points),N.isSeparated(t)||(r.crossVectors(B,F),t.setFromPoints(r,x.points),n.setFromPoints(r,d.points),t.isSeparated(n)))return!1}return h&&(_||console.warn("ExtendedTriangle.intersectsTriangle: Triangles are coplanar which does not support an output edge. Setting edge to 0, 0, 0."),h.start.set(0,0,0),h.end.set(0,0,0)),!0}function m(x,d,h,_,B,E,b,P,I,S,N){let F=b/(b-P);S.x=_+(B-_)*F,N.start.subVectors(d,x).multiplyScalar(F).add(x),F=b/(b-I),S.y=_+(E-_)*F,N.end.subVectors(h,x).multiplyScalar(F).add(x)}function T(x,d,h,_,B,E,b,P,I,S,N){if(B>0)m(x.c,x.a,x.b,_,d,h,I,b,P,S,N);else if(E>0)m(x.b,x.a,x.c,h,d,_,P,b,I,S,N);else if(P*I>0||b!=0)m(x.a,x.b,x.c,d,h,_,b,P,I,S,N);else if(P!=0)m(x.b,x.a,x.c,h,d,_,P,b,I,S,N);else if(I!=0)m(x.c,x.a,x.b,_,d,h,I,b,P,S,N);else return!0;return!1}function w(x,d,h,_){let B=d.degenerateSegment,E=x.plane.distanceToPoint(B.start),b=x.plane.distanceToPoint(B.end);return Z(E)?Z(b)?f(x,d,h,_):(h&&(h.start.copy(B.start),h.end.copy(B.start)),x.containsPoint(B.start)):Z(b)?(h&&(h.start.copy(B.end),h.end.copy(B.end)),x.containsPoint(B.end)):x.plane.intersectLine(B,e)!=null?(h&&(h.start.copy(e),h.end.copy(e)),x.containsPoint(e)):!1}function A(x,d,h){let _=d.a;return Z(x.plane.distanceToPoint(_))&&x.containsPoint(_)?(h&&(h.start.copy(_),h.end.copy(_)),!0):!1}function g(x,d,h){let _=x.degenerateSegment,B=d.a;return _.closestPointToPoint(B,!0,e),B.distanceToSquared(e)<se?(h&&(h.start.copy(B),h.end.copy(B)),!0):!1}function y(x,d,h,_){if(x.isDegenerateIntoSegment)if(d.isDegenerateIntoSegment){let B=x.degenerateSegment,E=d.degenerateSegment,b=s,P=o;B.delta(b),E.delta(P);let I=e.subVectors(E.start,B.start),S=b.x*P.y-b.y*P.x;if(Z(S))return!1;let N=(I.x*P.y-I.y*P.x)/S,F=-(b.x*I.y-b.y*I.x)/S;if(N<0||N>1||F<0||F>1)return!1;let D=B.start.z+b.z*N,z=E.start.z+P.z*F;return Z(D-z)?(h&&(h.start.copy(B.start).addScaledVector(b,N),h.end.copy(B.start).addScaledVector(b,N)),!0):!1}else return d.isDegenerateIntoPoint?g(x,d,h):w(d,x,h,_);else{if(x.isDegenerateIntoPoint)return d.isDegenerateIntoPoint?d.a.distanceToSquared(x.a)<se?(h&&(h.start.copy(x.a),h.end.copy(x.a)),!0):!1:d.isDegenerateIntoSegment?g(d,x,h):A(d,x,h);if(d.isDegenerateIntoPoint)return A(x,d,h);if(d.isDegenerateIntoSegment)return w(x,d,h,_)}}return function(d,h=null,_=!1){this.needsUpdate&&this.update(),d.isExtendedTriangle?d.needsUpdate&&d.update():(i.copy(d),i.update(),d=i);let B=y(this,d,h,_);if(B!==void 0)return B;let E=this.plane,b=d.plane,P=b.distanceToPoint(this.a),I=b.distanceToPoint(this.b),S=b.distanceToPoint(this.c);Z(P)&&(P=0),Z(I)&&(I=0),Z(S)&&(S=0);let N=P*I,F=P*S;if(N>0&&F>0)return!1;let D=E.distanceToPoint(d.a),z=E.distanceToPoint(d.b),zt=E.distanceToPoint(d.c);Z(D)&&(D=0),Z(z)&&(z=0),Z(zt)&&(zt=0);let Hn=D*z,qn=D*zt;if(Hn>0&&qn>0)return!1;s.copy(E.normal),o.copy(b.normal);let pn=s.cross(o),mn=0,yn=Math.abs(pn.x),kn=Math.abs(pn.y);kn>yn&&(yn=kn,mn=1),Math.abs(pn.z)>yn&&(mn=2);let at=mi[mn],Ce=this.a[at],Ve=this.b[at],ze=this.c[at],He=d.a[at],qe=d.b[at],ke=d.c[at];if(T(this,Ce,Ve,ze,N,F,P,I,S,u,l))return f(this,d,h,_);if(T(d,He,qe,ke,Hn,qn,D,z,zt,a,c))return f(this,d,h,_);if(u.y<u.x){let dn=u.y;u.y=u.x,u.x=dn,p.copy(l.start),l.start.copy(l.end),l.end.copy(p)}if(a.y<a.x){let dn=a.y;a.y=a.x,a.x=dn,p.copy(c.start),c.start.copy(c.end),c.end.copy(p)}return u.y<a.x||a.y<u.x?!1:(h&&(a.x>u.x?h.start.copy(c.start):h.start.copy(l.start),a.y<u.y?h.end.copy(c.end):h.end.copy(l.end)),!0)}})();k.prototype.distanceToPoint=(function(){let i=new $;return function(n){return this.closestPointToPoint(n,i),n.distanceTo(i)}})();k.prototype.distanceToTriangle=(function(){let i=new $,t=new $,n=["a","b","c"],e=new wt,s=new wt;return function(r,l=null,c=null){let p=l||c?e:null;if(this.intersectsTriangle(r,p,!0))return(l||c)&&(l&&p.getCenter(l),c&&p.getCenter(c)),0;let u=1/0;for(let a=0;a<3;a++){let f,m=n[a],T=r[m];this.closestPointToPoint(T,i),f=T.distanceToSquared(i),f<u&&(u=f,l&&l.copy(i),c&&c.copy(T));let w=this[m];r.closestPointToPoint(w,i),f=w.distanceToSquared(i),f<u&&(u=f,l&&l.copy(w),c&&c.copy(i))}for(let a=0;a<3;a++){let f=n[a],m=n[(a+1)%3];e.set(this[f],this[m]);for(let T=0;T<3;T++){let w=n[T],A=n[(T+1)%3];s.set(r[w],r[A]),Dt(e,s,i,t);let g=i.distanceToSquared(t);g<u&&(u=g,l&&l.copy(i),c&&c.copy(t))}}return Math.sqrt(u)}})();var H=class{constructor(t,n,e){this.isOrientedBox=!0,this.min=new rt,this.max=new rt,this.matrix=new re,this.invMatrix=new re,this.points=new Array(8).fill().map(()=>new rt),this.satAxes=new Array(3).fill().map(()=>new rt),this.satBounds=new Array(3).fill().map(()=>new G),this.alignedSatBounds=new Array(3).fill().map(()=>new G),this.needsUpdate=!1,t&&this.min.copy(t),n&&this.max.copy(n),e&&this.matrix.copy(e)}set(t,n,e){this.min.copy(t),this.max.copy(n),this.matrix.copy(e),this.needsUpdate=!0}copy(t){this.min.copy(t.min),this.max.copy(t.max),this.matrix.copy(t.matrix),this.needsUpdate=!0}};H.prototype.update=(function(){return function(){let t=this.matrix,n=this.min,e=this.max,s=this.points;for(let p=0;p<=1;p++)for(let u=0;u<=1;u++)for(let a=0;a<=1;a++){let f=1*p|2*u|4*a,m=s[f];m.x=p?e.x:n.x,m.y=u?e.y:n.y,m.z=a?e.z:n.z,m.applyMatrix4(t)}let o=this.satBounds,r=this.satAxes,l=s[0];for(let p=0;p<3;p++){let u=r[p],a=o[p],f=1<<p,m=s[f];u.subVectors(l,m),a.setFromPoints(u,s)}let c=this.alignedSatBounds;c[0].setFromPointsField(s,"x"),c[1].setFromPointsField(s,"y"),c[2].setFromPointsField(s,"z"),this.invMatrix.copy(this.matrix).invert(),this.needsUpdate=!1}})();H.prototype.intersectsBox=(function(){let i=new G;return function(n){this.needsUpdate&&this.update();let e=n.min,s=n.max,o=this.satBounds,r=this.satAxes,l=this.alignedSatBounds;if(i.min=e.x,i.max=s.x,l[0].isSeparated(i)||(i.min=e.y,i.max=s.y,l[1].isSeparated(i))||(i.min=e.z,i.max=s.z,l[2].isSeparated(i)))return!1;for(let c=0;c<3;c++){let p=r[c],u=o[c];if(i.setFromBox(p,n),u.isSeparated(i))return!1}return!0}})();H.prototype.intersectsTriangle=(function(){let i=new k,t=new Array(3),n=new G,e=new G,s=new rt;return function(r){this.needsUpdate&&this.update(),r.isExtendedTriangle?r.needsUpdate&&r.update():(i.copy(r),i.update(),r=i);let l=this.satBounds,c=this.satAxes;t[0]=r.a,t[1]=r.b,t[2]=r.c;for(let f=0;f<3;f++){let m=l[f],T=c[f];if(n.setFromPoints(T,t),m.isSeparated(n))return!1}let p=r.satBounds,u=r.satAxes,a=this.points;for(let f=0;f<3;f++){let m=p[f],T=u[f];if(n.setFromPoints(T,a),m.isSeparated(n))return!1}for(let f=0;f<3;f++){let m=c[f];for(let T=0;T<4;T++){let w=u[T];if(s.crossVectors(m,w),n.setFromPoints(s,t),e.setFromPoints(s,a),n.isSeparated(e))return!1}}return!0}})();H.prototype.closestPointToPoint=(function(){return function(t,n){return this.needsUpdate&&this.update(),n.copy(t).applyMatrix4(this.invMatrix).clamp(this.min,this.max).applyMatrix4(this.matrix),n}})();H.prototype.distanceToPoint=(function(){let i=new rt;return function(n){return this.closestPointToPoint(n,i),n.distanceTo(i)}})();H.prototype.distanceToBox=(function(){let i=["x","y","z"],t=new Array(12).fill().map(()=>new oe),n=new Array(12).fill().map(()=>new oe),e=new rt,s=new rt;return function(r,l=0,c=null,p=null){if(this.needsUpdate&&this.update(),this.intersectsBox(r))return(c||p)&&(r.getCenter(s),this.closestPointToPoint(s,e),r.closestPointToPoint(e,s),c&&c.copy(e),p&&p.copy(s)),0;let u=l*l,a=r.min,f=r.max,m=this.points,T=1/0;for(let A=0;A<8;A++){let g=m[A];s.copy(g).clamp(a,f);let y=g.distanceToSquared(s);if(y<T&&(T=y,c&&c.copy(g),p&&p.copy(s),y<u))return Math.sqrt(y)}let w=0;for(let A=0;A<3;A++)for(let g=0;g<=1;g++)for(let y=0;y<=1;y++){let x=(A+1)%3,d=(A+2)%3,h=g<<x|y<<d,_=1<<A|g<<x|y<<d,B=m[h],E=m[_];t[w].set(B,E);let P=i[A],I=i[x],S=i[d],N=n[w],F=N.start,D=N.end;F[P]=a[P],F[I]=g?a[I]:f[I],F[S]=y?a[S]:f[I],D[P]=f[P],D[I]=g?a[I]:f[I],D[S]=y?a[S]:f[I],w++}for(let A=0;A<=1;A++)for(let g=0;g<=1;g++)for(let y=0;y<=1;y++){s.x=A?f.x:a.x,s.y=g?f.y:a.y,s.z=y?f.z:a.z,this.closestPointToPoint(s,e);let x=s.distanceToSquared(e);if(x<T&&(T=x,c&&c.copy(e),p&&p.copy(s),x<u))return Math.sqrt(x)}for(let A=0;A<12;A++){let g=t[A];for(let y=0;y<12;y++){let x=n[y];Dt(g,x,e,s);let d=e.distanceToSquared(s);if(d<T&&(T=d,c&&c.copy(e),p&&p.copy(s),d<u))return Math.sqrt(d)}}return Math.sqrt(T)}})();var In=class extends nt{constructor(){super(()=>new k)}},Y=new In;import{Vector3 as ce}from"three";var Lt=new ce,Nn=new ce;function le(i,t,n={},e=0,s=1/0){let o=e*e,r=s*s,l=1/0,c=null;if(i.shapecast({boundsTraverseOrder:u=>(Lt.copy(t).clamp(u.min,u.max),Lt.distanceToSquared(t)),intersectsBounds:(u,a,f)=>f<l&&f<r,intersectsTriangle:(u,a)=>{u.closestPointToPoint(t,Lt);let f=t.distanceToSquared(Lt);return f<l&&(Nn.copy(Lt),l=f,c=a),f<o}}),l===1/0)return null;let p=Math.sqrt(l);return n.point?n.point.copy(Nn):n.point=Nn.clone(),n.distance=p,n.faceIndex=c,n}import{Vector3 as Q,Vector2 as Rt,Triangle as Mt,DoubleSide as yi,BackSide as di,REVISION as ye}from"three";var Qt=parseInt(ye)>=169,xi=parseInt(ye)<=161,ct=new Q,lt=new Q,ft=new Q,Jt=new Rt,jt=new Rt,tn=new Rt,fe=new Q,ae=new Q,ue=new Q,vt=new Q;function hi(i,t,n,e,s,o,r,l){let c;if(o===di?c=i.intersectTriangle(e,n,t,!0,s):c=i.intersectTriangle(t,n,e,o!==yi,s),c===null)return null;let p=i.origin.distanceTo(s);return p<r||p>l?null:{distance:p,point:s.clone()}}function pe(i,t,n,e,s,o,r,l,c,p,u){ct.fromBufferAttribute(t,o),lt.fromBufferAttribute(t,r),ft.fromBufferAttribute(t,l);let a=hi(i,ct,lt,ft,vt,c,p,u);if(a){if(e){Jt.fromBufferAttribute(e,o),jt.fromBufferAttribute(e,r),tn.fromBufferAttribute(e,l),a.uv=new Rt;let m=Mt.getInterpolation(vt,ct,lt,ft,Jt,jt,tn,a.uv);Qt||(a.uv=m)}if(s){Jt.fromBufferAttribute(s,o),jt.fromBufferAttribute(s,r),tn.fromBufferAttribute(s,l),a.uv1=new Rt;let m=Mt.getInterpolation(vt,ct,lt,ft,Jt,jt,tn,a.uv1);Qt||(a.uv1=m),xi&&(a.uv2=a.uv1)}if(n){fe.fromBufferAttribute(n,o),ae.fromBufferAttribute(n,r),ue.fromBufferAttribute(n,l),a.normal=new Q;let m=Mt.getInterpolation(vt,ct,lt,ft,fe,ae,ue,a.normal);a.normal.dot(i.direction)>0&&a.normal.multiplyScalar(-1),Qt||(a.normal=m)}let f={a:o,b:r,c:l,normal:new Q,materialIndex:0};if(Mt.getNormal(ct,lt,ft,f.normal),a.face=f,a.faceIndex=o,Qt){let m=new Q;Mt.getBarycoord(vt,ct,lt,ft,m),a.barycoord=m}}return a}function me(i){return i&&i.isMaterial?i.side:i}function gt(i,t,n,e,s,o,r){let l=e*3,c=l+0,p=l+1,u=l+2,{index:a,groups:f}=i;i.index&&(c=a.getX(c),p=a.getX(p),u=a.getX(u));let{position:m,normal:T,uv:w,uv1:A}=i.attributes;if(Array.isArray(t)){let g=e*3;for(let y=0,x=f.length;y<x;y++){let{start:d,count:h,materialIndex:_}=f[y];if(g>=d&&g<d+h){let B=me(t[_]),E=pe(n,m,T,w,A,c,p,u,B,o,r);if(E)if(E.faceIndex=e,E.face.materialIndex=_,s)s.push(E);else return E}}}else{let g=me(t),y=pe(n,m,T,w,A,c,p,u,g,o,r);if(y)if(y.faceIndex=e,y.face.materialIndex=0,s)s.push(y);else return y}return null}import{Vector2 as rr,Vector3 as or,Triangle as cr}from"three";function V(i,t,n,e){let s=i.a,o=i.b,r=i.c,l=t,c=t+1,p=t+2;n&&(l=n.getX(l),c=n.getX(c),p=n.getX(p)),s.x=e.getX(l),s.y=e.getY(l),s.z=e.getZ(l),o.x=e.getX(c),o.y=e.getY(c),o.z=e.getZ(c),r.x=e.getX(p),r.y=e.getY(p),r.z=e.getZ(p)}function de(i,t,n,e,s,o,r,l){let{geometry:c,_indirectBuffer:p}=i;for(let u=e,a=e+s;u<a;u++)gt(c,t,n,u,o,r,l)}function xe(i,t,n,e,s,o,r){let{geometry:l,_indirectBuffer:c}=i,p=1/0,u=null;for(let a=e,f=e+s;a<f;a++){let m;m=gt(l,t,n,a,null,o,r),m&&m.distance<p&&(u=m,p=m.distance)}return u}function he(i,t,n,e,s,o,r){let{geometry:l}=n,{index:c}=l,p=l.attributes.position;for(let u=i,a=t+i;u<a;u++){let f;if(f=u,V(r,f*3,c,p),r.needsUpdate=!0,e(r,f,s,o))return!0}return!1}function Te(i,t=null){t&&Array.isArray(t)&&(t=new Set(t));let n=i.geometry,e=n.index?n.index.array:null,s=n.attributes.position,o,r,l,c,p=0,u=i._roots;for(let f=0,m=u.length;f<m;f++)o=u[f],r=new Uint32Array(o),l=new Uint16Array(o),c=new Float32Array(o),a(0,p),p+=o.byteLength;function a(f,m,T=!1){let w=f*2;if(L(w,l)){let A=U(f,r),g=O(w,l),y=1/0,x=1/0,d=1/0,h=-1/0,_=-1/0,B=-1/0;for(let E=3*A,b=3*(A+g);E<b;E++){let P=e[E],I=s.getX(P),S=s.getY(P),N=s.getZ(P);I<y&&(y=I),I>h&&(h=I),S<x&&(x=S),S>_&&(_=S),N<d&&(d=N),N>B&&(B=N)}return c[f+0]!==y||c[f+1]!==x||c[f+2]!==d||c[f+3]!==h||c[f+4]!==_||c[f+5]!==B?(c[f+0]=y,c[f+1]=x,c[f+2]=d,c[f+3]=h,c[f+4]=_,c[f+5]=B,!0):!1}else{let A=v(f),g=R(f,r),y=T,x=!1,d=!1;if(t){if(!y){let P=A/8+m/32,I=g/8+m/32;x=t.has(P),d=t.has(I),y=!x&&!d}}else x=!0,d=!0;let h=y||x,_=y||d,B=!1;h&&(B=a(A,m,y));let E=!1;_&&(E=a(g,m,y));let b=B||E;if(b)for(let P=0;P<3;P++){let I=A+P,S=g+P,N=c[I],F=c[I+3],D=c[S],z=c[S+3];c[f+P]=N<D?N:D,c[f+P+3]=F>z?F:z}return b}}}function K(i,t,n,e,s){let o,r,l,c,p,u,a=1/n.direction.x,f=1/n.direction.y,m=1/n.direction.z,T=n.origin.x,w=n.origin.y,A=n.origin.z,g=t[i],y=t[i+3],x=t[i+1],d=t[i+3+1],h=t[i+2],_=t[i+3+2];return a>=0?(o=(g-T)*a,r=(y-T)*a):(o=(y-T)*a,r=(g-T)*a),f>=0?(l=(x-w)*f,c=(d-w)*f):(l=(d-w)*f,c=(x-w)*f),o>c||l>r||((l>o||isNaN(o))&&(o=l),(c<r||isNaN(r))&&(r=c),m>=0?(p=(h-A)*m,u=(_-A)*m):(p=(_-A)*m,u=(h-A)*m),o>u||p>r)?!1:((p>o||o!==o)&&(o=p),(u<r||r!==r)&&(r=u),o<=s&&r>=e)}function Ae(i,t,n,e,s,o,r,l){let{geometry:c,_indirectBuffer:p}=i;for(let u=e,a=e+s;u<a;u++){let f=p?p[u]:u;gt(c,t,n,f,o,r,l)}}function we(i,t,n,e,s,o,r){let{geometry:l,_indirectBuffer:c}=i,p=1/0,u=null;for(let a=e,f=e+s;a<f;a++){let m;m=gt(l,t,n,c?c[a]:a,null,o,r),m&&m.distance<p&&(u=m,p=m.distance)}return u}function ge(i,t,n,e,s,o,r){let{geometry:l}=n,{index:c}=l,p=l.attributes.position;for(let u=i,a=t+i;u<a;u++){let f;if(f=n.resolveTriangleIndex(u),V(r,f*3,c,p),r.needsUpdate=!0,e(r,f,s,o))return!0}return!1}function Be(i,t,n,e,s,o,r){M.setBuffer(i._roots[t]),Fn(0,i,n,e,s,o,r),M.clearBuffer()}function Fn(i,t,n,e,s,o,r){let{float32Array:l,uint16Array:c,uint32Array:p}=M,u=i*2;if(L(u,c)){let f=U(i,p),m=O(u,c);de(t,n,e,f,m,s,o,r)}else{let f=v(i);K(f,l,e,o,r)&&Fn(f,t,n,e,s,o,r);let m=R(i,p);K(m,l,e,o,r)&&Fn(m,t,n,e,s,o,r)}}var Ti=["x","y","z"];function Pe(i,t,n,e,s,o){M.setBuffer(i._roots[t]);let r=Dn(0,i,n,e,s,o);return M.clearBuffer(),r}function Dn(i,t,n,e,s,o){let{float32Array:r,uint16Array:l,uint32Array:c}=M,p=i*2;if(L(p,l)){let a=U(i,c),f=O(p,l);return xe(t,n,e,a,f,s,o)}else{let a=mt(i,c),f=Ti[a],T=e.direction[f]>=0,w,A;T?(w=v(i),A=R(i,c)):(w=R(i,c),A=v(i));let y=K(w,r,e,s,o)?Dn(w,t,n,e,s,o):null;if(y){let h=y.point[f];if(T?h<=r[A+a]:h>=r[A+a+3])return y}let d=K(A,r,e,s,o)?Dn(A,t,n,e,s,o):null;return y&&d?y.distance<=d.distance?y:d:y||d||null}}import{Box3 as Ai,Matrix4 as wi}from"three";var nn=new Ai,Bt=new k,Pt=new k,Ut=new wi,Se=new H,en=new H;function _e(i,t,n,e){M.setBuffer(i._roots[t]);let s=Ln(0,i,n,e);return M.clearBuffer(),s}function Ln(i,t,n,e,s=null){let{float32Array:o,uint16Array:r,uint32Array:l}=M,c=i*2;if(s===null&&(n.boundingBox||n.computeBoundingBox(),Se.set(n.boundingBox.min,n.boundingBox.max,e),s=Se),L(c,r)){let u=t.geometry,a=u.index,f=u.attributes.position,m=n.index,T=n.attributes.position,w=U(i,l),A=O(c,r);if(Ut.copy(e).invert(),n.boundsTree)return C(i,o,en),en.matrix.copy(Ut),en.needsUpdate=!0,n.boundsTree.shapecast({intersectsBounds:y=>en.intersectsBox(y),intersectsTriangle:y=>{y.a.applyMatrix4(e),y.b.applyMatrix4(e),y.c.applyMatrix4(e),y.needsUpdate=!0;for(let x=w*3,d=(A+w)*3;x<d;x+=3)if(V(Pt,x,a,f),Pt.needsUpdate=!0,y.intersectsTriangle(Pt))return!0;return!1}});{let g=st(n);for(let y=w*3,x=(A+w)*3;y<x;y+=3){V(Bt,y,a,f),Bt.a.applyMatrix4(Ut),Bt.b.applyMatrix4(Ut),Bt.c.applyMatrix4(Ut),Bt.needsUpdate=!0;for(let d=0,h=g*3;d<h;d+=3)if(V(Pt,d,m,T),Pt.needsUpdate=!0,Bt.intersectsTriangle(Pt))return!0}}}else{let u=v(i),a=R(i,l);return C(u,o,nn),!!(s.intersectsBox(nn)&&Ln(u,t,n,e,s)||(C(a,o,nn),s.intersectsBox(nn)&&Ln(a,t,n,e,s)))}}import{Matrix4 as gi,Vector3 as rn}from"three";var sn=new gi,Mn=new H,Ot=new H,Bi=new rn,Pi=new rn,Si=new rn,_i=new rn;function Ee(i,t,n,e={},s={},o=0,r=1/0){t.boundingBox||t.computeBoundingBox(),Mn.set(t.boundingBox.min,t.boundingBox.max,n),Mn.needsUpdate=!0;let l=i.geometry,c=l.attributes.position,p=l.index,u=t.attributes.position,a=t.index,f=Y.getPrimitive(),m=Y.getPrimitive(),T=Bi,w=Pi,A=null,g=null;s&&(A=Si,g=_i);let y=1/0,x=null,d=null;return sn.copy(n).invert(),Ot.matrix.copy(sn),i.shapecast({boundsTraverseOrder:h=>Mn.distanceToBox(h),intersectsBounds:(h,_,B)=>B<y&&B<r?(_&&(Ot.min.copy(h.min),Ot.max.copy(h.max),Ot.needsUpdate=!0),!0):!1,intersectsRange:(h,_)=>{if(t.boundsTree)return t.boundsTree.shapecast({boundsTraverseOrder:E=>Ot.distanceToBox(E),intersectsBounds:(E,b,P)=>P<y&&P<r,intersectsRange:(E,b)=>{for(let P=E,I=E+b;P<I;P++){V(m,3*P,a,u),m.a.applyMatrix4(n),m.b.applyMatrix4(n),m.c.applyMatrix4(n),m.needsUpdate=!0;for(let S=h,N=h+_;S<N;S++){V(f,3*S,p,c),f.needsUpdate=!0;let F=f.distanceToTriangle(m,T,A);if(F<y&&(w.copy(T),g&&g.copy(A),y=F,x=S,d=P),F<o)return!0}}}});{let B=st(t);for(let E=0,b=B;E<b;E++){V(m,3*E,a,u),m.a.applyMatrix4(n),m.b.applyMatrix4(n),m.c.applyMatrix4(n),m.needsUpdate=!0;for(let P=h,I=h+_;P<I;P++){V(f,3*P,p,c),f.needsUpdate=!0;let S=f.distanceToTriangle(m,T,A);if(S<y&&(w.copy(T),g&&g.copy(A),y=S,x=P,d=E),S<o)return!0}}}}}),Y.releasePrimitive(f),Y.releasePrimitive(m),y===1/0?null:(e.point?e.point.copy(w):e.point=w.clone(),e.distance=y,e.faceIndex=x,s&&(s.point?s.point.copy(g):s.point=g.clone(),s.point.applyMatrix4(sn),w.applyMatrix4(sn),s.distance=w.sub(s.point).length(),s.faceIndex=d),e)}function be(i,t=null){t&&Array.isArray(t)&&(t=new Set(t));let n=i.geometry,e=n.index?n.index.array:null,s=n.attributes.position,o,r,l,c,p=0,u=i._roots;for(let f=0,m=u.length;f<m;f++)o=u[f],r=new Uint32Array(o),l=new Uint16Array(o),c=new Float32Array(o),a(0,p),p+=o.byteLength;function a(f,m,T=!1){let w=f*2;if(L(w,l)){let A=U(f,r),g=O(w,l),y=1/0,x=1/0,d=1/0,h=-1/0,_=-1/0,B=-1/0;for(let E=A,b=A+g;E<b;E++){let P=3*i.resolveTriangleIndex(E);for(let I=0;I<3;I++){let S=P+I;S=e?e[S]:S;let N=s.getX(S),F=s.getY(S),D=s.getZ(S);N<y&&(y=N),N>h&&(h=N),F<x&&(x=F),F>_&&(_=F),D<d&&(d=D),D>B&&(B=D)}}return c[f+0]!==y||c[f+1]!==x||c[f+2]!==d||c[f+3]!==h||c[f+4]!==_||c[f+5]!==B?(c[f+0]=y,c[f+1]=x,c[f+2]=d,c[f+3]=h,c[f+4]=_,c[f+5]=B,!0):!1}else{let A=v(f),g=R(f,r),y=T,x=!1,d=!1;if(t){if(!y){let P=A/8+m/32,I=g/8+m/32;x=t.has(P),d=t.has(I),y=!x&&!d}}else x=!0,d=!0;let h=y||x,_=y||d,B=!1;h&&(B=a(A,m,y));let E=!1;_&&(E=a(g,m,y));let b=B||E;if(b)for(let P=0;P<3;P++){let I=A+P,S=g+P,N=c[I],F=c[I+3],D=c[S],z=c[S+3];c[f+P]=N<D?N:D,c[f+P+3]=F>z?F:z}return b}}}function Ie(i,t,n,e,s,o,r){M.setBuffer(i._roots[t]),vn(0,i,n,e,s,o,r),M.clearBuffer()}function vn(i,t,n,e,s,o,r){let{float32Array:l,uint16Array:c,uint32Array:p}=M,u=i*2;if(L(u,c)){let f=U(i,p),m=O(u,c);Ae(t,n,e,f,m,s,o,r)}else{let f=v(i);K(f,l,e,o,r)&&vn(f,t,n,e,s,o,r);let m=R(i,p);K(m,l,e,o,r)&&vn(m,t,n,e,s,o,r)}}var Ei=["x","y","z"];function Ne(i,t,n,e,s,o){M.setBuffer(i._roots[t]);let r=Rn(0,i,n,e,s,o);return M.clearBuffer(),r}function Rn(i,t,n,e,s,o){let{float32Array:r,uint16Array:l,uint32Array:c}=M,p=i*2;if(L(p,l)){let a=U(i,c),f=O(p,l);return we(t,n,e,a,f,s,o)}else{let a=mt(i,c),f=Ei[a],T=e.direction[f]>=0,w,A;T?(w=v(i),A=R(i,c)):(w=R(i,c),A=v(i));let y=K(w,r,e,s,o)?Rn(w,t,n,e,s,o):null;if(y){let h=y.point[f];if(T?h<=r[A+a]:h>=r[A+a+3])return y}let d=K(A,r,e,s,o)?Rn(A,t,n,e,s,o):null;return y&&d?y.distance<=d.distance?y:d:y||d||null}}import{Box3 as bi,Matrix4 as Ii}from"three";var on=new bi,St=new k,_t=new k,Ct=new Ii,Fe=new H,cn=new H;function De(i,t,n,e){M.setBuffer(i._roots[t]);let s=Un(0,i,n,e);return M.clearBuffer(),s}function Un(i,t,n,e,s=null){let{float32Array:o,uint16Array:r,uint32Array:l}=M,c=i*2;if(s===null&&(n.boundingBox||n.computeBoundingBox(),Fe.set(n.boundingBox.min,n.boundingBox.max,e),s=Fe),L(c,r)){let u=t.geometry,a=u.index,f=u.attributes.position,m=n.index,T=n.attributes.position,w=U(i,l),A=O(c,r);if(Ct.copy(e).invert(),n.boundsTree)return C(i,o,cn),cn.matrix.copy(Ct),cn.needsUpdate=!0,n.boundsTree.shapecast({intersectsBounds:y=>cn.intersectsBox(y),intersectsTriangle:y=>{y.a.applyMatrix4(e),y.b.applyMatrix4(e),y.c.applyMatrix4(e),y.needsUpdate=!0;for(let x=w,d=A+w;x<d;x++)if(V(_t,3*t.resolveTriangleIndex(x),a,f),_t.needsUpdate=!0,y.intersectsTriangle(_t))return!0;return!1}});{let g=st(n);for(let y=w,x=A+w;y<x;y++){let d=t.resolveTriangleIndex(y);V(St,3*d,a,f),St.a.applyMatrix4(Ct),St.b.applyMatrix4(Ct),St.c.applyMatrix4(Ct),St.needsUpdate=!0;for(let h=0,_=g*3;h<_;h+=3)if(V(_t,h,m,T),_t.needsUpdate=!0,St.intersectsTriangle(_t))return!0}}}else{let u=v(i),a=R(i,l);return C(u,o,on),!!(s.intersectsBox(on)&&Un(u,t,n,e,s)||(C(a,o,on),s.intersectsBox(on)&&Un(a,t,n,e,s)))}}import{Matrix4 as Ni,Vector3 as fn}from"three";var ln=new Ni,On=new H,Vt=new H,Fi=new fn,Di=new fn,Li=new fn,Mi=new fn;function Le(i,t,n,e={},s={},o=0,r=1/0){t.boundingBox||t.computeBoundingBox(),On.set(t.boundingBox.min,t.boundingBox.max,n),On.needsUpdate=!0;let l=i.geometry,c=l.attributes.position,p=l.index,u=t.attributes.position,a=t.index,f=Y.getPrimitive(),m=Y.getPrimitive(),T=Fi,w=Di,A=null,g=null;s&&(A=Li,g=Mi);let y=1/0,x=null,d=null;return ln.copy(n).invert(),Vt.matrix.copy(ln),i.shapecast({boundsTraverseOrder:h=>On.distanceToBox(h),intersectsBounds:(h,_,B)=>B<y&&B<r?(_&&(Vt.min.copy(h.min),Vt.max.copy(h.max),Vt.needsUpdate=!0),!0):!1,intersectsRange:(h,_)=>{if(t.boundsTree){let B=t.boundsTree;return B.shapecast({boundsTraverseOrder:E=>Vt.distanceToBox(E),intersectsBounds:(E,b,P)=>P<y&&P<r,intersectsRange:(E,b)=>{for(let P=E,I=E+b;P<I;P++){let S=B.resolveTriangleIndex(P);V(m,3*S,a,u),m.a.applyMatrix4(n),m.b.applyMatrix4(n),m.c.applyMatrix4(n),m.needsUpdate=!0;for(let N=h,F=h+_;N<F;N++){let D=i.resolveTriangleIndex(N);V(f,3*D,p,c),f.needsUpdate=!0;let z=f.distanceToTriangle(m,T,A);if(z<y&&(w.copy(T),g&&g.copy(A),y=z,x=N,d=P),z<o)return!0}}}})}else{let B=st(t);for(let E=0,b=B;E<b;E++){V(m,3*E,a,u),m.a.applyMatrix4(n),m.b.applyMatrix4(n),m.c.applyMatrix4(n),m.needsUpdate=!0;for(let P=h,I=h+_;P<I;P++){let S=i.resolveTriangleIndex(P);V(f,3*S,p,c),f.needsUpdate=!0;let N=f.distanceToTriangle(m,T,A);if(N<y&&(w.copy(T),g&&g.copy(A),y=N,x=P,d=E),N<o)return!0}}}}}),Y.releasePrimitive(f),Y.releasePrimitive(m),y===1/0?null:(e.point?e.point.copy(w):e.point=w.clone(),e.distance=y,e.faceIndex=x,s&&(s.point?s.point.copy(g):s.point=g.clone(),s.point.applyMatrix4(ln),w.applyMatrix4(ln),s.distance=w.sub(s.point).length(),s.faceIndex=d),e)}function Cn(i,t,n){return i===null?null:(i.point.applyMatrix4(t.matrixWorld),i.distance=i.point.distanceTo(n.ray.origin),i.object=t,i)}var an=new H,un=new Ri,ve=new Oe,Re=new Ui,Ue=new Oe,Vn=["getX","getY","getZ"],zn=class i extends $t{static serialize(t,n={}){n={cloneBuffers:!0,...n};let e=t.geometry,s=t._roots,o=t._indirectBuffer,r=e.getIndex(),l={version:1,roots:null,index:null,indirectBuffer:null};return n.cloneBuffers?(l.roots=s.map(c=>c.slice()),l.index=r?r.array.slice():null,l.indirectBuffer=o?o.slice():null):(l.roots=s,l.index=r?r.array:null,l.indirectBuffer=o),l}static deserialize(t,n,e={}){e={setIndex:!0,indirect:!!t.indirectBuffer,...e};let{index:s,roots:o,indirectBuffer:r}=t;t.version||(console.warn("MeshBVH.deserialize: Serialization format has been changed and will be fixed up. It is recommended to regenerate any stored serialized data."),c(o));let l=new i(n,{...e,[Et]:!0});if(l._roots=o,l._indirectBuffer=r||null,e.setIndex){let p=n.getIndex();if(p===null){let u=new vi(t.index,1,!1);n.setIndex(u)}else p.array!==s&&(p.array.set(s),p.needsUpdate=!0)}return l;function c(p){for(let u=0;u<p.length;u++){let a=p[u],f=new Uint32Array(a),m=new Uint16Array(a);for(let T=0,w=a.byteLength/32;T<w;T++){let A=8*T,g=2*A;L(g,m)||(f[A+6]=f[A+6]/8-T)}}}}get primitiveStride(){return 3}get resolveTriangleIndex(){return this.resolvePrimitiveIndex}constructor(t,n={}){n.maxLeafTris&&(console.warn('MeshBVH: "maxLeafTris" option has been deprecated. Use "targetLeafSize", instead.'),n={...n,targetLeafSize:n.maxLeafTris}),super(t,n)}shiftTriangleOffsets(t){return super.shiftPrimitiveOffsets(t)}writePrimitiveBounds(t,n,e){let s=this.geometry,o=this._indirectBuffer,r=s.attributes.position,l=s.index?s.index.array:null,p=(o?o[t]:t)*3,u=p+0,a=p+1,f=p+2;l&&(u=l[u],a=l[a],f=l[f]);for(let m=0;m<3;m++){let T=r[Vn[m]](u),w=r[Vn[m]](a),A=r[Vn[m]](f),g=T;w<g&&(g=w),A<g&&(g=A);let y=T;w>y&&(y=w),A>y&&(y=A),n[e+m]=g,n[e+m+3]=y}return n}computePrimitiveBounds(t,n,e){let s=this.geometry,o=this._indirectBuffer,r=s.attributes.position,l=s.index?s.index.array:null,c=r.normalized;if(t<0||n+t-e.offset>e.length/6)throw new Error("MeshBVH: compute triangle bounds range is invalid.");let p=r.array,u=r.offset||0,a=3;r.isInterleavedBufferAttribute&&(a=r.data.stride);let f=["getX","getY","getZ"],m=e.offset;for(let T=t,w=t+n;T<w;T++){let g=(o?o[T]:T)*3,y=(T-m)*6,x=g+0,d=g+1,h=g+2;l&&(x=l[x],d=l[d],h=l[h]),c||(x=x*a+u,d=d*a+u,h=h*a+u);for(let _=0;_<3;_++){let B,E,b;c?(B=r[f[_]](x),E=r[f[_]](d),b=r[f[_]](h)):(B=p[x+_],E=p[d+_],b=p[h+_]);let P=B;E<P&&(P=E),b<P&&(P=b);let I=B;E>I&&(I=E),b>I&&(I=b);let S=(I-P)/2,N=_*2;e[y+N+0]=P+S,e[y+N+1]=S+(Math.abs(P)+S)*ut}}return e}raycastObject3D(t,n,e=[]){let{material:s}=t;if(s===void 0)return;Re.copy(t.matrixWorld).invert(),un.copy(n.ray).applyMatrix4(Re),Ue.setFromMatrixScale(t.matrixWorld),ve.copy(un.direction).multiply(Ue);let o=ve.length(),r=n.near/o,l=n.far/o;if(n.firstHitOnly===!0){let c=this.raycastFirst(un,s,r,l);c=Cn(c,t,n),c&&e.push(c)}else{let c=this.raycast(un,s,r,l);for(let p=0,u=c.length;p<u;p++){let a=Cn(c[p],t,n);a&&e.push(a)}}return e}refit(t=null){return(this.indirect?be:Te)(this,t)}raycast(t,n=Me,e=0,s=1/0){let o=this._roots,r=[],l=this.indirect?Ie:Be;for(let c=0,p=o.length;c<p;c++)l(this,c,n,t,r,e,s);return r}raycastFirst(t,n=Me,e=0,s=1/0){let o=this._roots,r=null,l=this.indirect?Ne:Pe;for(let c=0,p=o.length;c<p;c++){let u=l(this,c,n,t,e,s);u!=null&&(r==null||u.distance<r.distance)&&(r=u)}return r}intersectsGeometry(t,n){let e=!1,s=this._roots,o=this.indirect?De:_e;for(let r=0,l=s.length;r<l&&(e=o(this,r,t,n),!e);r++);return e}shapecast(t){let n=Y.getPrimitive(),e=super.shapecast({...t,intersectsPrimitive:t.intersectsTriangle,scratchPrimitive:n,iterate:this.indirect?ge:he});return Y.releasePrimitive(n),e}bvhcast(t,n,e){let{intersectsRanges:s,intersectsTriangles:o}=e,r=Y.getPrimitive(),l=this.geometry.index,c=this.geometry.attributes.position,p=this.indirect?T=>{let w=this.resolveTriangleIndex(T);V(r,w*3,l,c)}:T=>{V(r,T*3,l,c)},u=Y.getPrimitive(),a=t.geometry.index,f=t.geometry.attributes.position,m=t.indirect?T=>{let w=t.resolveTriangleIndex(T);V(u,w*3,a,f)}:T=>{V(u,T*3,a,f)};if(o){if(!(t instanceof i))throw new Error('MeshBVH: "intersectsTriangles" callback can only be used with another MeshBVH.');let T=(w,A,g,y,x,d,h,_)=>{for(let B=g,E=g+y;B<E;B++){m(B),u.a.applyMatrix4(n),u.b.applyMatrix4(n),u.c.applyMatrix4(n),u.needsUpdate=!0;for(let b=w,P=w+A;b<P;b++)if(p(b),r.needsUpdate=!0,o(r,u,b,B,x,d,h,_))return!0}return!1};if(s){let w=s;s=function(A,g,y,x,d,h,_,B){return w(A,g,y,x,d,h,_,B)?!0:T(A,g,y,x,d,h,_,B)}}else s=T}return super.bvhcast(t,n,{intersectsRanges:s})}intersectsBox(t,n){return an.set(t.min,t.max,n),an.needsUpdate=!0,this.shapecast({intersectsBounds:e=>an.intersectsBox(e),intersectsTriangle:e=>an.intersectsTriangle(e)})}intersectsSphere(t){return this.shapecast({intersectsBounds:n=>t.intersectsBox(n),intersectsTriangle:n=>n.intersectsSphere(t)})}closestPointToGeometry(t,n,e={},s={},o=0,r=1/0){return(this.indirect?Le:Ee)(this,t,n,e,s,o,r)}closestPointToPoint(t,n={},e=0,s=1/0){return le(this,t,n,e,s)}};export{zn as MeshBVH};
|
package/model.d.ts
CHANGED
|
@@ -58,7 +58,7 @@ export interface ModelOptions {
|
|
|
58
58
|
* cursor, untouched. Never behind the glass. OPT-IN: without it nothing
|
|
59
59
|
* is loaded or run. PlayCanvas: hit-tested with the engine's depth picker (meshes and splats,
|
|
60
60
|
* one low-res pass every other frame while the pointer is over the tile). three: a raycast
|
|
61
|
-
* against the subject. Pass an object to tune it: `{ margin, anchor, height, pointerScope }`
|
|
61
|
+
* against the subject. Pass an object to tune it: `{ margin, anchor, height, pointerScope, soften, shape, shapeFor }`
|
|
62
62
|
* (any object also means depth).
|
|
63
63
|
*/
|
|
64
64
|
cursor?: 'depth' | CursorOptions;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@displayxr/inline3d",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.45.0",
|
|
4
4
|
"description": "Turn any HTML <canvas> into a 3D window on a spatial display, inside an ordinary web page, for the DisplayXR Browser. Dependency-free; progressive enhancement (falls back to plain 2D everywhere else).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./index.d.ts",
|
|
@@ -77,6 +77,10 @@
|
|
|
77
77
|
"js/inline3d-cursor-option.js",
|
|
78
78
|
"js/inline3d-cursor-depth.js",
|
|
79
79
|
"js/inline3d-cursor-depth-playcanvas.js",
|
|
80
|
+
"js/inline3d-cursor-perf.js",
|
|
81
|
+
"js/inline3d-cursor-bvh.js",
|
|
82
|
+
"js/inline3d-cursor-shape.js",
|
|
83
|
+
"js/vendor/",
|
|
80
84
|
"js/inline3d-viewer.js",
|
|
81
85
|
"js/inline3d-splat.js",
|
|
82
86
|
"js/inline3d-splat-pc-entry.js",
|
|
@@ -172,10 +176,12 @@
|
|
|
172
176
|
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
173
177
|
"test": "tsc --noEmit -p tsconfig.json && node --test \"test/*.test.mjs\"",
|
|
174
178
|
"build:dist": "node tools/dist/build.mjs",
|
|
179
|
+
"vendor:bvh": "node tools/vendor/three-mesh-bvh.mjs",
|
|
175
180
|
"prepack": "node tools/dist/build.mjs",
|
|
176
181
|
"test:e2e": "node test/e2e/call-element.e2e.mjs",
|
|
177
182
|
"test:e2e:camera": "node test/e2e/camera.e2e.mjs",
|
|
178
183
|
"test:e2e:cursor": "node test/e2e/cursor-depth.e2e.mjs",
|
|
184
|
+
"test:e2e:cursor-perf": "node test/e2e/cursor-perf.e2e.mjs",
|
|
179
185
|
"test:e2e:samples-panel": "node test/e2e/samples-panel.e2e.mjs",
|
|
180
186
|
"api:check": "node tools/api-surface.mjs --check",
|
|
181
187
|
"api:update": "node tools/api-surface.mjs --update",
|
package/splat.d.ts
CHANGED
|
@@ -482,7 +482,7 @@ export interface SplatOptions {
|
|
|
482
482
|
* cursor, untouched. Never behind the glass. OPT-IN: without it nothing
|
|
483
483
|
* is loaded or run. PlayCanvas: hit-tested with the engine's depth picker (meshes and splats,
|
|
484
484
|
* one low-res pass every other frame while the pointer is over the tile). three: a raycast
|
|
485
|
-
* against the subject. Pass an object to tune it: `{ margin, anchor, height, pointerScope }`
|
|
485
|
+
* against the subject. Pass an object to tune it: `{ margin, anchor, height, pointerScope, soften, shape, shapeFor }`
|
|
486
486
|
* (any object also means depth).
|
|
487
487
|
*/
|
|
488
488
|
cursor?: 'depth' | CursorOptions;
|