gps-plus-slam-app-framework 1.7.0 → 1.8.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/{accuracy-circles-BtqOP_v1.d.ts → accuracy-circles-DkWBkF5g.d.ts} +16 -6
- package/dist/{app-selectors-ikTUQZpe.d.ts → app-selectors-JqydaUMN.d.ts} +1 -1
- package/dist/ar/bresenham3d.d.ts +1 -1
- package/dist/ar/camera-blit-capture.d.ts +1 -1
- 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 +1 -1
- package/dist/ar/depth-occluder.d.ts +127 -0
- package/dist/ar/depth-occluder.js +299 -0
- package/dist/ar/depth-sampler.d.ts +2 -2
- package/dist/ar/depth-sampler.js +24 -4
- package/dist/ar/depth-unprojection.d.ts +1 -1
- package/dist/ar/depth-unprojection.js +52 -21
- package/dist/ar/enable-gps-ar.d.ts +1 -1
- package/dist/ar/enable-gps-ar.js +1 -1
- package/dist/ar/frame-loop.d.ts +1 -1
- package/dist/ar/frame-loop.js +12 -2
- package/dist/ar/image-capture.d.ts +1 -1
- package/dist/ar/image-capture.js +1 -1
- package/dist/ar/image-quality.d.ts +1 -1
- package/dist/ar/image-quality.js +2 -1
- package/dist/ar/index.d.ts +32 -31
- package/dist/ar/index.js +5 -4
- package/dist/ar/occlusion-mesh-worker.d.ts +58 -0
- package/dist/ar/occlusion-mesh-worker.js +129 -0
- package/dist/ar/occupancy-grid.d.ts +2 -2
- package/dist/ar/occupancy-grid.js +287 -31
- package/dist/ar/occupancy-mesher.d.ts +2 -0
- package/dist/ar/occupancy-mesher.js +638 -0
- package/dist/ar/planar-pnp.d.ts +1 -1
- package/dist/ar/qr-debug-view.d.ts +1 -1
- package/dist/ar/qr-derived-pose.d.ts +1 -1
- package/dist/ar/qr-detection-controller.d.ts +1 -1
- package/dist/ar/qr-frontend.d.ts +1 -1
- package/dist/ar/qr-pose.d.ts +1 -1
- package/dist/ar/qr-size-depth-context.d.ts +2 -2
- package/dist/ar/qr-size-measurer.d.ts +1 -1
- 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/xr-frame-loop.js +12 -2
- package/dist/{ar-MFpFlV7j.js → ar-BqCudtqE.js} +3 -2
- package/dist/{ar-world-group-alignment-69fgnB39.d.ts → ar-world-group-alignment-BlvGcIAk.d.ts} +1 -1
- package/dist/{capture-motion-gate-4EscNZCw.js → capture-motion-gate-_NdTSwKi.js} +17 -5
- package/dist/cell-key-DIB4rOTV.js +51 -0
- package/dist/core/index.d.ts +1 -1
- package/dist/{create-slam-app-store-n_VF63D5.d.ts → create-slam-app-store-D3nzh9Wb.d.ts} +4 -4
- package/dist/{create-slam-app-store-DkCHOpvb.js → create-slam-app-store-DXiAnJwR.js} +9 -2
- package/dist/{depth-grid-lookup-DQ-IYhO3.d.ts → depth-grid-lookup-D5atpNZ3.d.ts} +1 -1
- package/dist/{depth-sampler-asc8exHt.d.ts → depth-sampler-CwObAwEA.d.ts} +33 -1
- package/dist/{depth-unprojection-DjsbJW9L.d.ts → depth-unprojection-DRdBU90S.d.ts} +1 -1
- package/dist/{enable-gps-ar-DkNhFv4Y.d.ts → enable-gps-ar-DvGzBOrp.d.ts} +4 -4
- package/dist/{frame-conversions-DObhj8Wf.d.ts → frame-conversions-C4bnNOEY.d.ts} +1 -1
- package/dist/{fused-path-v6eOmLl3.d.ts → fused-path-C5pp0PJU.d.ts} +1 -1
- package/dist/geo/h3-proximity.d.ts +1 -1
- package/dist/geo/index.d.ts +1 -1
- package/dist/{gps-anchor-BeFO2RYa.d.ts → gps-anchor-BjECcYnD.d.ts} +1 -1
- package/dist/{gps-ar-pose-sampler-DHMZmYAc.d.ts → gps-ar-pose-sampler-DEGNk2CI.d.ts} +1 -1
- package/dist/{gps-event-coordinator-CjWW636x.d.ts → gps-event-coordinator-CHtIkhb7.d.ts} +4 -4
- package/dist/{image-capture-CNZDrQXG.d.ts → image-capture-Bp6Pd4Md.d.ts} +3 -3
- package/dist/{image-capture-B2-b6tKK.js → image-capture-DVcuqMtX.js} +1 -1
- package/dist/{index-BODDUTvD.d.ts → index-DlsOo2IB.d.ts} +1 -1
- package/dist/{index-BneSj4_5.d.ts → index-cCQWuYqy.d.ts} +3 -3
- package/dist/index.d.ts +82 -80
- package/dist/index.js +10 -8
- package/dist/{leaflet-map-overlay-CmIyiE8n.d.ts → leaflet-map-overlay-BOZFW5kT.d.ts} +64 -10
- package/dist/leaflet-map-overlay-CBWPvaX9.js +452 -0
- package/dist/lerp-utils-Qs8OhumS.d.ts +42 -0
- package/dist/map-data-D7rpMC6f.js +120 -0
- package/dist/{map-data-B4oEehUh.d.ts → map-data-PNfGKGWx.d.ts} +22 -2
- package/dist/{map-overlay-draw-ymz1s7fG.d.ts → map-overlay-draw-DiroaJed.d.ts} +1 -1
- package/dist/{null-storage-backend-B9rtyDfG.d.ts → null-storage-backend-B1-jlpin.d.ts} +2 -2
- package/dist/occlusion-mesh-b28lRJ6S.d.ts +194 -0
- package/dist/occupancy-grid-BV7RhB7I.d.ts +194 -0
- package/dist/occupancy-mesher-C2ecWhNp.d.ts +100 -0
- package/dist/{opfs-storage-3VZh-qH6.d.ts → opfs-storage-CTkxvxN4.d.ts} +5 -0
- package/dist/{opfs-storage-backend-JJiUJo-3.d.ts → opfs-storage-backend-D6Z03fML.d.ts} +2 -2
- package/dist/{persistence-middleware-DAPTTwB2.d.ts → persistence-middleware-CG-t08X4.d.ts} +1 -1
- package/dist/{planar-pnp-my9bqULS.d.ts → planar-pnp-D7bc_rLX.d.ts} +1 -1
- package/dist/{qr-debug-view-Brl73HGO.d.ts → qr-debug-view-BJooqbiP.d.ts} +1 -1
- package/dist/{qr-derived-pose-CmxTP2m4.d.ts → qr-derived-pose-BwNWn8oV.d.ts} +2 -2
- package/dist/{qr-detected-slice-VQssZmQJ.d.ts → qr-detected-slice-TzVb8bij.d.ts} +4 -4
- package/dist/{qr-detection-controller-CDurHv8E.d.ts → qr-detection-controller-Bo4XfQTP.d.ts} +3 -3
- package/dist/{qr-frontend--fFX25mV.d.ts → qr-frontend-BPURlh3S.d.ts} +1 -1
- package/dist/{qr-pose-aggregation-B7tWJq7j.d.ts → qr-pose-aggregation-CypnmjA-.d.ts} +1 -1
- package/dist/{qr-size-depth-context-CeAG53fy.d.ts → qr-size-depth-context-apAOmbrZ.d.ts} +2 -2
- package/dist/{qr-size-measurer-DQdAsid1.d.ts → qr-size-measurer-DxiMqRUw.d.ts} +3 -3
- package/dist/{recording-options-BPCpMHLK.d.ts → recording-options-vASCFzc5.d.ts} +177 -24
- package/dist/{recording-replayer-DQKpAGyQ.d.ts → recording-replayer-D0V9WkmY.d.ts} +2 -2
- package/dist/{recording-slice-DaxHZvNu.d.ts → recording-slice-DTUtSVgd.d.ts} +2 -2
- package/dist/{replay-engine-CmKh_4wf.d.ts → replay-engine-xdrUgWJi.d.ts} +1 -1
- package/dist/{replay-scene-DBlDrV_x.d.ts → replay-scene-zJ8SFDjE.d.ts} +3 -3
- package/dist/sensors/absolute-orientation.d.ts +1 -1
- package/dist/sensors/absolute-orientation.js +23 -6
- package/dist/sensors/gps-error-handler.d.ts +1 -1
- package/dist/sensors/gps.d.ts +1 -1
- package/dist/sensors/index.d.ts +4 -4
- package/dist/sensors/permission-checker.d.ts +1 -1
- package/dist/state/app-selectors.d.ts +1 -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/create-slam-app-store.js +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 +19 -19
- package/dist/state/index.js +2 -2
- package/dist/state/persistence-middleware.d.ts +1 -1
- package/dist/state/qr-detected-slice.d.ts +3 -3
- package/dist/state/recording-options.d.ts +2 -2
- package/dist/state/recording-options.js +134 -15
- package/dist/state/recording-replayer.d.ts +2 -2
- package/dist/state/recording-replayer.js +1 -1
- package/dist/state/recording-slice.d.ts +1 -1
- package/dist/state/replay-engine.d.ts +1 -1
- package/dist/state/store-subscribers.d.ts +2 -2
- package/dist/state/store-subscribers.js +2 -1
- package/dist/state/subscribe-to-selector.d.ts +1 -1
- package/dist/state/tracking-quality.d.ts +1 -1
- package/dist/state/tracking-quality.js +10 -1
- package/dist/state/tracking-slice.d.ts +1 -1
- package/dist/{state-E51QT_-j.js → state-BeKvn4B-.js} +1 -1
- package/dist/storage/file-system-utils.d.ts +1 -1
- package/dist/storage/index.d.ts +8 -8
- 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.d.ts +1 -1
- package/dist/storage/opfs-storage.js +25 -1
- package/dist/storage/storage-backend.d.ts +1 -1
- package/dist/storage/zip-coverage-embed.d.ts +1 -1
- package/dist/storage/zip-export.d.ts +1 -1
- package/dist/storage/zip-reader.d.ts +1 -1
- package/dist/{storage-backend-BdVLD0dU.d.ts → storage-backend-sEtmM4yW.d.ts} +1 -1
- package/dist/{store-subscribers-CA6AJH_8.d.ts → store-subscribers-DScA7tdT.d.ts} +2 -2
- package/dist/{subscribe-to-selector-B6EUmQ3I.d.ts → subscribe-to-selector-B9ylM5Oh.d.ts} +1 -1
- package/dist/test-utils/browser-mocks.d.ts +1 -1
- package/dist/test-utils/zip-round-trip-helpers.d.ts +1 -1
- package/dist/{tracking-slice-BuAZxXZ5.d.ts → tracking-slice-DMkHlbny.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 +1 -1
- 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 +7 -7
- 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/accuracy-circles.js +17 -8
- 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 +1 -1
- package/dist/visualization/hit-test-reticle.d.ts +1 -1
- package/dist/visualization/index.d.ts +20 -19
- package/dist/visualization/index.js +4 -3
- package/dist/visualization/leaflet-map-overlay.d.ts +1 -1
- package/dist/visualization/leaflet-map-overlay.js +1 -282
- package/dist/visualization/lerp-utils.d.ts +2 -2
- package/dist/visualization/lerp-utils.js +27 -3
- package/dist/visualization/map-data.d.ts +1 -1
- package/dist/visualization/map-data.js +1 -32
- package/dist/visualization/map-overlay-draw.d.ts +1 -1
- package/dist/visualization/map-overlay-draw.js +24 -2
- package/dist/visualization/map-overlay.d.ts +1 -1
- package/dist/visualization/occluder-mesh-driver.d.ts +130 -0
- package/dist/visualization/occluder-mesh-driver.js +219 -0
- package/dist/visualization/occlusion-mesh.d.ts +2 -0
- package/dist/visualization/occlusion-mesh.js +437 -0
- package/dist/visualization/three-dispose.d.ts +1 -1
- package/dist/visualization/vis-colors.d.ts +1 -1
- package/dist/{webxr-session-DG-eNfny.js → webxr-session-BCP2XK7k.js} +88 -13
- package/dist/{webxr-session-Do5L6G3B.d.ts → webxr-session-cRG2SYAQ.d.ts} +73 -10
- package/package.json +4 -4
- package/dist/lerp-utils-BLmHhkVe.d.ts +0 -20
- package/dist/occupancy-grid-DnOc-6PU.d.ts +0 -82
- /package/dist/{absolute-orientation-CAEh840t.d.ts → absolute-orientation-BAxc15J6.d.ts} +0 -0
- /package/dist/{alignment-lerper-Bil6vbVw.d.ts → alignment-lerper-gD70k7Fq.d.ts} +0 -0
- /package/dist/{ar-types-BFX2r1wk.d.ts → ar-types-Cc5yvBwn.d.ts} +0 -0
- /package/dist/{bresenham3d-CU1Gv2W4.d.ts → bresenham3d-DGc4nIb-.d.ts} +0 -0
- /package/dist/{camera-blit-capture-NKT9H5-e.d.ts → camera-blit-capture-BimSdyih.d.ts} +0 -0
- /package/dist/{camera-follower-CqJJ7zRj.d.ts → camera-follower-DfBm2J5i.d.ts} +0 -0
- /package/dist/{capability-checker-DUQLg6gq.d.ts → capability-checker-BTTpygvZ.d.ts} +0 -0
- /package/dist/{capture-failure-tracker-gsm8q7yi.d.ts → capture-failure-tracker-_BVfhpxv.d.ts} +0 -0
- /package/dist/{capture-motion-gate-0Yl2NpQG.d.ts → capture-motion-gate-BGoAMkmf.d.ts} +0 -0
- /package/dist/{chromium-camera-access-workaround-D4K2uwwQ.d.ts → chromium-camera-access-workaround-C6yJLXz9.d.ts} +0 -0
- /package/dist/{concurrency-By0oOTZt.d.ts → concurrency-DPeGBH0X.d.ts} +0 -0
- /package/dist/{css3d-renderer-manager-B3kGNtcn.d.ts → css3d-renderer-manager-CPpVtvgs.d.ts} +0 -0
- /package/dist/{failure-tracker-BO7M7jF_.d.ts → failure-tracker-CeKf5HIc.d.ts} +0 -0
- /package/dist/{file-system-utils-DOajnMm-.d.ts → file-system-utils-DueXHxo9.d.ts} +0 -0
- /package/dist/{format-file-size-Dc98ulzB.d.ts → format-file-size-DxN-EBLc.d.ts} +0 -0
- /package/dist/{frame-loop-CpVjQ1dH.d.ts → frame-loop-7GBMBu68.d.ts} +0 -0
- /package/dist/{frustum-visibility-CeoCZchO.d.ts → frustum-visibility-CokkgS_i.d.ts} +0 -0
- /package/dist/{geo-types-3Ip1NzVR.d.ts → geo-types-DrGVu8nS.d.ts} +0 -0
- /package/dist/{gps-BBO3hKfT.d.ts → gps-CDKDQokE.d.ts} +0 -0
- /package/dist/{gps-compass-cubes-DSN87L8p.d.ts → gps-compass-cubes-1mooS3BS.d.ts} +0 -0
- /package/dist/{gps-error-handler-BbPsfw-_.d.ts → gps-error-handler-C34GQuTu.d.ts} +0 -0
- /package/dist/{gps-event-markers-Cz9RMA2k.d.ts → gps-event-markers-Di2nBzx-.d.ts} +0 -0
- /package/dist/{h3-proximity-C-j0pw1j.d.ts → h3-proximity-D0GTHQmr.d.ts} +0 -0
- /package/dist/{hit-test-reticle-DV-2TpB9.d.ts → hit-test-reticle-CaQbrhbk.d.ts} +0 -0
- /package/dist/{image-quality-smCBoFj1.d.ts → image-quality-BMx2ko9-.d.ts} +0 -0
- /package/dist/{index-_Rhgoqkh.d.ts → index-D4vrgV4b.d.ts} +0 -0
- /package/dist/{index-BAPokxMb.d.ts → index-D74JTX4I.d.ts} +0 -0
- /package/dist/{list-formatter-KNMS0ay2.d.ts → list-formatter-DLFDnS70.d.ts} +0 -0
- /package/dist/{logger-CLnPrHiD.d.ts → logger-CqTd5Kpk.d.ts} +0 -0
- /package/dist/{map-overlay-Dh2B97MP.d.ts → map-overlay-BCQgvIgU.d.ts} +0 -0
- /package/dist/{permission-checker-CDuI8BwC.d.ts → permission-checker-B-VtjnBA.d.ts} +0 -0
- /package/dist/{qr-pose-D2rfu5DA.d.ts → qr-pose-y3vaEd6x.d.ts} +0 -0
- /package/dist/{scene-node-names-BiShOQDB.d.ts → scene-node-names-CGb-ylBd.d.ts} +0 -0
- /package/dist/{session-disposers-zv9OGXPB.js → session-disposers-BPrMplIC.js} +0 -0
- /package/dist/{three-dispose-Bt1k7WKh.d.ts → three-dispose-BMOAmPhb.d.ts} +0 -0
- /package/dist/{vis-colors-Obw2pLqT.d.ts → vis-colors-C7HI0u9_.d.ts} +0 -0
- /package/dist/{webxr-nue-basis-3nfjDJJp.d.ts → webxr-nue-basis-CaCnYxuq.d.ts} +0 -0
- /package/dist/{xr-camera-texture-Cva1q3Qj.d.ts → xr-camera-texture-q0eIDSRg.d.ts} +0 -0
- /package/dist/{xr-error-handler-CtvHpjfm.d.ts → xr-error-handler-uVGDu9IX.d.ts} +0 -0
- /package/dist/{xr-frame-loop-DIYtRcUa.d.ts → xr-frame-loop-DX3JPpAU.d.ts} +0 -0
- /package/dist/{zip-coverage-embed-DCAREVmw.d.ts → zip-coverage-embed-ncVbaZAz.d.ts} +0 -0
- /package/dist/{zip-export-ol0S_Ofd.d.ts → zip-export-CtiUnAlJ.d.ts} +0 -0
- /package/dist/{zip-reader-D9iPQwdQ.d.ts → zip-reader-CvruaGvD.d.ts} +0 -0
|
@@ -0,0 +1,638 @@
|
|
|
1
|
+
import { a as packCellKey } from "../cell-key-DIB4rOTV.js";
|
|
2
|
+
//#region ../src/ar/occupancy-mesher.ts
|
|
3
|
+
/** Resolve the effective mesher mode from the (possibly legacy) options. */
|
|
4
|
+
function resolveMode(options) {
|
|
5
|
+
if (options?.mode) return options.mode;
|
|
6
|
+
return options?.greedy ? "greedy" : "per-face";
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Right-handed cyclic axis assignment per face-normal axis `d`: `(d, u, v)`
|
|
10
|
+
* with `eu × ev = ed`, so a `(uMin,vMin)→(uMax,vMin)→(uMax,vMax)→(uMin,vMax)`
|
|
11
|
+
* quad has the `+d` outward normal (and the reverse order has `−d`). Used by the
|
|
12
|
+
* greedy mesher to keep merged-quad winding consistent with the per-face path.
|
|
13
|
+
*/
|
|
14
|
+
const GREEDY_DIRS = [
|
|
15
|
+
{
|
|
16
|
+
d: 0,
|
|
17
|
+
u: 1,
|
|
18
|
+
v: 2
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
d: 1,
|
|
22
|
+
u: 2,
|
|
23
|
+
v: 0
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
d: 2,
|
|
27
|
+
u: 0,
|
|
28
|
+
v: 1
|
|
29
|
+
}
|
|
30
|
+
];
|
|
31
|
+
/**
|
|
32
|
+
* The six cube faces with outward (CCW-from-outside) winding. Corner signs are
|
|
33
|
+
* ±1 multipliers of the half-cell extent. Triangulated as (0,1,2)+(0,2,3).
|
|
34
|
+
*/
|
|
35
|
+
const FACES = [
|
|
36
|
+
{
|
|
37
|
+
neighbour: [
|
|
38
|
+
1,
|
|
39
|
+
0,
|
|
40
|
+
0
|
|
41
|
+
],
|
|
42
|
+
corners: [
|
|
43
|
+
[
|
|
44
|
+
1,
|
|
45
|
+
-1,
|
|
46
|
+
-1
|
|
47
|
+
],
|
|
48
|
+
[
|
|
49
|
+
1,
|
|
50
|
+
1,
|
|
51
|
+
-1
|
|
52
|
+
],
|
|
53
|
+
[
|
|
54
|
+
1,
|
|
55
|
+
1,
|
|
56
|
+
1
|
|
57
|
+
],
|
|
58
|
+
[
|
|
59
|
+
1,
|
|
60
|
+
-1,
|
|
61
|
+
1
|
|
62
|
+
]
|
|
63
|
+
]
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
neighbour: [
|
|
67
|
+
-1,
|
|
68
|
+
0,
|
|
69
|
+
0
|
|
70
|
+
],
|
|
71
|
+
corners: [
|
|
72
|
+
[
|
|
73
|
+
-1,
|
|
74
|
+
-1,
|
|
75
|
+
-1
|
|
76
|
+
],
|
|
77
|
+
[
|
|
78
|
+
-1,
|
|
79
|
+
-1,
|
|
80
|
+
1
|
|
81
|
+
],
|
|
82
|
+
[
|
|
83
|
+
-1,
|
|
84
|
+
1,
|
|
85
|
+
1
|
|
86
|
+
],
|
|
87
|
+
[
|
|
88
|
+
-1,
|
|
89
|
+
1,
|
|
90
|
+
-1
|
|
91
|
+
]
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
neighbour: [
|
|
96
|
+
0,
|
|
97
|
+
1,
|
|
98
|
+
0
|
|
99
|
+
],
|
|
100
|
+
corners: [
|
|
101
|
+
[
|
|
102
|
+
-1,
|
|
103
|
+
1,
|
|
104
|
+
-1
|
|
105
|
+
],
|
|
106
|
+
[
|
|
107
|
+
-1,
|
|
108
|
+
1,
|
|
109
|
+
1
|
|
110
|
+
],
|
|
111
|
+
[
|
|
112
|
+
1,
|
|
113
|
+
1,
|
|
114
|
+
1
|
|
115
|
+
],
|
|
116
|
+
[
|
|
117
|
+
1,
|
|
118
|
+
1,
|
|
119
|
+
-1
|
|
120
|
+
]
|
|
121
|
+
]
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
neighbour: [
|
|
125
|
+
0,
|
|
126
|
+
-1,
|
|
127
|
+
0
|
|
128
|
+
],
|
|
129
|
+
corners: [
|
|
130
|
+
[
|
|
131
|
+
-1,
|
|
132
|
+
-1,
|
|
133
|
+
-1
|
|
134
|
+
],
|
|
135
|
+
[
|
|
136
|
+
1,
|
|
137
|
+
-1,
|
|
138
|
+
-1
|
|
139
|
+
],
|
|
140
|
+
[
|
|
141
|
+
1,
|
|
142
|
+
-1,
|
|
143
|
+
1
|
|
144
|
+
],
|
|
145
|
+
[
|
|
146
|
+
-1,
|
|
147
|
+
-1,
|
|
148
|
+
1
|
|
149
|
+
]
|
|
150
|
+
]
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
neighbour: [
|
|
154
|
+
0,
|
|
155
|
+
0,
|
|
156
|
+
1
|
|
157
|
+
],
|
|
158
|
+
corners: [
|
|
159
|
+
[
|
|
160
|
+
-1,
|
|
161
|
+
-1,
|
|
162
|
+
1
|
|
163
|
+
],
|
|
164
|
+
[
|
|
165
|
+
1,
|
|
166
|
+
-1,
|
|
167
|
+
1
|
|
168
|
+
],
|
|
169
|
+
[
|
|
170
|
+
1,
|
|
171
|
+
1,
|
|
172
|
+
1
|
|
173
|
+
],
|
|
174
|
+
[
|
|
175
|
+
-1,
|
|
176
|
+
1,
|
|
177
|
+
1
|
|
178
|
+
]
|
|
179
|
+
]
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
neighbour: [
|
|
183
|
+
0,
|
|
184
|
+
0,
|
|
185
|
+
-1
|
|
186
|
+
],
|
|
187
|
+
corners: [
|
|
188
|
+
[
|
|
189
|
+
-1,
|
|
190
|
+
-1,
|
|
191
|
+
-1
|
|
192
|
+
],
|
|
193
|
+
[
|
|
194
|
+
-1,
|
|
195
|
+
1,
|
|
196
|
+
-1
|
|
197
|
+
],
|
|
198
|
+
[
|
|
199
|
+
1,
|
|
200
|
+
1,
|
|
201
|
+
-1
|
|
202
|
+
],
|
|
203
|
+
[
|
|
204
|
+
1,
|
|
205
|
+
-1,
|
|
206
|
+
-1
|
|
207
|
+
]
|
|
208
|
+
]
|
|
209
|
+
}
|
|
210
|
+
];
|
|
211
|
+
/** Finite, integer, and within the packable key range on every axis.
|
|
212
|
+
* `Number.isInteger` subsumes the finiteness check (NaN/±Infinity are not
|
|
213
|
+
* integers) and rejects fractional coordinates, which the packed-key algebra
|
|
214
|
+
* cannot key safely (neighbour ±1 and half-lattice `2·coord ± 1` keys only
|
|
215
|
+
* coincide for integer cells). */
|
|
216
|
+
function isPackableCell(cell) {
|
|
217
|
+
for (let i = 0; i < 3; i++) {
|
|
218
|
+
const c = cell[i];
|
|
219
|
+
if (!Number.isInteger(c) || Math.abs(c) > 32767) return false;
|
|
220
|
+
}
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
/** True iff all three components are finite. A non-finite measured centroid
|
|
224
|
+
* from `getCellPoint` (an upstream tracking/accumulation glitch) must degrade
|
|
225
|
+
* to the geometric fallback exactly like a `null` one — otherwise it poisons
|
|
226
|
+
* every welded vertex / shared corner that averages it, and it also breaks
|
|
227
|
+
* `runMeshRequest`'s byte-identical parity with a direct mesh (the worker wire
|
|
228
|
+
* protocol packs "no centroid" as NaN, so NaN already falls back off-thread). */
|
|
229
|
+
function isFiniteVector3(v) {
|
|
230
|
+
return Number.isFinite(v[0]) && Number.isFinite(v[1]) && Number.isFinite(v[2]);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Mesh a snapshot of occupied cells into a face-culled surface + AABB list.
|
|
234
|
+
*
|
|
235
|
+
* Only faces whose neighbour cell is **not** in the occupied set are emitted
|
|
236
|
+
* (interior faces are dropped), so the triangle count scales with the surface
|
|
237
|
+
* area of the occupied set. Duplicate cells in `cells` are de-duplicated;
|
|
238
|
+
* cells with a non-finite or non-integer coordinate are skipped defensively (a
|
|
239
|
+
* tracking glitch upstream must not poison the mesh, and the packed cell keys
|
|
240
|
+
* are only collision-safe for integer coordinates).
|
|
241
|
+
*
|
|
242
|
+
* @param cells occupied cells (e.g. `grid.getOccupiedCells(minConfidence)`).
|
|
243
|
+
* @param cellSizeM cube edge length in metres (must be a positive finite number).
|
|
244
|
+
* @returns positions/indices (raw-WebXR metres) + one AABB per unique cell.
|
|
245
|
+
*/
|
|
246
|
+
function meshOccupiedCells(cells, cellSizeM, options) {
|
|
247
|
+
if (!Number.isFinite(cellSizeM) || cellSizeM <= 0) throw new RangeError(`cellSizeM must be a positive number, got ${cellSizeM}`);
|
|
248
|
+
const half = cellSizeM / 2;
|
|
249
|
+
const occupied = /* @__PURE__ */ new Set();
|
|
250
|
+
const uniqueCells = [];
|
|
251
|
+
for (const cell of cells) {
|
|
252
|
+
if (!isPackableCell(cell)) continue;
|
|
253
|
+
const key = packCellKey(cell[0], cell[1], cell[2]);
|
|
254
|
+
if (occupied.has(key)) continue;
|
|
255
|
+
occupied.add(key);
|
|
256
|
+
uniqueCells.push(cell);
|
|
257
|
+
}
|
|
258
|
+
const sharedHalfExtents = Object.freeze([
|
|
259
|
+
half,
|
|
260
|
+
half,
|
|
261
|
+
half
|
|
262
|
+
]);
|
|
263
|
+
const aabbs = uniqueCells.map(([x, y, z]) => ({
|
|
264
|
+
center: [
|
|
265
|
+
x * cellSizeM,
|
|
266
|
+
y * cellSizeM,
|
|
267
|
+
z * cellSizeM
|
|
268
|
+
],
|
|
269
|
+
halfExtents: sharedHalfExtents
|
|
270
|
+
}));
|
|
271
|
+
const positions = [];
|
|
272
|
+
const indices = [];
|
|
273
|
+
const mode = resolveMode(options);
|
|
274
|
+
if (mode === "greedy") buildGreedy(occupied, uniqueCells, cellSizeM, positions, indices);
|
|
275
|
+
else if (mode === "smooth") buildSmooth(occupied, uniqueCells, cellSizeM, options?.getCellPoint, positions, indices);
|
|
276
|
+
else if (mode === "corner-fit") buildCornerFit(occupied, uniqueCells, cellSizeM, options?.getCellPoint, positions, indices);
|
|
277
|
+
else buildCulled(occupied, uniqueCells, cellSizeM, positions, indices);
|
|
278
|
+
return {
|
|
279
|
+
positions: new Float32Array(positions),
|
|
280
|
+
indices: new Uint32Array(indices),
|
|
281
|
+
aabbs
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
/** Push a quad (4 corners, already ordered) as two triangles. */
|
|
285
|
+
/** Per-face culling: emit each exposed unit face as its own quad. */
|
|
286
|
+
function buildCulled(occupied, uniqueCells, cellSizeM, positions, indices) {
|
|
287
|
+
const half = cellSizeM / 2;
|
|
288
|
+
for (const [x, y, z] of uniqueCells) {
|
|
289
|
+
const cx = x * cellSizeM;
|
|
290
|
+
const cy = y * cellSizeM;
|
|
291
|
+
const cz = z * cellSizeM;
|
|
292
|
+
for (const face of FACES) {
|
|
293
|
+
const nx = x + face.neighbour[0];
|
|
294
|
+
const ny = y + face.neighbour[1];
|
|
295
|
+
const nz = z + face.neighbour[2];
|
|
296
|
+
if (occupied.has(packCellKey(nx, ny, nz))) continue;
|
|
297
|
+
const base = positions.length / 3;
|
|
298
|
+
const corners = face.corners;
|
|
299
|
+
for (let i = 0; i < 4; i++) {
|
|
300
|
+
const c = corners[i];
|
|
301
|
+
positions.push(cx + c[0] * half, cy + c[1] * half, cz + c[2] * half);
|
|
302
|
+
}
|
|
303
|
+
indices.push(base, base + 1, base + 2, base, base + 2, base + 3);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* 'smooth' mode — **standard Naive Surface Nets (dual contouring)** over the
|
|
309
|
+
* occupancy field, consuming the per-cell measured centroids the cube meshers
|
|
310
|
+
* discard.
|
|
311
|
+
*
|
|
312
|
+
* Treats occupancy as a binary field sampled at integer cell coordinates and
|
|
313
|
+
* contours the occupied/empty boundary:
|
|
314
|
+
* - **Vertices** — one welded vertex per "dual cell" (a unit cube whose 8
|
|
315
|
+
* corners are the cells `b … b+1`) that **straddles** the boundary (≥1
|
|
316
|
+
* occupied AND ≥1 empty corner), placed at the **mean of its occupied
|
|
317
|
+
* corners' `getCellPoint()`** (the measured surface points; the corners'
|
|
318
|
+
* geometric centres without a provider). Welding by dual-cell key makes the
|
|
319
|
+
* surface crack-free.
|
|
320
|
+
* - **Quads** — one per occupied↔empty **crossing**: for every occupied-cell
|
|
321
|
+
* face whose neighbour is empty (the SAME set the cube mesher emits), a quad
|
|
322
|
+
* joins the 4 dual cells sharing that edge, wound to face the empty side.
|
|
323
|
+
*
|
|
324
|
+
* Because there is one quad per crossing, **coverage matches the cubes** — unlike
|
|
325
|
+
* the previous 2×2-fully-occupied-patch heuristic, which only meshed flat solid
|
|
326
|
+
* blocks and so missed 80–90 % of a real, ragged depth surface (the reported
|
|
327
|
+
* "barely any surfaces" bug; 2026-06-30 rewrite). The result is smooth (welded
|
|
328
|
+
* vertices pulled onto the measured surface) and watertight for closed regions;
|
|
329
|
+
* over a thin feature (a one-cell floor) the top and bottom dual vertices average
|
|
330
|
+
* the same cells and coincide, so it reads as a single smooth sheet — the
|
|
331
|
+
* smoothest of the modes. Exception: a dual cell with exactly ONE occupied
|
|
332
|
+
* corner is nudged toward its dual-cell centre ({@link SINGLE_CORNER_NUDGE_K}),
|
|
333
|
+
* so features thin in ≥2 dimensions (isolated voxels, line/pillar ends) keep a
|
|
334
|
+
* non-zero area instead of collapsing onto a single point; on a thin floor this
|
|
335
|
+
* puffs only the perimeter-corner vertices by ±0.25·cell.
|
|
336
|
+
*/
|
|
337
|
+
/**
|
|
338
|
+
* 'smooth' single-occupied-corner fallback strength: a dual cell with exactly
|
|
339
|
+
* one occupied corner places its vertex ON that corner's cell point, so every
|
|
340
|
+
* dual cell around a feature thin in ≥2 dimensions (an isolated voxel, the end
|
|
341
|
+
* of a 1-cell line/pillar) coincided with its neighbours → all-degenerate
|
|
342
|
+
* (zero-area) triangles → thin features were invisible to the occluder despite
|
|
343
|
+
* a full per-face triangle count. Nudging the `n === 1` vertex toward the
|
|
344
|
+
* dual-cell centre by this fraction of the corner→centre distance (0.5 ⇒
|
|
345
|
+
* ±0.25·cell per axis) keeps it a pure function of the dual cell, so welding /
|
|
346
|
+
* watertightness and the measured-offset invariant are preserved. Trade-off
|
|
347
|
+
* (accepted 2026-07-02): the `n === 1` perimeter corners of a thin floor (and
|
|
348
|
+
* of a solid box) puff by ±0.25·cell — imperceptible for AR occlusion. Known
|
|
349
|
+
* residual: the `n === 2` shaft rings of a long 1×1×N feature still collapse
|
|
350
|
+
* (locally indistinguishable from a thin floor's intentionally-flat edges).
|
|
351
|
+
* 0.25 was rejected as too close to imperceptibly-non-zero; 1.0 discards the
|
|
352
|
+
* measured centroid exactly where data is sparsest. See
|
|
353
|
+
* 2026-07-01-followup-smooth-mesher-single-corner-degeneracy.md.
|
|
354
|
+
*/
|
|
355
|
+
const SINGLE_CORNER_NUDGE_K = .5;
|
|
356
|
+
function buildSmooth(occupied, uniqueCells, cellSizeM, getCellPoint, positions, indices) {
|
|
357
|
+
const pointCache = /* @__PURE__ */ new Map();
|
|
358
|
+
const scratch = [
|
|
359
|
+
0,
|
|
360
|
+
0,
|
|
361
|
+
0
|
|
362
|
+
];
|
|
363
|
+
const cellPoint = (ckey, x, y, z) => {
|
|
364
|
+
const hit = pointCache.get(ckey);
|
|
365
|
+
if (hit !== void 0) return hit;
|
|
366
|
+
let p = [
|
|
367
|
+
x * cellSizeM,
|
|
368
|
+
y * cellSizeM,
|
|
369
|
+
z * cellSizeM
|
|
370
|
+
];
|
|
371
|
+
if (getCellPoint) {
|
|
372
|
+
scratch[0] = x;
|
|
373
|
+
scratch[1] = y;
|
|
374
|
+
scratch[2] = z;
|
|
375
|
+
const cp = getCellPoint(scratch);
|
|
376
|
+
if (cp && isFiniteVector3(cp)) p = [
|
|
377
|
+
cp[0],
|
|
378
|
+
cp[1],
|
|
379
|
+
cp[2]
|
|
380
|
+
];
|
|
381
|
+
}
|
|
382
|
+
pointCache.set(ckey, p);
|
|
383
|
+
return p;
|
|
384
|
+
};
|
|
385
|
+
const vertexIndex = /* @__PURE__ */ new Map();
|
|
386
|
+
const dualVertex = (bx, by, bz) => {
|
|
387
|
+
const dkey = packCellKey(bx, by, bz);
|
|
388
|
+
const existing = vertexIndex.get(dkey);
|
|
389
|
+
if (existing !== void 0) return existing;
|
|
390
|
+
let sx = 0;
|
|
391
|
+
let sy = 0;
|
|
392
|
+
let sz = 0;
|
|
393
|
+
let n = 0;
|
|
394
|
+
let odx = 0;
|
|
395
|
+
let ody = 0;
|
|
396
|
+
let odz = 0;
|
|
397
|
+
for (let dx = 0; dx <= 1; dx++) for (let dy = 0; dy <= 1; dy++) for (let dz = 0; dz <= 1; dz++) {
|
|
398
|
+
const cx = bx + dx;
|
|
399
|
+
const cy = by + dy;
|
|
400
|
+
const cz = bz + dz;
|
|
401
|
+
const ckey = packCellKey(cx, cy, cz);
|
|
402
|
+
if (!occupied.has(ckey)) continue;
|
|
403
|
+
const p = cellPoint(ckey, cx, cy, cz);
|
|
404
|
+
sx += p[0];
|
|
405
|
+
sy += p[1];
|
|
406
|
+
sz += p[2];
|
|
407
|
+
n += 1;
|
|
408
|
+
odx = dx;
|
|
409
|
+
ody = dy;
|
|
410
|
+
odz = dz;
|
|
411
|
+
}
|
|
412
|
+
let px = sx / n;
|
|
413
|
+
let py = sy / n;
|
|
414
|
+
let pz = sz / n;
|
|
415
|
+
if (n === 1) {
|
|
416
|
+
const nudge = cellSizeM * SINGLE_CORNER_NUDGE_K;
|
|
417
|
+
px += (.5 - odx) * nudge;
|
|
418
|
+
py += (.5 - ody) * nudge;
|
|
419
|
+
pz += (.5 - odz) * nudge;
|
|
420
|
+
}
|
|
421
|
+
const idx = positions.length / 3;
|
|
422
|
+
positions.push(px, py, pz);
|
|
423
|
+
vertexIndex.set(dkey, idx);
|
|
424
|
+
return idx;
|
|
425
|
+
};
|
|
426
|
+
const dualBase = [
|
|
427
|
+
0,
|
|
428
|
+
0,
|
|
429
|
+
0
|
|
430
|
+
];
|
|
431
|
+
const c = [
|
|
432
|
+
0,
|
|
433
|
+
0,
|
|
434
|
+
0
|
|
435
|
+
];
|
|
436
|
+
for (const cell of uniqueCells) {
|
|
437
|
+
c[0] = cell[0];
|
|
438
|
+
c[1] = cell[1];
|
|
439
|
+
c[2] = cell[2];
|
|
440
|
+
for (const { d, u, v } of GREEDY_DIRS) for (let sgn = 1; sgn >= -1; sgn -= 2) {
|
|
441
|
+
dualBase[d] = c[d] + sgn;
|
|
442
|
+
dualBase[u] = c[u];
|
|
443
|
+
dualBase[v] = c[v];
|
|
444
|
+
if (occupied.has(packCellKey(dualBase[0], dualBase[1], dualBase[2]))) continue;
|
|
445
|
+
const baseD = sgn > 0 ? c[d] : c[d] - 1;
|
|
446
|
+
const bu0 = c[u] - 1;
|
|
447
|
+
const bv0 = c[v] - 1;
|
|
448
|
+
dualBase[d] = baseD;
|
|
449
|
+
dualBase[u] = bu0;
|
|
450
|
+
dualBase[v] = bv0;
|
|
451
|
+
const iA = dualVertex(dualBase[0], dualBase[1], dualBase[2]);
|
|
452
|
+
dualBase[u] = bu0 + 1;
|
|
453
|
+
const iB = dualVertex(dualBase[0], dualBase[1], dualBase[2]);
|
|
454
|
+
dualBase[v] = bv0 + 1;
|
|
455
|
+
const iC = dualVertex(dualBase[0], dualBase[1], dualBase[2]);
|
|
456
|
+
dualBase[u] = bu0;
|
|
457
|
+
const iD = dualVertex(dualBase[0], dualBase[1], dualBase[2]);
|
|
458
|
+
if (sgn > 0) indices.push(iA, iB, iC, iA, iC, iD);
|
|
459
|
+
else indices.push(iA, iD, iC, iA, iC, iB);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* 'corner-fit' mode — the per-face cube mesher with **displaced shared corners**.
|
|
465
|
+
*
|
|
466
|
+
* Keeps {@link buildCulled}'s exact face topology (same exposed faces), but each
|
|
467
|
+
* lattice corner — identified by its integer half-lattice key `(2x±1, 2y±1,
|
|
468
|
+
* 2z±1)` so every cell sharing it produces the SAME key — is **nudged by the mean
|
|
469
|
+
* sub-cell offset** (`getCellPoint() − cellCentre`) of the occupied cells
|
|
470
|
+
* touching it. Vertices are welded by corner key, so adjacent faces reference the
|
|
471
|
+
* identical displaced position: seams stay coincident ⇒ the surface deforms to
|
|
472
|
+
* hug the measured points yet stays **watertight** (the even-edge-cover invariant
|
|
473
|
+
* `'smooth'` gives up). Without a `getCellPoint` provider every corner falls back
|
|
474
|
+
* to the geometric corner `key · cellSize/2`, i.e. plain cubes.
|
|
475
|
+
*
|
|
476
|
+
* Why the **offset**, not the absolute centroid mean (2026-06-30 fix): moving a
|
|
477
|
+
* corner onto the absolute mean collapsed thin features — a one-cell-thick floor's
|
|
478
|
+
* top and bottom corners average the SAME cells, so they coincided into a flat
|
|
479
|
+
* sheet visually indistinguishable from `'smooth'`. Adding the offset to each
|
|
480
|
+
* corner's OWN geometric position keeps the cube's thickness, so `'corner-fit'`
|
|
481
|
+
* stays a distinct, cube-like, watertight option.
|
|
482
|
+
*
|
|
483
|
+
* Tradeoffs vs `'smooth'`: watertight and exact-cube topology, but corners are
|
|
484
|
+
* 8-way averages (so geometry only *approaches* the measured points, never lands
|
|
485
|
+
* on them) and the per-face O(surface-area) triangle cost is unchanged. Greedy
|
|
486
|
+
* merging does not apply (displaced corners are non-coplanar).
|
|
487
|
+
*/
|
|
488
|
+
function buildCornerFit(occupied, uniqueCells, cellSizeM, getCellPoint, positions, indices) {
|
|
489
|
+
const half = cellSizeM / 2;
|
|
490
|
+
const cornerSum = /* @__PURE__ */ new Map();
|
|
491
|
+
const addCornerOffset = (key, ox, oy, oz) => {
|
|
492
|
+
let acc = cornerSum.get(key);
|
|
493
|
+
if (!acc) {
|
|
494
|
+
acc = {
|
|
495
|
+
x: 0,
|
|
496
|
+
y: 0,
|
|
497
|
+
z: 0,
|
|
498
|
+
n: 0
|
|
499
|
+
};
|
|
500
|
+
cornerSum.set(key, acc);
|
|
501
|
+
}
|
|
502
|
+
acc.x += ox;
|
|
503
|
+
acc.y += oy;
|
|
504
|
+
acc.z += oz;
|
|
505
|
+
acc.n += 1;
|
|
506
|
+
};
|
|
507
|
+
for (const cell of uniqueCells) {
|
|
508
|
+
const cp = getCellPoint ? getCellPoint(cell) : null;
|
|
509
|
+
if (!cp || !isFiniteVector3(cp)) continue;
|
|
510
|
+
const ox = cp[0] - cell[0] * cellSizeM;
|
|
511
|
+
const oy = cp[1] - cell[1] * cellSizeM;
|
|
512
|
+
const oz = cp[2] - cell[2] * cellSizeM;
|
|
513
|
+
for (let sx = -1; sx <= 1; sx += 2) for (let sy = -1; sy <= 1; sy += 2) for (let sz = -1; sz <= 1; sz += 2) addCornerOffset(packCellKey(2 * cell[0] + sx, 2 * cell[1] + sy, 2 * cell[2] + sz), ox, oy, oz);
|
|
514
|
+
}
|
|
515
|
+
const vertexIndex = /* @__PURE__ */ new Map();
|
|
516
|
+
const cornerVertex = (kx, ky, kz) => {
|
|
517
|
+
const key = packCellKey(kx, ky, kz);
|
|
518
|
+
const existing = vertexIndex.get(key);
|
|
519
|
+
if (existing !== void 0) return existing;
|
|
520
|
+
const acc = cornerSum.get(key);
|
|
521
|
+
const px = kx * half + (acc ? acc.x / acc.n : 0);
|
|
522
|
+
const py = ky * half + (acc ? acc.y / acc.n : 0);
|
|
523
|
+
const pz = kz * half + (acc ? acc.z / acc.n : 0);
|
|
524
|
+
const idx = positions.length / 3;
|
|
525
|
+
positions.push(px, py, pz);
|
|
526
|
+
vertexIndex.set(key, idx);
|
|
527
|
+
return idx;
|
|
528
|
+
};
|
|
529
|
+
for (const [x, y, z] of uniqueCells) for (const face of FACES) {
|
|
530
|
+
const nx = x + face.neighbour[0];
|
|
531
|
+
const ny = y + face.neighbour[1];
|
|
532
|
+
const nz = z + face.neighbour[2];
|
|
533
|
+
if (occupied.has(packCellKey(nx, ny, nz))) continue;
|
|
534
|
+
const corners = face.corners;
|
|
535
|
+
const x2 = 2 * x;
|
|
536
|
+
const y2 = 2 * y;
|
|
537
|
+
const z2 = 2 * z;
|
|
538
|
+
const c0 = corners[0];
|
|
539
|
+
const c1 = corners[1];
|
|
540
|
+
const c2 = corners[2];
|
|
541
|
+
const c3 = corners[3];
|
|
542
|
+
const v0 = cornerVertex(x2 + c0[0], y2 + c0[1], z2 + c0[2]);
|
|
543
|
+
const v1 = cornerVertex(x2 + c1[0], y2 + c1[1], z2 + c1[2]);
|
|
544
|
+
const v2 = cornerVertex(x2 + c2[0], y2 + c2[1], z2 + c2[2]);
|
|
545
|
+
const v3 = cornerVertex(x2 + c3[0], y2 + c3[1], z2 + c3[2]);
|
|
546
|
+
indices.push(v0, v1, v2, v0, v2, v3);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Greedy meshing: for each face-normal axis and side, sweep slices and merge
|
|
551
|
+
* adjacent coplanar exposed faces into maximal rectangles, emitting one quad
|
|
552
|
+
* per rectangle. The covered unit faces are identical to {@link buildCulled};
|
|
553
|
+
* only the triangle count drops.
|
|
554
|
+
*/
|
|
555
|
+
function buildGreedy(occupied, uniqueCells, cellSizeM, positions, indices) {
|
|
556
|
+
const half = cellSizeM / 2;
|
|
557
|
+
const neighbour = [
|
|
558
|
+
0,
|
|
559
|
+
0,
|
|
560
|
+
0
|
|
561
|
+
];
|
|
562
|
+
for (const { d, u, v } of GREEDY_DIRS) for (let sign = 1; sign >= -1; sign -= 2) {
|
|
563
|
+
const slices = /* @__PURE__ */ new Map();
|
|
564
|
+
for (const cell of uniqueCells) {
|
|
565
|
+
neighbour[0] = cell[0];
|
|
566
|
+
neighbour[1] = cell[1];
|
|
567
|
+
neighbour[2] = cell[2];
|
|
568
|
+
neighbour[d] += sign;
|
|
569
|
+
if (occupied.has(packCellKey(neighbour[0], neighbour[1], neighbour[2]))) continue;
|
|
570
|
+
const k = cell[d];
|
|
571
|
+
const iu = cell[u];
|
|
572
|
+
const iv = cell[v];
|
|
573
|
+
let slice = slices.get(k);
|
|
574
|
+
if (!slice) {
|
|
575
|
+
slice = /* @__PURE__ */ new Map();
|
|
576
|
+
slices.set(k, slice);
|
|
577
|
+
}
|
|
578
|
+
slice.set(packCellKey(iu, iv, 0), [iu, iv]);
|
|
579
|
+
}
|
|
580
|
+
for (const [k, slice] of [...slices.entries()].sort((a, b) => a[0] - b[0])) greedyMergeSlice(slice, half, cellSizeM, d, u, v, k, sign, positions, indices);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
/** Greedy-merge one slice's exposed (iu,iv) mask into maximal rectangles. */
|
|
584
|
+
function greedyMergeSlice(slice, half, cellSizeM, d, u, v, k, sign, positions, indices) {
|
|
585
|
+
const has = (iu, iv) => slice.has(packCellKey(iu, iv, 0));
|
|
586
|
+
const used = /* @__PURE__ */ new Set();
|
|
587
|
+
const isUsed = (iu, iv) => used.has(packCellKey(iu, iv, 0));
|
|
588
|
+
const p = [
|
|
589
|
+
0,
|
|
590
|
+
0,
|
|
591
|
+
0
|
|
592
|
+
];
|
|
593
|
+
const cells = [...slice.values()].sort((a, b) => a[1] !== b[1] ? a[1] - b[1] : a[0] - b[0]);
|
|
594
|
+
for (const [iu, iv] of cells) {
|
|
595
|
+
if (isUsed(iu, iv)) continue;
|
|
596
|
+
let w = 1;
|
|
597
|
+
while (has(iu + w, iv) && !isUsed(iu + w, iv)) w++;
|
|
598
|
+
let h = 1;
|
|
599
|
+
let canGrow = true;
|
|
600
|
+
while (canGrow) {
|
|
601
|
+
for (let du = 0; du < w; du++) {
|
|
602
|
+
if (has(iu + du, iv + h) && !isUsed(iu + du, iv + h)) continue;
|
|
603
|
+
canGrow = false;
|
|
604
|
+
break;
|
|
605
|
+
}
|
|
606
|
+
if (canGrow) h++;
|
|
607
|
+
}
|
|
608
|
+
for (let dv = 0; dv < h; dv++) for (let du = 0; du < w; du++) used.add(packCellKey(iu + du, iv + dv, 0));
|
|
609
|
+
const plane = k * cellSizeM + sign * half;
|
|
610
|
+
const uMin = iu * cellSizeM - half;
|
|
611
|
+
const uMax = (iu + w - 1) * cellSizeM + half;
|
|
612
|
+
const vMin = iv * cellSizeM - half;
|
|
613
|
+
const vMax = (iv + h - 1) * cellSizeM + half;
|
|
614
|
+
const base = positions.length / 3;
|
|
615
|
+
p[d] = plane;
|
|
616
|
+
p[u] = uMin;
|
|
617
|
+
p[v] = vMin;
|
|
618
|
+
positions.push(p[0], p[1], p[2]);
|
|
619
|
+
if (sign > 0) {
|
|
620
|
+
p[u] = uMax;
|
|
621
|
+
positions.push(p[0], p[1], p[2]);
|
|
622
|
+
p[v] = vMax;
|
|
623
|
+
positions.push(p[0], p[1], p[2]);
|
|
624
|
+
p[u] = uMin;
|
|
625
|
+
positions.push(p[0], p[1], p[2]);
|
|
626
|
+
} else {
|
|
627
|
+
p[v] = vMax;
|
|
628
|
+
positions.push(p[0], p[1], p[2]);
|
|
629
|
+
p[u] = uMax;
|
|
630
|
+
positions.push(p[0], p[1], p[2]);
|
|
631
|
+
p[v] = vMin;
|
|
632
|
+
positions.push(p[0], p[1], p[2]);
|
|
633
|
+
}
|
|
634
|
+
indices.push(base, base + 1, base + 2, base, base + 2, base + 3);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
//#endregion
|
|
638
|
+
export { meshOccupiedCells };
|
package/dist/ar/planar-pnp.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as homographyFromCorrespondences, c as rotationToRodrigues, i as PoseCandidate, l as solveLinear, n as Mat3, o as ippePoseCandidates, r as PlanarPnpSquare, s as nearestRotation3x3, t as Homography } from "../planar-pnp-
|
|
1
|
+
import { a as homographyFromCorrespondences, c as rotationToRodrigues, i as PoseCandidate, l as solveLinear, n as Mat3, o as ippePoseCandidates, r as PlanarPnpSquare, s as nearestRotation3x3, t as Homography } from "../planar-pnp-D7bc_rLX.js";
|
|
2
2
|
export { Homography, Mat3, PlanarPnpSquare, PoseCandidate, homographyFromCorrespondences, ippePoseCandidates, nearestRotation3x3, rotationToRodrigues, solveLinear };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as createQrDebugView, t as QrDebugView } from "../qr-debug-view-
|
|
1
|
+
import { n as createQrDebugView, t as QrDebugView } from "../qr-debug-view-BJooqbiP.js";
|
|
2
2
|
export { QrDebugView, createQrDebugView };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as createIncrementalQrPlacement, c as deriveSolvedQrPose, i as RawQrObservation, l as solveQrPoseFromObservation, n as DerivedQrPlacement, o as deriveQrPlacement, r as IncrementalQrPlacement, s as deriveQrSizeM, t as DeriveQrPoseDeps } from "../qr-derived-pose-
|
|
1
|
+
import { a as createIncrementalQrPlacement, c as deriveSolvedQrPose, i as RawQrObservation, l as solveQrPoseFromObservation, n as DerivedQrPlacement, o as deriveQrPlacement, r as IncrementalQrPlacement, s as deriveQrSizeM, t as DeriveQrPoseDeps } from "../qr-derived-pose-BwNWn8oV.js";
|
|
2
2
|
export { DeriveQrPoseDeps, DerivedQrPlacement, IncrementalQrPlacement, RawQrObservation, createIncrementalQrPlacement, deriveQrPlacement, deriveQrSizeM, deriveSolvedQrPose, solveQrPoseFromObservation };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as createQrDetectionController, i as RawObservationSink, n as QrDetectionControllerDeps, r as QrScanStatus, t as QrDetectionController } from "../qr-detection-controller-
|
|
1
|
+
import { a as createQrDetectionController, i as RawObservationSink, n as QrDetectionControllerDeps, r as QrScanStatus, t as QrDetectionController } from "../qr-detection-controller-Bo4XfQTP.js";
|
|
2
2
|
export { QrDetectionController, QrDetectionControllerDeps, QrScanStatus, RawObservationSink, createQrDetectionController };
|
package/dist/ar/qr-frontend.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as QrFrontEnd, c as createBarcodeDetectorFrontEnd, i as QrDetection, n as BarcodeDetectorLike, o as RgbaImage, r as DetectedBarcodeLike, s as ToImageBitmapSource, t as BarcodeDetectorFrontEnd } from "../qr-frontend
|
|
1
|
+
import { a as QrFrontEnd, c as createBarcodeDetectorFrontEnd, i as QrDetection, n as BarcodeDetectorLike, o as RgbaImage, r as DetectedBarcodeLike, s as ToImageBitmapSource, t as BarcodeDetectorFrontEnd } from "../qr-frontend-BPURlh3S.js";
|
|
2
2
|
export { BarcodeDetectorFrontEnd, BarcodeDetectorLike, DetectedBarcodeLike, QrDetection, QrFrontEnd, RgbaImage, ToImageBitmapSource, createBarcodeDetectorFrontEnd };
|
package/dist/ar/qr-pose.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as solveQrPose, a as QrPoseSolution, c as SolveQrPoseInput, d as intrinsicsFromProjection, f as invertPose, g as signedQuadArea, h as reprojectionErrorPx, i as Pose, l as buildObjectPoints, m as qrInCameraFromOpenCv, n as OpenCvPnpResult, o as QuadValidation, p as projectViewPoint, r as Point2, s as SolvePnpSquare, t as CameraIntrinsics, u as composePose, v as transformPoint, y as validateQuad } from "../qr-pose-
|
|
1
|
+
import { _ as solveQrPose, a as QrPoseSolution, c as SolveQrPoseInput, d as intrinsicsFromProjection, f as invertPose, g as signedQuadArea, h as reprojectionErrorPx, i as Pose, l as buildObjectPoints, m as qrInCameraFromOpenCv, n as OpenCvPnpResult, o as QuadValidation, p as projectViewPoint, r as Point2, s as SolvePnpSquare, t as CameraIntrinsics, u as composePose, v as transformPoint, y as validateQuad } from "../qr-pose-y3vaEd6x.js";
|
|
2
2
|
export { CameraIntrinsics, OpenCvPnpResult, Point2, Pose, QrPoseSolution, QuadValidation, SolvePnpSquare, SolveQrPoseInput, buildObjectPoints, composePose, intrinsicsFromProjection, invertPose, projectViewPoint, qrInCameraFromOpenCv, reprojectionErrorPx, signedQuadArea, solveQrPose, transformPoint, validateQuad };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as QrSizeDepthContext } from "../qr-size-measurer-
|
|
2
|
-
import { t as createQrSizeDepthContext } from "../qr-size-depth-context-
|
|
1
|
+
import { n as QrSizeDepthContext } from "../qr-size-measurer-DxiMqRUw.js";
|
|
2
|
+
import { t as createQrSizeDepthContext } from "../qr-size-depth-context-apAOmbrZ.js";
|
|
3
3
|
export { QrSizeDepthContext, createQrSizeDepthContext };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as QrSizeMeasurerOptions, i as QrSizeMeasurer, n as QrSizeDepthContext, o as createQrSizeMeasurer, r as QrSizeMeasurement, t as ImageSize } from "../qr-size-measurer-
|
|
1
|
+
import { a as QrSizeMeasurerOptions, i as QrSizeMeasurer, n as QrSizeDepthContext, o as createQrSizeMeasurer, r as QrSizeMeasurement, t as ImageSize } from "../qr-size-measurer-DxiMqRUw.js";
|
|
2
2
|
export { ImageSize, QrSizeDepthContext, QrSizeMeasurement, QrSizeMeasurer, QrSizeMeasurerOptions, createQrSizeMeasurer };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as getCameraFollower, c as getReplayState, d as updateOrbitTarget, i as getAlignmentLerper, l as initReplayScene, n as ReplaySceneState, o as getCameraMode, r as disposeReplayScene, s as getCss3dManager, t as CameraMode, u as toggleCameraMode } from "../replay-scene-
|
|
1
|
+
import { a as getCameraFollower, c as getReplayState, d as updateOrbitTarget, i as getAlignmentLerper, l as initReplayScene, n as ReplaySceneState, o as getCameraMode, r as disposeReplayScene, s as getCss3dManager, t as CameraMode, u as toggleCameraMode } from "../replay-scene-zJ8SFDjE.js";
|
|
2
2
|
export { CameraMode, ReplaySceneState, disposeReplayScene, getAlignmentLerper, getCameraFollower, getCameraMode, getCss3dManager, getReplayState, initReplayScene, toggleCameraMode, updateOrbitTarget };
|
package/dist/ar/replay-scene.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createLogger } from "../utils/logger.js";
|
|
2
|
-
import {
|
|
2
|
+
import { A as setArWorldGroup, L as setScene, j as setCamera, k as setArPose, s as createSceneHierarchy } from "../webxr-session-BCP2XK7k.js";
|
|
3
3
|
import { createCss3dRendererManager } from "../visualization/css3d-renderer-manager.js";
|
|
4
4
|
import { createCameraFollower } from "../visualization/camera-follower.js";
|
|
5
5
|
import { createAlignmentLerper } from "../visualization/alignment-lerper.js";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as SCENE_NODE } from "../scene-node-names-
|
|
1
|
+
import { t as SCENE_NODE } from "../scene-node-names-CGb-ylBd.js";
|
|
2
2
|
export { SCENE_NODE };
|