@displayxr/inline3d 1.43.1 → 1.44.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 +63 -0
- package/THIRD_PARTY_NOTICES.md +26 -2
- package/camera.d.ts +3 -0
- package/cursor-depth.d.ts +124 -1
- package/dist/call.js +4 -4
- package/js/camera/pair-cursor.js +74 -5
- package/js/inline3d-cursor-bvh.js +147 -0
- package/js/inline3d-cursor-depth-playcanvas.js +150 -4
- package/js/inline3d-cursor-depth.js +407 -24
- package/js/inline3d-cursor-option.js +121 -6
- package/js/inline3d-cursor-perf.js +199 -0
- package/js/inline3d-model.js +30 -1
- package/js/inline3d-playcanvas-engine.js +1 -0
- package/js/inline3d-three.js +149 -27
- package/js/vendor/three-mesh-bvh.js +3 -0
- package/model.d.ts +1 -1
- package/package.json +6 -1
- package/splat.d.ts +1 -1
- package/three.d.ts +33 -4
package/js/inline3d-three.js
CHANGED
|
@@ -59,10 +59,15 @@ import {
|
|
|
59
59
|
cursorArrowFootprint,
|
|
60
60
|
cursorDefaultHeight,
|
|
61
61
|
cursorModelMatrix,
|
|
62
|
+
cursorPlacementSoften,
|
|
63
|
+
cursorSoftArrowBox,
|
|
64
|
+
cursorSoftArrowGLSL,
|
|
62
65
|
cursorViewRay,
|
|
66
|
+
resolveCursorSoften,
|
|
63
67
|
CURSOR_DEFAULT_TUNING,
|
|
64
68
|
CURSOR_OUTLINE_COLOR,
|
|
65
69
|
} from './inline3d-cursor-depth.js';
|
|
70
|
+
import { CursorAmortisedPick, CursorDebugStats, cursorDebugMode } from './inline3d-cursor-perf.js';
|
|
66
71
|
|
|
67
72
|
/**
|
|
68
73
|
* A reusable three.js camera driven directly by an XRView's matrices. Construct once with
|
|
@@ -496,33 +501,63 @@ export class DepthCursor {
|
|
|
496
501
|
* content) while it is still; 'screen' never parallaxes; 'world' always does.
|
|
497
502
|
* @param {'canvas'|'window'} [opts.pointerScope='canvas'] 'window' keeps the cursor over DOM
|
|
498
503
|
* layered on the canvas (overlay buttons) and hides the CSS cursor page-wide meanwhile.
|
|
504
|
+
* @param {'both'|'off'|'alpha'|'blur'|object} [opts.soften='both'] crosstalk softening of the
|
|
505
|
+
* LIFTED arrow (runtime ADR-046 Amendment 2 §B.7): an edge blur of 0.1 × its ghost offset
|
|
506
|
+
* (capped at 6% of its height, 8 px) and an opacity easing to 0.5 over 0.03 baselines of
|
|
507
|
+
* lift, both zero on the glass. A preset, or `{ mode, blurK, blurMaxPx, blurMaxFrac,
|
|
508
|
+
* alphaMin, fullD }` over the defaults. Drawn in the arrow's own shader.
|
|
499
509
|
* @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
|
-
*
|
|
510
|
+
* @param {number} [opts.raysPerFrame=0] 0 = the whole footprint every frame (two eyes × 10
|
|
511
|
+
* points), synchronously. N > 0 = amortised: N rays a frame, cycling the footprint
|
|
512
|
+
* (alternating eyes), each point's last hit kept until the pointer moves away from where it
|
|
513
|
+
* was cast. The sprite still follows the NEWEST pointer position every frame, at the depth
|
|
514
|
+
* the pick has so far; the depth filter absorbs the cadence. ./model passes 3, ./splat 1
|
|
515
|
+
* (a gaussian-splat raycast costs ~8 ms a ray).
|
|
516
|
+
* @param {boolean|'both'} [opts.debug=false] true: log update() cost, rays a frame and the frame
|
|
517
|
+
* interval (rolling stats, at most once a second; `cursor.debugStats.last` holds the newest).
|
|
518
|
+
* 'both': that, and the OS cursor stays visible beside the sprite (the latency check).
|
|
504
519
|
*/
|
|
505
520
|
constructor(
|
|
506
521
|
THREE,
|
|
507
|
-
{ canvas, hitTest, height = null, color = 0xffffff, viewSpace = null, raysPerFrame = 0, margin, anchor = 'hybrid', pointerScope = 'canvas' },
|
|
522
|
+
{ canvas, hitTest, height = null, color = 0xffffff, viewSpace = null, raysPerFrame = 0, margin, anchor = 'hybrid', pointerScope = 'canvas', debug = false, soften },
|
|
508
523
|
) {
|
|
509
524
|
this._THREE = THREE;
|
|
510
525
|
this.canvas = canvas;
|
|
511
526
|
this.hitTest = hitTest;
|
|
527
|
+
const debugMode = cursorDebugMode(debug);
|
|
528
|
+
/** `cursor: { debug }` only: the rolling stats (null otherwise — nothing is measured). */
|
|
529
|
+
this.debugStats = null;
|
|
530
|
+
if (debugMode) {
|
|
531
|
+
this.debugStats = new CursorDebugStats({ info: typeof hitTest.info === 'function' ? hitTest.info : null });
|
|
532
|
+
this._rays = 0;
|
|
533
|
+
this._seenSamples = 0;
|
|
534
|
+
this._seenTime = 0;
|
|
535
|
+
const inner = hitTest;
|
|
536
|
+
this.hitTest = (o, d) => {
|
|
537
|
+
this._rays++;
|
|
538
|
+
return inner(o, d);
|
|
539
|
+
};
|
|
540
|
+
}
|
|
512
541
|
/** Sprite height (canvas heights) when set; null = the OS arrow's size, from the canvas's on-page height. */
|
|
513
542
|
this.height = height > 0 && Number.isFinite(height) ? height : null;
|
|
514
543
|
this.viewSpace = viewSpace;
|
|
515
544
|
this.raysPerFrame = raysPerFrame;
|
|
516
|
-
this.
|
|
517
|
-
this._next = 0;
|
|
545
|
+
this._pick = null; // amortised mode (raysPerFrame > 0): a CursorAmortisedPick, built on first use
|
|
518
546
|
const tuning = margin > 0 && Number.isFinite(margin) ? { ...CURSOR_DEFAULT_TUNING, margin } : CURSOR_DEFAULT_TUNING;
|
|
519
547
|
this.placer = new CursorDepthPlacer(tuning, { anchor });
|
|
520
|
-
this.pointer = new CursorPointer(canvas, { scope: pointerScope });
|
|
548
|
+
this.pointer = new CursorPointer(canvas, { scope: pointerScope, keepCss: debugMode === 'both' });
|
|
549
|
+
if (this.debugStats) this.debugStats.source = this.pointer.source;
|
|
521
550
|
/** The last placement (diagnostics): `{active, position, height, disparity, targetDisparity, anchored}`. */
|
|
522
551
|
this.placement = { active: false };
|
|
552
|
+
/** Crosstalk softening parameters (resolveCursorSoften). */
|
|
553
|
+
this.soften = resolveCursorSoften(soften, '@displayxr/inline3d/three DepthCursor');
|
|
554
|
+
/** The last frame's softening (diagnostics): `{blurPx, alpha, ghostPx, spritePx, radius, aa, soft}`. */
|
|
555
|
+
this.softening = null;
|
|
556
|
+
this._soft = null; // { geometry, material } — built on the first softened frame
|
|
523
557
|
|
|
524
558
|
// The arrow: a dark outline polygon, the fill inset over it; tip at the origin (the hotspot).
|
|
525
559
|
const fill = [((color >> 16) & 255) / 255, ((color >> 8) & 255) / 255, (color & 255) / 255, 1];
|
|
560
|
+
this._fill = fill;
|
|
526
561
|
const m = cursorArrowMesh(fill, CURSOR_OUTLINE_COLOR);
|
|
527
562
|
const geom = new THREE.BufferGeometry();
|
|
528
563
|
geom.setAttribute('position', new THREE.Float32BufferAttribute(m.positions, 3));
|
|
@@ -541,6 +576,7 @@ export class DepthCursor {
|
|
|
541
576
|
this.object.frustumCulled = false;
|
|
542
577
|
this.object.renderOrder = 1e9; // last: never occluded, it is in front by construction
|
|
543
578
|
this.object.visible = false;
|
|
579
|
+
this._crisp = { geometry: geom, material: mat };
|
|
544
580
|
}
|
|
545
581
|
|
|
546
582
|
/** Set the pointer position directly (canvas-normalised, v down), or null — for scripted input. */
|
|
@@ -554,12 +590,34 @@ export class DepthCursor {
|
|
|
554
590
|
* @param {number} [nowMs=performance.now()]
|
|
555
591
|
*/
|
|
556
592
|
update(views, nowMs = globalThis.performance ? globalThis.performance.now() : Date.now()) {
|
|
593
|
+
if (this.debugStats) return this._updateMeasured(views, nowMs);
|
|
594
|
+
return this._update(views, nowMs);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// `cursor: { debug }`: the same update, timed. Off, update() never reaches this.
|
|
598
|
+
_updateMeasured(views, nowMs) {
|
|
599
|
+
const clock = () => (globalThis.performance ? globalThis.performance.now() : Date.now());
|
|
600
|
+
this._rays = 0;
|
|
601
|
+
const t0 = clock();
|
|
602
|
+
const p = this._update(views, nowMs);
|
|
603
|
+
const t1 = clock();
|
|
604
|
+
const ptr = this.pointer;
|
|
605
|
+
const fresh = ptr.samples !== this._seenSamples && ptr.sampleTime > 0 && ptr.sampleTime !== this._seenTime;
|
|
606
|
+
const samples = ptr.samples - this._seenSamples;
|
|
607
|
+
this._seenSamples = ptr.samples;
|
|
608
|
+
this._seenTime = ptr.sampleTime;
|
|
609
|
+
this.debugStats.frame(t1 - t0, this._rays, t0, fresh ? t0 - ptr.sampleTime : null, samples);
|
|
610
|
+
return p;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
_update(views, nowMs) {
|
|
557
614
|
const vs = this._worldViews(views);
|
|
558
615
|
const uv = this.pointer.uv;
|
|
559
616
|
let p = { active: false };
|
|
617
|
+
let h = 0;
|
|
560
618
|
if (uv && vs.length >= 2) {
|
|
561
619
|
const [u, v] = uv;
|
|
562
|
-
|
|
620
|
+
h = this.height ?? cursorDefaultHeight(this.pointer.cssHeight());
|
|
563
621
|
const nearestPoint = this._footprintHit(vs, u, v, h);
|
|
564
622
|
p = this.placer.update(vs, { u, v, nearestPoint, cursorHeight: h, canvasPx: this.pointer.panelPx() }, nowMs / 1000);
|
|
565
623
|
}
|
|
@@ -568,17 +626,83 @@ export class DepthCursor {
|
|
|
568
626
|
if (p.active) {
|
|
569
627
|
this.object.matrix.fromArray(cursorModelMatrix(p));
|
|
570
628
|
this.object.matrixWorldNeedsUpdate = true;
|
|
629
|
+
const [pw, ph] = this.pointer.panelSize();
|
|
630
|
+
const s = (this.softening = cursorPlacementSoften(p, vs, pw, ph, h, this.soften));
|
|
631
|
+
this._useSoft(s);
|
|
632
|
+
} else {
|
|
633
|
+
this.softening = null;
|
|
571
634
|
}
|
|
572
635
|
this.pointer.hideCss(!!p.active);
|
|
573
636
|
return p;
|
|
574
637
|
}
|
|
575
638
|
|
|
639
|
+
// Crisp frames draw the arrow mesh exactly as without softening; softened ones swap in a quad
|
|
640
|
+
// whose shader evaluates the arrow at the runtime's 13 blur taps, times the opacity.
|
|
641
|
+
_useSoft(s) {
|
|
642
|
+
if (!s.soft) {
|
|
643
|
+
this.object.geometry = this._crisp.geometry;
|
|
644
|
+
this.object.material = this._crisp.material;
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
const soft = this._soft || (this._soft = this._makeSoft());
|
|
648
|
+
const u = soft.material.uniforms;
|
|
649
|
+
const [x0, y0, x1, y1] = cursorSoftArrowBox(s.radius, s.aa);
|
|
650
|
+
u.inline3dCursorBox.value.set(x0, y0, x1, y1);
|
|
651
|
+
u.inline3dCursorSoft.value.set(s.radius, s.alpha, s.aa, 0);
|
|
652
|
+
this.object.geometry = soft.geometry;
|
|
653
|
+
this.object.material = soft.material;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
_makeSoft() {
|
|
657
|
+
const THREE = this._THREE;
|
|
658
|
+
const geometry = new THREE.BufferGeometry();
|
|
659
|
+
// A unit quad; the vertex shader spreads it over the padded arrow box (arrow units, y down).
|
|
660
|
+
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));
|
|
661
|
+
// three >= 0.154 names the output-transform chunk colorspace_fragment; 0.150-0.153 encodings_fragment.
|
|
662
|
+
const chunk = THREE.ShaderChunk && THREE.ShaderChunk.colorspace_fragment !== undefined ? 'colorspace_fragment' : 'encodings_fragment';
|
|
663
|
+
const material = new THREE.ShaderMaterial({
|
|
664
|
+
uniforms: {
|
|
665
|
+
inline3dCursorBox: { value: new THREE.Vector4() },
|
|
666
|
+
inline3dCursorSoft: { value: new THREE.Vector4(0, 1, 0, 0) },
|
|
667
|
+
inline3dCursorFill: { value: new THREE.Vector3(this._fill[0], this._fill[1], this._fill[2]) },
|
|
668
|
+
inline3dCursorOutline: { value: new THREE.Vector3(CURSOR_OUTLINE_COLOR[0], CURSOR_OUTLINE_COLOR[1], CURSOR_OUTLINE_COLOR[2]) },
|
|
669
|
+
},
|
|
670
|
+
vertexShader: `
|
|
671
|
+
uniform vec4 inline3dCursorBox;
|
|
672
|
+
varying vec2 vArrow;
|
|
673
|
+
void main() {
|
|
674
|
+
vArrow = vec2(mix(inline3dCursorBox.x, inline3dCursorBox.z, position.x), mix(inline3dCursorBox.y, inline3dCursorBox.w, position.y));
|
|
675
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(vArrow.x, -vArrow.y, 0.0, 1.0);
|
|
676
|
+
}`,
|
|
677
|
+
fragmentShader: `
|
|
678
|
+
uniform vec4 inline3dCursorSoft; // radius, opacity, aa (arrow units)
|
|
679
|
+
uniform vec3 inline3dCursorFill;
|
|
680
|
+
uniform vec3 inline3dCursorOutline;
|
|
681
|
+
varying vec2 vArrow;
|
|
682
|
+
${cursorSoftArrowGLSL()}
|
|
683
|
+
void main() {
|
|
684
|
+
vec4 c = inline3dSoftArrow(vArrow, inline3dCursorSoft.x, inline3dCursorSoft.z, inline3dCursorFill, inline3dCursorOutline);
|
|
685
|
+
gl_FragColor = vec4(c.rgb, c.a * inline3dCursorSoft.y);
|
|
686
|
+
#include <${chunk}>
|
|
687
|
+
}`,
|
|
688
|
+
transparent: true,
|
|
689
|
+
depthTest: false,
|
|
690
|
+
depthWrite: false,
|
|
691
|
+
side: THREE.DoubleSide,
|
|
692
|
+
toneMapped: false,
|
|
693
|
+
});
|
|
694
|
+
return { geometry, material };
|
|
695
|
+
}
|
|
696
|
+
|
|
576
697
|
/** Remove listeners, give the CSS cursor back, free the sprite's GPU resources. */
|
|
577
698
|
dispose() {
|
|
578
699
|
this.pointer.dispose();
|
|
579
700
|
this.object.visible = false;
|
|
580
|
-
this.
|
|
581
|
-
|
|
701
|
+
for (const r of [this._crisp, this._soft]) {
|
|
702
|
+
if (!r) continue;
|
|
703
|
+
r.geometry.dispose();
|
|
704
|
+
r.material.dispose();
|
|
705
|
+
}
|
|
582
706
|
}
|
|
583
707
|
|
|
584
708
|
// Nearest content point under the footprint, from the two outer views (or, amortised, from
|
|
@@ -589,23 +713,21 @@ export class DepthCursor {
|
|
|
589
713
|
const fl = Math.hypot(m[8], m[9], m[10]) || 1;
|
|
590
714
|
const f = [-m[8] / fl, -m[9] / fl, -m[10] / fl];
|
|
591
715
|
const fp = cursorArrowFootprint(u, v, height, this.pointer.aspect());
|
|
592
|
-
let candidates;
|
|
593
716
|
if (this.raysPerFrame > 0) {
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
}
|
|
717
|
+
// Amortised: N rays a frame over the (point, eye) slots; the newest pointer position is
|
|
718
|
+
// placed this frame regardless, with the depth the pick has so far (CursorAmortisedPick).
|
|
719
|
+
const pick = (this._pick ||= new CursorAmortisedPick(this.raysPerFrame));
|
|
720
|
+
const eyes = [a, b];
|
|
721
|
+
return pick.step(fp, 2, (e, su, sv) => {
|
|
722
|
+
const ray = cursorViewRay(eyes[e], su, sv);
|
|
723
|
+
return this.hitTest(ray.origin, ray.direction);
|
|
724
|
+
}, f, this.pointer.aspect(), height);
|
|
725
|
+
}
|
|
726
|
+
const candidates = [];
|
|
727
|
+
for (const [su, sv] of fp) {
|
|
728
|
+
for (const view of [a, b]) {
|
|
729
|
+
const ray = cursorViewRay(view, su, sv);
|
|
730
|
+
candidates.push(this.hitTest(ray.origin, ray.direction));
|
|
609
731
|
}
|
|
610
732
|
}
|
|
611
733
|
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 }`
|
|
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.44.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,9 @@
|
|
|
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/vendor/",
|
|
80
83
|
"js/inline3d-viewer.js",
|
|
81
84
|
"js/inline3d-splat.js",
|
|
82
85
|
"js/inline3d-splat-pc-entry.js",
|
|
@@ -172,10 +175,12 @@
|
|
|
172
175
|
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
173
176
|
"test": "tsc --noEmit -p tsconfig.json && node --test \"test/*.test.mjs\"",
|
|
174
177
|
"build:dist": "node tools/dist/build.mjs",
|
|
178
|
+
"vendor:bvh": "node tools/vendor/three-mesh-bvh.mjs",
|
|
175
179
|
"prepack": "node tools/dist/build.mjs",
|
|
176
180
|
"test:e2e": "node test/e2e/call-element.e2e.mjs",
|
|
177
181
|
"test:e2e:camera": "node test/e2e/camera.e2e.mjs",
|
|
178
182
|
"test:e2e:cursor": "node test/e2e/cursor-depth.e2e.mjs",
|
|
183
|
+
"test:e2e:cursor-perf": "node test/e2e/cursor-perf.e2e.mjs",
|
|
179
184
|
"test:e2e:samples-panel": "node test/e2e/samples-panel.e2e.mjs",
|
|
180
185
|
"api:check": "node tools/api-surface.mjs --check",
|
|
181
186
|
"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 }`
|
|
486
486
|
* (any object also means depth).
|
|
487
487
|
*/
|
|
488
488
|
cursor?: 'depth' | CursorOptions;
|
package/three.d.ts
CHANGED
|
@@ -143,7 +143,19 @@ export class EdgeFeather {
|
|
|
143
143
|
): void;
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
import type { CursorAnchorMode, CursorPlacement, CursorView } from './cursor-depth.js';
|
|
146
|
+
import type { CursorAnchorMode, CursorPlacement, CursorSoftenOption, CursorSoftenParams, CursorSoftening, CursorView } from './cursor-depth.js';
|
|
147
|
+
|
|
148
|
+
/** One second of `debug` stats: each figure as `{ mean, p95, max, n }`. */
|
|
149
|
+
export interface CursorDebugSummary {
|
|
150
|
+
frames: number;
|
|
151
|
+
seconds: number;
|
|
152
|
+
updateMs: { mean: number; p95: number; max: number; n: number };
|
|
153
|
+
rays: { mean: number; p95: number; max: number; n: number };
|
|
154
|
+
frameMs: { mean: number; p95: number; max: number; n: number };
|
|
155
|
+
/** Age of the pointer sample a frame used, on frames where it was new. */
|
|
156
|
+
pointerAgeMs: { mean: number; p95: number; max: number; n: number };
|
|
157
|
+
samplesPerFrame: number;
|
|
158
|
+
}
|
|
147
159
|
|
|
148
160
|
/**
|
|
149
161
|
* A hit test for {@link DepthCursor} that raycasts three.js objects (recursively): the first hit
|
|
@@ -179,22 +191,39 @@ export class DepthCursor {
|
|
|
179
191
|
height?: number;
|
|
180
192
|
/** Fill colour of the arrow (default 0xffffff; the outline is always dark). */
|
|
181
193
|
color?: number;
|
|
182
|
-
/** How far in front of out-of-screen content it floats, in eye-baseline units (default 0.
|
|
194
|
+
/** How far in front of out-of-screen content it floats, in eye-baseline units (default 0.015 ≈ 1 mm at a 63-65 mm IPD). */
|
|
183
195
|
margin?: number;
|
|
184
196
|
/** Default `'hybrid'`: exact while the pointer moves, world-fixed (parallaxing) while it is still. */
|
|
185
197
|
anchor?: CursorAnchorMode;
|
|
186
198
|
/** `'window'`: keep the cursor over DOM layered on the canvas; hides the CSS cursor page-wide meanwhile. */
|
|
187
199
|
pointerScope?: 'canvas' | 'window';
|
|
188
|
-
/**
|
|
200
|
+
/** 0 (default): the whole footprint every frame. N: amortised — N rays a frame cycling the footprint (both eyes); the arrow still follows the newest pointer each frame. */
|
|
189
201
|
raysPerFrame?: number;
|
|
202
|
+
/**
|
|
203
|
+
* Crosstalk softening of the LIFTED arrow (runtime ADR-046 Amendment 2 §B.7), in the arrow's own
|
|
204
|
+
* shader: blur = 0.1 × its ghost offset (capped at 6% of its height, 8 px), opacity easing to
|
|
205
|
+
* 0.5 over 0.03 baselines of lift; both zero on the glass. Default `'both'`; `'off'` = the crisp arrow.
|
|
206
|
+
*/
|
|
207
|
+
soften?: CursorSoftenOption;
|
|
190
208
|
/** Attach pattern: the Object3D the eye cameras hang off; its world matrix carries the views to world. */
|
|
191
209
|
viewSpace?: unknown;
|
|
210
|
+
/** `true`: log update() cost, rays a frame and the frame interval once a second; `'both'`: also keep the OS cursor visible. */
|
|
211
|
+
debug?: boolean | 'both';
|
|
192
212
|
},
|
|
193
213
|
);
|
|
194
|
-
/**
|
|
214
|
+
/** With `debug` only (else null): the rolling stats; `last` is the newest one-second summary, `history` the last 120. */
|
|
215
|
+
readonly debugStats: { last: CursorDebugSummary | null; history: CursorDebugSummary[] } | null;
|
|
216
|
+
/**
|
|
217
|
+
* The arrow (a `THREE.Mesh`: dark outline, white fill, tip at its origin; depth test off, drawn last). Add it to the scene root.
|
|
218
|
+
* While it is softened its geometry and material are a padded quad and the soft-arrow shader; otherwise the crisp mesh.
|
|
219
|
+
*/
|
|
195
220
|
readonly object: unknown;
|
|
196
221
|
/** The last placement, for diagnostics. */
|
|
197
222
|
readonly placement: CursorPlacement | { active: false };
|
|
223
|
+
/** The resolved softening parameters. */
|
|
224
|
+
readonly soften: CursorSoftenParams;
|
|
225
|
+
/** The last drawn frame's softening (diagnostics); null while nothing is drawn. */
|
|
226
|
+
readonly softening: CursorSoftening | null;
|
|
198
227
|
/** Place the sprite for this frame — call with the views you are about to render, before rendering. */
|
|
199
228
|
update(views: ArrayLike<XRView | CursorView>, nowMs?: number): CursorPlacement | { active: false };
|
|
200
229
|
/** Set the pointer directly (canvas-normalised, v down), or null — for scripted input. */
|