@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.
@@ -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
- if (cursorOpts) viewer.useDepthCursor(DepthCursor, (content) => raycastHitTest(THREE, [content]), cursorOpts);
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';
@@ -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 × 9
501
- * points). N > 0 = an EXPENSIVE hit test (e.g. a gaussian-splat raycast, ~8 ms a ray):
502
- * cast N rays a frame from the first eye, cycling through the footprint, and take the
503
- * nearest of the most recent full cycle.
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._ring = []; // amortised mode: the last hit per footprint point (null = a miss)
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
- const h = this.height ?? cursorDefaultHeight(this.pointer.cssHeight());
563
- const nearestPoint = this._footprintHit(vs, u, v, h);
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
- this.object.visible = !!p.active;
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.object.geometry.dispose();
581
- this.object.material.dispose();
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
- const ring = this._ring;
595
- ring.length = fp.length;
596
- for (let i = 0; i < this.raysPerFrame; i++) {
597
- const k = this._next++ % fp.length;
598
- const ray = cursorViewRay(a, fp[k][0], fp[k][1]);
599
- ring[k] = this.hitTest(ray.origin, ray.direction);
600
- }
601
- candidates = ring;
602
- } else {
603
- candidates = [];
604
- for (const [su, sv] of fp) {
605
- for (const view of [a, b]) {
606
- const ray = cursorViewRay(view, su, sv);
607
- candidates.push(this.hitTest(ray.origin, ray.direction));
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.43.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;