@navaramap/three 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +70 -0
  2. package/dist/assets/fontWorker-wz61edjR.js +2 -0
  3. package/dist/assets/fontWorker-wz61edjR.js.map +1 -0
  4. package/dist/assets/index-ywHSGImj.js +25 -0
  5. package/dist/assets/index-ywHSGImj.js.map +1 -0
  6. package/dist/assets/{navara_wasm_font_worker_bg-Bnck8OGf.wasm → navara_wasm_font_worker_bg-Du9nb2Pn.wasm} +0 -0
  7. package/dist/assets/{navara_wasm_worker_bg-DG9ORAmj.wasm → navara_wasm_worker_bg-Xadu67fw.wasm} +0 -0
  8. package/dist/draco_decoder.wasm +0 -0
  9. package/dist/draco_decoder2.wasm +0 -0
  10. package/dist/index.d.ts +578 -18
  11. package/dist/index.js +5298 -4843
  12. package/dist/index.js.map +1 -1
  13. package/dist/index.umd.cjs +266 -234
  14. package/dist/index.umd.cjs.map +1 -1
  15. package/package.json +34 -33
  16. package/src/atmosphere.ts +43 -1
  17. package/src/core/EffectDesc.ts +2 -4
  18. package/src/core/MeshDesc.ts +1 -2
  19. package/src/core/MeshDescWithSelectiveEffect.ts +1 -2
  20. package/src/declutter/DeclutterManager.test.ts +235 -0
  21. package/src/declutter/DeclutterManager.ts +256 -0
  22. package/src/declutter/index.ts +7 -0
  23. package/src/declutter/kernel.ts +46 -0
  24. package/src/declutter/types.ts +61 -0
  25. package/src/declutter/wasmKernel.ts +13 -0
  26. package/src/device.ts +18 -4
  27. package/src/evaluations/FeatureEvaluator.ts +21 -0
  28. package/src/event/context.ts +12 -0
  29. package/src/event/feature.ts +43 -13
  30. package/src/event/features/modelGpuBytes.ts +1 -3
  31. package/src/event/features/polygon.ts +2 -1
  32. package/src/event/hillshade.test.ts +7 -13
  33. package/src/event/index.ts +2 -3
  34. package/src/event/tileHandler.ts +54 -0
  35. package/src/index.ts +137 -35
  36. package/src/input.ts +48 -15
  37. package/src/material/enhancer/ShaderReplacer.ts +1 -2
  38. package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/mutates.test.ts +1 -0
  39. package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/mutates.ts +2 -0
  40. package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/types.ts +2 -0
  41. package/src/material/enhancer/polygon/polygonBaseEnhancer/mutates.ts +2 -0
  42. package/src/material/enhancer/polygon/polygonBaseEnhancer/shader.ts +5 -1
  43. package/src/material/enhancer/polygon/polygonBaseEnhancer/types.ts +2 -0
  44. package/src/material/enhancer/polyline/polylineBaseEnhancer/mutates.ts +2 -0
  45. package/src/material/enhancer/polyline/polylineBaseEnhancer/types.ts +2 -0
  46. package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/mutates.ts +8 -0
  47. package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/types.ts +13 -0
  48. package/src/material/enhancer/tileComposite/tileCompositeBaseEnhancer/mutates.test.ts +83 -0
  49. package/src/material/enhancer/tileComposite/tileCompositeBaseEnhancer/mutates.ts +13 -3
  50. package/src/material/overrideMaterialsForMRT.ts +7 -2
  51. package/src/mesh/batchTexture.ts +2 -4
  52. package/src/mesh/batchedSdfText.ts +294 -70
  53. package/src/mesh/instanced.ts +1 -1
  54. package/src/mesh/polygon.ts +11 -4
  55. package/src/mesh/polyline.ts +10 -2
  56. package/src/mesh/sdfText.ts +176 -6
  57. package/src/mesh/sprite/instancedSprite.ts +245 -3
  58. package/src/orchestrators/RenderPassOrchestrator.ts +25 -0
  59. package/src/passes/CustomRenderPass.ts +21 -5
  60. package/src/passes/RenderTargetCopyPass.ts +24 -2
  61. package/src/solar.test.ts +33 -0
  62. package/src/solar.ts +31 -0
  63. package/src/test-utils/engine.ts +53 -0
  64. package/src/tileTexture/TileTextureCompositor.test.ts +2 -0
  65. package/src/tileTexture/TileTextureCompositor.ts +7 -1
  66. package/src/utils/fixedGpuFootprint.test.ts +110 -0
  67. package/src/utils/fixedGpuFootprint.ts +162 -0
  68. package/src/worker/tasks/toCreasedNormals.ts +2 -7
  69. package/dist/assets/fontWorker-CCWL5pbx.js +0 -2
  70. package/dist/assets/fontWorker-CCWL5pbx.js.map +0 -1
  71. package/dist/assets/index-BdtHOOT9.js +0 -12
  72. package/dist/assets/index-BdtHOOT9.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -224,6 +224,40 @@ export declare class Atmosphere extends EventHandler<AtmosphereEvents> {
224
224
  * @returns `true` if the position is on the night side, `false` otherwise.
225
225
  */
226
226
  isAtNight(position: XYZ): boolean;
227
+ /**
228
+ * Returns the sun's elevation angle in degrees above the local horizon at
229
+ * `location` for the current {@link date}. Positive is above the horizon,
230
+ * negative below (night); includes atmospheric refraction.
231
+ *
232
+ * @example
233
+ * const elevation = view.atmosphere.getSunElevation(view.camera.positionGeographic);
234
+ * if (elevation < 0) console.log("The sun has set.");
235
+ */
236
+ getSunElevation(location: {
237
+ lat: number;
238
+ lng: number;
239
+ }): number;
240
+ /**
241
+ * Returns the local apparent solar time at `lng` for the current
242
+ * {@link date}, in hours in the range [0, 24) where 12 is solar noon.
243
+ * Accounts for the equation of time.
244
+ *
245
+ * @example
246
+ * const hours = view.atmosphere.getSolarTime({ lng: 139.69 }); // e.g. 6.3 = 06:18
247
+ */
248
+ getSolarTime(location: {
249
+ lng: number;
250
+ }): number;
251
+ /**
252
+ * Sets {@link date} so the local apparent solar time at `lng` equals `hours`
253
+ * (0–24), keeping the same solar day. Inverse of {@link getSolarTime}.
254
+ *
255
+ * @example
256
+ * view.atmosphere.setSolarTime({ lng: 139.69 }, 6.3); // sunrise over Tokyo
257
+ */
258
+ setSolarTime(location: {
259
+ lng: number;
260
+ }, hours: number): void;
227
261
  /**
228
262
  * Gets the current date used for calculating sun/moon positions.
229
263
  */
@@ -863,7 +897,7 @@ export declare class BatchedFeatureMesh<Buf extends BufferGeometry<BatchedFeatur
863
897
  clone(): this;
864
898
  }
865
899
 
