@multisetai/vps 1.0.7-beta.2 → 1.0.7-beta.3
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.
Potentially problematic release.
This version of @multisetai/vps might be problematic. Click here for more details.
- package/dist/core/index.d.ts +2 -5
- package/dist/core/index.js +9 -29
- package/dist/core/index.js.map +1 -1
- package/dist/index.js +97 -90
- package/dist/index.js.map +1 -1
- package/dist/webxr/index.js +88 -61
- package/dist/webxr/index.js.map +1 -1
- package/package.json +1 -1
package/dist/webxr/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import * as THREE3 from 'three';
|
|
|
2
2
|
import { ARButton } from 'three/examples/jsm/webxr/ARButton.js';
|
|
3
3
|
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
|
|
4
4
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
5
|
+
import { TransformControls } from 'three/examples/jsm/controls/TransformControls.js';
|
|
5
6
|
|
|
6
7
|
// src/lib/webxr/controller.ts
|
|
7
8
|
|
|
@@ -32,7 +33,7 @@ async function compressToJpeg(buffer, width, height, quality = 0.8) {
|
|
|
32
33
|
const imageData = new ImageData(new Uint8ClampedArray(buffer), width, height);
|
|
33
34
|
ctx.putImageData(imageData, 0, 0);
|
|
34
35
|
return new Promise((resolve) => {
|
|
35
|
-
canvas.toBlob((blob) => resolve(blob
|
|
36
|
+
canvas.toBlob((blob) => resolve(blob ?? new Blob()), "image/jpeg", quality);
|
|
36
37
|
});
|
|
37
38
|
}
|
|
38
39
|
async function getCameraTextureAsImage(renderer, webGLTexture, width, height) {
|
|
@@ -218,21 +219,20 @@ void main() {
|
|
|
218
219
|
}
|
|
219
220
|
`;
|
|
220
221
|
function createGridMaterial(options = {}) {
|
|
221
|
-
|
|
222
|
-
const
|
|
223
|
-
const
|
|
224
|
-
const
|
|
225
|
-
const
|
|
226
|
-
const
|
|
227
|
-
const
|
|
228
|
-
const
|
|
229
|
-
const
|
|
230
|
-
const
|
|
231
|
-
const
|
|
232
|
-
const
|
|
233
|
-
const
|
|
234
|
-
const
|
|
235
|
-
const lightDirection = (_n = options.lightDirection) != null ? _n : new THREE3.Vector3(0.3, 1, 0.3).normalize();
|
|
222
|
+
const color = options.color ?? "#7B2CBF";
|
|
223
|
+
const opacity = options.opacity ?? 0.6;
|
|
224
|
+
const gridColor = options.gridColor ?? "#ffeb3b";
|
|
225
|
+
const gridScale = options.gridScale ?? 2;
|
|
226
|
+
const gridLineWidth = options.gridLineWidth ?? 0.02;
|
|
227
|
+
const showGrid = options.showGrid ?? 1;
|
|
228
|
+
const center = options.center ?? new THREE3.Vector3(0, 0, 0);
|
|
229
|
+
const radius = options.radius ?? 1;
|
|
230
|
+
const progress = options.progress ?? 1;
|
|
231
|
+
const glowColor = options.glowColor ?? "#00ffff";
|
|
232
|
+
const glowWidth = options.glowWidth ?? 0.05;
|
|
233
|
+
const glowIntensity = options.glowIntensity ?? 2;
|
|
234
|
+
const lightColor = options.lightColor ?? "#ffffff";
|
|
235
|
+
const lightDirection = options.lightDirection ?? new THREE3.Vector3(0.3, 1, 0.3).normalize();
|
|
236
236
|
return new THREE3.ShaderMaterial({
|
|
237
237
|
vertexShader: VERTEX,
|
|
238
238
|
fragmentShader: FRAGMENT,
|
|
@@ -266,9 +266,13 @@ function createGridMaterial(options = {}) {
|
|
|
266
266
|
// src/lib/webxr/mapMeshVisualizer.ts
|
|
267
267
|
var LARGE_MAP_THRESHOLD = 50;
|
|
268
268
|
var MapMeshVisualizer = class {
|
|
269
|
-
constructor(scene, client) {
|
|
269
|
+
constructor(scene, client, renderer, camera) {
|
|
270
270
|
this.scene = scene;
|
|
271
271
|
this.client = client;
|
|
272
|
+
this.renderer = renderer;
|
|
273
|
+
this.camera = camera;
|
|
274
|
+
this.gizmoControl = null;
|
|
275
|
+
this.gizmoHelper = null;
|
|
272
276
|
this.meshMaterial = null;
|
|
273
277
|
this.localCenter = new THREE3.Vector3();
|
|
274
278
|
this.localRadius = 0;
|
|
@@ -290,12 +294,29 @@ var MapMeshVisualizer = class {
|
|
|
290
294
|
getMeshGroup() {
|
|
291
295
|
return this.meshGroup;
|
|
292
296
|
}
|
|
297
|
+
async ensureGizmoLoaded() {
|
|
298
|
+
const cfg = this.client.getConfig();
|
|
299
|
+
if (cfg.showGizmo === false) {
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
if (!this.gizmoControl) {
|
|
303
|
+
const gizmo = new TransformControls(this.camera, this.renderer.domElement);
|
|
304
|
+
gizmo.setMode("translate");
|
|
305
|
+
gizmo.setSpace("local");
|
|
306
|
+
gizmo.enabled = false;
|
|
307
|
+
const helper = gizmo.getHelper();
|
|
308
|
+
this.scene.add(helper);
|
|
309
|
+
gizmo.attach(this.meshGroup);
|
|
310
|
+
this.gizmoControl = gizmo;
|
|
311
|
+
this.gizmoHelper = helper;
|
|
312
|
+
}
|
|
313
|
+
this.gizmoHelper.visible = true;
|
|
314
|
+
}
|
|
293
315
|
async ensureMeshLoaded(mapDetails) {
|
|
294
|
-
var _a, _b;
|
|
295
316
|
if (this.scene.getObjectByName(mapDetails._id)) {
|
|
296
317
|
return;
|
|
297
318
|
}
|
|
298
|
-
const meshKey =
|
|
319
|
+
const meshKey = mapDetails.mapMesh?.rawMesh?.meshLink;
|
|
299
320
|
if (!meshKey) {
|
|
300
321
|
return;
|
|
301
322
|
}
|
|
@@ -379,7 +400,6 @@ var MapMeshVisualizer = class {
|
|
|
379
400
|
}
|
|
380
401
|
}
|
|
381
402
|
update(deltaSeconds, viewerWorldPosition) {
|
|
382
|
-
var _a;
|
|
383
403
|
if (!this.meshMaterial) {
|
|
384
404
|
return;
|
|
385
405
|
}
|
|
@@ -390,7 +410,7 @@ var MapMeshVisualizer = class {
|
|
|
390
410
|
if (!uniforms.uProgress) {
|
|
391
411
|
return;
|
|
392
412
|
}
|
|
393
|
-
const current =
|
|
413
|
+
const current = uniforms.uProgress.value ?? 0;
|
|
394
414
|
if (current === 0 && uniforms.uCenter && this.lastViewerWorldPosition.lengthSq() > 0) {
|
|
395
415
|
uniforms.uCenter.value.copy(this.lastViewerWorldPosition);
|
|
396
416
|
}
|
|
@@ -424,13 +444,22 @@ var MapMeshVisualizer = class {
|
|
|
424
444
|
});
|
|
425
445
|
this.scene.remove(this.meshGroup);
|
|
426
446
|
this.dracoLoader.dispose();
|
|
447
|
+
if (this.gizmoHelper) {
|
|
448
|
+
this.scene.remove(this.gizmoHelper);
|
|
449
|
+
}
|
|
450
|
+
if (this.gizmoControl) {
|
|
451
|
+
this.gizmoControl.dispose();
|
|
452
|
+
}
|
|
427
453
|
}
|
|
428
454
|
};
|
|
429
455
|
|
|
430
456
|
// src/lib/webxr/world/World.ts
|
|
431
457
|
var World = class {
|
|
432
|
-
constructor(scene, client) {
|
|
433
|
-
this.meshVisualizer = new MapMeshVisualizer(scene, client);
|
|
458
|
+
constructor(scene, client, renderer, camera) {
|
|
459
|
+
this.meshVisualizer = new MapMeshVisualizer(scene, client, renderer, camera);
|
|
460
|
+
}
|
|
461
|
+
async ensureGizmoLoaded() {
|
|
462
|
+
await this.meshVisualizer.ensureGizmoLoaded();
|
|
434
463
|
}
|
|
435
464
|
async ensureMeshLoaded(mapDetails) {
|
|
436
465
|
await this.meshVisualizer.ensureMeshLoaded(mapDetails);
|
|
@@ -467,23 +496,21 @@ var WebxrController = class {
|
|
|
467
496
|
this.trackerSpace = null;
|
|
468
497
|
}
|
|
469
498
|
async initialize(buttonContainer) {
|
|
470
|
-
var _a, _b, _c, _d;
|
|
471
499
|
if (this.experience) {
|
|
472
500
|
return this.arButton;
|
|
473
501
|
}
|
|
474
502
|
if (!window.isSecureContext) {
|
|
475
503
|
throw new Error("WebXR requires a secure context (HTTPS).");
|
|
476
504
|
}
|
|
477
|
-
const canvas =
|
|
505
|
+
const canvas = this.options.canvas ?? document.createElement("canvas");
|
|
478
506
|
this.experience = new Experience(canvas);
|
|
479
|
-
this.world = new World(this.experience.getScene(), this.options.client);
|
|
480
507
|
const renderer = this.experience.getRenderer();
|
|
481
508
|
const camera = this.experience.getCamera();
|
|
482
509
|
const scene = this.experience.getScene();
|
|
510
|
+
this.world = new World(scene, this.options.client, renderer, camera);
|
|
483
511
|
renderer.xr.addEventListener("sessionstart", () => {
|
|
484
|
-
var _a2, _b2;
|
|
485
512
|
this.isSessionActive = true;
|
|
486
|
-
|
|
513
|
+
this.options.onSessionStart?.();
|
|
487
514
|
const cfg = this.options.client.getConfig();
|
|
488
515
|
if (cfg.autoLocalize) {
|
|
489
516
|
const session = renderer.xr.getSession();
|
|
@@ -497,9 +524,8 @@ var WebxrController = class {
|
|
|
497
524
|
}
|
|
498
525
|
});
|
|
499
526
|
renderer.xr.addEventListener("sessionend", () => {
|
|
500
|
-
var _a2, _b2;
|
|
501
527
|
this.isSessionActive = false;
|
|
502
|
-
|
|
528
|
+
this.options.onSessionEnd?.();
|
|
503
529
|
});
|
|
504
530
|
let lastTime = 0;
|
|
505
531
|
const animationLoop = (time, frame) => {
|
|
@@ -544,11 +570,10 @@ var WebxrController = class {
|
|
|
544
570
|
};
|
|
545
571
|
renderer.setAnimationLoop(animationLoop);
|
|
546
572
|
const resizeHandler = () => {
|
|
547
|
-
|
|
548
|
-
(_a2 = this.experience) == null ? void 0 : _a2.resize();
|
|
573
|
+
this.experience?.resize();
|
|
549
574
|
};
|
|
550
575
|
window.addEventListener("resize", resizeHandler);
|
|
551
|
-
const overlayRoot =
|
|
576
|
+
const overlayRoot = this.options.overlayRoot ?? document.body;
|
|
552
577
|
const arButton = ARButton.createButton(renderer, {
|
|
553
578
|
requiredFeatures: ["camera-access", "dom-overlay"],
|
|
554
579
|
domOverlay: { root: overlayRoot }
|
|
@@ -559,7 +584,7 @@ var WebxrController = class {
|
|
|
559
584
|
}
|
|
560
585
|
this.arButton = arButton;
|
|
561
586
|
this.resizeHandler = resizeHandler;
|
|
562
|
-
|
|
587
|
+
this.options.onARButtonCreated?.(arButton);
|
|
563
588
|
return arButton;
|
|
564
589
|
}
|
|
565
590
|
getScene() {
|
|
@@ -581,8 +606,7 @@ var WebxrController = class {
|
|
|
581
606
|
return this.experience.getRenderer();
|
|
582
607
|
}
|
|
583
608
|
hasActiveSession() {
|
|
584
|
-
|
|
585
|
-
return this.isSessionActive && ((_a = this.experience) == null ? void 0 : _a.getRenderer().xr.isPresenting) === true;
|
|
609
|
+
return this.isSessionActive && this.experience?.getRenderer().xr.isPresenting === true;
|
|
586
610
|
}
|
|
587
611
|
/**
|
|
588
612
|
* Runs a single-frame localization: captures one frame, evaluates the result
|
|
@@ -591,24 +615,23 @@ var WebxrController = class {
|
|
|
591
615
|
* Aligns with Unity SingleFrameLocalizationManager.LocalizeFrame().
|
|
592
616
|
*/
|
|
593
617
|
async localizeFrame() {
|
|
594
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
595
618
|
if (!this.experience) {
|
|
596
619
|
throw new Error("WebXR: WebXR controller has not been initialized.");
|
|
597
620
|
}
|
|
598
621
|
const renderer = this.experience.getRenderer();
|
|
599
|
-
const session =
|
|
622
|
+
const session = renderer.xr.getSession?.();
|
|
600
623
|
if (!session) {
|
|
601
624
|
throw new Error(
|
|
602
625
|
"WebXR Session: No active WebXR session. Start AR before calling localizeFrame()."
|
|
603
626
|
);
|
|
604
627
|
}
|
|
605
628
|
const cfg = this.options.client.getConfig();
|
|
606
|
-
const confidenceCheck =
|
|
629
|
+
const confidenceCheck = cfg.confidenceCheck ?? false;
|
|
607
630
|
const confidenceThreshold = Math.max(
|
|
608
631
|
CONFIDENCE_THRESHOLD_MIN,
|
|
609
|
-
Math.min(
|
|
632
|
+
Math.min(cfg.confidenceThreshold ?? 0.5, CONFIDENCE_THRESHOLD_MAX)
|
|
610
633
|
);
|
|
611
|
-
|
|
634
|
+
cfg.onLocalizationInit?.();
|
|
612
635
|
this.isLocalizing = true;
|
|
613
636
|
let best = null;
|
|
614
637
|
let failureReason;
|
|
@@ -619,20 +642,27 @@ var WebxrController = class {
|
|
|
619
642
|
} finally {
|
|
620
643
|
this.isLocalizing = false;
|
|
621
644
|
}
|
|
622
|
-
const accepted = best && (!confidenceCheck || (
|
|
645
|
+
const accepted = best && (!confidenceCheck || (best.localizeData.confidence ?? 0) >= confidenceThreshold);
|
|
623
646
|
if (accepted && best) {
|
|
624
|
-
|
|
625
|
-
if (
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
647
|
+
cfg.onLocalizationSuccess?.(best);
|
|
648
|
+
if (this.world && this.trackerSpace) {
|
|
649
|
+
const willShowMesh = cfg.showMesh && !!best.mapDetails;
|
|
650
|
+
const willShowGizmo = cfg.showGizmo !== false;
|
|
651
|
+
if (willShowMesh || willShowGizmo) {
|
|
652
|
+
try {
|
|
653
|
+
await this.world.ensureGizmoLoaded();
|
|
654
|
+
if (willShowMesh) {
|
|
655
|
+
await this.world.ensureMeshLoaded(best.mapDetails);
|
|
656
|
+
}
|
|
657
|
+
this.world.applyMeshTransform(best, this.trackerSpace);
|
|
658
|
+
} catch {
|
|
659
|
+
}
|
|
630
660
|
}
|
|
631
661
|
}
|
|
632
662
|
return best;
|
|
633
663
|
}
|
|
634
|
-
const reason = failureReason
|
|
635
|
-
|
|
664
|
+
const reason = failureReason ?? (!best ? "All attempts failed to produce a pose." : confidenceCheck ? `Best confidence ${best.localizeData.confidence ?? 0} below threshold ${confidenceThreshold}.` : void 0);
|
|
665
|
+
cfg.onLocalizationFailure?.(reason);
|
|
636
666
|
return null;
|
|
637
667
|
}
|
|
638
668
|
/**
|
|
@@ -642,12 +672,11 @@ var WebxrController = class {
|
|
|
642
672
|
* result, apiCalled, and an optional failureReason for onLocalizationFailure.
|
|
643
673
|
*/
|
|
644
674
|
async captureFrame() {
|
|
645
|
-
var _a, _b, _c;
|
|
646
675
|
if (!this.experience) {
|
|
647
676
|
throw new Error("WebXR: WebXR controller has not been initialized.");
|
|
648
677
|
}
|
|
649
678
|
const renderer = this.experience.getRenderer();
|
|
650
|
-
const session =
|
|
679
|
+
const session = renderer.xr.getSession?.();
|
|
651
680
|
if (!session) {
|
|
652
681
|
throw new Error(
|
|
653
682
|
"WebXR Session: No active WebXR session. Start AR before capturing."
|
|
@@ -661,12 +690,11 @@ var WebxrController = class {
|
|
|
661
690
|
}
|
|
662
691
|
const gl = renderer.getContext();
|
|
663
692
|
const cfg = this.options.client.getConfig();
|
|
664
|
-
const timeoutMs =
|
|
693
|
+
const timeoutMs = cfg.localizationTrackingTimeoutMs ?? DEFAULT_TRACKING_TIMEOUT_MS;
|
|
665
694
|
return new Promise((resolve, reject) => {
|
|
666
695
|
const startTime = Date.now();
|
|
667
696
|
const tryFrame = (attempt, cameraAttemptsWithPose) => {
|
|
668
697
|
session.requestAnimationFrame(async (_time, xrFrame) => {
|
|
669
|
-
var _a2, _b2, _c2, _d;
|
|
670
698
|
try {
|
|
671
699
|
const elapsed = Date.now() - startTime;
|
|
672
700
|
const viewerPose = xrFrame.getViewerPose(referenceSpace);
|
|
@@ -691,7 +719,7 @@ var WebxrController = class {
|
|
|
691
719
|
const gl2 = gl;
|
|
692
720
|
const bindingCtor = XRWebGLBinding;
|
|
693
721
|
const binding = new bindingCtor(session, gl2);
|
|
694
|
-
const cameraTexture =
|
|
722
|
+
const cameraTexture = binding.getCameraImage?.(xrCamera) ?? null;
|
|
695
723
|
if (!cameraTexture) continue;
|
|
696
724
|
const width = xrCamera.width;
|
|
697
725
|
const height = xrCamera.height;
|
|
@@ -732,7 +760,7 @@ var WebxrController = class {
|
|
|
732
760
|
} finally {
|
|
733
761
|
gl.bindFramebuffer(
|
|
734
762
|
gl.FRAMEBUFFER,
|
|
735
|
-
|
|
763
|
+
session.renderState.baseLayer?.framebuffer ?? null
|
|
736
764
|
);
|
|
737
765
|
}
|
|
738
766
|
});
|
|
@@ -741,18 +769,17 @@ var WebxrController = class {
|
|
|
741
769
|
});
|
|
742
770
|
}
|
|
743
771
|
dispose() {
|
|
744
|
-
var _a, _b, _c, _d;
|
|
745
772
|
if (this.resizeHandler) {
|
|
746
773
|
window.removeEventListener("resize", this.resizeHandler);
|
|
747
774
|
}
|
|
748
|
-
|
|
749
|
-
|
|
775
|
+
this.experience?.getRenderer().setAnimationLoop(null);
|
|
776
|
+
this.experience?.dispose();
|
|
750
777
|
this.experience = null;
|
|
751
|
-
|
|
778
|
+
this.world?.dispose();
|
|
752
779
|
this.world = null;
|
|
753
780
|
this.trackingLossFrames = 0;
|
|
754
781
|
this.hadTrackingLoss = false;
|
|
755
|
-
if (
|
|
782
|
+
if (this.arButton?.parentElement) {
|
|
756
783
|
this.arButton.parentElement.removeChild(this.arButton);
|
|
757
784
|
}
|
|
758
785
|
this.arButton = null;
|
package/dist/webxr/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/webxr/internal/cameraIntrinsics.ts","../../src/lib/webxr/internal/frameCapture.ts","../../src/lib/webxr/experience/Experience.ts","../../src/lib/webxr/materials/gridMaterial.ts","../../src/lib/webxr/mapMeshVisualizer.ts","../../src/lib/webxr/world/World.ts","../../src/lib/webxr/controller.ts"],"names":["THREE","THREE2","_a","_b","THREE4","_c"],"mappings":"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","file":"index.js","sourcesContent":["import type { ICameraIntrinsicsEvent } from '../../core';\n\nexport function getCameraIntrinsics(\n projectionMatrix: Float32Array,\n viewport: XRViewport\n): ICameraIntrinsicsEvent {\n const p = projectionMatrix;\n const u0 = ((1 - p[8]) * viewport.width) / 2 + viewport.x;\n const v0 = ((1 - p[9]) * viewport.height) / 2 + viewport.y;\n const ax = (viewport.width / 2) * p[0];\n const ay = (viewport.height / 2) * p[5];\n\n return {\n fx: ax,\n fy: ay,\n px: u0,\n py: v0,\n width: viewport.width,\n height: viewport.height,\n };\n}\n","import * as THREE from 'three';\nimport type { IFrameCaptureEvent } from '../../core';\n\nexport async function compressToJpeg(\n buffer: ArrayBuffer,\n width: number,\n height: number,\n quality = 0.8\n): Promise<Blob> {\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d');\n if (!ctx) return new Blob();\n\n const imageData = new ImageData(new Uint8ClampedArray(buffer), width, height);\n ctx.putImageData(imageData, 0, 0);\n\n return new Promise((resolve) => {\n canvas.toBlob((blob) => resolve(blob ?? new Blob()), 'image/jpeg', quality);\n });\n}\n\nexport async function getCameraTextureAsImage(\n renderer: THREE.WebGLRenderer,\n webGLTexture: WebGLTexture,\n width: number,\n height: number\n): Promise<IFrameCaptureEvent | null> {\n const gl = renderer.getContext();\n if (!gl) return null;\n\n const framebuffer = gl.createFramebuffer();\n if (!framebuffer) return null;\n\n let pixelBuffer: Uint8Array;\n try {\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n gl.framebufferTexture2D(\n gl.FRAMEBUFFER,\n gl.COLOR_ATTACHMENT0,\n gl.TEXTURE_2D,\n webGLTexture,\n 0\n );\n\n pixelBuffer = new Uint8Array(width * height * 4);\n gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixelBuffer);\n } finally {\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.deleteFramebuffer(framebuffer);\n }\n\n const flippedData = new Uint8ClampedArray(pixelBuffer.length);\n for (let row = 0; row < height; row += 1) {\n const sourceStart = row * width * 4;\n const destStart = (height - row - 1) * width * 4;\n flippedData.set(\n pixelBuffer.subarray(sourceStart, sourceStart + width * 4),\n destStart\n );\n }\n\n const blob = await compressToJpeg(flippedData.buffer, width, height, 0.7);\n\n if (!blob.size) {\n return null;\n }\n\n return {\n blob,\n width,\n height,\n };\n}\n","import * as THREE from 'three';\n\n/**\n * Owns the Three.js scene, camera, and renderer for the AR session.\n * Handles resize and dispose; animation loop remains in the controller.\n */\nexport class Experience {\n private scene: THREE.Scene;\n private camera: THREE.PerspectiveCamera;\n private renderer: THREE.WebGLRenderer;\n\n constructor(canvas: HTMLCanvasElement) {\n this.renderer = new THREE.WebGLRenderer({\n canvas,\n antialias: true,\n alpha: true,\n });\n this.renderer.setSize(window.innerWidth, window.innerHeight);\n this.renderer.setPixelRatio(window.devicePixelRatio);\n this.renderer.xr.enabled = true;\n\n this.camera = new THREE.PerspectiveCamera(\n 45,\n window.innerWidth / window.innerHeight,\n 0.2,\n 10000\n );\n\n this.scene = new THREE.Scene();\n this.setupLights();\n }\n\n private setupLights(): void {\n const light = new THREE.HemisphereLight(0xffffff, 0xf8f0ff, 1);\n light.position.set(0.5, 2, 0.25);\n this.scene.add(light);\n\n const diLight = new THREE.DirectionalLight('#7B2CBF');\n diLight.position.set(0, 2, 0);\n this.scene.add(diLight);\n }\n\n getScene(): THREE.Scene {\n return this.scene;\n }\n\n getCamera(): THREE.PerspectiveCamera {\n return this.camera;\n }\n\n getRenderer(): THREE.WebGLRenderer {\n return this.renderer;\n }\n\n resize(): void {\n this.camera.aspect = window.innerWidth / window.innerHeight;\n this.camera.updateProjectionMatrix();\n this.renderer.setSize(window.innerWidth, window.innerHeight);\n }\n\n dispose(): void {\n this.renderer.dispose();\n (this as unknown as { scene: THREE.Scene | null }).scene = null;\n (this as unknown as { camera: THREE.PerspectiveCamera | null }).camera = null;\n (this as unknown as { renderer: THREE.WebGLRenderer | null }).renderer = null;\n }\n}\n","import * as THREE from 'three';\n\nconst VERTEX = `\nvarying vec3 vWorldPosition;\nvarying vec3 vWorldNormal;\n\nvoid main() {\n vec4 worldPos = modelMatrix * vec4(position, 1.0);\n vWorldPosition = worldPos.xyz;\n vWorldNormal = normalize(mat3(modelMatrix) * normal);\n\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}\n`;\n\nconst FRAGMENT = `\nuniform vec3 uColor;\nuniform float uOpacity;\n\nuniform vec3 uGridColor;\nuniform float uGridSize;\nuniform float uGridLineWidth;\nuniform float uShowGrid;\n\nuniform vec3 uCenter;\nuniform float uRadius;\nuniform float uProgress;\n\nuniform vec3 uGlowColor;\nuniform float uGlowWidth;\nuniform float uGlowIntensity;\n\nuniform vec3 uLightColor;\nuniform vec3 uLightDirection;\n\nvarying vec3 vWorldPosition;\nvarying vec3 vWorldNormal;\n\nfloat getGridFactor(vec3 worldPos, vec3 worldNormal, float gridSize, float lineWidth) {\n vec3 absNormal = abs(worldNormal);\n vec2 gridCoord;\n\n if (absNormal.y > absNormal.x && absNormal.y > absNormal.z) {\n gridCoord = worldPos.xz / gridSize;\n } else if (absNormal.x > absNormal.z) {\n gridCoord = worldPos.yz / gridSize;\n } else {\n gridCoord = worldPos.xy / gridSize;\n }\n\n vec2 gridFract = fract(abs(gridCoord));\n vec2 distToLine = min(gridFract, 1.0 - gridFract);\n float minDist = min(distToLine.x, distToLine.y);\n float gridFactor = 1.0 - smoothstep(0.0, lineWidth, minDist);\n\n return gridFactor;\n}\n\nvoid main() {\n vec3 baseColor = uColor;\n float baseAlpha = uOpacity;\n\n float distanceFromCenter = length(vWorldPosition - uCenter);\n float normalizedDistance = distanceFromCenter / max(uRadius, 0.001);\n float threshold = uProgress;\n\n if (threshold - normalizedDistance - 0.001 < 0.0) {\n discard;\n }\n\n float distanceFromEdge = threshold - normalizedDistance;\n\n float gridFactor = getGridFactor(vWorldPosition, normalize(vWorldNormal), uGridSize, uGridLineWidth);\n\n vec3 colorGridMixed = mix(baseColor, uGridColor, gridFactor * uShowGrid);\n float alphaGridMixed = max(baseAlpha, gridFactor * uShowGrid);\n\n float glowFactor = clamp(1.0 - clamp(distanceFromEdge / max(uGlowWidth, 0.001), 0.0, 1.0), 0.0, 1.0);\n glowFactor *= glowFactor;\n\n vec3 glowContribution = uGlowColor * glowFactor * uGlowIntensity;\n\n float alphaWithGlow = max(alphaGridMixed, glowFactor);\n alphaWithGlow = max(alphaWithGlow, 0.3);\n\n vec3 N = normalize(vWorldNormal);\n vec3 L = normalize(uLightDirection);\n float ndotl = max(0.3, dot(N, L));\n vec3 ambient = vec3(0.4);\n vec3 lighting = uLightColor * ndotl + ambient;\n\n vec3 litColor = colorGridMixed * lighting;\n vec3 finalColor = litColor + glowContribution * 0.5;\n\n gl_FragColor = vec4(finalColor, alphaWithGlow);\n}\n`;\n\nexport interface IGridMaterialOptions {\n color?: string | THREE.Color;\n opacity?: number;\n\n gridColor?: string | THREE.Color;\n gridScale?: number;\n gridLineWidth?: number;\n showGrid?: number;\n\n /** Center of radial effect (world space; can be updated after creation). */\n center?: THREE.Vector3;\n /** Max radius for radial progress (world units). */\n radius?: number;\n /** Progress 0–1; 1 = fully visible. */\n progress?: number;\n\n glowColor?: string | THREE.Color;\n glowWidth?: number;\n glowIntensity?: number;\n\n lightColor?: string | THREE.Color;\n /** Direction from surface toward light (world space). */\n lightDirection?: THREE.Vector3;\n}\n\n/**\n * Creates a ShaderMaterial with radial progress reveal, grid overlay, edge glow,\n * and simple directional lighting (Unity-style).\n */\nexport function createGridMaterial(\n options: IGridMaterialOptions = {}\n): THREE.ShaderMaterial {\n const color = options.color ?? '#7B2CBF';\n const opacity = options.opacity ?? 0.6;\n\n const gridColor = options.gridColor ?? '#ffeb3b';\n const gridScale = options.gridScale ?? 2.0;\n const gridLineWidth = options.gridLineWidth ?? 0.02;\n const showGrid = options.showGrid ?? 1.0;\n\n const center = options.center ?? new THREE.Vector3(0, 0, 0);\n const radius = options.radius ?? 1.0;\n const progress = options.progress ?? 1.0;\n\n const glowColor = options.glowColor ?? '#00ffff';\n const glowWidth = options.glowWidth ?? 0.05;\n const glowIntensity = options.glowIntensity ?? 2.0;\n\n const lightColor = options.lightColor ?? '#ffffff';\n const lightDirection =\n options.lightDirection ?? new THREE.Vector3(0.3, 1.0, 0.3).normalize();\n\n return new THREE.ShaderMaterial({\n vertexShader: VERTEX,\n fragmentShader: FRAGMENT,\n transparent: true,\n side: THREE.DoubleSide,\n uniforms: {\n uColor: { value: typeof color === 'string' ? new THREE.Color(color) : color },\n uOpacity: { value: opacity },\n\n uGridColor: {\n value: typeof gridColor === 'string' ? new THREE.Color(gridColor) : gridColor,\n },\n uGridSize: { value: gridScale },\n uGridLineWidth: { value: gridLineWidth },\n uShowGrid: { value: showGrid },\n\n uCenter: { value: center.clone() },\n uRadius: { value: radius },\n uProgress: { value: progress },\n\n uGlowColor: {\n value: typeof glowColor === 'string' ? new THREE.Color(glowColor) : glowColor,\n },\n uGlowWidth: { value: glowWidth },\n uGlowIntensity: { value: glowIntensity },\n\n uLightColor: {\n value: typeof lightColor === 'string' ? new THREE.Color(lightColor) : lightColor,\n },\n uLightDirection: { value: lightDirection.clone() },\n },\n });\n}\n","import * as THREE from 'three';\nimport type { MultisetClient, ILocalizeAndMapDetails } from '../core';\nimport type { IGetMapsDetailsResponse } from '../core';\nimport { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { createGridMaterial } from './materials/gridMaterial';\n\nconst LARGE_MAP_THRESHOLD = 50.0;\n\nexport class MapMeshVisualizer {\n private readonly meshGroup: THREE.Group;\n private readonly gltfLoader: GLTFLoader;\n private readonly dracoLoader: DRACOLoader;\n\n private meshMaterial: THREE.ShaderMaterial | null = null;\n private readonly localCenter = new THREE.Vector3();\n private localRadius = 0;\n private readonly radialDuration = 4.0; // seconds for full radial reveal\n private readonly radialRepeatInterval = 20.0; // seconds before replaying the effect\n private idleTimeAfterReveal = 0; // seconds since progress reached 1\n private readonly lastViewerWorldPosition = new THREE.Vector3();\n\n constructor(\n private readonly scene: THREE.Scene,\n private readonly client: MultisetClient\n ) {\n this.meshGroup = new THREE.Group();\n this.meshGroup.visible = false;\n this.scene.add(this.meshGroup);\n\n this.dracoLoader = new DRACOLoader();\n this.dracoLoader.setDecoderPath('/draco/');\n\n this.gltfLoader = new GLTFLoader();\n this.gltfLoader.setDRACOLoader(this.dracoLoader);\n }\n\n getMeshGroup(): THREE.Group {\n return this.meshGroup;\n }\n\n async ensureMeshLoaded(mapDetails: IGetMapsDetailsResponse): Promise<void> {\n if (this.scene.getObjectByName(mapDetails._id)) {\n return;\n }\n\n const meshKey = mapDetails.mapMesh?.rawMesh?.meshLink;\n if (!meshKey) {\n return;\n }\n\n const url = await this.client.downloadFile(meshKey);\n if (!url) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n this.gltfLoader.load(\n url,\n (gltf) => {\n const box = new THREE.Box3().setFromObject(gltf.scene);\n const sizeVec = box.getSize(new THREE.Vector3());\n let size = sizeVec.length();\n const center = box.getCenter(new THREE.Vector3());\n\n if (size > LARGE_MAP_THRESHOLD) {\n size = LARGE_MAP_THRESHOLD;\n }\n\n this.localCenter.copy(center);\n this.localRadius = Math.max(size / 2, 0.001);\n\n const meshMaterial = createGridMaterial({\n color: '#7B2CBF',\n opacity: 0.4,\n gridColor: '#ffeb3b',\n gridScale: 2.0,\n gridLineWidth: 0.02,\n showGrid: 1.0,\n center: this.localCenter.clone(),\n radius: this.localRadius,\n progress: 0.0,\n glowColor: '#00ffff',\n glowWidth: 0.05,\n glowIntensity: 2.0,\n });\n\n this.meshMaterial = meshMaterial;\n\n gltf.scene.traverse((child) => {\n if ((child as THREE.Mesh).isMesh) {\n (child as THREE.Mesh).material = meshMaterial;\n }\n });\n\n gltf.scene.name = mapDetails._id;\n this.meshGroup.add(gltf.scene);\n resolve();\n },\n undefined,\n (error) => {\n reject(error instanceof Error ? error : new Error(String(error)));\n }\n );\n });\n }\n\n applyMeshTransform(\n best: ILocalizeAndMapDetails,\n trackerSpace: THREE.Matrix4\n ): void {\n const pose = best.localizeData;\n\n const resPosition = new THREE.Vector3(\n pose.position.x,\n pose.position.y,\n pose.position.z\n );\n\n const resRotation = new THREE.Quaternion(\n pose.rotation.x,\n pose.rotation.y,\n pose.rotation.z,\n pose.rotation.w\n );\n\n const responseMatrix = new THREE.Matrix4();\n responseMatrix.compose(resPosition, resRotation, new THREE.Vector3(1, 1, 1));\n\n const inverseResponseMatrix = responseMatrix.clone().invert();\n\n const resultantMatrix = new THREE.Matrix4();\n resultantMatrix.multiplyMatrices(trackerSpace, inverseResponseMatrix);\n\n const position = new THREE.Vector3();\n const rotation = new THREE.Quaternion();\n const scale = new THREE.Vector3();\n resultantMatrix.decompose(position, rotation, scale);\n\n this.meshGroup.position.copy(position);\n this.meshGroup.quaternion.copy(rotation);\n this.meshGroup.scale.set(1, 1, 1);\n this.meshGroup.visible = true;\n this.meshGroup.updateMatrix();\n\n if (this.meshMaterial) {\n this.meshMaterial.uniforms.uCenter.value\n .copy(this.localCenter)\n .applyMatrix4(this.meshGroup.matrixWorld);\n }\n }\n\n update(\n deltaSeconds: number,\n viewerWorldPosition?: THREE.Vector3 | null\n ): void {\n if (!this.meshMaterial) {\n return;\n }\n\n if (viewerWorldPosition) {\n this.lastViewerWorldPosition.copy(viewerWorldPosition);\n }\n\n const uniforms = this.meshMaterial.uniforms as {\n uProgress?: { value: number };\n uCenter?: { value: THREE.Vector3 };\n };\n\n if (!uniforms.uProgress) {\n return;\n }\n\n const current = uniforms.uProgress.value ?? 0;\n\n if (current === 0 && uniforms.uCenter && this.lastViewerWorldPosition.lengthSq() > 0) {\n uniforms.uCenter.value.copy(this.lastViewerWorldPosition);\n }\n\n if (current >= 1) {\n this.idleTimeAfterReveal += deltaSeconds;\n if (this.idleTimeAfterReveal >= this.radialRepeatInterval) {\n uniforms.uProgress.value = 0;\n this.idleTimeAfterReveal = 0;\n }\n return;\n }\n\n this.idleTimeAfterReveal = 0;\n const next = Math.min(\n current + deltaSeconds / this.radialDuration,\n 1\n );\n\n uniforms.uProgress.value = next;\n }\n\n dispose(): void {\n this.meshMaterial = null;\n this.meshGroup.traverse((child) => {\n const mesh = child as THREE.Mesh;\n if (mesh.isMesh) {\n mesh.geometry.dispose();\n if (Array.isArray(mesh.material)) {\n mesh.material.forEach((m) => m.dispose());\n } else {\n (mesh.material as THREE.Material).dispose();\n }\n }\n });\n this.scene.remove(this.meshGroup);\n this.dracoLoader.dispose();\n }\n}\n\n","import * as THREE from 'three';\nimport type { MultisetClient, ILocalizeAndMapDetails } from '../../core';\nimport type { IGetMapsDetailsResponse } from '../../core';\nimport { MapMeshVisualizer } from '../mapMeshVisualizer';\n\n/**\n * Composes scene content for the AR session (e.g. map mesh).\n * Delegates to MapMeshVisualizer for mesh load and transform.\n */\nexport class World {\n private readonly meshVisualizer: MapMeshVisualizer;\n\n constructor(scene: THREE.Scene, client: MultisetClient) {\n this.meshVisualizer = new MapMeshVisualizer(scene, client);\n }\n\n async ensureMeshLoaded(mapDetails: IGetMapsDetailsResponse): Promise<void> {\n await this.meshVisualizer.ensureMeshLoaded(mapDetails);\n }\n\n applyMeshTransform(\n best: ILocalizeAndMapDetails,\n trackerSpace: THREE.Matrix4\n ): void {\n this.meshVisualizer.applyMeshTransform(best, trackerSpace);\n }\n\n update(\n deltaSeconds: number,\n viewerWorldPosition?: THREE.Vector3 | null\n ): void {\n this.meshVisualizer.update(deltaSeconds, viewerWorldPosition);\n }\n\n dispose(): void {\n this.meshVisualizer.dispose();\n }\n}\n","import * as THREE from 'three';\nimport { ARButton } from 'three/examples/jsm/webxr/ARButton.js';\n\nimport type {\n MultisetClient,\n ILocalizeAndMapDetails,\n} from '../core';\nimport { getCameraIntrinsics } from './internal/cameraIntrinsics';\nimport { getCameraTextureAsImage } from './internal/frameCapture';\nimport { Experience } from './experience/Experience';\nimport { World } from './world/World';\nconst CONFIDENCE_THRESHOLD_MIN = 0.2;\nconst CONFIDENCE_THRESHOLD_MAX = 0.8;\nconst TRACKING_LOSS_FRAME_THRESHOLD = 60;\n/** Default max time (ms) to wait for a valid viewer pose before failing. */\nconst DEFAULT_TRACKING_TIMEOUT_MS = 10_000;\n/** Max XR frames to wait for viewer pose (backup cap; ~10s at 30fps). */\nconst TRACKING_FRAME_CAP = 300;\n/** Max frames with valid pose but no camera image before failing. */\nconst CAMERA_IMAGE_MAX_ATTEMPTS = 10;\n\n/**\n * Options for WebxrController. Property names align with Unity SingleFrameLocalizationManager\n * where applicable (see https://docs.multiset.ai/unity-sdk/api-reference/singleframelocalizationmanager).\n */\nexport interface IWebxrControllerOptions {\n client: MultisetClient;\n canvas?: HTMLCanvasElement;\n overlayRoot?: HTMLElement;\n buttonContainer?: HTMLElement;\n onARButtonCreated?: (button: HTMLButtonElement) => void;\n onSessionStart?: () => void;\n onSessionEnd?: () => void;\n}\n\ntype XRViewWithCamera = XRView & {\n camera?: {\n width: number;\n height: number;\n [key: string]: unknown;\n };\n};\n\ntype XRWebGLBindingLike = {\n getCameraImage: (camera: XRViewWithCamera['camera']) => WebGLTexture | null;\n};\n\nexport class WebxrController {\n private experience: Experience | null = null;\n private world: World | null = null;\n private arButton: HTMLButtonElement | null = null;\n private resizeHandler: (() => void) | null = null;\n private isSessionActive: boolean = false;\n private trackingLossFrames: number = 0;\n private hadTrackingLoss: boolean = false;\n private isLocalizing: boolean = false;\n private trackerSpace: THREE.Matrix4 | null = null;\n\n constructor(private readonly options: IWebxrControllerOptions) { }\n\n async initialize(buttonContainer?: HTMLElement): Promise<HTMLButtonElement> {\n if (this.experience) {\n return this.arButton!;\n }\n\n if (!window.isSecureContext) {\n throw new Error('WebXR requires a secure context (HTTPS).');\n }\n\n const canvas = this.options.canvas ?? document.createElement('canvas');\n\n this.experience = new Experience(canvas);\n this.world = new World(this.experience.getScene(), this.options.client);\n\n const renderer = this.experience.getRenderer();\n const camera = this.experience.getCamera();\n const scene = this.experience.getScene();\n\n renderer.xr.addEventListener('sessionstart', () => {\n this.isSessionActive = true;\n this.options.onSessionStart?.();\n const cfg = this.options.client.getConfig();\n if (cfg.autoLocalize) {\n const session = renderer.xr.getSession();\n if (session) {\n session.requestAnimationFrame(() => {\n void this.localizeFrame();\n });\n } else {\n void this.localizeFrame();\n }\n }\n });\n\n renderer.xr.addEventListener('sessionend', () => {\n this.isSessionActive = false;\n this.options.onSessionEnd?.();\n });\n\n let lastTime = 0;\n\n const animationLoop = (time: number, frame: XRFrame | null) => {\n const deltaSeconds = lastTime === 0 ? 0 : (time - lastTime) / 1000;\n lastTime = time;\n\n let viewerWorldPosition: THREE.Vector3 | null = null;\n if (frame) {\n const refSpace = renderer.xr.getReferenceSpace();\n if (refSpace) {\n const viewerPose = frame.getViewerPose(refSpace);\n if (viewerPose) {\n const p = viewerPose.transform.position;\n viewerWorldPosition = new THREE.Vector3(p.x, p.y, p.z);\n }\n }\n }\n\n if (this.world && deltaSeconds > 0) {\n this.world.update(deltaSeconds, viewerWorldPosition);\n }\n\n renderer.render(scene, camera);\n const cfg = this.options.client.getConfig();\n if (cfg.relocalization && frame && !this.isLocalizing) {\n const refSpace = renderer.xr.getReferenceSpace();\n if (refSpace) {\n const viewerPose = frame.getViewerPose(refSpace);\n if (!viewerPose) {\n this.trackingLossFrames += 1;\n if (this.trackingLossFrames >= TRACKING_LOSS_FRAME_THRESHOLD) {\n this.hadTrackingLoss = true;\n }\n } else {\n if (this.hadTrackingLoss) {\n this.hadTrackingLoss = false;\n this.trackingLossFrames = 0;\n void this.localizeFrame();\n } else {\n this.trackingLossFrames = 0;\n }\n }\n }\n }\n };\n renderer.setAnimationLoop(animationLoop);\n\n const resizeHandler = () => {\n this.experience?.resize();\n };\n window.addEventListener('resize', resizeHandler);\n\n const overlayRoot = this.options.overlayRoot ?? document.body;\n const arButton = ARButton.createButton(renderer, {\n requiredFeatures: ['camera-access', 'dom-overlay'],\n domOverlay: { root: overlayRoot },\n }) as HTMLButtonElement;\n\n const buttonParent =\n buttonContainer && buttonContainer instanceof HTMLElement\n ? buttonContainer\n : this.options.buttonContainer &&\n this.options.buttonContainer instanceof HTMLElement\n ? this.options.buttonContainer\n : overlayRoot;\n\n if (!buttonParent.contains(arButton)) {\n buttonParent.appendChild(arButton);\n }\n\n this.arButton = arButton;\n this.resizeHandler = resizeHandler;\n\n this.options.onARButtonCreated?.(arButton);\n return arButton;\n }\n\n getScene(): THREE.Scene {\n if (!this.experience) {\n throw new Error('Scene: WebXR controller has not been initialized.');\n }\n return this.experience.getScene();\n }\n\n getCamera(): THREE.PerspectiveCamera {\n if (!this.experience) {\n throw new Error('Camera: WebXR controller has not been initialized.');\n }\n return this.experience.getCamera();\n }\n\n getRenderer(): THREE.WebGLRenderer {\n if (!this.experience) {\n throw new Error('Renderer: WebXR controller has not been initialized.');\n }\n return this.experience.getRenderer();\n }\n\n hasActiveSession(): boolean {\n return this.isSessionActive && this.experience?.getRenderer().xr.isPresenting === true;\n }\n\n /**\n * Runs a single-frame localization: captures one frame, evaluates the result\n * against the optional confidenceThreshold, and fires\n * onLocalizationInit / onLocalizationSuccess / onLocalizationFailure.\n * Aligns with Unity SingleFrameLocalizationManager.LocalizeFrame().\n */\n async localizeFrame(): Promise<ILocalizeAndMapDetails | null> {\n if (!this.experience) {\n throw new Error('WebXR: WebXR controller has not been initialized.');\n }\n const renderer = this.experience.getRenderer();\n const session = renderer.xr.getSession?.();\n if (!session) {\n throw new Error(\n 'WebXR Session: No active WebXR session. Start AR before calling localizeFrame().'\n );\n }\n\n const cfg = this.options.client.getConfig();\n const confidenceCheck = cfg.confidenceCheck ?? false;\n const confidenceThreshold = Math.max(\n CONFIDENCE_THRESHOLD_MIN,\n Math.min(cfg.confidenceThreshold ?? 0.5, CONFIDENCE_THRESHOLD_MAX)\n );\n\n cfg.onLocalizationInit?.();\n this.isLocalizing = true;\n\n let best: ILocalizeAndMapDetails | null = null;\n\n let failureReason: string | undefined;\n try {\n const captureResult = await this.captureFrame();\n best = captureResult.result;\n failureReason = captureResult.failureReason;\n } finally {\n this.isLocalizing = false;\n }\n\n const accepted =\n best &&\n (!confidenceCheck ||\n (best.localizeData.confidence ?? 0) >= confidenceThreshold);\n\n if (accepted && best) {\n cfg.onLocalizationSuccess?.(best);\n\n if (cfg.showMesh && best.mapDetails && this.world && this.trackerSpace) {\n try {\n await this.world.ensureMeshLoaded(best.mapDetails);\n this.world.applyMeshTransform(best, this.trackerSpace);\n } catch {\n // Mesh loading failure must not prevent returning the localization result\n }\n }\n return best;\n }\n\n const reason =\n failureReason ??\n (!best\n ? 'All attempts failed to produce a pose.'\n : confidenceCheck\n ? `Best confidence ${best.localizeData.confidence ?? 0} below threshold ${confidenceThreshold}.`\n : undefined);\n cfg.onLocalizationFailure?.(reason);\n return null;\n }\n\n /**\n * Internal: captures one frame and calls the localization API. Waits for a\n * valid viewer pose up to localizationTrackingTimeoutMs (and TRACKING_FRAME_CAP),\n * then tries to get a camera image (up to CAMERA_IMAGE_MAX_ATTEMPTS). Returns\n * result, apiCalled, and an optional failureReason for onLocalizationFailure.\n */\n private async captureFrame(): Promise<{\n result: ILocalizeAndMapDetails | null;\n apiCalled: boolean;\n failureReason?: string;\n }> {\n if (!this.experience) {\n throw new Error('WebXR: WebXR controller has not been initialized.');\n }\n const renderer = this.experience.getRenderer();\n\n const session = renderer.xr.getSession?.();\n if (!session) {\n throw new Error(\n 'WebXR Session: No active WebXR session. Start AR before capturing.'\n );\n }\n\n const referenceSpace = renderer.xr.getReferenceSpace();\n if (!referenceSpace) {\n throw new Error(\n 'WebXR Reference Space: Unable to acquire XR reference space.'\n );\n }\n\n const gl = renderer.getContext();\n const cfg = this.options.client.getConfig();\n const timeoutMs = cfg.localizationTrackingTimeoutMs ?? DEFAULT_TRACKING_TIMEOUT_MS;\n\n return new Promise((resolve, reject) => {\n const startTime = Date.now();\n\n const tryFrame = (attempt: number, cameraAttemptsWithPose: number) => {\n session.requestAnimationFrame(async (_time: number, xrFrame: XRFrame) => {\n try {\n const elapsed = Date.now() - startTime;\n const viewerPose = xrFrame.getViewerPose(referenceSpace);\n if (!viewerPose) {\n if (elapsed >= timeoutMs || attempt + 1 >= TRACKING_FRAME_CAP) {\n const sec = (timeoutMs / 1000).toFixed(1);\n resolve({\n result: null,\n apiCalled: false,\n failureReason: `Tracking unavailable: no viewer pose within ${sec}s. Try moving the device or ensuring good lighting.`,\n });\n } else {\n tryFrame(attempt + 1, cameraAttemptsWithPose);\n }\n return;\n }\n\n const views = viewerPose.views as XRViewWithCamera[];\n for (let i = 0; i < views.length; i += 1) {\n const view = views[i];\n const xrCamera = view.camera;\n if (!xrCamera) continue;\n\n const gl2 = gl as unknown as WebGL2RenderingContext;\n const bindingCtor = XRWebGLBinding as unknown as {\n new(\n session: XRSession,\n context: WebGL2RenderingContext\n ): XRWebGLBindingLike;\n };\n const binding = new bindingCtor(session, gl2);\n const cameraTexture = binding.getCameraImage?.(xrCamera) ?? null;\n if (!cameraTexture) continue;\n\n const width = xrCamera.width;\n const height = xrCamera.height;\n if (!width || !height) continue;\n\n const frameData = await getCameraTextureAsImage(\n renderer,\n cameraTexture,\n width,\n height\n );\n\n const intrinsics = getCameraIntrinsics(view.projectionMatrix, {\n width,\n height,\n x: 0,\n y: 0,\n });\n\n if (frameData && intrinsics) {\n // Capture the camera pose from the current XRFrame's view transform\n // (column-major Float32Array, same convention as THREE.Matrix4.fromArray).\n // Using camera.matrix would give the previous render frame's pose.\n this.trackerSpace = new THREE.Matrix4().fromArray(view.transform.matrix);\n\n const result = await this.options.client.localizeWithFrame(\n frameData,\n intrinsics\n );\n resolve({ result, apiCalled: true });\n return;\n }\n }\n\n if (cameraAttemptsWithPose + 1 >= CAMERA_IMAGE_MAX_ATTEMPTS) {\n resolve({\n result: null,\n apiCalled: false,\n failureReason:\n 'Camera image not available. The device or browser may not support camera access in AR.',\n });\n } else {\n tryFrame(attempt + 1, cameraAttemptsWithPose + 1);\n }\n } catch (error) {\n reject(error);\n } finally {\n gl.bindFramebuffer(\n gl.FRAMEBUFFER,\n session.renderState.baseLayer?.framebuffer ?? null\n );\n }\n });\n };\n tryFrame(0, 0);\n });\n }\n\n dispose(): void {\n if (this.resizeHandler) {\n window.removeEventListener('resize', this.resizeHandler);\n }\n\n this.experience?.getRenderer().setAnimationLoop(null);\n this.experience?.dispose();\n this.experience = null;\n this.world?.dispose();\n this.world = null;\n this.trackingLossFrames = 0;\n this.hadTrackingLoss = false;\n\n if (this.arButton?.parentElement) {\n this.arButton.parentElement.removeChild(this.arButton);\n }\n this.arButton = null;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/lib/webxr/internal/cameraIntrinsics.ts","../../src/lib/webxr/internal/frameCapture.ts","../../src/lib/webxr/experience/Experience.ts","../../src/lib/webxr/materials/gridMaterial.ts","../../src/lib/webxr/mapMeshVisualizer.ts","../../src/lib/webxr/world/World.ts","../../src/lib/webxr/controller.ts"],"names":["THREE","THREE2","THREE4"],"mappings":"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","file":"index.js","sourcesContent":["import type { ICameraIntrinsicsEvent } from '../../core';\n\nexport function getCameraIntrinsics(\n projectionMatrix: Float32Array,\n viewport: XRViewport\n): ICameraIntrinsicsEvent {\n const p = projectionMatrix;\n const u0 = ((1 - p[8]) * viewport.width) / 2 + viewport.x;\n const v0 = ((1 - p[9]) * viewport.height) / 2 + viewport.y;\n const ax = (viewport.width / 2) * p[0];\n const ay = (viewport.height / 2) * p[5];\n\n return {\n fx: ax,\n fy: ay,\n px: u0,\n py: v0,\n width: viewport.width,\n height: viewport.height,\n };\n}\n","import * as THREE from 'three';\nimport type { IFrameCaptureEvent } from '../../core';\n\nexport async function compressToJpeg(\n buffer: ArrayBuffer,\n width: number,\n height: number,\n quality = 0.8\n): Promise<Blob> {\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d');\n if (!ctx) return new Blob();\n\n const imageData = new ImageData(new Uint8ClampedArray(buffer), width, height);\n ctx.putImageData(imageData, 0, 0);\n\n return new Promise((resolve) => {\n canvas.toBlob((blob) => resolve(blob ?? new Blob()), 'image/jpeg', quality);\n });\n}\n\nexport async function getCameraTextureAsImage(\n renderer: THREE.WebGLRenderer,\n webGLTexture: WebGLTexture,\n width: number,\n height: number\n): Promise<IFrameCaptureEvent | null> {\n const gl = renderer.getContext();\n if (!gl) return null;\n\n const framebuffer = gl.createFramebuffer();\n if (!framebuffer) return null;\n\n let pixelBuffer: Uint8Array;\n try {\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n gl.framebufferTexture2D(\n gl.FRAMEBUFFER,\n gl.COLOR_ATTACHMENT0,\n gl.TEXTURE_2D,\n webGLTexture,\n 0\n );\n\n pixelBuffer = new Uint8Array(width * height * 4);\n gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixelBuffer);\n } finally {\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.deleteFramebuffer(framebuffer);\n }\n\n const flippedData = new Uint8ClampedArray(pixelBuffer.length);\n for (let row = 0; row < height; row += 1) {\n const sourceStart = row * width * 4;\n const destStart = (height - row - 1) * width * 4;\n flippedData.set(\n pixelBuffer.subarray(sourceStart, sourceStart + width * 4),\n destStart\n );\n }\n\n const blob = await compressToJpeg(flippedData.buffer, width, height, 0.7);\n\n if (!blob.size) {\n return null;\n }\n\n return {\n blob,\n width,\n height,\n };\n}\n","import * as THREE from 'three';\n\n/**\n * Owns the Three.js scene, camera, and renderer for the AR session.\n * Handles resize and dispose; animation loop remains in the controller.\n */\nexport class Experience {\n private scene: THREE.Scene;\n private camera: THREE.PerspectiveCamera;\n private renderer: THREE.WebGLRenderer;\n\n constructor(canvas: HTMLCanvasElement) {\n this.renderer = new THREE.WebGLRenderer({\n canvas,\n antialias: true,\n alpha: true,\n });\n this.renderer.setSize(window.innerWidth, window.innerHeight);\n this.renderer.setPixelRatio(window.devicePixelRatio);\n this.renderer.xr.enabled = true;\n\n this.camera = new THREE.PerspectiveCamera(\n 45,\n window.innerWidth / window.innerHeight,\n 0.2,\n 10000\n );\n\n this.scene = new THREE.Scene();\n this.setupLights();\n }\n\n private setupLights(): void {\n const light = new THREE.HemisphereLight(0xffffff, 0xf8f0ff, 1);\n light.position.set(0.5, 2, 0.25);\n this.scene.add(light);\n\n const diLight = new THREE.DirectionalLight('#7B2CBF');\n diLight.position.set(0, 2, 0);\n this.scene.add(diLight);\n }\n\n getScene(): THREE.Scene {\n return this.scene;\n }\n\n getCamera(): THREE.PerspectiveCamera {\n return this.camera;\n }\n\n getRenderer(): THREE.WebGLRenderer {\n return this.renderer;\n }\n\n resize(): void {\n this.camera.aspect = window.innerWidth / window.innerHeight;\n this.camera.updateProjectionMatrix();\n this.renderer.setSize(window.innerWidth, window.innerHeight);\n }\n\n dispose(): void {\n this.renderer.dispose();\n (this as unknown as { scene: THREE.Scene | null }).scene = null;\n (this as unknown as { camera: THREE.PerspectiveCamera | null }).camera = null;\n (this as unknown as { renderer: THREE.WebGLRenderer | null }).renderer = null;\n }\n}\n","import * as THREE from 'three';\n\nconst VERTEX = `\nvarying vec3 vWorldPosition;\nvarying vec3 vWorldNormal;\n\nvoid main() {\n vec4 worldPos = modelMatrix * vec4(position, 1.0);\n vWorldPosition = worldPos.xyz;\n vWorldNormal = normalize(mat3(modelMatrix) * normal);\n\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}\n`;\n\nconst FRAGMENT = `\nuniform vec3 uColor;\nuniform float uOpacity;\n\nuniform vec3 uGridColor;\nuniform float uGridSize;\nuniform float uGridLineWidth;\nuniform float uShowGrid;\n\nuniform vec3 uCenter;\nuniform float uRadius;\nuniform float uProgress;\n\nuniform vec3 uGlowColor;\nuniform float uGlowWidth;\nuniform float uGlowIntensity;\n\nuniform vec3 uLightColor;\nuniform vec3 uLightDirection;\n\nvarying vec3 vWorldPosition;\nvarying vec3 vWorldNormal;\n\nfloat getGridFactor(vec3 worldPos, vec3 worldNormal, float gridSize, float lineWidth) {\n vec3 absNormal = abs(worldNormal);\n vec2 gridCoord;\n\n if (absNormal.y > absNormal.x && absNormal.y > absNormal.z) {\n gridCoord = worldPos.xz / gridSize;\n } else if (absNormal.x > absNormal.z) {\n gridCoord = worldPos.yz / gridSize;\n } else {\n gridCoord = worldPos.xy / gridSize;\n }\n\n vec2 gridFract = fract(abs(gridCoord));\n vec2 distToLine = min(gridFract, 1.0 - gridFract);\n float minDist = min(distToLine.x, distToLine.y);\n float gridFactor = 1.0 - smoothstep(0.0, lineWidth, minDist);\n\n return gridFactor;\n}\n\nvoid main() {\n vec3 baseColor = uColor;\n float baseAlpha = uOpacity;\n\n float distanceFromCenter = length(vWorldPosition - uCenter);\n float normalizedDistance = distanceFromCenter / max(uRadius, 0.001);\n float threshold = uProgress;\n\n if (threshold - normalizedDistance - 0.001 < 0.0) {\n discard;\n }\n\n float distanceFromEdge = threshold - normalizedDistance;\n\n float gridFactor = getGridFactor(vWorldPosition, normalize(vWorldNormal), uGridSize, uGridLineWidth);\n\n vec3 colorGridMixed = mix(baseColor, uGridColor, gridFactor * uShowGrid);\n float alphaGridMixed = max(baseAlpha, gridFactor * uShowGrid);\n\n float glowFactor = clamp(1.0 - clamp(distanceFromEdge / max(uGlowWidth, 0.001), 0.0, 1.0), 0.0, 1.0);\n glowFactor *= glowFactor;\n\n vec3 glowContribution = uGlowColor * glowFactor * uGlowIntensity;\n\n float alphaWithGlow = max(alphaGridMixed, glowFactor);\n alphaWithGlow = max(alphaWithGlow, 0.3);\n\n vec3 N = normalize(vWorldNormal);\n vec3 L = normalize(uLightDirection);\n float ndotl = max(0.3, dot(N, L));\n vec3 ambient = vec3(0.4);\n vec3 lighting = uLightColor * ndotl + ambient;\n\n vec3 litColor = colorGridMixed * lighting;\n vec3 finalColor = litColor + glowContribution * 0.5;\n\n gl_FragColor = vec4(finalColor, alphaWithGlow);\n}\n`;\n\nexport interface IGridMaterialOptions {\n color?: string | THREE.Color;\n opacity?: number;\n\n gridColor?: string | THREE.Color;\n gridScale?: number;\n gridLineWidth?: number;\n showGrid?: number;\n\n /** Center of radial effect (world space; can be updated after creation). */\n center?: THREE.Vector3;\n /** Max radius for radial progress (world units). */\n radius?: number;\n /** Progress 0–1; 1 = fully visible. */\n progress?: number;\n\n glowColor?: string | THREE.Color;\n glowWidth?: number;\n glowIntensity?: number;\n\n lightColor?: string | THREE.Color;\n /** Direction from surface toward light (world space). */\n lightDirection?: THREE.Vector3;\n}\n\n/**\n * Creates a ShaderMaterial with radial progress reveal, grid overlay, edge glow,\n * and simple directional lighting (Unity-style).\n */\nexport function createGridMaterial(\n options: IGridMaterialOptions = {}\n): THREE.ShaderMaterial {\n const color = options.color ?? '#7B2CBF';\n const opacity = options.opacity ?? 0.6;\n\n const gridColor = options.gridColor ?? '#ffeb3b';\n const gridScale = options.gridScale ?? 2.0;\n const gridLineWidth = options.gridLineWidth ?? 0.02;\n const showGrid = options.showGrid ?? 1.0;\n\n const center = options.center ?? new THREE.Vector3(0, 0, 0);\n const radius = options.radius ?? 1.0;\n const progress = options.progress ?? 1.0;\n\n const glowColor = options.glowColor ?? '#00ffff';\n const glowWidth = options.glowWidth ?? 0.05;\n const glowIntensity = options.glowIntensity ?? 2.0;\n\n const lightColor = options.lightColor ?? '#ffffff';\n const lightDirection =\n options.lightDirection ?? new THREE.Vector3(0.3, 1.0, 0.3).normalize();\n\n return new THREE.ShaderMaterial({\n vertexShader: VERTEX,\n fragmentShader: FRAGMENT,\n transparent: true,\n side: THREE.DoubleSide,\n uniforms: {\n uColor: { value: typeof color === 'string' ? new THREE.Color(color) : color },\n uOpacity: { value: opacity },\n\n uGridColor: {\n value: typeof gridColor === 'string' ? new THREE.Color(gridColor) : gridColor,\n },\n uGridSize: { value: gridScale },\n uGridLineWidth: { value: gridLineWidth },\n uShowGrid: { value: showGrid },\n\n uCenter: { value: center.clone() },\n uRadius: { value: radius },\n uProgress: { value: progress },\n\n uGlowColor: {\n value: typeof glowColor === 'string' ? new THREE.Color(glowColor) : glowColor,\n },\n uGlowWidth: { value: glowWidth },\n uGlowIntensity: { value: glowIntensity },\n\n uLightColor: {\n value: typeof lightColor === 'string' ? new THREE.Color(lightColor) : lightColor,\n },\n uLightDirection: { value: lightDirection.clone() },\n },\n });\n}\n","import * as THREE from 'three';\nimport type { MultisetClient, ILocalizeAndMapDetails } from '../core';\nimport type { IGetMapsDetailsResponse } from '../core';\nimport { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';\nimport { TransformControls } from 'three/examples/jsm/controls/TransformControls.js';\nimport { createGridMaterial } from './materials/gridMaterial';\n\nconst LARGE_MAP_THRESHOLD = 50.0;\n\nexport class MapMeshVisualizer {\n private readonly meshGroup: THREE.Group;\n private readonly gltfLoader: GLTFLoader;\n private readonly dracoLoader: DRACOLoader;\n\n private gizmoControl: TransformControls | null = null;\n private gizmoHelper: THREE.Object3D | null = null;\n private meshMaterial: THREE.ShaderMaterial | null = null;\n private readonly localCenter = new THREE.Vector3();\n private localRadius = 0;\n private readonly radialDuration = 4.0; // seconds for full radial reveal\n private readonly radialRepeatInterval = 20.0; // seconds before replaying the effect\n private idleTimeAfterReveal = 0; // seconds since progress reached 1\n private readonly lastViewerWorldPosition = new THREE.Vector3();\n\n constructor(\n private readonly scene: THREE.Scene,\n private readonly client: MultisetClient,\n private readonly renderer: THREE.WebGLRenderer,\n private readonly camera: THREE.Camera\n ) {\n this.meshGroup = new THREE.Group();\n this.meshGroup.visible = false;\n this.scene.add(this.meshGroup);\n\n this.dracoLoader = new DRACOLoader();\n this.dracoLoader.setDecoderPath('/draco/');\n\n this.gltfLoader = new GLTFLoader();\n this.gltfLoader.setDRACOLoader(this.dracoLoader);\n }\n\n getMeshGroup(): THREE.Group {\n return this.meshGroup;\n }\n\n async ensureGizmoLoaded(): Promise<void> {\n const cfg = this.client.getConfig();\n if (cfg.showGizmo === false) {\n return;\n }\n if (!this.gizmoControl) {\n const gizmo = new TransformControls(this.camera, this.renderer.domElement);\n gizmo.setMode('translate');\n gizmo.setSpace('local');\n gizmo.enabled = false;\n const helper = gizmo.getHelper();\n this.scene.add(helper);\n gizmo.attach(this.meshGroup);\n this.gizmoControl = gizmo;\n this.gizmoHelper = helper;\n }\n this.gizmoHelper!.visible = true;\n }\n\n async ensureMeshLoaded(mapDetails: IGetMapsDetailsResponse): Promise<void> {\n if (this.scene.getObjectByName(mapDetails._id)) {\n return;\n }\n\n const meshKey = mapDetails.mapMesh?.rawMesh?.meshLink;\n if (!meshKey) {\n return;\n }\n\n const url = await this.client.downloadFile(meshKey);\n if (!url) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n this.gltfLoader.load(\n url,\n (gltf) => {\n const box = new THREE.Box3().setFromObject(gltf.scene);\n const sizeVec = box.getSize(new THREE.Vector3());\n let size = sizeVec.length();\n const center = box.getCenter(new THREE.Vector3());\n\n if (size > LARGE_MAP_THRESHOLD) {\n size = LARGE_MAP_THRESHOLD;\n }\n\n this.localCenter.copy(center);\n this.localRadius = Math.max(size / 2, 0.001);\n\n const meshMaterial = createGridMaterial({\n color: '#7B2CBF',\n opacity: 0.4,\n gridColor: '#ffeb3b',\n gridScale: 2.0,\n gridLineWidth: 0.02,\n showGrid: 1.0,\n center: this.localCenter.clone(),\n radius: this.localRadius,\n progress: 0.0,\n glowColor: '#00ffff',\n glowWidth: 0.05,\n glowIntensity: 2.0,\n });\n\n this.meshMaterial = meshMaterial;\n\n gltf.scene.traverse((child) => {\n if ((child as THREE.Mesh).isMesh) {\n (child as THREE.Mesh).material = meshMaterial;\n }\n });\n\n gltf.scene.name = mapDetails._id;\n this.meshGroup.add(gltf.scene);\n resolve();\n },\n undefined,\n (error) => {\n reject(error instanceof Error ? error : new Error(String(error)));\n }\n );\n });\n }\n\n applyMeshTransform(\n best: ILocalizeAndMapDetails,\n trackerSpace: THREE.Matrix4\n ): void {\n const pose = best.localizeData;\n\n const resPosition = new THREE.Vector3(\n pose.position.x,\n pose.position.y,\n pose.position.z\n );\n\n const resRotation = new THREE.Quaternion(\n pose.rotation.x,\n pose.rotation.y,\n pose.rotation.z,\n pose.rotation.w\n );\n\n const responseMatrix = new THREE.Matrix4();\n responseMatrix.compose(resPosition, resRotation, new THREE.Vector3(1, 1, 1));\n\n const inverseResponseMatrix = responseMatrix.clone().invert();\n\n const resultantMatrix = new THREE.Matrix4();\n resultantMatrix.multiplyMatrices(trackerSpace, inverseResponseMatrix);\n\n const position = new THREE.Vector3();\n const rotation = new THREE.Quaternion();\n const scale = new THREE.Vector3();\n resultantMatrix.decompose(position, rotation, scale);\n\n this.meshGroup.position.copy(position);\n this.meshGroup.quaternion.copy(rotation);\n this.meshGroup.scale.set(1, 1, 1);\n this.meshGroup.visible = true;\n this.meshGroup.updateMatrix();\n\n if (this.meshMaterial) {\n this.meshMaterial.uniforms.uCenter.value\n .copy(this.localCenter)\n .applyMatrix4(this.meshGroup.matrixWorld);\n }\n }\n\n update(\n deltaSeconds: number,\n viewerWorldPosition?: THREE.Vector3 | null\n ): void {\n if (!this.meshMaterial) {\n return;\n }\n\n if (viewerWorldPosition) {\n this.lastViewerWorldPosition.copy(viewerWorldPosition);\n }\n\n const uniforms = this.meshMaterial.uniforms as {\n uProgress?: { value: number };\n uCenter?: { value: THREE.Vector3 };\n };\n\n if (!uniforms.uProgress) {\n return;\n }\n\n const current = uniforms.uProgress.value ?? 0;\n\n if (current === 0 && uniforms.uCenter && this.lastViewerWorldPosition.lengthSq() > 0) {\n uniforms.uCenter.value.copy(this.lastViewerWorldPosition);\n }\n\n if (current >= 1) {\n this.idleTimeAfterReveal += deltaSeconds;\n if (this.idleTimeAfterReveal >= this.radialRepeatInterval) {\n uniforms.uProgress.value = 0;\n this.idleTimeAfterReveal = 0;\n }\n return;\n }\n\n this.idleTimeAfterReveal = 0;\n const next = Math.min(\n current + deltaSeconds / this.radialDuration,\n 1\n );\n\n uniforms.uProgress.value = next;\n }\n\n dispose(): void {\n this.meshMaterial = null;\n this.meshGroup.traverse((child) => {\n const mesh = child as THREE.Mesh;\n if (mesh.isMesh) {\n mesh.geometry.dispose();\n if (Array.isArray(mesh.material)) {\n mesh.material.forEach((m) => m.dispose());\n } else {\n (mesh.material as THREE.Material).dispose();\n }\n }\n });\n this.scene.remove(this.meshGroup);\n this.dracoLoader.dispose();\n if (this.gizmoHelper) {\n this.scene.remove(this.gizmoHelper);\n }\n if (this.gizmoControl) {\n this.gizmoControl.dispose();\n }\n }\n}\n\n","import * as THREE from 'three';\nimport type { MultisetClient, ILocalizeAndMapDetails } from '../../core';\nimport type { IGetMapsDetailsResponse } from '../../core';\nimport { MapMeshVisualizer } from '../mapMeshVisualizer';\n\n/**\n * Composes scene content for the AR session (e.g. map mesh).\n * Delegates to MapMeshVisualizer for mesh load and transform.\n */\nexport class World {\n private readonly meshVisualizer: MapMeshVisualizer;\n\n constructor(\n scene: THREE.Scene,\n client: MultisetClient,\n renderer: THREE.WebGLRenderer,\n camera: THREE.Camera\n ) {\n this.meshVisualizer = new MapMeshVisualizer(scene, client, renderer, camera);\n }\n\n async ensureGizmoLoaded(): Promise<void> {\n await this.meshVisualizer.ensureGizmoLoaded();\n }\n\n async ensureMeshLoaded(mapDetails: IGetMapsDetailsResponse): Promise<void> {\n await this.meshVisualizer.ensureMeshLoaded(mapDetails);\n }\n\n applyMeshTransform(\n best: ILocalizeAndMapDetails,\n trackerSpace: THREE.Matrix4\n ): void {\n this.meshVisualizer.applyMeshTransform(best, trackerSpace);\n }\n\n update(\n deltaSeconds: number,\n viewerWorldPosition?: THREE.Vector3 | null\n ): void {\n this.meshVisualizer.update(deltaSeconds, viewerWorldPosition);\n }\n\n dispose(): void {\n this.meshVisualizer.dispose();\n }\n}\n","import * as THREE from 'three';\nimport { ARButton } from 'three/examples/jsm/webxr/ARButton.js';\n\nimport type {\n MultisetClient,\n ILocalizeAndMapDetails,\n} from '../core';\nimport { getCameraIntrinsics } from './internal/cameraIntrinsics';\nimport { getCameraTextureAsImage } from './internal/frameCapture';\nimport { Experience } from './experience/Experience';\nimport { World } from './world/World';\nconst CONFIDENCE_THRESHOLD_MIN = 0.2;\nconst CONFIDENCE_THRESHOLD_MAX = 0.8;\nconst TRACKING_LOSS_FRAME_THRESHOLD = 60;\n/** Default max time (ms) to wait for a valid viewer pose before failing. */\nconst DEFAULT_TRACKING_TIMEOUT_MS = 10_000;\n/** Max XR frames to wait for viewer pose (backup cap; ~10s at 30fps). */\nconst TRACKING_FRAME_CAP = 300;\n/** Max frames with valid pose but no camera image before failing. */\nconst CAMERA_IMAGE_MAX_ATTEMPTS = 10;\n\n/**\n * Options for WebxrController. Property names align with Unity SingleFrameLocalizationManager\n * where applicable (see https://docs.multiset.ai/unity-sdk/api-reference/singleframelocalizationmanager).\n */\nexport interface IWebxrControllerOptions {\n client: MultisetClient;\n canvas?: HTMLCanvasElement;\n overlayRoot?: HTMLElement;\n buttonContainer?: HTMLElement;\n onARButtonCreated?: (button: HTMLButtonElement) => void;\n onSessionStart?: () => void;\n onSessionEnd?: () => void;\n}\n\ntype XRViewWithCamera = XRView & {\n camera?: {\n width: number;\n height: number;\n [key: string]: unknown;\n };\n};\n\ntype XRWebGLBindingLike = {\n getCameraImage: (camera: XRViewWithCamera['camera']) => WebGLTexture | null;\n};\n\nexport class WebxrController {\n private experience: Experience | null = null;\n private world: World | null = null;\n private arButton: HTMLButtonElement | null = null;\n private resizeHandler: (() => void) | null = null;\n private isSessionActive: boolean = false;\n private trackingLossFrames: number = 0;\n private hadTrackingLoss: boolean = false;\n private isLocalizing: boolean = false;\n private trackerSpace: THREE.Matrix4 | null = null;\n\n constructor(private readonly options: IWebxrControllerOptions) { }\n\n async initialize(buttonContainer?: HTMLElement): Promise<HTMLButtonElement> {\n if (this.experience) {\n return this.arButton!;\n }\n\n if (!window.isSecureContext) {\n throw new Error('WebXR requires a secure context (HTTPS).');\n }\n\n const canvas = this.options.canvas ?? document.createElement('canvas');\n\n this.experience = new Experience(canvas);\n const renderer = this.experience.getRenderer();\n const camera = this.experience.getCamera();\n const scene = this.experience.getScene();\n\n this.world = new World(scene, this.options.client, renderer, camera);\n\n renderer.xr.addEventListener('sessionstart', () => {\n this.isSessionActive = true;\n this.options.onSessionStart?.();\n const cfg = this.options.client.getConfig();\n if (cfg.autoLocalize) {\n const session = renderer.xr.getSession();\n if (session) {\n session.requestAnimationFrame(() => {\n void this.localizeFrame();\n });\n } else {\n void this.localizeFrame();\n }\n }\n });\n\n renderer.xr.addEventListener('sessionend', () => {\n this.isSessionActive = false;\n this.options.onSessionEnd?.();\n });\n\n let lastTime = 0;\n\n const animationLoop = (time: number, frame: XRFrame | null) => {\n const deltaSeconds = lastTime === 0 ? 0 : (time - lastTime) / 1000;\n lastTime = time;\n\n let viewerWorldPosition: THREE.Vector3 | null = null;\n if (frame) {\n const refSpace = renderer.xr.getReferenceSpace();\n if (refSpace) {\n const viewerPose = frame.getViewerPose(refSpace);\n if (viewerPose) {\n const p = viewerPose.transform.position;\n viewerWorldPosition = new THREE.Vector3(p.x, p.y, p.z);\n }\n }\n }\n\n if (this.world && deltaSeconds > 0) {\n this.world.update(deltaSeconds, viewerWorldPosition);\n }\n\n renderer.render(scene, camera);\n const cfg = this.options.client.getConfig();\n if (cfg.relocalization && frame && !this.isLocalizing) {\n const refSpace = renderer.xr.getReferenceSpace();\n if (refSpace) {\n const viewerPose = frame.getViewerPose(refSpace);\n if (!viewerPose) {\n this.trackingLossFrames += 1;\n if (this.trackingLossFrames >= TRACKING_LOSS_FRAME_THRESHOLD) {\n this.hadTrackingLoss = true;\n }\n } else {\n if (this.hadTrackingLoss) {\n this.hadTrackingLoss = false;\n this.trackingLossFrames = 0;\n void this.localizeFrame();\n } else {\n this.trackingLossFrames = 0;\n }\n }\n }\n }\n };\n renderer.setAnimationLoop(animationLoop);\n\n const resizeHandler = () => {\n this.experience?.resize();\n };\n window.addEventListener('resize', resizeHandler);\n\n const overlayRoot = this.options.overlayRoot ?? document.body;\n const arButton = ARButton.createButton(renderer, {\n requiredFeatures: ['camera-access', 'dom-overlay'],\n domOverlay: { root: overlayRoot },\n }) as HTMLButtonElement;\n\n const buttonParent =\n buttonContainer && buttonContainer instanceof HTMLElement\n ? buttonContainer\n : this.options.buttonContainer &&\n this.options.buttonContainer instanceof HTMLElement\n ? this.options.buttonContainer\n : overlayRoot;\n\n if (!buttonParent.contains(arButton)) {\n buttonParent.appendChild(arButton);\n }\n\n this.arButton = arButton;\n this.resizeHandler = resizeHandler;\n\n this.options.onARButtonCreated?.(arButton);\n return arButton;\n }\n\n getScene(): THREE.Scene {\n if (!this.experience) {\n throw new Error('Scene: WebXR controller has not been initialized.');\n }\n return this.experience.getScene();\n }\n\n getCamera(): THREE.PerspectiveCamera {\n if (!this.experience) {\n throw new Error('Camera: WebXR controller has not been initialized.');\n }\n return this.experience.getCamera();\n }\n\n getRenderer(): THREE.WebGLRenderer {\n if (!this.experience) {\n throw new Error('Renderer: WebXR controller has not been initialized.');\n }\n return this.experience.getRenderer();\n }\n\n hasActiveSession(): boolean {\n return this.isSessionActive && this.experience?.getRenderer().xr.isPresenting === true;\n }\n\n /**\n * Runs a single-frame localization: captures one frame, evaluates the result\n * against the optional confidenceThreshold, and fires\n * onLocalizationInit / onLocalizationSuccess / onLocalizationFailure.\n * Aligns with Unity SingleFrameLocalizationManager.LocalizeFrame().\n */\n async localizeFrame(): Promise<ILocalizeAndMapDetails | null> {\n if (!this.experience) {\n throw new Error('WebXR: WebXR controller has not been initialized.');\n }\n const renderer = this.experience.getRenderer();\n const session = renderer.xr.getSession?.();\n if (!session) {\n throw new Error(\n 'WebXR Session: No active WebXR session. Start AR before calling localizeFrame().'\n );\n }\n\n const cfg = this.options.client.getConfig();\n const confidenceCheck = cfg.confidenceCheck ?? false;\n const confidenceThreshold = Math.max(\n CONFIDENCE_THRESHOLD_MIN,\n Math.min(cfg.confidenceThreshold ?? 0.5, CONFIDENCE_THRESHOLD_MAX)\n );\n\n cfg.onLocalizationInit?.();\n this.isLocalizing = true;\n\n let best: ILocalizeAndMapDetails | null = null;\n\n let failureReason: string | undefined;\n try {\n const captureResult = await this.captureFrame();\n best = captureResult.result;\n failureReason = captureResult.failureReason;\n } finally {\n this.isLocalizing = false;\n }\n\n const accepted =\n best &&\n (!confidenceCheck ||\n (best.localizeData.confidence ?? 0) >= confidenceThreshold);\n\n if (accepted && best) {\n cfg.onLocalizationSuccess?.(best);\n\n if (this.world && this.trackerSpace) {\n const willShowMesh = cfg.showMesh && !!best.mapDetails;\n const willShowGizmo = cfg.showGizmo !== false;\n if (willShowMesh || willShowGizmo) {\n try {\n await this.world.ensureGizmoLoaded();\n if (willShowMesh) {\n await this.world.ensureMeshLoaded(best.mapDetails!);\n }\n this.world.applyMeshTransform(best, this.trackerSpace);\n } catch {\n // Mesh/gizmo loading failure must not prevent returning the localization result\n }\n }\n }\n return best;\n }\n\n const reason =\n failureReason ??\n (!best\n ? 'All attempts failed to produce a pose.'\n : confidenceCheck\n ? `Best confidence ${best.localizeData.confidence ?? 0} below threshold ${confidenceThreshold}.`\n : undefined);\n cfg.onLocalizationFailure?.(reason);\n return null;\n }\n\n /**\n * Internal: captures one frame and calls the localization API. Waits for a\n * valid viewer pose up to localizationTrackingTimeoutMs (and TRACKING_FRAME_CAP),\n * then tries to get a camera image (up to CAMERA_IMAGE_MAX_ATTEMPTS). Returns\n * result, apiCalled, and an optional failureReason for onLocalizationFailure.\n */\n private async captureFrame(): Promise<{\n result: ILocalizeAndMapDetails | null;\n apiCalled: boolean;\n failureReason?: string;\n }> {\n if (!this.experience) {\n throw new Error('WebXR: WebXR controller has not been initialized.');\n }\n const renderer = this.experience.getRenderer();\n\n const session = renderer.xr.getSession?.();\n if (!session) {\n throw new Error(\n 'WebXR Session: No active WebXR session. Start AR before capturing.'\n );\n }\n\n const referenceSpace = renderer.xr.getReferenceSpace();\n if (!referenceSpace) {\n throw new Error(\n 'WebXR Reference Space: Unable to acquire XR reference space.'\n );\n }\n\n const gl = renderer.getContext();\n const cfg = this.options.client.getConfig();\n const timeoutMs = cfg.localizationTrackingTimeoutMs ?? DEFAULT_TRACKING_TIMEOUT_MS;\n\n return new Promise((resolve, reject) => {\n const startTime = Date.now();\n\n const tryFrame = (attempt: number, cameraAttemptsWithPose: number) => {\n session.requestAnimationFrame(async (_time: number, xrFrame: XRFrame) => {\n try {\n const elapsed = Date.now() - startTime;\n const viewerPose = xrFrame.getViewerPose(referenceSpace);\n if (!viewerPose) {\n if (elapsed >= timeoutMs || attempt + 1 >= TRACKING_FRAME_CAP) {\n const sec = (timeoutMs / 1000).toFixed(1);\n resolve({\n result: null,\n apiCalled: false,\n failureReason: `Tracking unavailable: no viewer pose within ${sec}s. Try moving the device or ensuring good lighting.`,\n });\n } else {\n tryFrame(attempt + 1, cameraAttemptsWithPose);\n }\n return;\n }\n\n const views = viewerPose.views as XRViewWithCamera[];\n for (let i = 0; i < views.length; i += 1) {\n const view = views[i];\n const xrCamera = view.camera;\n if (!xrCamera) continue;\n\n const gl2 = gl as unknown as WebGL2RenderingContext;\n const bindingCtor = XRWebGLBinding as unknown as {\n new(\n session: XRSession,\n context: WebGL2RenderingContext\n ): XRWebGLBindingLike;\n };\n const binding = new bindingCtor(session, gl2);\n const cameraTexture = binding.getCameraImage?.(xrCamera) ?? null;\n if (!cameraTexture) continue;\n\n const width = xrCamera.width;\n const height = xrCamera.height;\n if (!width || !height) continue;\n\n const frameData = await getCameraTextureAsImage(\n renderer,\n cameraTexture,\n width,\n height\n );\n\n const intrinsics = getCameraIntrinsics(view.projectionMatrix, {\n width,\n height,\n x: 0,\n y: 0,\n });\n\n if (frameData && intrinsics) {\n // Capture the camera pose from the current XRFrame's view transform\n // (column-major Float32Array, same convention as THREE.Matrix4.fromArray).\n // Using camera.matrix would give the previous render frame's pose.\n this.trackerSpace = new THREE.Matrix4().fromArray(view.transform.matrix);\n\n const result = await this.options.client.localizeWithFrame(\n frameData,\n intrinsics\n );\n resolve({ result, apiCalled: true });\n return;\n }\n }\n\n if (cameraAttemptsWithPose + 1 >= CAMERA_IMAGE_MAX_ATTEMPTS) {\n resolve({\n result: null,\n apiCalled: false,\n failureReason:\n 'Camera image not available. The device or browser may not support camera access in AR.',\n });\n } else {\n tryFrame(attempt + 1, cameraAttemptsWithPose + 1);\n }\n } catch (error) {\n reject(error);\n } finally {\n gl.bindFramebuffer(\n gl.FRAMEBUFFER,\n session.renderState.baseLayer?.framebuffer ?? null\n );\n }\n });\n };\n tryFrame(0, 0);\n });\n }\n\n dispose(): void {\n if (this.resizeHandler) {\n window.removeEventListener('resize', this.resizeHandler);\n }\n\n this.experience?.getRenderer().setAnimationLoop(null);\n this.experience?.dispose();\n this.experience = null;\n this.world?.dispose();\n this.world = null;\n this.trackingLossFrames = 0;\n this.hadTrackingLoss = false;\n\n if (this.arButton?.parentElement) {\n this.arButton.parentElement.removeChild(this.arButton);\n }\n this.arButton = null;\n }\n}\n"]}
|