gps-plus-slam-app-framework 1.2.0 → 1.4.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/dist/{app-selectors-CcZ5UV-8.d.ts → app-selectors-CrOucL00.d.ts} +1 -1
- package/dist/ar/bresenham3d.d.ts +1 -1
- package/dist/ar/camera-blit-capture.d.ts +2 -2
- package/dist/ar/camera-blit-capture.js +87 -9
- package/dist/ar/capability-checker.d.ts +1 -1
- package/dist/ar/capture-failure-tracker.d.ts +1 -1
- package/dist/ar/chromium-camera-access-workaround.d.ts +1 -1
- package/dist/ar/depth-grid-lookup.d.ts +2 -0
- package/dist/ar/depth-grid-lookup.js +43 -0
- package/dist/ar/depth-sampler.d.ts +2 -2
- package/dist/ar/depth-sampler.js +2 -4
- package/dist/ar/depth-unprojection.d.ts +1 -1
- package/dist/ar/enable-gps-ar.d.ts +1 -1
- package/dist/ar/enable-gps-ar.js +26 -1
- package/dist/ar/frame-loop.d.ts +1 -1
- package/dist/ar/image-capture.d.ts +2 -2
- package/dist/ar/image-capture.js +7 -5
- package/dist/ar/index.d.ts +30 -19
- package/dist/ar/index.js +15 -4
- package/dist/ar/occupancy-grid.d.ts +1 -1
- package/dist/ar/occupancy-grid.js +29 -2
- package/dist/ar/planar-pnp.d.ts +2 -0
- package/dist/ar/planar-pnp.js +425 -0
- package/dist/ar/qr-debug-view.d.ts +2 -0
- package/dist/ar/qr-debug-view.js +89 -0
- package/dist/ar/qr-derived-pose.d.ts +2 -0
- package/dist/ar/qr-derived-pose.js +114 -0
- package/dist/ar/qr-detection-controller.d.ts +2 -0
- package/dist/ar/qr-detection-controller.js +2 -0
- package/dist/ar/qr-frontend.d.ts +2 -0
- package/dist/ar/qr-frontend.js +60 -0
- package/dist/ar/qr-pose.d.ts +2 -0
- package/dist/ar/qr-pose.js +267 -0
- package/dist/ar/qr-size-depth-context.d.ts +3 -0
- package/dist/ar/qr-size-depth-context.js +42 -0
- package/dist/ar/qr-size-measurer.d.ts +2 -0
- package/dist/ar/qr-size-measurer.js +2 -0
- package/dist/ar/replay-scene.d.ts +1 -1
- package/dist/ar/replay-scene.js +1 -1
- package/dist/ar/scene-node-names.d.ts +1 -1
- package/dist/ar/webxr-nue-basis.d.ts +1 -1
- package/dist/ar/webxr-session.d.ts +4 -4
- package/dist/ar/webxr-session.js +2 -2
- package/dist/ar/xr-camera-texture.d.ts +1 -1
- package/dist/ar/xr-error-handler.d.ts +1 -1
- package/dist/ar/xr-frame-loop.d.ts +1 -1
- package/dist/ar-Dc72Ksiu.js +382 -0
- package/dist/{ar-world-group-alignment-ColHB_5A.d.ts → ar-world-group-alignment-DDLkgNf_.d.ts} +1 -1
- package/dist/{camera-blit-capture-D5_mNhla.d.ts → camera-blit-capture-CqWe1G7s.d.ts} +66 -4
- package/dist/concurrency-DqAlKX4j.d.ts +50 -0
- package/dist/core/index.d.ts +1 -1
- package/dist/{create-slam-app-store-qNXQ-tq5.d.ts → create-slam-app-store-Ce2FMKCp.d.ts} +5 -5
- package/dist/depth-grid-lookup-vMDrGTk_.d.ts +21 -0
- package/dist/{depth-sampler-Bhanfwla.d.ts → depth-sampler-DwfPYzS7.d.ts} +1 -1
- package/dist/{depth-unprojection-Y6i_mJuT.d.ts → depth-unprojection-CK3b9htH.d.ts} +1 -1
- package/dist/{enable-gps-ar-CapmADVN.d.ts → enable-gps-ar-CjZ1nEdu.d.ts} +4 -4
- package/dist/file-system-utils-Bs7lpeVP.d.ts +40 -0
- package/dist/{frame-conversions-BfsafGWR.d.ts → frame-conversions-D_Af8Dt3.d.ts} +1 -1
- package/dist/{fused-path-DJoVu98b.d.ts → fused-path-C0FHe67t.d.ts} +1 -1
- package/dist/geo/h3-proximity.d.ts +2 -2
- package/dist/geo/h3-proximity.js +61 -2
- package/dist/geo/index.d.ts +2 -2
- package/dist/geo/index.js +2 -2
- package/dist/{gps-anchor-dYeCvvp5.d.ts → gps-anchor-C6I9NDHA.d.ts} +1 -1
- package/dist/{gps-ar-pose-sampler-DVb96iOy.d.ts → gps-ar-pose-sampler-DaHg2aPZ.d.ts} +1 -1
- package/dist/{gps-event-coordinator-BDIQde2x.d.ts → gps-event-coordinator-C7hwHyLA.d.ts} +3 -3
- package/dist/{gps-event-markers-Dc9FT-q1.d.ts → gps-event-markers-Dd0G2bD0.d.ts} +18 -0
- package/dist/{h3-proximity-I1msGPgE.d.ts → h3-proximity-B57C6rYL.d.ts} +39 -1
- package/dist/{image-capture-DZ4HFRgS.d.ts → image-capture-C2Feywet.d.ts} +30 -4
- package/dist/index-BvLo2poy.d.ts +399 -0
- package/dist/{index-KJq2amHF.d.ts → index-m_LneUSi.d.ts} +1 -1
- package/dist/index.d.ts +77 -67
- package/dist/index.js +18 -9
- package/dist/{leaflet-map-overlay-6CJC-E1l.d.ts → leaflet-map-overlay-bnb2U1NQ.d.ts} +1 -1
- package/dist/{map-data-CkloBxIl.d.ts → map-data-DdjPiSav.d.ts} +1 -1
- package/dist/{map-overlay-draw-krOKwDAq.d.ts → map-overlay-draw-CPVdAsFq.d.ts} +1 -1
- package/dist/{null-storage-backend-CxEjZHRW.d.ts → null-storage-backend-CuSdYFsM.d.ts} +2 -2
- package/dist/{occupancy-grid-BRNRaPyT.d.ts → occupancy-grid-Bvi2Gw1U.d.ts} +12 -2
- package/dist/{opfs-storage-DYm8WHq7.d.ts → opfs-storage-DMtlt57S.d.ts} +25 -6
- package/dist/{opfs-storage-backend-CjSAuqg_.d.ts → opfs-storage-backend-CeQAb0SD.d.ts} +3 -3
- package/dist/{persistence-middleware-DwyzgfWr.d.ts → persistence-middleware-5eearhSV.d.ts} +1 -1
- package/dist/planar-pnp-cjthe7Be.d.ts +67 -0
- package/dist/qr-debug-view-B8gTzjMm.d.ts +29 -0
- package/dist/qr-derived-pose-DinKE600.d.ts +122 -0
- package/dist/qr-detected-slice-Cpv-dg82.d.ts +166 -0
- package/dist/qr-detection-controller-B-tLVd-S.js +119 -0
- package/dist/qr-detection-controller-Cd2Ih4cC.d.ts +48 -0
- package/dist/qr-frontend-DufZp2xS.d.ts +58 -0
- package/dist/qr-pose-Bt2reSw7.d.ts +138 -0
- package/dist/qr-pose-aggregation-CFlmLm6w.d.ts +90 -0
- package/dist/qr-pose-aggregation-DXR9STHs.js +200 -0
- package/dist/qr-size-depth-context-onu36E9s.d.ts +13 -0
- package/dist/qr-size-measurer-D7739ZpB.d.ts +165 -0
- package/dist/qr-size-measurer-DLb33geH.js +596 -0
- package/dist/recording-options-D93kksJU.d.ts +369 -0
- package/dist/{recording-replayer-BL-x-7k0.d.ts → recording-replayer-CUEK82tM.d.ts} +2 -2
- package/dist/recording-slice-B-uCgGoh.d.ts +55 -0
- package/dist/{replay-engine-BRqszuQ9.d.ts → replay-engine-BSVd7Zzb.d.ts} +7 -4
- package/dist/{replay-scene-Bw58VL6p.d.ts → replay-scene-CPt56pps.d.ts} +3 -3
- package/dist/sensors/gps-error-handler.d.ts +1 -1
- package/dist/sensors/gps.d.ts +1 -1
- package/dist/sensors/index.d.ts +3 -3
- package/dist/sensors/permission-checker.d.ts +1 -1
- package/dist/sensors/permission-checker.js +1 -1
- package/dist/state/app-selectors.d.ts +1 -1
- package/dist/state/app-selectors.js +3 -1
- package/dist/state/combined-root-state.d.ts +1 -1
- package/dist/state/create-slam-app-store.d.ts +1 -1
- package/dist/state/gps-ar-pose-sampler.d.ts +3 -3
- package/dist/state/gps-event-coordinator.d.ts +1 -1
- package/dist/state/index.d.ts +20 -17
- package/dist/state/index.js +3 -2
- package/dist/state/persistence-middleware.d.ts +1 -1
- package/dist/state/qr-detected-slice.d.ts +4 -0
- package/dist/state/qr-detected-slice.js +311 -0
- package/dist/state/recording-options.d.ts +2 -2
- package/dist/state/recording-options.js +128 -4
- package/dist/state/recording-replayer.d.ts +2 -2
- package/dist/state/recording-slice.d.ts +1 -1
- package/dist/state/recording-slice.js +5 -1
- package/dist/state/replay-engine.d.ts +1 -1
- package/dist/state/replay-engine.js +7 -3
- package/dist/state/store-subscribers.d.ts +2 -2
- package/dist/state/subscribe-to-selector.d.ts +1 -1
- package/dist/state/tracking-quality.d.ts +1 -1
- package/dist/state/tracking-slice.d.ts +1 -1
- package/dist/{state-BkIfpiyA.js → state-IEw0ZsBu.js} +1 -0
- package/dist/storage/file-system-utils.d.ts +2 -2
- package/dist/storage/file-system-utils.js +17 -1
- package/dist/storage/index.d.ts +9 -9
- package/dist/storage/index.js +4 -4
- package/dist/storage/null-storage-backend.d.ts +1 -1
- package/dist/storage/opfs-storage-backend.d.ts +1 -1
- package/dist/storage/opfs-storage-backend.js +3 -3
- package/dist/storage/opfs-storage.d.ts +1 -1
- package/dist/storage/opfs-storage.js +9 -8
- package/dist/storage/storage-backend.d.ts +1 -1
- package/dist/storage/zip-coverage-embed.d.ts +2 -0
- package/dist/storage/zip-coverage-embed.js +88 -0
- package/dist/storage/zip-export.d.ts +2 -2
- package/dist/storage/zip-export.js +38 -60
- package/dist/storage/zip-reader.d.ts +1 -1
- package/dist/storage/zip-reader.js +1 -1
- package/dist/{storage-backend-C9HLFtgz.d.ts → storage-backend-CTJHNdMp.d.ts} +1 -1
- package/dist/{store-subscribers-rrkLkFTt.d.ts → store-subscribers-BZP81hjh.d.ts} +2 -2
- package/dist/{subscribe-to-selector-CP3BKSbF.d.ts → subscribe-to-selector-Bp3sLx8L.d.ts} +1 -1
- package/dist/test-utils/browser-mocks.d.ts +7 -1
- package/dist/test-utils/browser-mocks.js +6 -0
- package/dist/test-utils/zip-round-trip-helpers.d.ts +9 -1
- package/dist/test-utils/zip-round-trip-helpers.js +8 -3
- package/dist/{tracking-slice-CdK8c-8P.d.ts → tracking-slice-DJZ9qeGg.d.ts} +1 -1
- package/dist/types/ar-types.d.ts +1 -1
- package/dist/types/geo-types.d.ts +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/utils/concurrency.d.ts +2 -2
- package/dist/utils/concurrency.js +66 -2
- package/dist/utils/failure-tracker.d.ts +1 -1
- package/dist/utils/format-file-size.d.ts +1 -1
- package/dist/utils/fused-path.d.ts +1 -1
- package/dist/utils/index.d.ts +6 -6
- package/dist/utils/list-formatter.d.ts +1 -1
- package/dist/utils/logger.d.ts +1 -1
- package/dist/visualization/accuracy-circles.d.ts +1 -1
- package/dist/visualization/alignment-lerper.d.ts +1 -1
- package/dist/visualization/ar-world-group-alignment.d.ts +1 -1
- package/dist/visualization/ar-world-group-alignment.js +1 -1
- package/dist/visualization/camera-follower.d.ts +1 -1
- package/dist/visualization/css3d-renderer-manager.d.ts +1 -1
- package/dist/visualization/frame-conversions.d.ts +1 -1
- package/dist/visualization/frustum-visibility.d.ts +1 -1
- package/dist/visualization/gps-anchor.d.ts +1 -1
- package/dist/visualization/gps-compass-cubes.d.ts +1 -1
- package/dist/visualization/gps-event-markers.d.ts +1 -1
- package/dist/visualization/gps-event-markers.js +40 -5
- package/dist/visualization/hit-test-reticle.d.ts +1 -1
- package/dist/visualization/hit-test-reticle.js +1 -0
- package/dist/visualization/index.d.ts +18 -18
- package/dist/visualization/leaflet-map-overlay.d.ts +1 -1
- package/dist/visualization/leaflet-map-overlay.js +15 -3
- package/dist/visualization/lerp-utils.d.ts +1 -1
- package/dist/visualization/map-data.d.ts +1 -1
- package/dist/visualization/map-overlay-draw.d.ts +1 -1
- package/dist/visualization/map-overlay.d.ts +1 -1
- package/dist/visualization/three-dispose.d.ts +1 -1
- package/dist/visualization/vis-colors.d.ts +1 -1
- package/dist/{webxr-session-QhcSSub5.js → webxr-session-CJF9Nijp.js} +234 -9
- package/dist/{webxr-session-DtAG9srK.d.ts → webxr-session-COsOjJwn.d.ts} +76 -8
- package/dist/zip-coverage-embed-tFohI2J4.d.ts +41 -0
- package/dist/{zip-export-D_5HAvFz.d.ts → zip-export-DDWXInTR.d.ts} +28 -24
- package/package.json +2 -2
- package/dist/concurrency-CO1FQvs3.d.ts +0 -24
- package/dist/file-system-C_eqiEA8.d.ts +0 -114
- package/dist/file-system-utils-DyAmcuvX.d.ts +0 -24
- package/dist/recording-options-DJBXuMxV.d.ts +0 -182
- package/dist/recording-slice-89O07ebs.d.ts +0 -36
- package/dist/storage/file-system.d.ts +0 -2
- package/dist/storage/file-system.js +0 -289
- /package/dist/{accuracy-circles-BpwWAs8G.d.ts → accuracy-circles-Pi2YeCrM.d.ts} +0 -0
- /package/dist/{alignment-lerper-Dm9G7JJO.d.ts → alignment-lerper-BUTsQ2yu.d.ts} +0 -0
- /package/dist/{ar-types-Dan1MVTi.d.ts → ar-types-BckI1E-O.d.ts} +0 -0
- /package/dist/{bresenham3d-CFfd7n6B.d.ts → bresenham3d-ByjcmEgM.d.ts} +0 -0
- /package/dist/{camera-follower-C2mwEn7c.d.ts → camera-follower-BTb2Yp12.d.ts} +0 -0
- /package/dist/{capability-checker-CQXJHxXg.d.ts → capability-checker-CXqoJYtb.d.ts} +0 -0
- /package/dist/{capture-failure-tracker-CUeU3L_M.d.ts → capture-failure-tracker-BL5SoG2a.d.ts} +0 -0
- /package/dist/{chromium-camera-access-workaround-Jqbn0apH.d.ts → chromium-camera-access-workaround-BNK189P0.d.ts} +0 -0
- /package/dist/{css3d-renderer-manager-ptu_t3B3.d.ts → css3d-renderer-manager-m-ab19vp.d.ts} +0 -0
- /package/dist/{failure-tracker-Cn8Fo9D4.d.ts → failure-tracker-Cnc_xWUw.d.ts} +0 -0
- /package/dist/{format-file-size-CLCZz3lC.d.ts → format-file-size-BFUWvir1.d.ts} +0 -0
- /package/dist/{frame-loop-CMewS8cY.d.ts → frame-loop-BEO9_q3k.d.ts} +0 -0
- /package/dist/{frustum-visibility-CmI96ESS.d.ts → frustum-visibility-D_RGmH98.d.ts} +0 -0
- /package/dist/{geo-types-SaPnIEUM.d.ts → geo-types-DqiBzPO9.d.ts} +0 -0
- /package/dist/{gps-VuezJWK3.d.ts → gps-C5inWeNV.d.ts} +0 -0
- /package/dist/{gps-compass-cubes-BM1uGiYV.d.ts → gps-compass-cubes-BExxrWJ-.d.ts} +0 -0
- /package/dist/{gps-error-handler-CJl_2MVm.d.ts → gps-error-handler-C2bS69oJ.d.ts} +0 -0
- /package/dist/{hit-test-reticle-BEzEybxZ.d.ts → hit-test-reticle-Dqak9hiR.d.ts} +0 -0
- /package/dist/{index-CF05QV2m.d.ts → index-eaI1Z1KR.d.ts} +0 -0
- /package/dist/{lerp-utils-BpV-0Dtk.d.ts → lerp-utils-kLxMJ2Xj.d.ts} +0 -0
- /package/dist/{list-formatter-RRcBe8Vg.d.ts → list-formatter-ct8txwvR.d.ts} +0 -0
- /package/dist/{logger-BEHXsnnq.d.ts → logger-CzQrCe6C.d.ts} +0 -0
- /package/dist/{map-overlay-bcogY5fK.d.ts → map-overlay-Dci4yvm3.d.ts} +0 -0
- /package/dist/{permission-checker-GpAiSCwd.d.ts → permission-checker-CtPtPQRq.d.ts} +0 -0
- /package/dist/{scene-node-names-Bu0S66H1.d.ts → scene-node-names-CdNeQjOE.d.ts} +0 -0
- /package/dist/{session-disposers-M-oashRH.js → session-disposers-D8wnO-uW.js} +0 -0
- /package/dist/{three-dispose-D950t71B.d.ts → three-dispose-BCZkSJp2.d.ts} +0 -0
- /package/dist/{vis-colors-D6omC64K.d.ts → vis-colors-BZsSLI4i.d.ts} +0 -0
- /package/dist/{webxr-nue-basis-CqKQmZzT.d.ts → webxr-nue-basis-CW1wsbm6.d.ts} +0 -0
- /package/dist/{xr-camera-texture-DBwCaKTd.d.ts → xr-camera-texture-BmrP7iNZ.d.ts} +0 -0
- /package/dist/{xr-error-handler-C0AQRmxs.d.ts → xr-error-handler-BEjRgZjt.d.ts} +0 -0
- /package/dist/{xr-frame-loop-BtYytZJg.d.ts → xr-frame-loop-K8ebdjLw.d.ts} +0 -0
- /package/dist/{zip-reader-DSEXt7K6.d.ts → zip-reader-Q2ue6zlC.d.ts} +0 -0
|
@@ -1,19 +1,92 @@
|
|
|
1
1
|
import { createLogger } from "./utils/logger.js";
|
|
2
|
-
import { CameraBlitCapture, computeCaptureSize } from "./ar/camera-blit-capture.js";
|
|
2
|
+
import { CameraBlitCapture, computeAspectFitSize, computeCaptureSize } from "./ar/camera-blit-capture.js";
|
|
3
3
|
import { getLastDeviceOrientation } from "./state/gps-event-coordinator.js";
|
|
4
4
|
import { DepthSampler, wrapXRDepthInfo } from "./ar/depth-sampler.js";
|
|
5
|
+
import { WEBXR_TO_NUE } from "./ar/webxr-nue-basis.js";
|
|
5
6
|
import { clearFrameUpdates, runFrameUpdates } from "./ar/frame-loop.js";
|
|
6
7
|
import { clearXrFrameUpdates, runXrFrameUpdates } from "./ar/xr-frame-loop.js";
|
|
7
|
-
import { WEBXR_TO_NUE } from "./ar/webxr-nue-basis.js";
|
|
8
8
|
import { DEFAULT_CAPTURE_CONFIG, ImageCaptureManager } from "./ar/image-capture.js";
|
|
9
9
|
import { clearLastRestartedPayload, originReset, poseLost, poseReceived, resetTracking, selectLastRestartedPayload, selectTrackingPhase } from "./state/tracking-slice.js";
|
|
10
10
|
import { acquireCameraTexture } from "./ar/xr-camera-texture.js";
|
|
11
|
-
import { n as runSessionDisposers } from "./session-disposers-
|
|
11
|
+
import { n as runSessionDisposers } from "./session-disposers-D8wnO-uW.js";
|
|
12
12
|
import { DEFAULT_RECORDING_OPTIONS, validateArCrashIsolationOptions } from "./state/recording-options.js";
|
|
13
13
|
import { SCENE_NODE } from "./ar/scene-node-names.js";
|
|
14
14
|
import { createCss3dRendererManager } from "./visualization/css3d-renderer-manager.js";
|
|
15
15
|
import * as THREE from "three";
|
|
16
16
|
import { nueQuaternionToWebXR, nueToWebXR } from "gps-plus-slam-js";
|
|
17
|
+
//#region ../src/ar/camera-frame-source.ts
|
|
18
|
+
const DEFAULT_CONFIG = { intervalMs: 125 };
|
|
19
|
+
/**
|
|
20
|
+
* Throttled RGBA capturer. Construct with the injected `capture`/`onCapture`
|
|
21
|
+
* pair, `start()`, then call `onFrame(timestamp)` once per XR frame.
|
|
22
|
+
*/
|
|
23
|
+
var CameraFrameSource = class {
|
|
24
|
+
callbacks;
|
|
25
|
+
config;
|
|
26
|
+
running = false;
|
|
27
|
+
captureCount = 0;
|
|
28
|
+
lastCaptureTime = -Infinity;
|
|
29
|
+
constructor(callbacks, config) {
|
|
30
|
+
this.callbacks = callbacks;
|
|
31
|
+
this.config = { ...DEFAULT_CONFIG };
|
|
32
|
+
if (config) this.updateConfig(config);
|
|
33
|
+
}
|
|
34
|
+
/** Begin throttling. Resets the cadence so the first tick captures. */
|
|
35
|
+
start() {
|
|
36
|
+
this.running = true;
|
|
37
|
+
this.captureCount = 0;
|
|
38
|
+
this.lastCaptureTime = -Infinity;
|
|
39
|
+
}
|
|
40
|
+
/** Stop capturing. `onFrame` becomes a no-op until `start()` is called again. */
|
|
41
|
+
stop() {
|
|
42
|
+
this.running = false;
|
|
43
|
+
}
|
|
44
|
+
isRunning() {
|
|
45
|
+
return this.running;
|
|
46
|
+
}
|
|
47
|
+
/** Number of frames successfully captured + delivered since `start()`. */
|
|
48
|
+
getFrameCount() {
|
|
49
|
+
return this.captureCount;
|
|
50
|
+
}
|
|
51
|
+
getConfig() {
|
|
52
|
+
return { ...this.config };
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Apply partial config (e.g. the app's detection cadence). Invalid values
|
|
56
|
+
* are ignored defensively — `intervalMs` requires a finite positive number.
|
|
57
|
+
*/
|
|
58
|
+
updateConfig(config) {
|
|
59
|
+
if (typeof config.intervalMs === "number" && Number.isFinite(config.intervalMs) && config.intervalMs > 0) this.config.intervalMs = config.intervalMs;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Per-XR-frame tick. Captures + delivers a frame at most once per
|
|
63
|
+
* `intervalMs`; otherwise a cheap no-op so it is safe to call every frame.
|
|
64
|
+
*
|
|
65
|
+
* @param timestamp - monotonic frame time in ms (the XR `time` argument).
|
|
66
|
+
*/
|
|
67
|
+
onFrame(timestamp) {
|
|
68
|
+
if (!this.running) return;
|
|
69
|
+
if (timestamp - this.lastCaptureTime < this.config.intervalMs) return;
|
|
70
|
+
const image = this.captureSafely();
|
|
71
|
+
if (!image) return;
|
|
72
|
+
this.lastCaptureTime = timestamp;
|
|
73
|
+
this.captureCount++;
|
|
74
|
+
this.callbacks.onCapture(image);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Run the injected capture, guarded so a blit failure (e.g. GL context loss)
|
|
78
|
+
* can never throw out of the XR frame loop — it degrades to "no frame this
|
|
79
|
+
* tick", exactly like a missing texture.
|
|
80
|
+
*/
|
|
81
|
+
captureSafely() {
|
|
82
|
+
try {
|
|
83
|
+
return this.callbacks.capture();
|
|
84
|
+
} catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
//#endregion
|
|
17
90
|
//#region ../src/ar/depth-rgb-lookup.ts
|
|
18
91
|
/**
|
|
19
92
|
* Build an {@link RgbLookup} over an RGBA readback buffer.
|
|
@@ -159,6 +232,13 @@ function resetWebXRState() {
|
|
|
159
232
|
depthRgbBlit.dispose();
|
|
160
233
|
depthRgbBlit = null;
|
|
161
234
|
}
|
|
235
|
+
cameraFrameSource = null;
|
|
236
|
+
onCameraFrame = null;
|
|
237
|
+
cameraFrameCaptureSize = DEFAULT_CAMERA_FRAME_CAPTURE_SIZE;
|
|
238
|
+
if (cameraFrameBlit) {
|
|
239
|
+
cameraFrameBlit.dispose();
|
|
240
|
+
cameraFrameBlit = null;
|
|
241
|
+
}
|
|
162
242
|
onFrameCallback = null;
|
|
163
243
|
if (css3dManager) {
|
|
164
244
|
css3dManager.dispose();
|
|
@@ -285,6 +365,53 @@ const DEPTH_RGB_BLIT_CONFIG = {
|
|
|
285
365
|
height: 192
|
|
286
366
|
};
|
|
287
367
|
/**
|
|
368
|
+
* Session-owned blit target for the generic camera-frame RGBA capture
|
|
369
|
+
* (framework-wiring options Part A / B2) — feeds QR detection today, object
|
|
370
|
+
* detection / OpenCV later. Separate from `depthRgbBlit` (256×192) on purpose:
|
|
371
|
+
* CV detection needs more pixels across the target (~1024 long edge) than a
|
|
372
|
+
* colour lookup, but only at the detection cadence, so the {@link CameraFrameSource}
|
|
373
|
+
* throttle keeps the readback off the per-frame path. Created lazily on the
|
|
374
|
+
* first capture, disposed by resetWebXRState(). The longer-edge size is
|
|
375
|
+
* configurable via `startCameraFrameCapture`; the blit preserves the camera
|
|
376
|
+
* aspect (see `acquireCameraFrameRgba`).
|
|
377
|
+
*/
|
|
378
|
+
let cameraFrameBlit = null;
|
|
379
|
+
/**
|
|
380
|
+
* Default longer-edge resolution (px) for the camera-frame blit the QR / CV
|
|
381
|
+
* detector sees. The on-device capture-resolution sweep (2026-06-17, via the
|
|
382
|
+
* `?capture=` override) showed **1024** decodes a small / out-of-focus QR
|
|
383
|
+
* markedly better than the prior 512 with no perceptible cadence cost on the
|
|
384
|
+
* test phone; 2048 helped slightly more but risks low-end devices (4096 lagged),
|
|
385
|
+
* so 1024 is the safe default. Raise per-consumer via
|
|
386
|
+
* `startCameraFrameCapture({ captureSize })`.
|
|
387
|
+
*
|
|
388
|
+
* @see GpsPlusSlamJs_Docs/docs/2026-06-17-qr-size-accuracy-and-thin-demo-plan.md (WS-C)
|
|
389
|
+
*/
|
|
390
|
+
const DEFAULT_CAMERA_FRAME_CAPTURE_SIZE = 1024;
|
|
391
|
+
/**
|
|
392
|
+
* Longer-edge resolution of the camera-frame blit (px), default
|
|
393
|
+
* {@link DEFAULT_CAMERA_FRAME_CAPTURE_SIZE}. The blit preserves the camera
|
|
394
|
+
* aspect, so the actual target is e.g. 1024×768 for a 4:3 frame — see
|
|
395
|
+
* `computeAspectFitSize` / `acquireCameraFrameRgba`.
|
|
396
|
+
*/
|
|
397
|
+
let cameraFrameCaptureSize = DEFAULT_CAMERA_FRAME_CAPTURE_SIZE;
|
|
398
|
+
/**
|
|
399
|
+
* Throttled camera frame source (created in initAR when `onCameraFrame` is
|
|
400
|
+
* set). Blits the camera texture to RGBA at the detection cadence and hands it
|
|
401
|
+
* to `onCameraFrame`. @see camera-frame-source.ts
|
|
402
|
+
*
|
|
403
|
+
* SINGLE consumer by design: one source, one callback, one blit. That covers
|
|
404
|
+
* one CV consumer at a time (QR *or* object detection). To run two live CV
|
|
405
|
+
* consumers **simultaneously** at independent cadences/resolutions, replace this
|
|
406
|
+
* single-callback wiring with a small registry (e.g.
|
|
407
|
+
* `registerCameraFrameConsumer({ intervalMs, captureSize, onFrame })`) holding a
|
|
408
|
+
* `CameraFrameSource` per consumer — the class is already per-instance. See the
|
|
409
|
+
* SCOPE note in `camera-frame-source.ts`.
|
|
410
|
+
*/
|
|
411
|
+
let cameraFrameSource = null;
|
|
412
|
+
/** Callback for each throttled camera RGBA frame (set via setCameraFrameCallback). */
|
|
413
|
+
let onCameraFrame = null;
|
|
414
|
+
/**
|
|
288
415
|
* Latest WebXR camera texture, updated each frame when camera-access is enabled.
|
|
289
416
|
* Acquired via Three.js's renderer.xr.getCameraTexture() API (ExternalTexture).
|
|
290
417
|
* @see xr-camera-texture.ts
|
|
@@ -333,6 +460,20 @@ function acquireDepthRgbLookup() {
|
|
|
333
460
|
return readback ? createRgbLookup(readback.pixels, readback.width, readback.height) : null;
|
|
334
461
|
}
|
|
335
462
|
/**
|
|
463
|
+
* Capture the current XR frame as top-left RGBA for CV detection (the
|
|
464
|
+
* `capture` injected into {@link CameraFrameSource}; called at most once per
|
|
465
|
+
* detection interval). Returns null — no frame this tick — when camera access
|
|
466
|
+
* or the texture is unavailable; the lazy blit makes a disposal elsewhere
|
|
467
|
+
* self-healing. Reuses `latestCameraTexture`, exactly like the depth-RGB path.
|
|
468
|
+
*/
|
|
469
|
+
function acquireCameraFrameRgba() {
|
|
470
|
+
if (!renderer || !latestCameraTexture) return null;
|
|
471
|
+
const target = computeAspectFitSize(latestCameraWidth, latestCameraHeight, cameraFrameCaptureSize);
|
|
472
|
+
if (!cameraFrameBlit) cameraFrameBlit = new CameraBlitCapture(target);
|
|
473
|
+
else cameraFrameBlit.resizeIfNeeded(target.width, target.height);
|
|
474
|
+
return cameraFrameBlit.captureToRgba(renderer, latestCameraTexture);
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
336
477
|
* Extract the reset transform from an XRReferenceSpaceEvent-like object.
|
|
337
478
|
*
|
|
338
479
|
* Distinguishes three cases per OdometryTrackingRestartedPayload semantics:
|
|
@@ -563,6 +704,13 @@ async function initAR(container, isolationOptions = {}, sessionFeatures = {}) {
|
|
|
563
704
|
acquireRgbLookup: acquireDepthRgbLookup,
|
|
564
705
|
onDepthUnavailable: onDepthUnavailable ?? void 0
|
|
565
706
|
});
|
|
707
|
+
if (onCameraFrame) {
|
|
708
|
+
const deliver = onCameraFrame;
|
|
709
|
+
cameraFrameSource = new CameraFrameSource({
|
|
710
|
+
capture: acquireCameraFrameRgba,
|
|
711
|
+
onCapture: (image) => deliver(image)
|
|
712
|
+
});
|
|
713
|
+
}
|
|
566
714
|
renderer.setAnimationLoop(onXRFrame);
|
|
567
715
|
log.info("AR session started");
|
|
568
716
|
}
|
|
@@ -681,6 +829,7 @@ function onXRFrame(time, frame) {
|
|
|
681
829
|
const depthInfo = getDepthInfoFromFrame(frame, pose);
|
|
682
830
|
depthSampler.onFrame(time, depthInfo);
|
|
683
831
|
}
|
|
832
|
+
if (cameraFrameSource) cameraFrameSource.onFrame(time);
|
|
684
833
|
if (onFrameCallback) try {
|
|
685
834
|
onFrameCallback();
|
|
686
835
|
} catch (error) {
|
|
@@ -897,14 +1046,28 @@ function startImageCapture(config) {
|
|
|
897
1046
|
const currentRenderer = renderer;
|
|
898
1047
|
const divisor = mergedConfig.resolutionDivisor;
|
|
899
1048
|
callbacks.captureFrame = async (quality) => {
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
1049
|
+
const bc = blitCapture;
|
|
1050
|
+
if (!bc || !latestCameraTexture) {
|
|
1051
|
+
const canvas = currentRenderer.domElement;
|
|
1052
|
+
return new Promise((resolve) => {
|
|
1053
|
+
canvas.toBlob((blob) => resolve(blob ? {
|
|
1054
|
+
blob,
|
|
1055
|
+
width: canvas.width,
|
|
1056
|
+
height: canvas.height
|
|
1057
|
+
} : null), "image/jpeg", quality);
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
903
1060
|
if (latestCameraWidth > 0 && latestCameraHeight > 0) {
|
|
904
1061
|
const target = computeCaptureSize(latestCameraWidth, latestCameraHeight, divisor);
|
|
905
|
-
|
|
1062
|
+
bc.resizeIfNeeded(target.width, target.height);
|
|
906
1063
|
}
|
|
907
|
-
|
|
1064
|
+
const blob = await bc.captureToBlob(currentRenderer, latestCameraTexture, quality);
|
|
1065
|
+
if (!blob) return null;
|
|
1066
|
+
return {
|
|
1067
|
+
blob,
|
|
1068
|
+
width: bc.getWidth(),
|
|
1069
|
+
height: bc.getHeight()
|
|
1070
|
+
};
|
|
908
1071
|
};
|
|
909
1072
|
log.info(`Blit capture pipeline initialized (resolutionDivisor=${divisor})`);
|
|
910
1073
|
imageCaptureManager = new ImageCaptureManager(renderer.domElement, callbacks, mergedConfig);
|
|
@@ -1020,6 +1183,68 @@ function getDepthSampleCount() {
|
|
|
1020
1183
|
return depthSampler?.getSampleCount() ?? 0;
|
|
1021
1184
|
}
|
|
1022
1185
|
/**
|
|
1186
|
+
* Set the per-frame camera RGBA callback (B2) — the generic CV frame feed (QR
|
|
1187
|
+
* detection today, object detection / OpenCV later). Call this BEFORE initAR to
|
|
1188
|
+
* enable in-session camera frame capture; `startCameraFrameCapture` then begins
|
|
1189
|
+
* delivering frames.
|
|
1190
|
+
*
|
|
1191
|
+
* The callback receives a **top-left-origin** RGBA image (no JPEG round-trip),
|
|
1192
|
+
* captured at the throttled detection cadence — feed it straight to a
|
|
1193
|
+
* `BarcodeDetector` / OpenCV front-end. Mirrors `setDepthCaptureCallback`.
|
|
1194
|
+
*
|
|
1195
|
+
* @param onFrame - Called with each throttled camera frame, or `null` to clear.
|
|
1196
|
+
*/
|
|
1197
|
+
function setCameraFrameCallback(onFrame) {
|
|
1198
|
+
onCameraFrame = onFrame;
|
|
1199
|
+
}
|
|
1200
|
+
/**
|
|
1201
|
+
* Start camera frame capture during an AR session. Must call
|
|
1202
|
+
* setCameraFrameCallback before initAR (the source is created there). No-op if
|
|
1203
|
+
* the source was not initialized (callback not set before initAR).
|
|
1204
|
+
*
|
|
1205
|
+
* The source is the single cadence owner: drive your detection scheduler from
|
|
1206
|
+
* the delivered frames with its own `minIntervalMs: 0` (Option A).
|
|
1207
|
+
*
|
|
1208
|
+
* @param config - optional cadence / blit-resolution overrides.
|
|
1209
|
+
*/
|
|
1210
|
+
function startCameraFrameCapture(config) {
|
|
1211
|
+
if (!cameraFrameSource) {
|
|
1212
|
+
log.warn("Cannot start camera frame capture - frame source not initialized");
|
|
1213
|
+
return;
|
|
1214
|
+
}
|
|
1215
|
+
if (typeof config?.captureSize === "number" && Number.isFinite(config.captureSize) && config.captureSize > 0) cameraFrameCaptureSize = Math.floor(config.captureSize);
|
|
1216
|
+
if (config?.intervalMs !== void 0) cameraFrameSource.updateConfig({ intervalMs: config.intervalMs });
|
|
1217
|
+
cameraFrameSource.start();
|
|
1218
|
+
log.info(`Camera frame capture started (interval: ${cameraFrameSource.getConfig().intervalMs}ms, long edge ${cameraFrameCaptureSize}px, aspect-preserved)`);
|
|
1219
|
+
}
|
|
1220
|
+
/**
|
|
1221
|
+
* Stop camera frame capture. Safe to call when not running.
|
|
1222
|
+
*/
|
|
1223
|
+
function stopCameraFrameCapture() {
|
|
1224
|
+
if (cameraFrameSource) {
|
|
1225
|
+
const count = cameraFrameSource.getFrameCount();
|
|
1226
|
+
cameraFrameSource.stop();
|
|
1227
|
+
log.info(`Camera frame capture stopped (${count} frames captured)`);
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
/**
|
|
1231
|
+
* Get the number of camera frames captured since the last
|
|
1232
|
+
* `startCameraFrameCapture`.
|
|
1233
|
+
*/
|
|
1234
|
+
function getCameraFrameCount() {
|
|
1235
|
+
return cameraFrameSource?.getFrameCount() ?? 0;
|
|
1236
|
+
}
|
|
1237
|
+
/**
|
|
1238
|
+
* The current longer-edge resolution (px) of the camera-frame blit — the
|
|
1239
|
+
* {@link DEFAULT_CAMERA_FRAME_CAPTURE_SIZE} default unless overridden via
|
|
1240
|
+
* `startCameraFrameCapture({ captureSize })`. Exposed for diagnostics and to
|
|
1241
|
+
* let tests assert the on-device-tuned default without reaching into module
|
|
1242
|
+
* state.
|
|
1243
|
+
*/
|
|
1244
|
+
function getCameraFrameCaptureSize() {
|
|
1245
|
+
return cameraFrameCaptureSize;
|
|
1246
|
+
}
|
|
1247
|
+
/**
|
|
1023
1248
|
* Set a per-frame callback for custom updates.
|
|
1024
1249
|
* The callback is invoked every XR frame after pose updates but before render.
|
|
1025
1250
|
* Useful for updating elements that need to follow the camera smoothly
|
|
@@ -1038,4 +1263,4 @@ function getLiveCss3dManager() {
|
|
|
1038
1263
|
return css3dManager;
|
|
1039
1264
|
}
|
|
1040
1265
|
//#endregion
|
|
1041
|
-
export {
|
|
1266
|
+
export { setFrameCallback as A, startImageCapture as B, nueQuaternionToWebXR$1 as C, setCamera as D, setArWorldGroup as E, setTrackingRecoveredCallback as F, stopDepthCapture as H, setTrackingStore as I, shouldLogCameraAccessDiagnostic as L, setScene as M, setTrackingCallbacks as N, setCameraFrameCallback as O, setTrackingLostCallback as P, startCameraFrameCapture as R, nuePositionToWebXR as S, setArPose as T, stopImageCapture as U, stopCameraFrameCapture as V, CameraFrameSource as W, getScene as _, endARSession as a, isWebXRSupported as b, getArPose as c, getCameraFrameCaptureSize as d, getCameraFrameCount as f, getLiveCss3dManager as g, getImageCaptureFrameCount as h, createSceneHierarchy as i, setImageCaptureCallback as j, setDepthCaptureCallback as k, getArWorldGroup as l, getDepthSampleCount as m, applyAlignmentMatrix as n, extractPoseFromViewer as o, getCurrentArPose as p, buildSessionOptions as r, extractResetTransformData as s, DEFAULT_CAMERA_FRAME_CAPTURE_SIZE as t, getCamera as u, getXrCameraFromPose as v, resetWebXRState as w, isXRCameraLike as x, initAR as y, startDepthCapture as z };
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { i as DepthSample, t as ARPose } from "./ar-types-
|
|
2
|
-
import { i as DepthSamplerConfig } from "./depth-sampler-
|
|
3
|
-
import { t as ArCrashIsolationOptions } from "./recording-options-
|
|
4
|
-
import {
|
|
5
|
-
import { a as TrackingSliceState, r as ResetTransformData } from "./tracking-slice-
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
import { i as DepthSample, t as ARPose } from "./ar-types-BckI1E-O.js";
|
|
2
|
+
import { i as DepthSamplerConfig } from "./depth-sampler-DwfPYzS7.js";
|
|
3
|
+
import { t as ArCrashIsolationOptions } from "./recording-options-D93kksJU.js";
|
|
4
|
+
import { a as ImageCaptureConfig, n as CapturedImage } from "./image-capture-C2Feywet.js";
|
|
5
|
+
import { a as TrackingSliceState, r as ResetTransformData } from "./tracking-slice-DJZ9qeGg.js";
|
|
6
|
+
import { o as RgbaImage } from "./qr-frontend-DufZp2xS.js";
|
|
7
|
+
import { t as Css3dRendererManager } from "./css3d-renderer-manager-m-ab19vp.js";
|
|
8
|
+
import { r as XRCameraLike } from "./xr-camera-texture-BmrP7iNZ.js";
|
|
8
9
|
import * as THREE from "three";
|
|
9
10
|
import { OdometryTrackingRestartedPayload } from "gps-plus-slam-js";
|
|
10
11
|
|
|
@@ -68,6 +69,18 @@ declare function shouldLogCameraAccessDiagnostic(pose: XRViewerPose | null, alre
|
|
|
68
69
|
* @internal
|
|
69
70
|
*/
|
|
70
71
|
declare function resetWebXRState(): void;
|
|
72
|
+
/**
|
|
73
|
+
* Default longer-edge resolution (px) for the camera-frame blit the QR / CV
|
|
74
|
+
* detector sees. The on-device capture-resolution sweep (2026-06-17, via the
|
|
75
|
+
* `?capture=` override) showed **1024** decodes a small / out-of-focus QR
|
|
76
|
+
* markedly better than the prior 512 with no perceptible cadence cost on the
|
|
77
|
+
* test phone; 2048 helped slightly more but risks low-end devices (4096 lagged),
|
|
78
|
+
* so 1024 is the safe default. Raise per-consumer via
|
|
79
|
+
* `startCameraFrameCapture({ captureSize })`.
|
|
80
|
+
*
|
|
81
|
+
* @see GpsPlusSlamJs_Docs/docs/2026-06-17-qr-size-accuracy-and-thin-demo-plan.md (WS-C)
|
|
82
|
+
*/
|
|
83
|
+
declare const DEFAULT_CAMERA_FRAME_CAPTURE_SIZE = 1024;
|
|
71
84
|
/**
|
|
72
85
|
* Extract the reset transform from an XRReferenceSpaceEvent-like object.
|
|
73
86
|
*
|
|
@@ -371,6 +384,61 @@ declare function stopDepthCapture(): void;
|
|
|
371
384
|
* Get the current depth sample count.
|
|
372
385
|
*/
|
|
373
386
|
declare function getDepthSampleCount(): number;
|
|
387
|
+
/** Optional tuning for {@link startCameraFrameCapture}. */
|
|
388
|
+
interface CameraFrameCaptureConfig {
|
|
389
|
+
/** Detection cadence (ms between captures). Default 125 (~8 Hz). */
|
|
390
|
+
intervalMs?: number;
|
|
391
|
+
/**
|
|
392
|
+
* Longer-edge resolution (px) of the camera-frame blit. Default
|
|
393
|
+
* {@link DEFAULT_CAMERA_FRAME_CAPTURE_SIZE} (1024). The blit preserves the
|
|
394
|
+
* camera ASPECT with its longer edge at this value (e.g. 1024 → 1024×768 for a
|
|
395
|
+
* 4:3 camera), so the target reaches the detector undistorted. A QR needs ~3–5
|
|
396
|
+
* px per module; the on-device sweep settled on 1024 (512 made small QRs decode
|
|
397
|
+
* only at very close range). Applied before the first capture.
|
|
398
|
+
*/
|
|
399
|
+
captureSize?: number;
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Set the per-frame camera RGBA callback (B2) — the generic CV frame feed (QR
|
|
403
|
+
* detection today, object detection / OpenCV later). Call this BEFORE initAR to
|
|
404
|
+
* enable in-session camera frame capture; `startCameraFrameCapture` then begins
|
|
405
|
+
* delivering frames.
|
|
406
|
+
*
|
|
407
|
+
* The callback receives a **top-left-origin** RGBA image (no JPEG round-trip),
|
|
408
|
+
* captured at the throttled detection cadence — feed it straight to a
|
|
409
|
+
* `BarcodeDetector` / OpenCV front-end. Mirrors `setDepthCaptureCallback`.
|
|
410
|
+
*
|
|
411
|
+
* @param onFrame - Called with each throttled camera frame, or `null` to clear.
|
|
412
|
+
*/
|
|
413
|
+
declare function setCameraFrameCallback(onFrame: ((image: RgbaImage) => void) | null): void;
|
|
414
|
+
/**
|
|
415
|
+
* Start camera frame capture during an AR session. Must call
|
|
416
|
+
* setCameraFrameCallback before initAR (the source is created there). No-op if
|
|
417
|
+
* the source was not initialized (callback not set before initAR).
|
|
418
|
+
*
|
|
419
|
+
* The source is the single cadence owner: drive your detection scheduler from
|
|
420
|
+
* the delivered frames with its own `minIntervalMs: 0` (Option A).
|
|
421
|
+
*
|
|
422
|
+
* @param config - optional cadence / blit-resolution overrides.
|
|
423
|
+
*/
|
|
424
|
+
declare function startCameraFrameCapture(config?: CameraFrameCaptureConfig): void;
|
|
425
|
+
/**
|
|
426
|
+
* Stop camera frame capture. Safe to call when not running.
|
|
427
|
+
*/
|
|
428
|
+
declare function stopCameraFrameCapture(): void;
|
|
429
|
+
/**
|
|
430
|
+
* Get the number of camera frames captured since the last
|
|
431
|
+
* `startCameraFrameCapture`.
|
|
432
|
+
*/
|
|
433
|
+
declare function getCameraFrameCount(): number;
|
|
434
|
+
/**
|
|
435
|
+
* The current longer-edge resolution (px) of the camera-frame blit — the
|
|
436
|
+
* {@link DEFAULT_CAMERA_FRAME_CAPTURE_SIZE} default unless overridden via
|
|
437
|
+
* `startCameraFrameCapture({ captureSize })`. Exposed for diagnostics and to
|
|
438
|
+
* let tests assert the on-device-tuned default without reaching into module
|
|
439
|
+
* state.
|
|
440
|
+
*/
|
|
441
|
+
declare function getCameraFrameCaptureSize(): number;
|
|
374
442
|
/**
|
|
375
443
|
* Set a per-frame callback for custom updates.
|
|
376
444
|
* The callback is invoked every XR frame after pose updates but before render.
|
|
@@ -386,4 +454,4 @@ declare function setFrameCallback(callback: (() => void) | null): void;
|
|
|
386
454
|
*/
|
|
387
455
|
declare function getLiveCss3dManager(): Css3dRendererManager | null;
|
|
388
456
|
//#endregion
|
|
389
|
-
export {
|
|
457
|
+
export { setCamera as A, shouldLogCameraAccessDiagnostic as B, isWebXRSupported as C, resetWebXRState as D, nueQuaternionToWebXR$1 as E, setScene as F, stopDepthCapture as G, startDepthCapture as H, setTrackingCallbacks as I, stopImageCapture as K, setTrackingLostCallback as L, setDepthCaptureCallback as M, setFrameCallback as N, setArPose as O, setImageCaptureCallback as P, setTrackingRecoveredCallback as R, initAR as S, nuePositionToWebXR as T, startImageCapture as U, startCameraFrameCapture as V, stopCameraFrameCapture as W, getDepthSampleCount as _, applyAlignmentMatrix as a, getScene as b, endARSession as c, getArPose as d, getArWorldGroup as f, getCurrentArPose as g, getCameraFrameCount as h, TrackingSubscribableStore as i, setCameraFrameCallback as j, setArWorldGroup as k, extractPoseFromViewer as l, getCameraFrameCaptureSize as m, DEFAULT_CAMERA_FRAME_CAPTURE_SIZE as n, buildSessionOptions as o, getCamera as p, SessionFeatureOptions as r, createSceneHierarchy as s, CameraFrameCaptureConfig as t, extractResetTransformData as u, getImageCaptureFrameCount as v, isXRCameraLike as w, getXrCameraFromPose as x, getLiveCss3dManager as y, setTrackingStore as z };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//#region ../src/storage/zip-coverage-embed.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Zip Coverage Embed — write a recording's H3 coverage into its `session.json`.
|
|
4
|
+
*
|
|
5
|
+
* The map-centric browser indexes legacy recordings (those predating the
|
|
6
|
+
* `h3Cells` field) by reading their full GPS path — slow, and repeated on every
|
|
7
|
+
* folder open. This primitive lets a one-time "upgrade" embed the derived
|
|
8
|
+
* coverage **inside the recording's own `session.json`**, so the recording
|
|
9
|
+
* indexes instantly on every future open in this app *and any other reader*
|
|
10
|
+
* (the portability the user asked for; O3 — in-zip rewrite).
|
|
11
|
+
*
|
|
12
|
+
* It is a pure transform `(zip, cells, resolution) -> zip`: it reads every entry
|
|
13
|
+
* and re-emits a new zip identical to the input except that `session.json` gains
|
|
14
|
+
* `h3Cells` + `h3Resolution`. It never mutates anything in place — the caller
|
|
15
|
+
* (the RecorderApp backfill) owns the safe write-then-verify-then-overwrite
|
|
16
|
+
* protocol around it.
|
|
17
|
+
*
|
|
18
|
+
* @see ./zip-coverage-embed.ts.md
|
|
19
|
+
* @see GpsPlusSlamJs_Docs/docs/2026-06-14-followup-progressive-map-browser-indexing-and-backfill.md (B3)
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Return a new zip blob identical to `zip` except its `session.json` gains
|
|
23
|
+
* `h3Cells` + `h3Resolution`.
|
|
24
|
+
*
|
|
25
|
+
* **Skips (returns the input blob unchanged, by reference) when:**
|
|
26
|
+
* - the zip has no `session.json` (nothing to embed into);
|
|
27
|
+
* - `session.json` is present but unparseable (never write over a broken one);
|
|
28
|
+
* - `session.json` already carries `h3Cells` (idempotent — re-running the
|
|
29
|
+
* upgrade is a no-op, and new recordings are skipped).
|
|
30
|
+
*
|
|
31
|
+
* On any unexpected read/write failure it also returns the input untouched —
|
|
32
|
+
* it never emits a partial zip. Callers can detect a skip via reference
|
|
33
|
+
* equality (`result === zip`).
|
|
34
|
+
*
|
|
35
|
+
* Built on `@zip.js/zip.js` (the same library as the exporter) in store mode, so
|
|
36
|
+
* every non-`session.json` entry is re-emitted with byte-identical uncompressed
|
|
37
|
+
* content.
|
|
38
|
+
*/
|
|
39
|
+
declare function embedCoverageInSessionJson(zip: Blob, h3Cells: string[], h3Resolution: number): Promise<Blob>;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { embedCoverageInSessionJson as t };
|
|
@@ -78,24 +78,38 @@ interface ExportSessionAsZipOptions {
|
|
|
78
78
|
readonly contributors?: readonly ZipExportContributor[];
|
|
79
79
|
}
|
|
80
80
|
/**
|
|
81
|
-
* Export a session from OPFS as a ZIP blob.
|
|
81
|
+
* Export a flat-layout session from OPFS as a ZIP blob.
|
|
82
82
|
*
|
|
83
83
|
* The ZIP structure mirrors the OPFS session structure:
|
|
84
84
|
* - session.json (at root)
|
|
85
85
|
* - actions/000001.json, actions/000002.json, ...
|
|
86
|
-
* -
|
|
87
|
-
* - refPoints/{h3}.json (only observations from this session, scenario layout only)
|
|
86
|
+
* - images/frame-000001.jpg, images/frame-000002.jpg, ... (legacy: frames/)
|
|
88
87
|
*
|
|
89
|
-
* Uses "store" mode (compression level 0) for fast packaging.
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* - `exportSessionAsZip(sessionName)` — flat layout (sessions/)
|
|
93
|
-
* - `exportSessionAsZip(scenarioName, sessionName)` — scenario layout (scenarios/{name}/)
|
|
88
|
+
* Uses "store" mode (compression level 0) for fast packaging. Consumers with a
|
|
89
|
+
* different on-disk layout (one that nests sessions under a named bucket)
|
|
90
|
+
* resolve their own session handle and call {@link exportSessionHandleAsZip}.
|
|
94
91
|
*
|
|
92
|
+
* @param sessionName - Name of the session folder under `sessions/`.
|
|
95
93
|
* @returns ZIP export result with blob and file count
|
|
96
|
-
* @throws Error if session not found
|
|
94
|
+
* @throws Error if the session is not found
|
|
95
|
+
*/
|
|
96
|
+
declare function exportSessionAsZip(sessionName: string, options?: ExportSessionAsZipOptions): Promise<ZipExportResult>;
|
|
97
|
+
/**
|
|
98
|
+
* Stream an already-resolved session directory handle to a ZIP blob, running
|
|
99
|
+
* any caller-supplied extension {@link ZipExportContributor}s after the
|
|
100
|
+
* framework-owned files.
|
|
101
|
+
*
|
|
102
|
+
* This is the layout-agnostic core of {@link exportSessionAsZip}: consumers
|
|
103
|
+
* that resolve a session directory handle themselves (e.g. an app that nests
|
|
104
|
+
* sessions under its own grouping layer) call this directly so the framework's
|
|
105
|
+
* ZIP schema stays the single source of truth without the framework needing to
|
|
106
|
+
* know how the handle was located.
|
|
107
|
+
*
|
|
108
|
+
* @param sessionHandle - The session directory to package (must contain the
|
|
109
|
+
* framework-owned `session.json` / `actions/` / `images/` tree).
|
|
110
|
+
* @returns ZIP export result with blob and file count.
|
|
97
111
|
*/
|
|
98
|
-
declare function
|
|
112
|
+
declare function exportSessionHandleAsZip(sessionHandle: FileSystemDirectoryHandle, options?: ExportSessionAsZipOptions): Promise<ZipExportResult>;
|
|
99
113
|
/**
|
|
100
114
|
* Sync current OPFS session data to an external file handle.
|
|
101
115
|
*
|
|
@@ -109,12 +123,11 @@ declare function exportSessionAsZip(scenarioNameOrSessionName: string, sessionNa
|
|
|
109
123
|
* the last synced ZIP contains all data up to that point.
|
|
110
124
|
*
|
|
111
125
|
* @param fileHandle - File handle from showSaveFilePicker
|
|
112
|
-
* @param
|
|
113
|
-
* @param sessionName - Name of the session folder
|
|
126
|
+
* @param sessionName - Name of the session folder under `sessions/`
|
|
114
127
|
* @returns ZIP export result with blob and file count
|
|
115
|
-
* @throws Error if
|
|
128
|
+
* @throws Error if the session is not found
|
|
116
129
|
*/
|
|
117
|
-
declare function syncToExternalZip(fileHandle: FileSystemFileHandle,
|
|
130
|
+
declare function syncToExternalZip(fileHandle: FileSystemFileHandle, sessionName: string, options?: ExportSessionAsZipOptions): Promise<ZipExportResult>;
|
|
118
131
|
/**
|
|
119
132
|
* Trigger a file download in the browser.
|
|
120
133
|
*
|
|
@@ -125,14 +138,5 @@ declare function syncToExternalZip(fileHandle: FileSystemFileHandle, scenarioNam
|
|
|
125
138
|
* @param filename - Suggested filename
|
|
126
139
|
*/
|
|
127
140
|
declare function downloadZip(blob: Blob, filename: string): Promise<void>;
|
|
128
|
-
/**
|
|
129
|
-
* Export and download a session in one step.
|
|
130
|
-
*
|
|
131
|
-
* Convenience function combining exportSessionAsZip and downloadZip.
|
|
132
|
-
*
|
|
133
|
-
* @param scenarioName - Name of the scenario
|
|
134
|
-
* @param sessionName - Name of the session folder
|
|
135
|
-
*/
|
|
136
|
-
declare function exportAndDownloadSession(scenarioName: string, sessionName: string): Promise<void>;
|
|
137
141
|
//#endregion
|
|
138
|
-
export { downloadZip as a, syncToExternalZip as c, ZipExportResult as i, ZipContributorAddFile as n,
|
|
142
|
+
export { downloadZip as a, syncToExternalZip as c, ZipExportResult as i, ZipContributorAddFile as n, exportSessionAsZip as o, ZipExportContributor as r, exportSessionHandleAsZip as s, ExportSessionAsZipOptions as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gps-plus-slam-app-framework",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Reusable AR+GPS app framework layer — WebXR session management, Three.js visualization, GPS sensors, storage abstractions, replay engine, and store wiring for gps-plus-slam-js.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@reduxjs/toolkit": "^2.11.2",
|
|
38
38
|
"gl-matrix": "3.4.4",
|
|
39
|
-
"gps-plus-slam-js": "^1.0
|
|
39
|
+
"gps-plus-slam-js": "^1.4.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"@sentry/browser": ">=10.0.0",
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
//#region ../src/utils/concurrency.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Concurrency Utilities
|
|
4
|
-
*
|
|
5
|
-
* Provides helpers for limiting the number of concurrent async operations.
|
|
6
|
-
* Used to prevent excessive memory consumption when scanning many files
|
|
7
|
-
* in parallel (e.g., reading zip metadata during scenario discovery).
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Map over an array with a concurrency limit on the async mapper function.
|
|
11
|
-
*
|
|
12
|
-
* Behaves like `Promise.all(items.map(fn))` but limits how many mapper
|
|
13
|
-
* invocations run simultaneously. Results are returned in the same order
|
|
14
|
-
* as the input items.
|
|
15
|
-
*
|
|
16
|
-
* @param items - Array of items to process
|
|
17
|
-
* @param limit - Maximum number of concurrent mapper invocations
|
|
18
|
-
* @param mapper - Async function to apply to each item
|
|
19
|
-
* @returns Array of results in the same order as input items
|
|
20
|
-
* @throws Re-throws the first error from any mapper invocation (fail-fast)
|
|
21
|
-
*/
|
|
22
|
-
declare function mapWithConcurrencyLimit<T, R>(items: T[], limit: number, mapper: (item: T, index: number) => Promise<R>): Promise<R[]>;
|
|
23
|
-
//#endregion
|
|
24
|
-
export { mapWithConcurrencyLimit as t };
|