866
- export declare class BatchedSdfTextMesh extends InstancedMesh<SDFTextMesh> implements PickableMesh {
900
+ export declare class BatchedSdfTextMesh extends InstancedMesh<SDFTextMesh> implements PickableMesh, DeclutterParticipant {
867
901
  readonly ctx: EventContext;
868
902
  /** The font identifier from material — may be a family name or a URL. */
869
903
  private _fontIdentifier;
@@ -881,7 +915,23 @@ export declare class BatchedSdfTextMesh extends InstancedMesh<SDFTextMesh> imple
881
915
  * and must be balanced with unloadFont() on dispose or font change.
882
916
  */
883
917
  private _loadedFaceUrls;
918
+ /** Geometry-extracted anchor data; per-index meshes slice it lazily. */
919
+ private _positions;
920
+ /** Sparse batchIndex → mesh; `allMeshes` holds only created meshes. */
921
+ private _meshByIndex;
922
+ /** Evaluator state received before a feature's mesh exists. */
923
+ private _pending;
924
+ /** Material/transform used when creating meshes lazily. */
925
+ private _material;
926
+ private _transform;
884
927
  constructor(ctx: EventContext, m: TextMesh, fontIdentifier: string, options: InstancedMeshOptions, loadedFaceUrls?: Set<string>);
928
+ collectDeclutterCandidates(out: DeclutterCandidate[]): void;
929
+ applyDeclutter(handle: number, hidden: boolean): void;
930
+ stepDeclutterFade(deltaMs: number): boolean;
931
+ /** Candidates changed (text, style, position, visibility): ask the shared
932
+ * declutter pass to re-place on its next update. */
933
+ private _markDeclutterDirty;
934
+ setActive(active: boolean): void;
885
935
  /**
886
936
  * After an atlas eviction, re-prepare and force-rebuild any visible mesh whose
887
937
  * shaped text is now stale (its pinned glyphs may have been evicted before the
@@ -891,17 +941,48 @@ export declare class BatchedSdfTextMesh extends InstancedMesh<SDFTextMesh> imple
891
941
  private _revalidateStaleMeshes;
892
942
  get fontIdentifier(): string;
893
943
  get highQuality(): boolean;
944
+ /**
945
+ * A mesh per anchor is expensive (geometry + ShaderMaterial + enhancer
946
+ * mount), and with per-feature texts (MVT) most features never receive a
947
+ * non-empty text — they'd sit invisible while still costing construction and
948
+ * every per-frame loop. So meshes are created lazily by `_ensureMeshAt` on
949
+ * the first non-empty `setTextByBatchIndex`. Only a non-empty material-level
950
+ * default text (single-label sources) renders without the evaluator ever
951
+ * setting text, so only that case creates all meshes eagerly.
952
+ */
894
953
  private initMeshes;
954
+ /** The font-level shared atlas textures for this batch's font+quality (the
955
+ * color atlas is `null` for monochrome fonts). */
956
+ private _sharedTextures;
957
+ /**
958
+ * The feature's mesh, created on first need (see `initMeshes`). `shared`
959
+ * lets a batch creation pass hoist the atlas lookups; when omitted (a single
960
+ * lazy creation) they are fetched here, since the atlas may have been
961
+ * (re)allocated since this batch was constructed.
962
+ */
963
+ private _ensureMeshAt;
964
+ /** Pending-state slot for a feature whose mesh doesn't exist yet. */
965
+ private _pendingAt;
895
966
  _update(m: TextMesh, needRender?: () => void): Promise<void>;
896
967
  private _applyUpdate;
897
968
  onBeforePicking(): void;
898
969
  onAfterPicking(): void;
899
970
  private extractPositions;
900
971
  setTextByBatchIndex(batchIndex: number, text: string): void;
972
+ /**
973
+ * The mesh for a feature's `batchIndex`, or `undefined` if not created yet.
974
+ * Meshes are created lazily and pushed onto `allMeshes` in creation order, so
975
+ * `allMeshes[batchIndex]` (the base-class mapping) does NOT hold here; the
976
+ * batchIndex→mesh mapping lives in `_meshByIndex`. Overriding this one
977
+ * accessor keeps the base-class setters and any external caller (picking,
978
+ * plugins) correct without patching each call site.
979
+ */
980
+ getMeshByBatchIndex(batchIndex: number): SDFTextMesh | undefined;
901
981
  setFeatureColorByBatchIndex(batchIndex: number, color: Color_3): void;
902
982
  setFeatureShowByBatchIndex(batchIndex: number, rawVisible: boolean): void;
903
983
  setFeatureHeightByBatchIndex(batchIndex: number, height: number): void;
904
984
  setFeatureSizeByBatchIndex(batchIndex: number, size: number): void;
985
+ setFeatureDeclutterPriorityByBatchIndex(batchIndex: number, priority: number): void;
905
986
  setFeatureOpacityByBatchIndex(batchIndex: number, opacity: number): void;
906
987
  dispose(): void;
907
988
  }
@@ -951,6 +1032,28 @@ declare class BillboardMaterial {
951
1032
  set clampToGround(value: boolean | null | undefined);
952
1033
  get color(): number | undefined;
953
1034
  set color(value: number | null | undefined);
1035
+ /**
1036
+ * Placement priority for decluttering; higher wins. Only meaningful when
1037
+ * `declutter` is enabled. Defaults to `0.0`.
1038
+ */
1039
+ get declutterPriority(): number | undefined;
1040
+ /**
1041
+ * Placement priority for decluttering; higher wins. Only meaningful when
1042
+ * `declutter` is enabled. Defaults to `0.0`.
1043
+ */
1044
+ set declutterPriority(value: number | null | undefined);
1045
+ /**
1046
+ * Participate in screen-space decluttering: when labels/sprites overlap
1047
+ * on screen, lower-priority ones are hidden. Defaults to `true`; set to
1048
+ * `false` to draw every label unconditionally.
1049
+ */
1050
+ get declutter(): boolean | undefined;
1051
+ /**
1052
+ * Participate in screen-space decluttering: when labels/sprites overlap
1053
+ * on screen, lower-priority ones are hidden. Defaults to `true`; set to
1054
+ * `false` to draw every label unconditionally.
1055
+ */
1056
+ set declutter(value: boolean | null | undefined);
954
1057
  get depthTest(): boolean | undefined;
955
1058
  set depthTest(value: boolean | null | undefined);
956
1059
  /**
@@ -1868,6 +1971,13 @@ declare class Core {
1868
1971
  */
1869
1972
  setDynamicSse(settings: DynamicSse): void;
1870
1973
  setExternalBuffer(handle: number, bits: bigint, byte_length: number): void;
1974
+ /**
1975
+ * Reports the estimated GPU bytes of fixed, screen-sized allocations
1976
+ * (the postprocessing render-target stack). Counted in the ledger's
1977
+ * usage so the tile budget binds against the remaining memory. The JS
1978
+ * side re-reports on init, resize, and pass-list changes.
1979
+ */
1980
+ setFixedGpuBytes(bytes: number): void;
1871
1981
  setFrustum(fov?: number | null, near?: number | null, far?: number | null): void;
1872
1982
  setGlobeColor(value: number): void;
1873
1983
  setGlobeElevationColormap(value: Float32Array): void;
@@ -2175,7 +2285,7 @@ export declare class CustomRenderPass extends RenderPass {
2175
2285
  constructor(scenes: Scenes, camera: PerspectiveCamera, inputBuffer: WebGLRenderTarget, globe: Globe, options?: CustomRenderPassOptions);
2176
2286
  protected _renderWithLight(renderer: WebGLRenderer, scene: Scene): void;
2177
2287
  render(renderer: WebGLRenderer, inputBuffer: WebGLRenderTarget | null, _outputBuffer: WebGLRenderTarget | null): void;
2178
- setDepthTexture(depthTexture: DepthTexture): void;
2288
+ setDepthTexture(): void;
2179
2289
  setSize(width: number, height: number): void;
2180
2290
  protected _renderDrapedMesh(renderer: WebGLRenderer): void;
2181
2291
  }
@@ -2245,6 +2355,179 @@ declare class DataRequestEvent {
2245
2355
  url: string;
2246
2356
  }
2247
2357
 
2358
+ /**
2359
+ * One label/sprite competing for screen space in a declutter pass.
2360
+ *
2361
+ * The local box is expressed around the projected anchor in the shader's
2362
+ * billboard-local units — CSS pixels when `sizeInMeters` is false, meters
2363
+ * otherwise — with +X right and +Y up (view-space convention). The manager
2364
+ * converts it to a screen-pixel AABB using the same `nvr_pxToWorld` math the
2365
+ * vertex shaders use, so the collision box matches what is actually drawn.
2366
+ */
2367
+ declare type DeclutterCandidate = {
2368
+ /** World-space anchor in ECEF meters (f64), before the height offset. */
2369
+ anchorX: number;
2370
+ anchorY: number;
2371
+ anchorZ: number;
2372
+ /** Extra offset in meters along the spherical surface normal — CPU mirror
2373
+ * of `mvr_getMvHeightOffset` (sprite_height_pars_vertex.glsl). */
2374
+ addHeight: number;
2375
+ /** Local box around the anchor (px or meters, see `sizeInMeters`). */
2376
+ minX: number;
2377
+ maxX: number;
2378
+ minY: number;
2379
+ maxY: number;
2380
+ /** Unit of the local box, mirroring the material's `sizeInMeters`. */
2381
+ sizeInMeters: boolean;
2382
+ /** Placement priority: higher wins an overlap. */
2383
+ priority: number;
2384
+ /** Whether the label is currently shown (its fade target is "visible").
2385
+ * Feeds placement hysteresis: shown labels win equal-priority ties and
2386
+ * tolerate marginal overlaps, so slow camera drift doesn't make near-tied
2387
+ * labels flicker in and out. */
2388
+ isShown: boolean;
2389
+ /** Participant that owns this candidate; receives the placement result. */
2390
+ owner: DeclutterParticipant;
2391
+ /** Participant-defined id (mesh index for text batches, instance index for
2392
+ * sprites) passed back to `applyDeclutter`. */
2393
+ handle: number;
2394
+ };
2395
+
2396
+ /**
2397
+ * The pure numeric placement kernel used by {@link DeclutterManager}.
2398
+ *
2399
+ * Given a flat list of candidates and the camera, it projects each anchor to a
2400
+ * screen-pixel box, sorts by priority (with placement hysteresis), and greedily
2401
+ * claims space in a uniform screen-space grid — returning one `hidden` flag
2402
+ * (`0` = shown, `1` = hidden) per candidate, in input order.
2403
+ *
2404
+ * The production implementation is the Rust `declutterPlace` in
2405
+ * `navara_wasm_api` (see {@link wasmDeclutterKernel}); the projection, collision
2406
+ * grid, and greedy placement all live there. Injecting it keeps the manager free
2407
+ * of an import-time WASM dependency, so its orchestration is unit-tested with a
2408
+ * stub. Placement correctness itself is covered by the crate's Rust tests.
2409
+ */
2410
+ declare type DeclutterKernel = {
2411
+ /**
2412
+ * @param candidates Packed `f64` data, {@link CANDIDATE_STRIDE} values per
2413
+ * candidate; pass a subarray of exactly `n * CANDIDATE_STRIDE`.
2414
+ * @param view Column-major view matrix (inverse of `camera.matrixWorld`), 16.
2415
+ * @param proj Column-major projection matrix, 16.
2416
+ * @returns One `hidden` flag (`0`/`1`) per candidate, in input order.
2417
+ */
2418
+ place(candidates: Float64Array, view: Float64Array, proj: Float64Array, cameraX: number, cameraY: number, cameraZ: number, near: number, widthPx: number, heightPx: number, fovRad: number, paddingPx: number, hysteresisPx: number): Uint8Array;
2419
+ };
2420
+
2421
+ /**
2422
+ * Shared screen-space label decluttering.
2423
+ *
2424
+ * Text batches and sprite meshes register as participants; each placement
2425
+ * pass packs every candidate label into a flat buffer and hands it to the
2426
+ * Rust {@link DeclutterKernel}, which projects the anchors, sorts by priority,
2427
+ * and greedily claims screen space — losers are hidden through the meshes'
2428
+ * declutter channels (`uDeclutterHide` uniform / `instanceDeclutterHide`
2429
+ * attribute), which are separate from user-driven `show` state and free to
2430
+ * toggle every pass.
2431
+ *
2432
+ * Placement is hysteretic: currently-shown labels win equal-priority ties
2433
+ * and tolerate {@link DeclutterManager.HYSTERESIS_PX} of marginal overlap
2434
+ * before eviction, so near-ties don't flicker while the camera drifts.
2435
+ *
2436
+ * The pass is view-dependent, so it runs from the render loop — but throttled:
2437
+ * placement only re-runs when the camera or the label set actually changed,
2438
+ * and at most once per {@link DeclutterManager.MIN_INTERVAL_MS}. Callers run
2439
+ * it *before* rendering so results land in the same frame.
2440
+ */
2441
+ declare class DeclutterManager {
2442
+ private readonly _kernel;
2443
+ /** Minimum time between placement passes (ms). */
2444
+ static readonly MIN_INTERVAL_MS = 150;
2445
+ /** Padding added around every collision box (px); two labels never sit
2446
+ * closer than twice this. */
2447
+ static readonly PADDING_PX = 2;
2448
+ /** Largest single fade step (ms), so a frame after an idle gap doesn't
2449
+ * swallow most of a fade in one jump. */
2450
+ static readonly MAX_FADE_STEP_MS = 50;
2451
+ /** Placement hysteresis (px): a currently-shown label's collision test box
2452
+ * shrinks by this per side, so it survives marginal overlaps that camera
2453
+ * drift toggles frame to frame instead of flickering. Its full box is
2454
+ * still claimed against competitors. */
2455
+ static readonly HYSTERESIS_PX = 6;
2456
+ private _participants;
2457
+ /** Set when the label set changed (register/update/text change) so the next
2458
+ * update re-places even with a static camera. */
2459
+ private _dirty;
2460
+ private _prevCamera;
2461
+ private _lastRunAt;
2462
+ private _lastStepAt;
2463
+ private _candidates;
2464
+ /** Packed candidate input for the kernel; grows as the label count does. */
2465
+ private _input;
2466
+ private _viewMatrix;
2467
+ private _view16;
2468
+ private _proj16;
2469
+ /** @param _kernel the placement kernel — the Rust-backed
2470
+ * `wasmDeclutterKernel` in production, a stub in unit tests. */
2471
+ constructor(_kernel: DeclutterKernel);
2472
+ /** Milliseconds until the throttle window since the last placement pass
2473
+ * elapses, clamped to `[0, MIN_INTERVAL_MS]`. Callers use this to schedule
2474
+ * a follow-up frame after a `"throttled"` result without overshooting the
2475
+ * window by waiting out the full constant from now. */
2476
+ remainingThrottleMs(nowMs: number): number;
2477
+ register(participant: DeclutterParticipant): void;
2478
+ unregister(participant: DeclutterParticipant): void;
2479
+ /** Signal that candidates changed (text, positions, visibility, style) so
2480
+ * the next update re-runs placement even if the camera is still. */
2481
+ markDirty(): void;
2482
+ /**
2483
+ * Run a placement pass if one is due, then advance any active show/hide
2484
+ * fades. `widthPx`/`heightPx` are the viewport in CSS pixels (matching the
2485
+ * `uScreenHeightPx` uniform); `nowMs` is the frame timestamp used for
2486
+ * throttling and fade stepping.
2487
+ */
2488
+ update(camera: PerspectiveCamera, widthPx: number, heightPx: number, nowMs: number): DeclutterUpdateResult;
2489
+ private _run;
2490
+ /** Drop all registered participants. Call when the owning view is disposed
2491
+ * so this manager doesn't keep strong references to removed meshes (and
2492
+ * their GPU/font resources) past the view's lifetime. */
2493
+ dispose(): void;
2494
+ private _snapshotChanged;
2495
+ private _takeSnapshot;
2496
+ }
2497
+
2498
+ /** A mesh that contributes label candidates to the shared declutter pass. */
2499
+ declare type DeclutterParticipant = {
2500
+ /**
2501
+ * Append the currently-visible, declutter-enabled candidates to `out`.
2502
+ * Called once per placement pass; must not retain `out`.
2503
+ */
2504
+ collectDeclutterCandidates: (out: DeclutterCandidate[]) => void;
2505
+ /**
2506
+ * Apply a placement result as the label's fade *target*. Must be cheap and
2507
+ * idempotent — the pass calls it for every candidate on every run, most
2508
+ * often with an unchanged value.
2509
+ */
2510
+ applyDeclutter: (handle: number, hidden: boolean) => void;
2511
+ /**
2512
+ * Advance this participant's hide factors toward their targets by
2513
+ * `deltaMs / DECLUTTER_FADE_MS`. Called by the manager every update while
2514
+ * anything is fading; returns true while any label is still mid-fade.
2515
+ */
2516
+ stepDeclutterFade: (deltaMs: number) => boolean;
2517
+ };
2518
+
2519
+ declare type DeclutterUpdateResult =
2520
+ /** Nothing to do: no participants, or camera and data unchanged. */
2521
+ "idle"
2522
+ /** A placement pass ran; results are applied to the participants. */
2523
+ | "ran"
2524
+ /** Labels are mid-fade — the caller should schedule a prompt follow-up
2525
+ * frame so the animation keeps stepping. */
2526
+ | "animating"
2527
+ /** A pass is due but the throttle window hasn't elapsed — the caller should
2528
+ * schedule another frame so placement settles after the camera stops. */
2529
+ | "throttled";
2530
+
2248
2531
  export declare const DEFAULT_EFFECT_OPTIONS: Required<EffectOptions>;
2249
2532
 
2250
2533
  export declare type DefaultBatchAttributeValues = {
@@ -2854,6 +3137,9 @@ export declare type EvaluatableMaterialProperty = {
2854
3137
  size: AvailableMaterialProperty["size"];
2855
3138
  /** Opacity expression from layer configuration (for polygons/points/text where supported). */
2856
3139
  opacity: AvailableMaterialProperty["opacity"];
3140
+ /** Per-feature declutter placement priority (for points/billboards/text);
3141
+ * higher wins an overlap. Overrides the layer's `declutterPriority`. */
3142
+ declutterPriority: AvailableMaterialProperty["declutterPriority"];
2857
3143
  /** Image URL for billboards; packed into a shared per-mesh texture atlas. */
2858
3144
  image: string;
2859
3145
  };
@@ -2869,6 +3155,7 @@ declare type EvaluatedMaterialProperty = {
2869
3155
  width: number;
2870
3156
  size: number;
2871
3157
  opacity: number;
3158
+ declutterPriority: number;
2872
3159
  image: string | null;
2873
3160
  };
2874
3161
 
@@ -2912,6 +3199,9 @@ declare class EventContext {
2912
3199
  readonly textureFragmentIndex?: Map<string, Set<TextureSlot>>;
2913
3200
  readonly tileMeshToFragmentIds?: Map<TileMesh, Set<string>>;
2914
3201
  readonly hillshadeContext?: HillshadeContext;
3202
+ /** Shared screen-space label declutterer; text/sprite meshes register as
3203
+ * participants on creation. Optional so headless contexts can skip it. */
3204
+ readonly declutter?: DeclutterManager;
2915
3205
  updatedAt: number;
2916
3206
  constructor(args: EventContextArgs);
2917
3207
  }
@@ -2944,6 +3234,7 @@ declare type EventContextArgs = {
2944
3234
  textureFragmentIndex?: Map<string, Set<TextureSlot>>;
2945
3235
  tileMeshToFragmentIds?: Map<TileMesh, Set<string>>;
2946
3236
  hillshadeContext?: HillshadeContext;
3237
+ declutter?: DeclutterManager;
2947
3238
  };
2948
3239
 
2949
3240
  export declare class EventHandler<T extends BaseEventMap = BaseEventMap, K extends keyof T = keyof T> {
@@ -3146,6 +3437,8 @@ export declare class FeatureEvaluator {
3146
3437
  * - `width` - Line width in pixels (for polylines)
3147
3438
  * - `size` - Feature size in pixels (for points/text)
3148
3439
  * - `opacity` - Feature opacity 0-1
3440
+ * - `declutterPriority` - Placement priority for decluttering; higher wins
3441
+ * an overlap (for points/billboards/text with `declutter` enabled)
3149
3442
  * - `image` - Image URL (for billboards); loaded once per distinct URL and
3150
3443
  * packed into the layer's texture atlas. Return `null` to clear a
3151
3444
  * previous per-feature image and revert to the material's default `url`;
@@ -3328,6 +3621,18 @@ declare class GeoJsonLayerDescription {
3328
3621
  get crs(): string | undefined;
3329
3622
  set crs(value: string | null | undefined);
3330
3623
  data: any;
3624
+ /**
3625
+ * Per-layer horizon dynamic-SSE relaxation strength for the tiled render
3626
+ * path (`0.0` off … `1.0` raster-equivalent). Omit for a content-based
3627
+ * default.
3628
+ */
3629
+ get dynamicSseScale(): number | undefined;
3630
+ /**
3631
+ * Per-layer horizon dynamic-SSE relaxation strength for the tiled render
3632
+ * path (`0.0` off … `1.0` raster-equivalent). Omit for a content-based
3633
+ * default.
3634
+ */
3635
+ set dynamicSseScale(value: number | null | undefined);
3331
3636
  get point(): PointMaterial | undefined;
3332
3637
  set point(value: PointMaterial | null | undefined);
3333
3638
  get polygon(): PolygonMaterial | undefined;
@@ -3816,7 +4121,7 @@ export declare class InstancedMesh<M extends Object3D> extends Mesh_2 implements
3816
4121
  addWithBatchIndex(m: M, batchIndex: number): void;
3817
4122
  markVisibility(m: M): void;
3818
4123
  meshes(): M[];
3819
- getMeshByBatchIndex(batchIndex: number): M;
4124
+ getMeshByBatchIndex(batchIndex: number): M | undefined;
3820
4125
  setFeatureColorByBatchIndex(batchIndex: number, color: Color_3): void;
3821
4126
  setFeatureShowByBatchIndex(batchIndex: number, rawVisible: boolean): void;
3822
4127
  setFeatureHeightByBatchIndex(batchIndex: number, height: number): void;
@@ -3995,6 +4300,8 @@ declare type InstancedSpriteBaseRefs = {
3995
4300
  uRTCCenterView: UniformValue<Vector3>;
3996
4301
  uEyeRTELow: UniformValue<Vector3>;
3997
4302
  uEyeRTEHigh: UniformValue<Vector3>;
4303
+ /** Always 1.0 — blocks fast-math reassociation of the RTE recombination. */
4304
+ u_rteOne?: UniformValue<number>;
3998
4305
  uScale: UniformValue<number>;
3999
4306
  uCenter: UniformValue<Vector2>;
4000
4307
  uSizeInMeters: UniformValue<boolean>;
@@ -4044,7 +4351,7 @@ export declare type InstancedSpriteMaterialProps = {
4044
4351
  base?: InstancedSpriteBaseProps;
4045
4352
  };
4046
4353
 
4047
- export declare class InstancedSpriteMesh extends Mesh_2 implements PickableMesh {
4354
+ export declare class InstancedSpriteMesh extends Mesh_2<BufferGeometry, Material | Material[], CustomObject3DEventMap> implements PickableMesh, DeclutterParticipant {
4048
4355
  private _batchIdToInstance;
4049
4356
  private _initialColor;
4050
4357
  private _initialHeight;
@@ -4068,8 +4375,31 @@ export declare class InstancedSpriteMesh extends Mesh_2 implements PickableMesh
4068
4375
  readonly ctx: EventContext;
4069
4376
  /** Material enhancer for encapsulated state management */
4070
4377
  private _enhancedMaterial?;
4378
+ /** Per-instance world anchors in ECEF meters (f64, 3 per instance), kept in
4379
+ * sync with the position attributes for the declutter pass. */
4380
+ private _anchors;
4381
+ /** Whether this mesh's instances participate in screen-space decluttering. */
4382
+ private _declutter;
4383
+ /** Layer-level placement priority from the material. */
4384
+ private _declutterPriority;
4385
+ /** Per-instance priorities set through the evaluator (NaN = no override,
4386
+ * fall back to the layer value). Lazily allocated on first use. */
4387
+ private _declutterPriorityOverrides;
4388
+ /** Per-instance fade targets for `instanceDeclutterHide` (0 = shown,
4389
+ * 1 = hidden); the attribute animates toward these in stepDeclutterFade. */
4390
+ private _declutterTargets;
4391
+ /** True while any instance's hide factor may differ from its target. */
4392
+ private _declutterAnimating;
4071
4393
  constructor(options: InstancedSpriteOptions);
4072
4394
  setActive(active: boolean): void;
4395
+ collectDeclutterCandidates(out: DeclutterCandidate[]): void;
4396
+ applyDeclutter(handle: number, hidden: boolean): void;
4397
+ stepDeclutterFade(deltaMs: number): boolean;
4398
+ private _cacheDeclutterState;
4399
+ private _clearDeclutterHidden;
4400
+ /** Reconstruct absolute ECEF anchors from the same arrays the position
4401
+ * attributes receive (RTE high+low split, or RTC-relative + center). */
4402
+ private _cacheAnchors;
4073
4403
  _init(m: PointMesh | BillboardMesh): Promise<void>;
4074
4404
  _update(m: PointMesh | BillboardMesh): Promise<void>;
4075
4405
  private _initGeometry;
@@ -4109,6 +4439,19 @@ export declare class InstancedSpriteMesh extends Mesh_2 implements PickableMesh
4109
4439
  setFeatureShowByBatchId(batchId: number, rawVisible: boolean): void;
4110
4440
  setFeatureOpacityByBatchId(batchId: number, opacity: number): void;
4111
4441
  setFeatureHeightByBatchId(batchId: number, height: number): void;
4442
+ /**
4443
+ * Set one instance's declutter fade target; the attribute animates toward
4444
+ * it in {@link stepDeclutterFade}. Deliberately separate from the `show`
4445
+ * component of `instanceParams` so user-driven visibility and declutter
4446
+ * results compose instead of clobbering each other.
4447
+ */
4448
+ setDeclutterHiddenByInstance(instanceIndex: number, hidden: boolean): void;
4449
+ /**
4450
+ * Set a per-feature placement priority (higher wins), overriding the
4451
+ * layer-level `declutterPriority` for this instance. Driven by the feature
4452
+ * evaluator.
4453
+ */
4454
+ setFeatureDeclutterPriorityByBatchId(batchId: number, priority: number): void;
4112
4455
  setFeatureSizeByBatchId(batchId: number, size: number): void;
4113
4456
  /**
4114
4457
  * Give one feature its own image, packed into this mesh's texture atlas.
@@ -4241,7 +4584,7 @@ declare type LayerId = string;
4241
4584
  declare class LayersManager {
4242
4585
  private layers;
4243
4586
  add(l: Layer | BaseHandle): void;
4244
- get(id: string): Layer | BaseHandle<BaseDesc<BaseDescConfig, BaseDescConfigUpdate, BaseInstance, BaseEventMap>> | undefined;
4587
+ get(id: string): Layer | BaseHandle< BaseDesc<BaseDescConfig, BaseDescConfigUpdate, BaseInstance, BaseEventMap>> | undefined;
4245
4588
  emitById<K extends keyof LayerEvent>(k: K, id: string, ...args: Parameters<LayerEvent[K]>): void;
4246
4589
  emitAll<K extends keyof LayerEvent>(k: K, ...args: Parameters<LayerEvent[K]>): void;
4247
4590
  getResourceLayers(): Generator<Layer, void, unknown>;
@@ -4386,6 +4729,16 @@ declare class LegacyVectorTileMaterial {
4386
4729
  [Symbol.dispose](): void;
4387
4730
  get castShadow(): boolean | undefined;
4388
4731
  set castShadow(value: boolean | null | undefined);
4732
+ /**
4733
+ * Per-layer horizon dynamic-SSE relaxation strength (`0.0` off … `1.0`
4734
+ * raster-equivalent). Omit for a content-based default.
4735
+ */
4736
+ get dynamicSseScale(): number | undefined;
4737
+ /**
4738
+ * Per-layer horizon dynamic-SSE relaxation strength (`0.0` off … `1.0`
4739
+ * raster-equivalent). Omit for a content-based default.
4740
+ */
4741
+ set dynamicSseScale(value: number | null | undefined);
4389
4742
  /**
4390
4743
  * Sub-layer filter (MapLibre's `source-layer`). This is the only render-side
4391
4744
  * field; the rest is fetch config carried onto the implicit source.
@@ -4400,6 +4753,8 @@ declare class LegacyVectorTileMaterial {
4400
4753
  set maxSse(value: number | null | undefined);
4401
4754
  get maxZoom(): number | undefined;
4402
4755
  set maxZoom(value: number | null | undefined);
4756
+ get minZoom(): number | undefined;
4757
+ set minZoom(value: number | null | undefined);
4403
4758
  get overscaledMaxZoom(): number | undefined;
4404
4759
  set overscaledMaxZoom(value: number | null | undefined);
4405
4760
  get receiveShadow(): boolean | undefined;
@@ -4703,6 +5058,10 @@ export declare type MemoryStats = {
4703
5058
  gpuBytesEst: number;
4704
5059
  externalCpuBytes: number;
4705
5060
  reservedBytes: number;
5061
+ /** Estimated GPU bytes of fixed screen-sized allocations (the
5062
+ * postprocessing render-target stack), reported via
5063
+ * `Core.setFixedGpuBytes` on init, resize, and pass-list changes. */
5064
+ fixedGpuBytes: number;
4706
5065
  budgetBytes: number | undefined;
4707
5066
  evictedCount: number;
4708
5067
  sseMultiplier: number;
@@ -4726,6 +5085,7 @@ declare class MemoryStats_2 {
4726
5085
  readonly evictedCount: number;
4727
5086
  readonly externalBufferBytes: number;
4728
5087
  readonly externalCpuBytes: number;
5088
+ readonly fixedGpuBytes: number;
4729
5089
  readonly gpuBytesEst: number;
4730
5090
  readonly reservedBytes: number;
4731
5091
  readonly retainedRaster: number;
@@ -5035,7 +5395,7 @@ export declare abstract class MeshDesc<Config extends MeshConfig = MeshConfig, U
5035
5395
  * `this.ctx.registerPickableMesh(this.id, wrapper)` before returning.
5036
5396
  */
5037
5397
  abstract createMesh(): Instance;
5038
- get raw(): (Instance extends Object3D<Object3DEventMap> ? Instance : never) | (Instance extends {
5398
+ get raw(): (Instance extends Object3D< Object3DEventMap> ? Instance : never) | (Instance extends {
5039
5399
  raw: infer Raw extends Object3D;
5040
5400
  } ? Raw : never) | undefined;
5041
5401
  onCreate(): void;
@@ -5688,7 +6048,10 @@ export declare type Options = {
5688
6048
  container?: HTMLElement;
5689
6049
  /** Canvas element for rendering. If not provided, a new canvas is created. */
5690
6050
  canvas?: HTMLCanvasElement | OffscreenCanvas;
5691
- /** Device pixel ratio override. Uses device default if not specified. */
6051
+ /** Device pixel ratio override. When not specified, the device value is
6052
+ * used, capped at 2 on mobile (1 with `mobileOptimization`) — screen-sized
6053
+ * render targets grow quadratically with pixel ratio and dominate mobile
6054
+ * GPU memory. An explicit value bypasses the caps. */
5692
6055
  pixelRatio?: number;
5693
6056
  /** Disables automatic resize handling on window resize events. */
5694
6057
  disableAutoResize?: boolean;
@@ -6090,6 +6453,28 @@ declare class PointMaterial {
6090
6453
  set clampToGround(value: boolean | null | undefined);
6091
6454
  get color(): number | undefined;
6092
6455
  set color(value: number | null | undefined);
6456
+ /**
6457
+ * Placement priority for decluttering; higher wins. Only meaningful when
6458
+ * `declutter` is enabled. Defaults to `0.0`.
6459
+ */
6460
+ get declutterPriority(): number | undefined;
6461
+ /**
6462
+ * Placement priority for decluttering; higher wins. Only meaningful when
6463
+ * `declutter` is enabled. Defaults to `0.0`.
6464
+ */
6465
+ set declutterPriority(value: number | null | undefined);
6466
+ /**
6467
+ * Participate in screen-space decluttering: when labels/sprites overlap
6468
+ * on screen, lower-priority ones are hidden. Defaults to `true`; set to
6469
+ * `false` to draw every label unconditionally.
6470
+ */
6471
+ get declutter(): boolean | undefined;
6472
+ /**
6473
+ * Participate in screen-space decluttering: when labels/sprites overlap
6474
+ * on screen, lower-priority ones are hidden. Defaults to `true`; set to
6475
+ * `false` to draw every label unconditionally.
6476
+ */
6477
+ set declutter(value: boolean | null | undefined);
6093
6478
  get depthTest(): boolean | undefined;
6094
6479
  set depthTest(value: boolean | null | undefined);
6095
6480
  /**
@@ -6246,6 +6631,8 @@ declare type PolygonBaseRefs = {
6246
6631
  modelViewMatrixRTE?: UniformValue<Matrix4>;
6247
6632
  u_cameraPositionHigh?: UniformValue<Vector3>;
6248
6633
  u_cameraPositionLow?: UniformValue<Vector3>;
6634
+ /** Always 1.0 — blocks fast-math reassociation of the RTE recombination. */
6635
+ u_rteOne?: UniformValue<number>;
6249
6636
  };
6250
6637
 
6251
6638
  /**
@@ -6741,6 +7128,8 @@ declare type PolylineBaseRefs = {
6741
7128
  modelViewMatrixRTE?: UniformValue<Matrix4>;
6742
7129
  u_cameraPositionHigh?: UniformValue<Vector3>;
6743
7130
  u_cameraPositionLow?: UniformValue<Vector3>;
7131
+ /** Always 1.0 — blocks fast-math reassociation of the RTE recombination. */
7132
+ u_rteOne?: UniformValue<number>;
6744
7133
  };
6745
7134
 
6746
7135
  /**
@@ -7327,16 +7716,21 @@ export declare class RenderPass extends RenderPass_2 {
7327
7716
  * Orchestrate rendering passes with ordered management and flexible insertion.
7328
7717
  */
7329
7718
  declare class RenderPassOrchestrator {
7330
- lights: Group<Object3DEventMap>;
7719
+ lights: Group< Object3DEventMap>;
7331
7720
  scenes: {
7332
- mrt: Scene<Object3DEventMap>;
7333
- globe: Scene<Object3DEventMap>;
7334
- draped: Scene<Object3DEventMap>;
7335
- opaque: Scene<Object3DEventMap>;
7336
- transparent: Scene<Object3DEventMap>;
7337
- skyEnvMap: Scene<Object3DEventMap>;
7721
+ mrt: Scene< Object3DEventMap>;
7722
+ globe: Scene< Object3DEventMap>;
7723
+ draped: Scene< Object3DEventMap>;
7724
+ opaque: Scene< Object3DEventMap>;
7725
+ transparent: Scene< Object3DEventMap>;
7726
+ skyEnvMap: Scene< Object3DEventMap>;
7338
7727
  };
7339
7728
  effectComposer: EffectComposer;
7729
+ /**
7730
+ * Invoked whenever the pass list changes (add/insert/remove/clear), so the
7731
+ * owner can re-report the fixed GPU footprint to the memory ledger.
7732
+ */
7733
+ onPassesChanged?: () => void;
7340
7734
  private passMap;
7341
7735
  constructor(renderer: WebGLRenderer, options: RenderPassOrchestratorOptions);
7342
7736
  setSize(width: number, height: number): void;
@@ -7369,6 +7763,12 @@ declare class RenderPassOrchestrator {
7369
7763
  * Clear all passes.
7370
7764
  */
7371
7765
  clearPasses(): void;
7766
+ /**
7767
+ * Estimates the resident GPU bytes of the fixed, screen-sized render-target
7768
+ * stack (composer buffers + every target reachable from the passes), for
7769
+ * reporting into the memory ledger's `fixed_gpu_bytes` term.
7770
+ */
7771
+ estimateFixedGpuBytes(): number;
7372
7772
  /**
7373
7773
  * Dispose all GPU resources held by the effect composer.
7374
7774
  */
@@ -7396,7 +7796,12 @@ export declare class RenderTargetCopyPass extends Pass_2 {
7396
7796
  get autoResize(): boolean;
7397
7797
  set autoResize(value: boolean);
7398
7798
  setTexture(texture: Texture): void;
7399
- setDepthTexture(texture: Texture): void;
7799
+ /**
7800
+ * When a depth texture is set, the pass copies its depth into the target's
7801
+ * depth buffer via gl_FragDepth. Depth test must be enabled (with AlwaysDepth)
7802
+ * because GL discards depth writes while the depth test is disabled.
7803
+ */
7804
+ setDepthTexture(texture: Texture | null): void;
7400
7805
  render(renderer: WebGLRenderer, inputBuffer: WebGLRenderTarget | null, _outputBuffer: WebGLRenderTarget | null): void;
7401
7806
  dispose(): void;
7402
7807
  }
@@ -7459,6 +7864,20 @@ declare class ReturnedTransferablePolylineBatchedFeature {
7459
7864
  material: PolylineMaterial;
7460
7865
  }
7461
7866
 
7867
+ /**
7868
+ * Shared `u_rteOne` uniform for RTE vertex shaders. Always 1.0.
7869
+ *
7870
+ * Multiplying the high-order difference by a uniform the shader compiler
7871
+ * cannot constant-fold blocks fast-math reassociation of
7872
+ * `(high - camHigh) + (low - camLow)` into `(high + low) - (camHigh + camLow)`,
7873
+ * which would collapse the math to absolute-ECEF f32 precision and make
7874
+ * geometry freeze/snap in ~0.25-0.5 m steps as the camera moves
7875
+ * (observed on ANGLE Metal). One frozen object is shared by every material.
7876
+ */
7877
+ export declare const RTE_ONE_UNIFORM: {
7878
+ readonly value: number;
7879
+ };
7880
+
7462
7881
  /**
7463
7882
  * Interface for objects that need RTE (Relative-To-Eye) rendering support
7464
7883
  */
@@ -7525,6 +7944,13 @@ export declare type SdfTextBaseMutates = Mutates<SdfTextBaseState, SdfTextBaseUn
7525
7944
  * Set the batch ID uniform (immutable after mount, but needed for batch creation).
7526
7945
  */
7527
7946
  setBatchId: (batchId: number) => void;
7947
+ /**
7948
+ * Set the declutter hide factor (0 = shown … 1 = hidden); the fragment
7949
+ * shader scales opacity by `1 - value` and the vertex shader hard-culls
7950
+ * at 1. Kept separate from `show`/`opacity` so user-driven visibility and
7951
+ * declutter results compose instead of clobbering each other.
7952
+ */
7953
+ setDeclutterHide: (value: number) => void;
7528
7954
  }>;
7529
7955
 
7530
7956
  /**
@@ -7583,10 +8009,16 @@ declare type SdfTextBaseRefs = {
7583
8009
  uTextWidth: UniformValue<number>;
7584
8010
  uTextHeight: UniformValue<number>;
7585
8011
  uBgYBounds: UniformValue<Vector2>;
8012
+ /** Screen-space declutter hide factor (0 = shown … 1 = hidden), animated
8013
+ * by the declutter fade. Driven by the declutter pass, not by material
8014
+ * style updates. */
8015
+ uDeclutterHide: UniformValue<number>;
7586
8016
  uRTCCenter: UniformValue<Vector3>;
7587
8017
  uRTCCenterView: UniformValue<Vector3>;
7588
8018
  uEyeRTELow: UniformValue<Vector3>;
7589
8019
  uEyeRTEHigh: UniformValue<Vector3>;
8020
+ /** Always 1.0 — blocks fast-math reassociation of the RTE recombination. */
8021
+ u_rteOne?: UniformValue<number>;
7590
8022
  nvr_uBatchId: UniformValue<number>;
7591
8023
  nvr_uPickable: UniformValue<number>;
7592
8024
  uAtlas: UniformValue<DataTexture | null>;
@@ -7670,11 +8102,31 @@ export declare class SDFTextMesh extends Mesh_2<InstancedBufferGeometry, ShaderM
7670
8102
  private _reprepare?;
7671
8103
  /** Ask the owner to schedule a render after an async re-prepare. */
7672
8104
  private _requestRender?;
8105
+ /** World-space anchor in ECEF meters (f64), kept in sync with the position
8106
+ * uniforms so the declutter pass can project it without touching WASM. */
8107
+ private _worldAnchor;
8108
+ /** Whether this label participates in screen-space decluttering. */
8109
+ private _declutter;
8110
+ /** Layer-level placement priority from the material. */
8111
+ private _declutterPriority;
8112
+ /** Per-feature priority set through the evaluator; overrides the layer
8113
+ * value when defined. */
8114
+ private _declutterPriorityOverride;
8115
+ /** Current animated hide factor (mirrors the uDeclutterHide uniform) and
8116
+ * the placement target it is fading toward. */
8117
+ private _declutterHide;
8118
+ private _declutterTarget;
8119
+ /** Text block dimensions in em units, mirroring the uTextWidth/uTextHeight/
8120
+ * uBgYBounds uniforms; 0 width means "no collision box" (empty text). */
8121
+ private _labelWidthEm;
8122
+ private _labelHeightEm;
8123
+ private _labelMinYEm;
8124
+ private _labelMaxYEm;
7673
8125
  private _enhancer;
7674
8126
  constructor(position: Float32Array | {
7675
8127
  high: Float32Array;
7676
8128
  low: Float32Array;
7677
- }, material: TextMaterial, transform: Transform_2, fontManager: FontManager, fontUrl: string, batchId: number | undefined, RTE: boolean);
8129
+ }, material: TextMaterial, transform: Transform_2, fontManager: FontManager, fontUrl: string, batchId: number | undefined, RTE: boolean, highQuality: boolean);
7678
8130
  /** The text this mesh currently renders (its baked glyph string). */
7679
8131
  get text(): string;
7680
8132
  /**
@@ -7716,12 +8168,42 @@ export declare class SDFTextMesh extends Mesh_2<InstancedBufferGeometry, ShaderM
7716
8168
  setHeight(height: number): void;
7717
8169
  setSize(size: number): void;
7718
8170
  setOpacity(opacity: number): void;
8171
+ /**
8172
+ * Set this label's declutter fade target; the actual hide factor animates
8173
+ * toward it in {@link stepDeclutterFade}. Deliberately separate from
8174
+ * `visible`/`show`: it neither churns scene-graph membership nor releases
8175
+ * glyph atlas retains, so the declutter pass can retarget it every
8176
+ * placement run at no cost.
8177
+ */
8178
+ setDeclutterHidden(hidden: boolean): void;
8179
+ /**
8180
+ * Advance the hide factor toward its target by `deltaMs / DECLUTTER_FADE_MS`
8181
+ * and push it to the uniform. Returns true while still mid-fade.
8182
+ */
8183
+ stepDeclutterFade(deltaMs: number): boolean;
7719
8184
  _setFeatureWidth(_width: number): void;
7720
8185
  _setFeatureOpacity(opacity: number): void;
7721
8186
  setPosition(position: Float32Array | {
7722
8187
  high: Float32Array;
7723
8188
  low: Float32Array;
7724
8189
  }, RTE: boolean, transform: Transform_2): void;
8190
+ /** Reconstruct the absolute ECEF anchor from the same inputs the position
8191
+ * uniforms receive (RTE high+low split, or RTC-relative + center). */
8192
+ private _cacheWorldAnchor;
8193
+ /**
8194
+ * Build this label's collision candidate for the shared declutter pass, or
8195
+ * null when it doesn't participate (declutter disabled, hidden, or empty).
8196
+ * The local box mirrors the vertex shader's layout: glyphs span
8197
+ * [0, textWidth] × [bgMinY, bgMaxY] in em units, shifted by the `center`
8198
+ * anchor and scaled by the font size (sdfText.vert.glsl:111-115).
8199
+ */
8200
+ getDeclutterCandidate(owner: DeclutterParticipant, handle: number): DeclutterCandidate | null;
8201
+ /**
8202
+ * Set a per-feature placement priority (higher wins), overriding the
8203
+ * layer-level `declutterPriority` for this label. Pass `undefined` to fall
8204
+ * back to the layer value. Driven by the feature evaluator.
8205
+ */
8206
+ setDeclutterPriority(priority: number | undefined): void;
7725
8207
  /**
7726
8208
  * Apply material properties from WASM TextMaterial.
7727
8209
  * Maps relevant properties to enhancer updates, with change tracking.
@@ -8322,6 +8804,28 @@ declare class TextMaterial {
8322
8804
  set clampToGround(value: boolean | null | undefined);
8323
8805
  get color(): number | undefined;
8324
8806
  set color(value: number | null | undefined);
8807
+ /**
8808
+ * Placement priority for decluttering; higher wins. Only meaningful when
8809
+ * `declutter` is enabled. Defaults to `0.0`.
8810
+ */
8811
+ get declutterPriority(): number | undefined;
8812
+ /**
8813
+ * Placement priority for decluttering; higher wins. Only meaningful when
8814
+ * `declutter` is enabled. Defaults to `0.0`.
8815
+ */
8816
+ set declutterPriority(value: number | null | undefined);
8817
+ /**
8818
+ * Participate in screen-space decluttering: when labels/sprites overlap
8819
+ * on screen, lower-priority ones are hidden. Defaults to `true`; set to
8820
+ * `false` to draw every label unconditionally.
8821
+ */
8822
+ get declutter(): boolean | undefined;
8823
+ /**
8824
+ * Participate in screen-space decluttering: when labels/sprites overlap
8825
+ * on screen, lower-priority ones are hidden. Defaults to `true`; set to
8826
+ * `false` to draw every label unconditionally.
8827
+ */
8828
+ set declutter(value: boolean | null | undefined);
8325
8829
  get depthTest(): boolean | undefined;
8326
8830
  set depthTest(value: boolean | null | undefined);
8327
8831
  /**
@@ -8591,6 +9095,14 @@ declare class ThreeView<D extends Descriptions = EmptyDescriptions> extends Even
8591
9095
  private _eventDisposer;
8592
9096
  private _disposed;
8593
9097
  private _renderFlag;
9098
+ /** Shared screen-space label declutterer for text/sprite features. */
9099
+ private _declutter;
9100
+ /** Reusable Vector2 for the declutter pass's per-frame viewport query. */
9101
+ private _declutterSize;
9102
+ /** Pending follow-up frame for a throttled declutter pass or an active
9103
+ * fade, with the delay it was scheduled at (so a shorter need preempts). */
9104
+ private _declutterRetry;
9105
+ private _declutterRetryDelay;
8594
9106
  private _isIdle;
8595
9107
  private _uniforms;
8596
9108
  private _meshes;
@@ -8636,6 +9148,10 @@ declare class ThreeView<D extends Descriptions = EmptyDescriptions> extends Even
8636
9148
  /** Built-in attribution UI; unset when disabled or in a worker (no DOM). */
8637
9149
  private _attribution?;
8638
9150
  private pixelRatioMatchedMedia?;
9151
+ private fixedGpuBytesReportScheduled;
9152
+ private fixedGpuBytesResyncPending;
9153
+ private framesSinceFixedGpuBytesReport;
9154
+ private lastReportedFixedGpuBytes;
8639
9155
  /**
8640
9156
  * The built-in attribution (credit) UI. `undefined` when disabled via
8641
9157
  * `defaultAttribution: false`, or in a worker / no-DOM environment. Feed it
@@ -8745,6 +9261,19 @@ declare class ThreeView<D extends Descriptions = EmptyDescriptions> extends Even
8745
9261
  * @param pixelRatio - Device pixel ratio
8746
9262
  */
8747
9263
  resize: (width?: number, height?: number, pixelRatio?: number) => void;
9264
+ /**
9265
+ * Walks the fixed render-target stack and pushes the estimate into the
9266
+ * memory ledger; the WASM call is skipped while the value is unchanged.
9267
+ */
9268
+ private _reportFixedGpuBytes;
9269
+ /**
9270
+ * Re-reports the fixed GPU footprint for event-triggered changes (init,
9271
+ * resize, pass add/remove). Scheduled as a microtask so bursts — e.g.
9272
+ * effect setup during init — coalesce into a single walk, and marks a
9273
+ * one-shot post-render resync because these events run before the GPU has
9274
+ * lazily allocated the affected targets.
9275
+ */
9276
+ private _scheduleFixedGpuBytesReport;
8748
9277
  private _updateUniforms;
8749
9278
  /** Returns true if the scene was updated and needs to be rendered. */
8750
9279
  private _update;
@@ -8753,6 +9282,14 @@ declare class ThreeView<D extends Descriptions = EmptyDescriptions> extends Even
8753
9282
  * This is called after the main update loop to batch feature updates
8754
9283
  */
8755
9284
  private _forceFeatureUpdates;
9285
+ /**
9286
+ * Ask for a future frame on behalf of the declutter pass. Runs through a
9287
+ * timer because the main loop clears `forceUpdate` right after `_render` —
9288
+ * a flag set synchronously here would be wiped before the next tick reads
9289
+ * it. A pending longer timer is preempted when a shorter delay is needed
9290
+ * (a fade must not wait out a throttle window).
9291
+ */
9292
+ private _scheduleDeclutterFrame;
8756
9293
  private _render;
8757
9294
  /**
8758
9295
  * Since passing Color class to WASM is tricky, converts Navara Color
@@ -9136,6 +9673,12 @@ declare type TileHandler = {
9136
9673
  * subdivision past the vector `maxZoom`. Pass 0 to release on dispose. */
9137
9674
  reportDrapeGpuBytes: (handle: bigint, bytes: number) => void;
9138
9675
  calcMetersPerTexel: (tileHandle: bigint, textureZoom: number, textureWidth: number) => number;
9676
+ /** Rust's clamped WebMercator northing (`navara_geometry::mercator_y`).
9677
+ * The composite paste derives its per-slot reprojection constants through
9678
+ * this so paste and bake (`uv_rect_from_extents_mercator`) share one
9679
+ * implementation — a drifting reimplementation misaligns the pasted
9680
+ * latitude band (and NaNs on the unclamped polar band). */
9681
+ mercatorY: (lat: number) => number;
9139
9682
  };
9140
9683
 
9141
9684
  declare class TileLayerDescription {
@@ -9200,7 +9743,7 @@ export declare class TileMesh extends Mesh_2<BufferGeometry, TileMaterial, Custo
9200
9743
  private buildCompositeLayers;
9201
9744
  _init(mesh: MeshAdded): Promise<void>;
9202
9745
  private createMesh;
9203
- createSkirtMesh(mesh: Mesh, terrainGeometry: BufferGeometry, position: Float32Array, uv: Float32Array | null, indices: Uint32Array, normals: Float32Array | null): BufferGeometry<NormalBufferAttributes, BufferGeometryEventMap>;
9746
+ createSkirtMesh(mesh: Mesh, terrainGeometry: BufferGeometry, position: Float32Array, uv: Float32Array | null, indices: Uint32Array, normals: Float32Array | null): BufferGeometry< NormalBufferAttributes, BufferGeometryEventMap>;
9204
9747
  private shouldUseNormal;
9205
9748
  private initMaterial;
9206
9749
  _update(mesh: MeshChanged): void;
@@ -9392,6 +9935,7 @@ declare class TileTextureCompositor {
9392
9935
  * per-tile GPU byte cost it reports to the memory ledger. */
9393
9936
  readonly size: number;
9394
9937
  private readonly texturizedScenes;
9938
+ private readonly mercatorY;
9395
9939
  private readonly bakeCamera;
9396
9940
  private readonly quadScene;
9397
9941
  private readonly quadCamera;
@@ -9502,6 +10046,10 @@ declare class TileTextureCompositor {
9502
10046
  declare type TileTextureCompositorOptions = {
9503
10047
  renderer: WebGLRenderer;
9504
10048
  texturizedSceneByTileCoordinates: TexturizedSceneByTileCoordinates;
10049
+ /** Rust's clamped WebMercator northing (`TileHandler.mercatorY`), handed to
10050
+ * the core uniform mutates so the paste-side reprojection constants come
10051
+ * from the same implementation as the Rust bake affine. */
10052
+ mercatorY: (lat: number) => number;
9505
10053
  /** Atlas RT side length (defaults to 512). */
9506
10054
  size?: number;
9507
10055
  /** Test seam: replace MRT RT creation. */
@@ -9727,7 +10275,7 @@ export declare type TransparentPassConfig = Description_4 & EffectConfig;
9727
10275
  export declare class TransparentPassEffectDesc extends EffectDesc<TransparentPassConfig, TransparentPassUpdate, RenderPass> {
9728
10276
  static key: string;
9729
10277
  static insertAfter: string[];
9730
- light: Group<Object3DEventMap>;
10278
+ light: Group< Object3DEventMap>;
9731
10279
  lightsSyncMap: Map<any, any>;
9732
10280
  createPass(): RenderPass;
9733
10281
  update(_time: number): void;
@@ -9901,10 +10449,22 @@ export declare class UnknownTypeError extends Error {
9901
10449
  [Symbol.dispose](): void;
9902
10450
  get crs(): string | undefined;
9903
10451
  set crs(value: string | null | undefined);
10452
+ /**
10453
+ * Per-layer horizon dynamic-SSE relaxation strength (`0.0` off … `1.0`
10454
+ * raster-equivalent). Omit for a content-based default.
10455
+ */
10456
+ get dynamicSseScale(): number | undefined;
10457
+ /**
10458
+ * Per-layer horizon dynamic-SSE relaxation strength (`0.0` off … `1.0`
10459
+ * raster-equivalent). Omit for a content-based default.
10460
+ */
10461
+ set dynamicSseScale(value: number | null | undefined);
9904
10462
  get maxSse(): number | undefined;
9905
10463
  set maxSse(value: number | null | undefined);
9906
10464
  get maxZoom(): number | undefined;
9907
10465
  set maxZoom(value: number | null | undefined);
10466
+ get minZoom(): number | undefined;
10467
+ set minZoom(value: number | null | undefined);
9908
10468
  get overscaledMaxZoom(): number | undefined;
9909
10469
  set overscaledMaxZoom(value: number | null | undefined);
9910
10470
  get type(): string | undefined;