@tangram.gl/tangram-renderer 0.0.0-stage → 0.0.1

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 (321) hide show
  1. package/README.md +60 -2
  2. package/dist/core.js +36923 -0
  3. package/dist/core.js.map +6 -0
  4. package/dist/index.js +32 -0
  5. package/dist/loaders-gl-worker.js +82 -0
  6. package/dist/loaders-gl-worker.js.map +6 -0
  7. package/dist/map-logic.js +2 -0
  8. package/dist/map-logic.js.map +6 -0
  9. package/dist/projected-basemaps-worker.js +3 -0
  10. package/dist/projected-basemaps-worker.js.map +6 -0
  11. package/dist/shader-modules.js +141 -0
  12. package/dist/shader-modules.js.map +6 -0
  13. package/dist/style-schema.js +126 -0
  14. package/dist/style-schema.js.map +6 -0
  15. package/dist/tangram-style.schema.json +882 -0
  16. package/dist/tangram.debug.mjs +37139 -0
  17. package/dist/tangram.debug.mjs.map +6 -0
  18. package/dist/tangram.min.mjs +4950 -0
  19. package/dist/types/builders/earcut.d.ts +15 -0
  20. package/dist/types/core.d.ts +29 -0
  21. package/dist/types/gl/constants.d.ts +2 -0
  22. package/dist/types/gl/globe_mesh.d.ts +48 -0
  23. package/dist/types/gl/glsl.d.ts +17 -0
  24. package/dist/types/gl/vertex-constants.d.ts +4 -0
  25. package/dist/types/gl/vertex-types.d.ts +34 -0
  26. package/dist/types/gl/vertex_data.d.ts +32 -0
  27. package/dist/types/gl/vertex_elements.d.ts +8 -0
  28. package/dist/types/gl/vertex_layout.d.ts +32 -0
  29. package/dist/types/glsl.d.ts +14 -0
  30. package/dist/types/gpu/luma_device_renderer.d.ts +66 -0
  31. package/dist/types/gpu/resource_lifecycle.d.ts +4 -0
  32. package/dist/types/gpu/tangram_gpu_backend.d.ts +151 -0
  33. package/dist/types/index.d.ts +155 -0
  34. package/dist/types/lights/light-definitions.d.ts +121 -0
  35. package/dist/types/map-logic/draped-terrain-bounds.d.ts +41 -0
  36. package/dist/types/map-logic/globe-terrain-preparation.d.ts +85 -0
  37. package/dist/types/map-logic/globe-terrain.d.ts +54 -0
  38. package/dist/types/map-logic/index.d.ts +33 -0
  39. package/dist/types/map-logic/label-identity.d.ts +22 -0
  40. package/dist/types/map-logic/label-placement.d.ts +32 -0
  41. package/dist/types/map-logic/screen-bounds.d.ts +15 -0
  42. package/dist/types/map-logic/terrain-data.d.ts +55 -0
  43. package/dist/types/map-logic/terrain-error.d.ts +51 -0
  44. package/dist/types/map-logic/terrain-ground-topology.d.ts +26 -0
  45. package/dist/types/map-logic/terrain-height-field.d.ts +59 -0
  46. package/dist/types/map-logic/terrain-navigation.d.ts +27 -0
  47. package/dist/types/map-logic/terrain-neighborhood.d.ts +5 -0
  48. package/dist/types/map-logic/terrain-query.d.ts +33 -0
  49. package/dist/types/map-logic/terrain-resource-budget.d.ts +51 -0
  50. package/dist/types/map-logic/terrain-transition-topology.d.ts +23 -0
  51. package/dist/types/map-logic/tile-build-queue.d.ts +51 -0
  52. package/dist/types/map-logic/tile-cache-policy.d.ts +46 -0
  53. package/dist/types/map-logic/tile-residency.d.ts +17 -0
  54. package/dist/types/map-logic/triangle-query-index.d.ts +87 -0
  55. package/dist/types/procedures/js-yaml.d.ts +15 -0
  56. package/dist/types/procedures/mesh-projector.d.ts +107 -0
  57. package/dist/types/procedures/mvt-dependencies.d.ts +20 -0
  58. package/dist/types/procedures/projected-coordinate-transform.d.ts +27 -0
  59. package/dist/types/procedures/projection-batch-executor.d.ts +53 -0
  60. package/dist/types/procedures/scene-yaml-legacy.d.ts +6 -0
  61. package/dist/types/procedures/terrain-draping.d.ts +165 -0
  62. package/dist/types/procedures/terrain-globe.d.ts +6 -0
  63. package/dist/types/procedures/terrain-styled-topology.d.ts +34 -0
  64. package/dist/types/procedures/web-mercator-legacy.d.ts +4 -0
  65. package/dist/types/procedures/web-mercator-math.d.ts +4 -0
  66. package/dist/types/scene/globals.d.ts +11 -0
  67. package/dist/types/scene/ground_footprint.d.ts +16 -0
  68. package/dist/types/scene/host_frame.d.ts +54 -0
  69. package/dist/types/scene/projection_math.d.ts +52 -0
  70. package/dist/types/scene/scene-resource-types.d.ts +177 -0
  71. package/dist/types/scene/scene_bundle.d.ts +69 -0
  72. package/dist/types/scene/visibility_adapter.d.ts +106 -0
  73. package/dist/types/selection/draped-terrain-surface.d.ts +78 -0
  74. package/dist/types/selection/terrain_surface.d.ts +149 -0
  75. package/dist/types/shader-modules/globe-horizon.d.ts +15 -0
  76. package/dist/types/shader-modules/height-decode.d.ts +13 -0
  77. package/dist/types/shader-modules/hillshade.d.ts +13 -0
  78. package/dist/types/shader-modules/index.d.ts +6 -0
  79. package/dist/types/shader-modules/planar.d.ts +12 -0
  80. package/dist/types/shader-modules/sphere-map.d.ts +13 -0
  81. package/dist/types/shader-modules/triplanar.d.ts +15 -0
  82. package/dist/types/sources/decoded_tile_store.d.ts +95 -0
  83. package/dist/types/sources/tile_source_metadata.d.ts +32 -0
  84. package/dist/types/styles/text/fontfaceobserver.d.ts +10 -0
  85. package/dist/types/tile/tile_id.d.ts +37 -0
  86. package/dist/types/tile/tile_traversal_adapter.d.ts +63 -0
  87. package/dist/types/types.d.ts +293 -0
  88. package/dist/types/utils/geo.d.ts +57 -0
  89. package/dist/types/utils/hash.d.ts +1 -0
  90. package/dist/types/utils/log.d.ts +27 -0
  91. package/dist/types/utils/props.d.ts +6 -0
  92. package/dist/types/utils/subscribe.d.ts +10 -0
  93. package/dist/types/utils/thread.d.ts +6 -0
  94. package/dist/types/utils/urls.d.ts +26 -0
  95. package/dist/types/utils/utils.d.ts +26 -0
  96. package/dist/types/utils/version.d.ts +2 -0
  97. package/dist/types/utils/worker-types.d.ts +68 -0
  98. package/dist/types/utils/worker_broker.d.ts +3 -0
  99. package/package.json +103 -3
  100. package/src/builders/common.ts +41 -0
  101. package/src/builders/earcut.d.ts +15 -0
  102. package/src/builders/geometry-types.ts +60 -0
  103. package/src/builders/points.ts +115 -0
  104. package/src/builders/polygons.ts +225 -0
  105. package/src/builders/polylines.ts +682 -0
  106. package/src/builders/wireframe.ts +31 -0
  107. package/src/core.d.ts +29 -0
  108. package/src/core.ts +33 -0
  109. package/src/experimental/loaders-gl-worker.ts +19 -0
  110. package/src/experimental/projected-basemaps-worker.ts +13 -0
  111. package/src/experimental/projected-mesh-cache.ts +137 -0
  112. package/src/experimental/projected-mesh-domain.ts +110 -0
  113. package/src/experimental/projected-mesh-refinement.ts +193 -0
  114. package/src/experimental/projected-mesh.ts +399 -0
  115. package/src/experimental/projected-normal.ts +26 -0
  116. package/src/experimental/projected-symbol-mesh.ts +74 -0
  117. package/src/gl/constants.ts +18 -0
  118. package/src/gl/context.ts +103 -0
  119. package/src/gl/extensions.ts +30 -0
  120. package/src/gl/globe_mesh.ts +285 -0
  121. package/src/gl/glsl.ts +257 -0
  122. package/src/gl/mesh-types.ts +56 -0
  123. package/src/gl/render_state.ts +111 -0
  124. package/src/gl/shader_program.ts +1310 -0
  125. package/src/gl/texture.ts +814 -0
  126. package/src/gl/uniform_buffer.ts +340 -0
  127. package/src/gl/vao.ts +154 -0
  128. package/src/gl/vbo_mesh.ts +349 -0
  129. package/src/gl/vertex-constants.ts +19 -0
  130. package/src/gl/vertex-types.ts +35 -0
  131. package/src/gl/vertex_data.ts +126 -0
  132. package/src/gl/vertex_elements.ts +54 -0
  133. package/src/gl/vertex_layout.ts +241 -0
  134. package/src/glsl.d.ts +14 -0
  135. package/src/gpu/luma_device_renderer.ts +579 -0
  136. package/src/gpu/pixel_readback.ts +51 -0
  137. package/src/gpu/resource_lifecycle.ts +32 -0
  138. package/src/gpu/tangram_gpu_backend.ts +195 -0
  139. package/src/index.d.ts +155 -0
  140. package/src/index.ts +105 -0
  141. package/src/labels/collision-types.ts +94 -0
  142. package/src/labels/collision.ts +273 -0
  143. package/src/labels/collision_grid.ts +61 -0
  144. package/src/labels/intersect.ts +30 -0
  145. package/src/labels/label-types.ts +91 -0
  146. package/src/labels/label.ts +207 -0
  147. package/src/labels/label_line.ts +801 -0
  148. package/src/labels/label_point.ts +131 -0
  149. package/src/labels/main-pass-types.ts +73 -0
  150. package/src/labels/main_pass.ts +221 -0
  151. package/src/labels/point_anchor.ts +100 -0
  152. package/src/labels/point_placement.ts +150 -0
  153. package/src/labels/projected-pass.ts +259 -0
  154. package/src/labels/repeat_group.ts +72 -0
  155. package/src/lights/ambient_light.glsl +18 -0
  156. package/src/lights/directional_light.glsl +39 -0
  157. package/src/lights/geographic-lights.ts +21 -0
  158. package/src/lights/light-definitions.ts +285 -0
  159. package/src/lights/light.ts +590 -0
  160. package/src/lights/lighting-uniforms.ts +80 -0
  161. package/src/lights/lighting-wgsl.ts +116 -0
  162. package/src/lights/material.glsl +237 -0
  163. package/src/lights/material.ts +145 -0
  164. package/src/lights/native-falloff.ts +37 -0
  165. package/src/lights/point_light.glsl +96 -0
  166. package/src/lights/spot_light.glsl +111 -0
  167. package/src/map-logic/draped-terrain-bounds.ts +71 -0
  168. package/src/map-logic/globe-terrain-preparation.ts +217 -0
  169. package/src/map-logic/globe-terrain.ts +296 -0
  170. package/src/map-logic/index.ts +37 -0
  171. package/src/map-logic/label-identity.ts +36 -0
  172. package/src/map-logic/label-placement.ts +117 -0
  173. package/src/map-logic/screen-bounds.ts +34 -0
  174. package/src/map-logic/terrain-data.ts +107 -0
  175. package/src/map-logic/terrain-error.ts +134 -0
  176. package/src/map-logic/terrain-ground-topology.ts +164 -0
  177. package/src/map-logic/terrain-height-field.ts +254 -0
  178. package/src/map-logic/terrain-navigation.ts +50 -0
  179. package/src/map-logic/terrain-neighborhood.ts +43 -0
  180. package/src/map-logic/terrain-query.ts +51 -0
  181. package/src/map-logic/terrain-resource-budget.ts +124 -0
  182. package/src/map-logic/terrain-transition-topology.ts +164 -0
  183. package/src/map-logic/tile-build-queue.ts +110 -0
  184. package/src/map-logic/tile-cache-policy.ts +89 -0
  185. package/src/map-logic/tile-residency.ts +50 -0
  186. package/src/map-logic/triangle-query-index.ts +265 -0
  187. package/src/procedures/js-yaml.d.ts +15 -0
  188. package/src/procedures/mesh-projector.ts +191 -0
  189. package/src/procedures/mlt-loaders.ts +55 -0
  190. package/src/procedures/mvt-dependencies.d.ts +20 -0
  191. package/src/procedures/mvt-legacy.ts +150 -0
  192. package/src/procedures/mvt-loaders.ts +53 -0
  193. package/src/procedures/mvt-parser.ts +48 -0
  194. package/src/procedures/mvt-properties.ts +36 -0
  195. package/src/procedures/mvt-tile-provider.ts +72 -0
  196. package/src/procedures/pmtiles-loader.ts +75 -0
  197. package/src/procedures/projected-coordinate-transform.ts +79 -0
  198. package/src/procedures/projection-batch-executor.ts +140 -0
  199. package/src/procedures/scene-yaml-legacy.ts +16 -0
  200. package/src/procedures/scene-yaml-loaders.ts +10 -0
  201. package/src/procedures/terrain-draping.ts +713 -0
  202. package/src/procedures/terrain-globe.ts +32 -0
  203. package/src/procedures/terrain-styled-topology.ts +184 -0
  204. package/src/procedures/web-mercator-legacy.ts +24 -0
  205. package/src/procedures/web-mercator-math.ts +50 -0
  206. package/src/scene/camera.ts +298 -0
  207. package/src/scene/camera_base.ts +116 -0
  208. package/src/scene/classic_scene.ts +20 -0
  209. package/src/scene/external_camera.ts +101 -0
  210. package/src/scene/globals.ts +120 -0
  211. package/src/scene/ground_footprint.ts +139 -0
  212. package/src/scene/host_frame.ts +326 -0
  213. package/src/scene/projected_tile_lod.ts +125 -0
  214. package/src/scene/projection_math.ts +142 -0
  215. package/src/scene/projection_shaders.ts +183 -0
  216. package/src/scene/renderer.ts +516 -0
  217. package/src/scene/scene-resource-types.ts +174 -0
  218. package/src/scene/scene.ts +2378 -0
  219. package/src/scene/scene_bundle.ts +304 -0
  220. package/src/scene/scene_debug.ts +129 -0
  221. package/src/scene/scene_loader.ts +402 -0
  222. package/src/scene/scene_worker.ts +528 -0
  223. package/src/scene/view.ts +683 -0
  224. package/src/scene/visibility_adapter.ts +319 -0
  225. package/src/scene/worker_url.ts +15 -0
  226. package/src/selection/draped-terrain-surface.ts +377 -0
  227. package/src/selection/selection-types.ts +79 -0
  228. package/src/selection/selection.ts +542 -0
  229. package/src/selection/selection_fragment.glsl +18 -0
  230. package/src/selection/selection_globals.glsl +9 -0
  231. package/src/selection/selection_pixels.ts +59 -0
  232. package/src/selection/selection_vertex.glsl +15 -0
  233. package/src/selection/terrain_surface.ts +298 -0
  234. package/src/shader-modules/globe-horizon.ts +52 -0
  235. package/src/shader-modules/height-decode.ts +41 -0
  236. package/src/shader-modules/hillshade.ts +70 -0
  237. package/src/shader-modules/index.ts +10 -0
  238. package/src/shader-modules/planar.ts +24 -0
  239. package/src/shader-modules/sphere-map.ts +38 -0
  240. package/src/shader-modules/triplanar.ts +45 -0
  241. package/src/sources/aligned_tile_source.ts +122 -0
  242. package/src/sources/data_source.ts +655 -0
  243. package/src/sources/decoded_tile_store.ts +245 -0
  244. package/src/sources/geojson.ts +300 -0
  245. package/src/sources/mvt.ts +247 -0
  246. package/src/sources/raster.ts +341 -0
  247. package/src/sources/shared_tile_source_adapter.ts +117 -0
  248. package/src/sources/sources.ts +10 -0
  249. package/src/sources/tile_source_adapter.ts +84 -0
  250. package/src/sources/tile_source_metadata.ts +65 -0
  251. package/src/sources/tile_source_state.ts +112 -0
  252. package/src/sources/topojson.ts +90 -0
  253. package/src/styles/feature_annotations.ts +16 -0
  254. package/src/styles/filter.ts +190 -0
  255. package/src/styles/geometry-style-types.ts +209 -0
  256. package/src/styles/globe_visibility_wgsl.ts +22 -0
  257. package/src/styles/layer-types.ts +45 -0
  258. package/src/styles/layer.ts +586 -0
  259. package/src/styles/lines/dasharray.ts +49 -0
  260. package/src/styles/lines/lines.ts +707 -0
  261. package/src/styles/lines/lines_wgsl.ts +224 -0
  262. package/src/styles/points/point-runtime-types.ts +125 -0
  263. package/src/styles/points/points.ts +1079 -0
  264. package/src/styles/points/points_fragment.glsl +126 -0
  265. package/src/styles/points/points_vertex.glsl +230 -0
  266. package/src/styles/points/points_wgsl.ts +189 -0
  267. package/src/styles/polygons/polygons.ts +268 -0
  268. package/src/styles/polygons/polygons_fragment.glsl +173 -0
  269. package/src/styles/polygons/polygons_vertex.glsl +213 -0
  270. package/src/styles/polygons/polygons_wgsl.ts +127 -0
  271. package/src/styles/property-types.ts +125 -0
  272. package/src/styles/raster/raster.ts +33 -0
  273. package/src/styles/raster/raster_globals.glsl +46 -0
  274. package/src/styles/style-mixing-types.ts +101 -0
  275. package/src/styles/style-runtime-types.ts +220 -0
  276. package/src/styles/style-schema.ts +133 -0
  277. package/src/styles/style.ts +1033 -0
  278. package/src/styles/style_globals.glsl +69 -0
  279. package/src/styles/style_manager.ts +464 -0
  280. package/src/styles/style_parser.ts +620 -0
  281. package/src/styles/text/font_manager.ts +180 -0
  282. package/src/styles/text/fontfaceobserver.d.ts +10 -0
  283. package/src/styles/text/text-types.ts +220 -0
  284. package/src/styles/text/text.ts +378 -0
  285. package/src/styles/text/text_canvas.ts +773 -0
  286. package/src/styles/text/text_labels.ts +436 -0
  287. package/src/styles/text/text_segments.ts +142 -0
  288. package/src/styles/text/text_settings.ts +228 -0
  289. package/src/styles/text/text_wgsl.ts +159 -0
  290. package/src/styles/text/text_wrap.ts +194 -0
  291. package/src/tile/globe_tile_preload.ts +40 -0
  292. package/src/tile/tangram_tileset_2d.ts +108 -0
  293. package/src/tile/tile-build-types.ts +155 -0
  294. package/src/tile/tile.ts +807 -0
  295. package/src/tile/tile_id.ts +172 -0
  296. package/src/tile/tile_manager.ts +889 -0
  297. package/src/tile/tile_pyramid.ts +119 -0
  298. package/src/tile/tile_resource_cache.ts +91 -0
  299. package/src/tile/tile_traversal_adapter.ts +132 -0
  300. package/src/types.ts +332 -0
  301. package/src/utils/debounce.ts +17 -0
  302. package/src/utils/debug_settings.ts +43 -0
  303. package/src/utils/errors.ts +12 -0
  304. package/src/utils/functions.ts +95 -0
  305. package/src/utils/geo.ts +364 -0
  306. package/src/utils/hash.ts +14 -0
  307. package/src/utils/log.ts +108 -0
  308. package/src/utils/media_capture.ts +193 -0
  309. package/src/utils/merge.ts +44 -0
  310. package/src/utils/obb.ts +134 -0
  311. package/src/utils/props.ts +43 -0
  312. package/src/utils/slice.ts +14 -0
  313. package/src/utils/subscribe.ts +58 -0
  314. package/src/utils/task.ts +154 -0
  315. package/src/utils/thread.ts +26 -0
  316. package/src/utils/urls.ts +223 -0
  317. package/src/utils/utils.ts +310 -0
  318. package/src/utils/vector.ts +197 -0
  319. package/src/utils/version.ts +8 -0
  320. package/src/utils/worker-types.ts +79 -0
  321. package/src/utils/worker_broker.ts +523 -0
@@ -0,0 +1,807 @@
1
+ // Tangram
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) 2013-2016 Brett Camper and Mapzen
4
+ // Copyright (c) 2026 vis.gl contributors
5
+
6
+ import log from '../utils/log';
7
+ import Utils from '../utils/utils';
8
+ import mergeObjects from '../utils/merge';
9
+ import Geo from '../utils/geo';
10
+ import {TileID} from './tile_id';
11
+ import type VBOMesh from '../gl/vbo_mesh';
12
+ import {addLayerDebugEntry} from '../styles/style';
13
+ import StyleParser from '../styles/style_parser';
14
+ import Collision from '../labels/collision';
15
+ import WorkerBroker from '../utils/worker_broker';
16
+ import Task from '../utils/task';
17
+ import Texture from '../gl/texture';
18
+ import {getTileSourceRequest, updateTileSourceRequest} from '../sources/tile_source_state';
19
+
20
+ import {Matrix4} from '@math.gl/core';
21
+ import type {TileCoordinate, TileCoordinates, TileSource, TileReference} from './tile_id';
22
+ import type {BrokerMethod, BrokerWorker} from '../utils/worker-types';
23
+ import type {Meters} from '../utils/geo';
24
+ import type UniformBuffer from '../gl/uniform_buffer';
25
+ import type {TileDebug, TileBuildStyle, TileStylePayload, TileBuildProgress, WorkerBuildTile, LayerDebugCounts, TileBuildLayer, DecodedTileFeature} from './tile-build-types';
26
+ import type {StyleFeature} from '../styles/property-types';
27
+
28
+ /** Source identity and retention policy consumed by tile ownership. */
29
+ interface TileSourcePolicy extends TileSource {
30
+ id: number | string;
31
+ tiled?: boolean;
32
+ preserve_tiles_within_zoom?: number;
33
+ max_zoom?: number;
34
+ }
35
+
36
+ let id = 0; // unique tile id
37
+ let build_id = 0; // id tracking order in which tiles were build
38
+
39
+ export default class Tile {
40
+ /** Constructor-owned source metadata. */
41
+ declare source: TileSourcePolicy;
42
+ /** Host view identity; geometry construction does not inspect it. */
43
+ declare view: unknown;
44
+ /** Actual normalized source coordinates. */
45
+ declare coords: TileCoordinate;
46
+ /** Style detail independent of source zoom. */
47
+ declare style_z: number;
48
+ /** Overzoom conversion factors. */
49
+ declare overzoom: number;
50
+ declare overzoom2: number;
51
+ /** Absolute Mercator tile origin, extent and bounds. */
52
+ declare min: Meters;
53
+ declare max: Meters;
54
+ declare span: Meters;
55
+ declare bounds: {sw: Meters; ne: Meters};
56
+ /** Style-unit conversion factors copied to the worker. */
57
+ declare meters_per_pixel: number;
58
+ declare meters_per_pixel_sq: number;
59
+ declare units_per_pixel: number;
60
+ declare units_per_meter_overzoom: number;
61
+ declare preserve_tiles_within_zoom?: number;
62
+ /** Selected worker and its pool offset; destruction clears the worker reference. */
63
+ declare worker: BrokerWorker | null;
64
+ declare worker_id: number;
65
+ /** Residency, loading and proxy state. */
66
+ declare valid: boolean;
67
+ declare loaded: boolean;
68
+ declare labeled: boolean;
69
+ declare fade_in: boolean;
70
+ declare proxy_for: Tile[] | null;
71
+ declare proxied_as: 'child' | 'parent' | null;
72
+ declare proxy_level: number;
73
+ declare proxy_order_offset: number;
74
+ declare fallback_for?: Map<string, readonly [number, number, number, number]> | null;
75
+ /** A coarse fallback currently replaces this detail tile in the draw membership. */
76
+ declare fallback_pending?: boolean;
77
+ /** Uploaded style names for the in-progress generation. */
78
+ declare new_mesh_styles: string[];
79
+ declare mesh_data?: Record<string, TileStylePayload>;
80
+ /** Last upload order and worker error/debug reply. */
81
+ declare build_id: number;
82
+ declare error: string | null;
83
+ declare debug: TileDebug;
84
+ /** Cached child coordinates, retained for classic compatibility. */
85
+ declare static coord_children: Record<string, Record<string, TileReference[]>>;
86
+ /** Worker-visible tile identity. */
87
+ declare id: number;
88
+ /** Source/style-normalized cache key. */
89
+ declare key: string;
90
+ /** Generation currently submitted to the worker, or null before the first build. */
91
+ declare generation: number | null;
92
+ /** Visibility shared by every host eye. */
93
+ declare visible: boolean;
94
+ /** Whether initial worker processing remains incomplete. */
95
+ declare loading: boolean;
96
+ /** Completion of every mesh batch for the current generation. */
97
+ declare built: boolean;
98
+ /** GPU mesh ownership by style. */
99
+ declare meshes: Record<string, VBOMesh[]>;
100
+ /** Admitted-generation annotations awaiting screen collision. */
101
+ declare pending_label_meshes: Record<string, VBOMesh[]> | null;
102
+ /** Replacement GPU owners kept out of the display until the worker generation drains. */
103
+ terrainStage?: {meshes: Record<string, VBOMesh[]>; labels: Record<string, VBOMesh[]> | null; styles: string[]; done?: boolean};
104
+ /** Upload owners created in one staged batch, including allocations not yet attached to a style. */
105
+ private terrainUploadOwners?: VBOMesh[];
106
+ matrix4 = new Matrix4();
107
+
108
+ /**
109
+ Tile
110
+ @constructor
111
+ Required properties:
112
+ coords: object with {x, y, z} properties identifying tile coordinate location
113
+ worker: web worker to handle tile construction
114
+ */
115
+ constructor({ coords, style_z, source, workers, view }: {coords: TileCoordinates; style_z: number; source: TileSourcePolicy; workers: BrokerWorker[]; view: unknown}) {
116
+ this.id = id++;
117
+ this.view = view;
118
+ this.source = source;
119
+ this.generation = null;
120
+ this.valid = true;
121
+
122
+ this.visible = false;
123
+ this.proxy_for = null;
124
+ this.proxied_as = null;
125
+ this.proxy_level = 0;
126
+ this.proxy_order_offset = 0;
127
+ this.fade_in = true;
128
+ this.loading = false;
129
+ this.loaded = false;
130
+ this.built = false;
131
+ this.labeled = false;
132
+ this.error = null;
133
+ this.debug = {};
134
+
135
+ this.style_z = style_z; // zoom level to be used for styling
136
+ this.coords = TileID.normalizedCoord(coords, this.source);
137
+ this.key = TileID.key(this.coords, this.source, this.style_z)!; // The manager validates the normalized key before constructing a tile.
138
+ this.overzoom = Math.max(this.style_z - this.coords.z, 0); // number of levels of overzooming
139
+ this.overzoom2 = Math.pow(2, this.overzoom);
140
+ this.min = Geo.metersForTile(this.coords);
141
+ this.max = Geo.metersForTile({x: this.coords.x + 1, y: this.coords.y + 1, z: this.coords.z }),
142
+ this.span = { x: (this.max.x - this.min.x), y: -(this.max.y - this.min.y) };
143
+ this.bounds = { sw: { x: this.min.x, y: this.max.y }, ne: { x: this.max.x, y: this.min.y } };
144
+
145
+ this.meters_per_pixel = Geo.metersPerPixel(this.style_z);
146
+ this.meters_per_pixel_sq = this.meters_per_pixel * this.meters_per_pixel;
147
+ this.units_per_pixel = Geo.units_per_pixel / this.overzoom2; // adjusted for overzoom
148
+ this.units_per_meter_overzoom = Geo.unitsPerMeter(this.coords.z) * this.overzoom2; // adjusted for overzoom
149
+ this.preserve_tiles_within_zoom = this.source.preserve_tiles_within_zoom; // source-specific tile retention policy
150
+
151
+ this.meshes = {}; // renderable VBO meshes keyed by style
152
+ this.new_mesh_styles = []; // meshes that have been built so far in current build generation
153
+ this.pending_label_meshes = null; // meshes that are pending collision (shouldn't be displayed yet)
154
+
155
+ this.setWorker(workers);
156
+ }
157
+
158
+ // Free resources owned by tile
159
+ freeResources () {
160
+ this.discardTerrainStage();
161
+ for (let m in this.meshes) {
162
+ this.meshes[m].forEach(m => m.destroy());
163
+ }
164
+ this.meshes = {};
165
+
166
+ if (this.pending_label_meshes) {
167
+ for (let m in this.pending_label_meshes) {
168
+ this.pending_label_meshes[m].forEach(m => m.destroy());
169
+ }
170
+ }
171
+ this.pending_label_meshes = null;
172
+ }
173
+
174
+ destroy() {
175
+ Task.removeForTile(this.id);
176
+ this.workerMessage('self.removeTile', this.key);
177
+ this.freeResources();
178
+ this.worker = null;
179
+ this.valid = false;
180
+ }
181
+
182
+ buildAsMessage() {
183
+ return {
184
+ id: this.id,
185
+ key: this.key,
186
+ source: this.source.name,
187
+ coords: this.coords,
188
+ min: this.min,
189
+ max: this.max,
190
+ units_per_pixel: this.units_per_pixel,
191
+ meters_per_pixel: this.meters_per_pixel,
192
+ meters_per_pixel_sq: this.meters_per_pixel_sq,
193
+ units_per_meter_overzoom: this.units_per_meter_overzoom,
194
+ style_z: this.style_z,
195
+ overzoom: this.overzoom,
196
+ overzoom2: this.overzoom2,
197
+ generation: this.generation,
198
+ debug: this.debug
199
+ };
200
+ }
201
+
202
+ // Find the appropriate worker thread for this tile
203
+ setWorker (workers: BrokerWorker[]) {
204
+ if (this.source.tiled) {
205
+ // Pin tile to a worker thread based on its coordinates
206
+ this.worker_id = Math.abs(this.coords.x + this.coords.y + this.coords.z) % workers.length;
207
+ }
208
+ else {
209
+ // Pin all tiles from each non-tiled source to a single worker
210
+ // Prevents data for these sources from being loaded more than once
211
+ this.worker_id = Number(this.source.id) % workers.length;
212
+ }
213
+
214
+ this.worker = workers[this.worker_id];
215
+ }
216
+
217
+ workerMessage (method: BrokerMethod, ...message: unknown[]) {
218
+ return WorkerBroker.postMessage(this.worker!, method, ...message); // Calls precede destroy(), which clears the worker.
219
+ }
220
+
221
+ build(generation: number, { fade_in = true } = {}) {
222
+ this.generation = generation;
223
+ this.fade_in = fade_in;
224
+ if (!this.loaded) {
225
+ this.loading = true;
226
+ this.built = false;
227
+ this.labeled = false;
228
+ }
229
+ return this.workerMessage('self.buildTile', { tile: this.buildAsMessage() }).catch(e => { throw e; });
230
+ }
231
+
232
+ /**
233
+ Called on worker to cancel loading
234
+ Static method because the worker only has object representations of tile data, there is no
235
+ tile instance created yet.
236
+ */
237
+ static cancel(tile: import('../sources/tile_source_state').TileDataContext & {canceled?: boolean; id?: string | number; key?: string; mesh_data?: Record<string, TileStylePayload>} | null | undefined) {
238
+ if (tile) {
239
+ tile.canceled = true;
240
+ const request = getTileSourceRequest(tile);
241
+ request.cancel?.();
242
+ if (request.requestId) {
243
+ Utils.cancelRequest(request.requestId); // cancel pending tile network request
244
+ updateTileSourceRequest(tile, {requestId: null});
245
+ }
246
+
247
+ Tile.abortBuild(tile);
248
+ }
249
+ }
250
+
251
+ // Process geometry for tile - called by web worker
252
+ // Returns a set of tile keys that should be sent to the main thread (so that we can minimize data exchange between worker and main thread)
253
+ static buildGeometry (tile: WorkerBuildTile, { scene_id, layers, styles, global }: {scene_id: number | string; layers: Record<string, TileBuildLayer>; styles: Record<string, TileBuildStyle>; global: unknown}) {
254
+ let data = tile.source_data;
255
+
256
+ tile.debug.building = +new Date();
257
+ tile.debug.feature_count = 0;
258
+ tile.debug.layers = null;
259
+
260
+ Collision.startTile(tile.id, {
261
+ apply_repeat_groups: !Object.values(styles).some(style => style.cpu_projection || style.screen_space_labels)
262
+ });
263
+
264
+ // Process each top-level layer
265
+ for (let layer_name in layers) {
266
+ let layer = layers[layer_name];
267
+ // Skip layers with no data source defined
268
+ if (!layer || !layer.config_data) {
269
+ log('warn', `Layer ${layer_name} was defined without a geometry data source and will not be rendered.`);
270
+ continue;
271
+ }
272
+
273
+ // Source names don't match
274
+ if (layer.config_data.source !== tile.source) {
275
+ continue;
276
+ }
277
+
278
+ // Get data for one or more layers from source
279
+ let source_layers = Tile.getDataForSource(data, layer.config_data, layer_name);
280
+
281
+ // Build features in layer
282
+ for (let s=0; s < source_layers.length; s++) {
283
+ let source_layer = source_layers[s];
284
+ let geom = source_layer.geom;
285
+ if (!geom) {
286
+ continue;
287
+ }
288
+
289
+ for (let f = 0; f < geom.features.length; f++) {
290
+ let feature = geom.features[f];
291
+ if (!hasFeatureGeometry(feature)) {
292
+ continue; // skip features w/o geometry (valid GeoJSON)
293
+ }
294
+
295
+ let context = StyleParser.getFeatureParseContext(feature, tile, global);
296
+ context.winding = tile.default_winding;
297
+ context.source = tile.source; // add data source name
298
+ context.layer = source_layer.layer; // add data source layer name
299
+
300
+ // Get draw groups for this feature
301
+ let draw_groups = layer.buildDrawGroups(context, true);
302
+ if (!draw_groups) {
303
+ continue;
304
+ }
305
+
306
+ // Build draw groups
307
+ for (let group_name in draw_groups) {
308
+ let group = draw_groups[group_name];
309
+
310
+ // Add to style
311
+ let style_name = group!.style || group_name;
312
+ let style = styles[style_name];
313
+
314
+ if (!style) {
315
+ log('warn', `Style '${style_name}' not found, skipping layer '${layer_name}':`, group, feature);
316
+ continue;
317
+ }
318
+
319
+ group = style.preprocess(group!);
320
+ if (group == null || group.visible === false) {
321
+ continue;
322
+ }
323
+
324
+ context.layers = group.layers; // add matching draw layers
325
+
326
+ style.addFeature(feature, group, context);
327
+ }
328
+
329
+ tile.debug.feature_count++;
330
+ }
331
+ }
332
+ }
333
+ tile.debug.building = +new Date() - tile.debug.building;
334
+
335
+ // Send styles back to main thread as they finish building, in two groups: collision vs. non-collision
336
+ let tile_styles = this.stylesForTile(tile, styles).map(s => styles[s]);
337
+ Tile.buildStyleGroups(tile, tile_styles, scene_id, style => style.collision ? 'collision' : 'non-collision');
338
+ // Tile.buildStyleGroups(tile, tile_styles, scene_id, style => style.name); // call for each style
339
+ // Tile.buildStyleGroups(tile, tile_styles, scene_id, style => 'styles'); // all styles in single call (previous behavior)
340
+ }
341
+
342
+ static stylesForTile (tile: WorkerBuildTile, styles: Record<string, TileBuildStyle>) {
343
+ let tile_styles: string[] = [];
344
+ for (let s in styles) {
345
+ if (styles[s].hasDataForTile(tile)) {
346
+ tile_styles.push(s);
347
+ }
348
+ }
349
+ return tile_styles;
350
+ }
351
+
352
+ // Build styles (grouped by the provided function) and send back to main thread as they finish building
353
+ static buildStyleGroups(tile: WorkerBuildTile, styles: TileBuildStyle[], scene_id: number | string, group_by: (style: TileBuildStyle) => string) {
354
+ // Group the styles; each group will be sent to the main thread when the styles in the group finish building.
355
+ const groups = styles.reduce<Record<string, TileBuildStyle[] | null>>((groups, style) => {
356
+ const group = group_by(style);
357
+ groups[group] = groups[group] || [];
358
+ groups[group]!.push(style);
359
+ return groups;
360
+ }, {});
361
+
362
+ // If nothing to build, return empty tile to main thread
363
+ if (Object.keys(groups).length === 0) {
364
+ WorkerBroker.postMessage(
365
+ `TileManager_${scene_id}.buildTileStylesCompleted`,
366
+ WorkerBroker.withTransferables({ tile: Tile.slice(tile), progress: { start: true, done: true } })
367
+ );
368
+ Collision.resetTile(tile.id); // clear collision if we're done with the tile
369
+ return;
370
+ }
371
+
372
+ // Build each group of styles
373
+ const progress: TileBuildProgress = {};
374
+ for (const group_name in groups) {
375
+ Tile.buildStyleGroup({ group_name, groups, tile, progress, scene_id });
376
+ }
377
+ }
378
+
379
+ // Build a single group of styles
380
+ static async buildStyleGroup({ group_name, groups, tile, progress, scene_id }: {group_name: string; groups: Record<string, TileBuildStyle[] | null>; tile: WorkerBuildTile; progress: TileBuildProgress; scene_id: number | string}) {
381
+ const group = groups[group_name]!;
382
+ const mesh_data: Record<string, TileStylePayload> = {};
383
+ try {
384
+ // For each group, build all styles in the group
385
+ await Promise.all(group.map(async (style) => {
386
+ try {
387
+ const style_data = await style.endData(tile);
388
+ if (style_data) {
389
+ mesh_data[style.name] = style_data;
390
+ }
391
+ } catch (error) {
392
+ // Drain sibling styles before transferring the failed batch,
393
+ // including any texture references they have acquired.
394
+ progress.error = progress.error || ((error && (error as {stack?: string}).stack) || String(error)) as string;
395
+ }
396
+ }));
397
+
398
+ // Mark the group as done, and check if all groups have finished
399
+ log('trace', `Finished style group '${group_name}' for tile ${tile.key}`);
400
+ groups[group_name] = null;
401
+ if (Object.keys(groups).every(g => groups[g] == null)) {
402
+ progress.done = true;
403
+ }
404
+
405
+ // Send meshes to main thread
406
+ WorkerBroker.postMessage(
407
+ `TileManager_${scene_id}.${progress.error ? 'buildTileError' : 'buildTileStylesCompleted'}`,
408
+ WorkerBroker.withTransferables(progress.error ?
409
+ { ...Tile.slice(tile), mesh_data, error: progress.error } :
410
+ { tile: { ...Tile.slice(tile), mesh_data }, progress })
411
+ );
412
+ if (progress.done) {
413
+ Collision.resetTile(tile.id); // clear collision if we're done with the tile
414
+ }
415
+ }
416
+ catch (e) {
417
+ log('error', `Error for style group '${group_name}' for tile ${tile.key}`, (e && (e as {stack?: string}).stack) || e);
418
+ WorkerBroker.postMessage(`TileManager_${scene_id}.buildTileError`,
419
+ WorkerBroker.withTransferables({ ...Tile.slice(tile), mesh_data, error: (e && (e as {stack?: string}).stack) || String(e) }));
420
+ }
421
+ }
422
+
423
+ /**
424
+ Retrieves geometry from a tile according to a data source definition
425
+ Returns an array of objects with:
426
+ layer: source layer name
427
+ geom: GeoJSON FeatureCollection
428
+ */
429
+ static getDataForSource (source_data: WorkerBuildTile['source_data'], source_config: TileBuildLayer['config_data'], scene_layer_name: string) {
430
+ var layers: {layer?: string; geom: {features: DecodedTileFeature[]} | undefined}[] = [];
431
+
432
+ if (source_config != null && source_data != null && source_data.layers != null) {
433
+ // If source wildcard is specified, combine all source layers
434
+ if (source_config.all_layers === true) {
435
+ // Wildcard takes precedence over explicit source layer(s)
436
+ if (source_config.layer != null) {
437
+ const msg = `Layer ${scene_layer_name} includes both 'all_layers: true' and an explicit ` +
438
+ '\'layer\' keyword in its \'data\' block. \'all_layers: true\' takes precedence, \'layer\' ' +
439
+ 'will be ignored.';
440
+ log({ level: 'warn', once: true }, msg);
441
+ }
442
+
443
+ for (const layer in source_data.layers) {
444
+ layers.push({ layer, geom: source_data.layers![layer] });
445
+ }
446
+ }
447
+ // If no source layer specified, and a default data source layer exists
448
+ else if (!source_config.layer && source_data.layers._default) {
449
+ layers.push({
450
+ geom: source_data.layers._default
451
+ });
452
+ }
453
+ // If no source layer is specified, and a layer for the scene layer name exists
454
+ else if (!source_config.layer && scene_layer_name) {
455
+ layers.push({
456
+ layer: scene_layer_name,
457
+ geom: source_data.layers[scene_layer_name]
458
+ });
459
+ }
460
+ // If a source layer is specified by name, use it
461
+ else if (typeof source_config.layer === 'string') {
462
+ layers.push({
463
+ layer: source_config.layer,
464
+ geom: source_data.layers[source_config.layer]
465
+ });
466
+ }
467
+ // If multiple source layers are specified by name, combine them
468
+ else if (Array.isArray(source_config.layer)) {
469
+ source_config.layer.forEach(layer => {
470
+ layers.push({ layer, geom: source_data.layers![layer] });
471
+ });
472
+ }
473
+ }
474
+
475
+ return layers;
476
+ }
477
+
478
+ /**
479
+ Called on main thread when a web worker completes processing
480
+ for a single tile.
481
+ */
482
+ /** Begin an isolated mesh generation; the existing display remains owned by this tile. */
483
+ beginTerrainStage(): void {
484
+ this.discardTerrainStage();
485
+ this.terrainStage = {meshes: {}, labels: null, styles: []};
486
+ }
487
+
488
+ /** Release only staged replacement buffers after cancellation, removal or failure. */
489
+ discardTerrainStage(): void {
490
+ const stage = this.terrainStage;
491
+ this.terrainStage = undefined;
492
+ if (stage) for (const meshes of [stage.meshes, stage.labels ?? {}]) for (const parts of Object.values(meshes)) for (const mesh of parts) mesh.destroy();
493
+ }
494
+
495
+ /** Publish complete draw owners together, with one shared transition origin for every tile. */
496
+ commitTerrainStage(time: number): void {
497
+ const stage = this.terrainStage;
498
+ if (!stage) return;
499
+ this.terrainStage = undefined;
500
+ this.freeResources();
501
+ this.meshes = stage.meshes; this.pending_label_meshes = stage.labels; this.new_mesh_styles = stage.styles;
502
+ if (stage.done) this.built = true;
503
+ for (const meshes of [stage.meshes, stage.labels ?? {}]) for (const parts of Object.values(meshes)) for (const mesh of parts) mesh.terrainVisibleAt = time;
504
+ }
505
+
506
+ /** Upload incrementally without replacing any currently admitted terrain draw owners. */
507
+ buildMeshes(styles: Record<string, TileBuildStyle>, progress: TileBuildProgress) {
508
+ const stage = this.terrainStage;
509
+ if (!stage) return this.buildMeshBatch(styles, progress);
510
+ const meshes = this.meshes, labels = this.pending_label_meshes, previousStyles = this.new_mesh_styles;
511
+ this.meshes = stage.meshes; this.pending_label_meshes = stage.labels; this.new_mesh_styles = stage.styles;
512
+ this.terrainUploadOwners = [];
513
+ try {this.buildMeshBatch(styles, progress);}
514
+ catch (error) {
515
+ // The rejected raw batch still owns its transferred texture references.
516
+ // Release new buffers here; TileManager aborts those references exactly once.
517
+ for (const mesh of this.terrainUploadOwners) {mesh.textures = undefined; mesh.destroy();}
518
+ throw error;
519
+ }
520
+ finally {
521
+ this.terrainUploadOwners = undefined;
522
+ stage.meshes = this.meshes; stage.labels = this.pending_label_meshes; stage.styles = this.new_mesh_styles;
523
+ this.meshes = meshes; this.pending_label_meshes = labels; this.new_mesh_styles = previousStyles;
524
+ }
525
+ }
526
+
527
+ buildMeshBatch(styles: Record<string, TileBuildStyle>, progress: TileBuildProgress) {
528
+ if (this.error) {
529
+ return;
530
+ }
531
+
532
+ this.build_id = build_id++; // record order in which tile was built
533
+
534
+ // Debug
535
+ if (progress.start) {
536
+ this.debug.geometry_count = 0;
537
+ this.debug.buffer_size = 0;
538
+ }
539
+
540
+ // Create VBOs
541
+ let meshes: Record<string, VBOMesh[]> = {}; // new data to be added to tile
542
+ let mesh_data = this.mesh_data;
543
+ if (mesh_data) {
544
+ for (let s in mesh_data) {
545
+ for (let variant in mesh_data[s].meshes) {
546
+ let mesh_variant = mesh_data[s].meshes[variant];
547
+ if (mesh_variant.vertex_data) {
548
+ if (!styles[s]) {
549
+ log('warn', `Could not create mesh because style '${s}' not found, for tile ${this.key}, aborting tile`);
550
+ break;
551
+ }
552
+
553
+ // first add style-level uniforms, then add any mesh-specific ones
554
+ let mesh_options = Object.assign({}, mesh_data[s]);
555
+ mesh_options.uniforms = Object.assign({}, mesh_options.uniforms, mesh_variant.uniforms);
556
+ mesh_options.variant = mesh_variant.variant;
557
+ mesh_options.tileZoom = this.coords.z;
558
+
559
+ // for labels, keep buffer data on CPU so they can be modified later
560
+ if (mesh_variant.labels) {
561
+ mesh_options.retain = true;
562
+ }
563
+
564
+ let mesh = styles[s].makeMesh(mesh_variant.vertex_data, mesh_variant.vertex_elements, mesh_options);
565
+ this.terrainUploadOwners?.push(mesh);
566
+ mesh.variant = mesh_options.variant;
567
+ mesh.labels = mesh_variant.labels;
568
+ mesh.terrainQueryMesh = mesh_variant.terrain_surface;
569
+ meshes[s] = meshes[s] || [];
570
+ meshes[s].push(mesh);
571
+ if (mesh.variant.mesh_order == null) {
572
+ mesh.variant.mesh_order = meshes[s].length - 1; // assign default variant render order
573
+ }
574
+
575
+ this.debug.buffer_size! += mesh.buffer_size;
576
+ this.debug.geometry_count! += mesh.geometry_count;
577
+ }
578
+ }
579
+
580
+ // Sort mesh variants by explicit render order (if present)
581
+ if (meshes[s]) {
582
+ meshes[s].sort((a, b) => {
583
+ // Sort variant order ascending if present, then all null values (where order is unspecified)
584
+ let ao = a.variant.mesh_order, bo = b.variant.mesh_order;
585
+ return (ao == null ? 1 : (bo == null ? -1 : (ao < bo ? -1 : 1)));
586
+ });
587
+ }
588
+ }
589
+ }
590
+ delete this.mesh_data;
591
+
592
+ // New meshes
593
+ for (let m in meshes) {
594
+ // swap in non-collision meshes right away
595
+ if (!styles[m].collision) {
596
+ if (this.meshes[m]) {
597
+ this.meshes[m].forEach(m => m.destroy()); // free old meshes
598
+ }
599
+
600
+ this.meshes[m] = meshes[m]; // set new mesh
601
+ this.new_mesh_styles.push(m);
602
+ }
603
+ // keep label meshes out of view until collision is complete
604
+ else {
605
+ this.pending_label_meshes = this.pending_label_meshes || {};
606
+ this.pending_label_meshes[m] = meshes[m];
607
+ }
608
+ }
609
+
610
+ if (progress.done) {
611
+ // Release un-replaced meshes (existing in previous generation, but weren't built for this one)
612
+ for (let m in this.meshes) {
613
+ if (this.new_mesh_styles.indexOf(m) === -1 && (!this.pending_label_meshes || this.pending_label_meshes[m] == null)) {
614
+ this.meshes[m].forEach(m => m.destroy());
615
+ delete this.meshes[m];
616
+ }
617
+ }
618
+ this.new_mesh_styles = [];
619
+
620
+ this.debug.geometry_ratio = (this.debug.geometry_count! / this.debug.feature_count!).toFixed(1);
621
+ }
622
+ this.printDebug(progress);
623
+ }
624
+
625
+ // How many styles are currently pending label collision
626
+ pendingLabelStyleCount () {
627
+ return this.pending_label_meshes ? Object.keys(this.pending_label_meshes).length : 0;
628
+ }
629
+
630
+ // Swap label style meshes after collision is complete
631
+ swapPendingLabels () {
632
+ this.labeled = true; // mark as labeled
633
+
634
+ if (this.pending_label_meshes) {
635
+ for (let m in this.pending_label_meshes) {
636
+ if (this.meshes[m]) {
637
+ this.meshes[m].forEach(m => m.destroy()); // free old meshes
638
+ }
639
+
640
+ this.meshes[m] = this.pending_label_meshes[m]; // set new mesh
641
+ }
642
+ this.pending_label_meshes = null;
643
+ }
644
+ }
645
+
646
+ /**
647
+ Called on main thread when web worker completes processing, but tile has since been discarded
648
+ Frees resources that would have been transferred to the tile object.
649
+ Static method because the tile object no longer exists (the tile data returned by the worker is passed instead).
650
+ */
651
+ static abortBuild (tile: {id?: string | number; key?: string; mesh_data?: Record<string, TileStylePayload>}) {
652
+ Task.removeForTile(tile.id);
653
+ Collision.abortTile(tile.id);
654
+
655
+ // Releases meshes
656
+ if (tile.mesh_data) {
657
+ for (let s in tile.mesh_data) {
658
+ let textures = tile.mesh_data[s].textures;
659
+ if (textures) {
660
+ textures.forEach(t => {
661
+ let texture = Texture.textures[t];
662
+ if (texture) {
663
+ log('trace', `releasing texture ${t} for tile ${tile.key}`);
664
+ Texture.release(t); // Worker metadata never owns a GPU release method.
665
+ }
666
+ });
667
+ }
668
+ }
669
+ }
670
+ }
671
+
672
+ // Set as a proxy tile for another tile
673
+ setProxyFor (tile?: Tile | null) {
674
+ if (tile) {
675
+ this.visible = true;
676
+ this.proxy_for = this.proxy_for || [];
677
+ this.proxy_for.push(tile);
678
+ this.proxy_order_offset = 1; // draw proxies a half-layer back (order is scaled 2x to avoid integer truncation)
679
+ tile.proxied_as = (tile.style_z > this.style_z ? 'child' : 'parent');
680
+ this.proxy_level = Math.abs(tile.style_z - this.style_z); // # of zoom levels proxy is above/below target tile
681
+ }
682
+ else {
683
+ this.proxy_for = null;
684
+ this.proxy_order_offset = 0;
685
+ this.proxy_level = 0;
686
+ }
687
+ }
688
+
689
+ isProxy () {
690
+ return this.proxy_for != null;
691
+ }
692
+
693
+ // Proxy tiles only need to render a specific style if any of the tiles they are proxying *for*
694
+ // haven't finished loading that style yet. If all proxied tiles *have* data for that style, then it's
695
+ // safe to hide the proxy tile's version.
696
+ shouldProxyForStyle (style: string) {
697
+ return !this.proxy_for || this.proxy_for.some(t => t.meshes[style] == null);
698
+ }
699
+
700
+ // Update model matrix and tile uniforms
701
+ setupProgram ({ model, model32 }: {model: Float64Array; model32: Float32Array}, program: {uniform(type: string, name: string, value: number | boolean | number[] | Float32Array): unknown}, uniform_buffer?: UniformBuffer) {
702
+ // Model - transform tile space into world space (meters, absolute mercator position)
703
+ this.matrix4.identity().translate([this.min.x, this.min.y, 0])
704
+ .scale([this.span.x / Geo.tile_scale, this.span.y / Geo.tile_scale, 1])
705
+ .toArray(model);
706
+ model32.set(model);
707
+ const tile_fade_in = this.fade_in && this.proxied_as !== 'child';
708
+
709
+ if (uniform_buffer) {
710
+ uniform_buffer.setUniforms({
711
+ u_tile_origin: [this.min.x, this.min.y, this.style_z, this.coords.z],
712
+ u_tile_proxy_order_offset: this.proxy_order_offset,
713
+ u_model: model32,
714
+ u_tile_fade_in: tile_fade_in
715
+ });
716
+ }
717
+ else {
718
+ program.uniform('4fv', 'u_tile_origin', [this.min.x, this.min.y, this.style_z, this.coords.z]);
719
+ program.uniform('1f', 'u_tile_proxy_order_offset', this.proxy_order_offset);
720
+ program.uniform('Matrix4fv', 'u_model', model32);
721
+
722
+ // Fade in labels according to proxy status, avoiding "flickering" where
723
+ // labels quickly go from invisible back to visible
724
+ program.uniform('1i', 'u_tile_fade_in', tile_fade_in);
725
+ }
726
+ }
727
+
728
+ // Slice a subset of keys out of a tile
729
+ // Includes a minimum set of pre-defined keys for load state, debug. etc.
730
+ // We use this to send a subset of the tile back to the main thread, to minimize unnecessary data transfer
731
+ // (e.g. very large items like feature geometry are not needed on the main thread)
732
+ static slice(tile: Tile, keys?: string[]): Pick<Tile, 'id' | 'key' | 'loading' | 'loaded' | 'generation' | 'error' | 'debug'> & Record<string, unknown>;
733
+ static slice(tile: Pick<WorkerBuildTile, 'id' | 'key' | 'loading' | 'loaded' | 'generation' | 'error' | 'debug'>, keys?: string[]): Pick<WorkerBuildTile, 'id' | 'key' | 'loading' | 'loaded' | 'generation' | 'error' | 'debug'> & Record<string, unknown>;
734
+ static slice (tile: Pick<WorkerBuildTile, 'id' | 'key' | 'loading' | 'loaded' | 'generation' | 'error' | 'debug'> | Tile, keys?: string[]) {
735
+ const keep = Array.isArray(keys) ? keys : [];
736
+
737
+ // Build the tile subset
738
+ var tile_subset = {id: tile.id, key: tile.key, loading: tile.loading, loaded: tile.loaded,
739
+ generation: tile.generation, error: tile.error, debug: tile.debug};
740
+ for (let k=0; k < keep.length; k++) {
741
+ const key = keep[k];
742
+ Reflect.set(tile_subset, key, Reflect.get(tile, key)); // Optional extension keys remain wire-envelope properties.
743
+ }
744
+
745
+ return tile_subset;
746
+ }
747
+
748
+ merge (other: Pick<WorkerBuildTile, 'mesh_data' | 'debug'> & {loading: boolean; loaded: boolean; generation: number | null; error: string | null}) {
749
+ this.loading = other.loading;
750
+ this.loaded = other.loaded;
751
+ this.generation = other.generation;
752
+ this.error = other.error;
753
+ this.mesh_data = other.mesh_data;
754
+ this.debug = mergeObjects(this.debug, other.debug);
755
+ return this;
756
+ }
757
+
758
+ printDebug (progress: TileBuildProgress) {
759
+ const exclude = ['layers'];
760
+ let copy: Record<string, unknown> = {};
761
+ for (let key in this.debug) {
762
+ if (exclude.indexOf(key) === -1) {
763
+ copy[key] = this.debug[key];
764
+ }
765
+ }
766
+
767
+ log('debug', `Tile ${progress.done ? '(done)' : ''}: debug for ${this.key}: [ ${JSON.stringify(copy)} ]`);
768
+ }
769
+
770
+ }
771
+
772
+ Tile.coord_children = {}; // only allocate children coordinates once per coordinate
773
+
774
+ /** Preserve the legacy null-geometry guard while narrowing decoded GeoJSON for style evaluation. */
775
+ function hasFeatureGeometry(feature: DecodedTileFeature): feature is DecodedTileFeature & StyleFeature {
776
+ return feature.geometry != null;
777
+ }
778
+
779
+ // Sum up layer feature/geometry stats from a set of tiles
780
+ export function debugSumLayerStats(tiles: readonly Pick<Tile, 'debug'>[]) {
781
+ let list: Record<string, LayerDebugCounts> = {}, tree: Record<string, LayerDebugCounts> = {};
782
+
783
+ tiles.filter(tile => tile.debug.layers).forEach(tile => {
784
+ // layer list
785
+ Object.keys(tile.debug.layers!.list).forEach(layer => {
786
+ let counts = tile.debug.layers!.list[layer];
787
+ addLayerDebugEntry(list, layer, counts.features, counts.geoms, counts.styles, counts.base);
788
+ });
789
+
790
+ // layer tree
791
+ addDebugLayers(tile.debug.layers!.tree, tree);
792
+ });
793
+
794
+ return { list, tree };
795
+ }
796
+
797
+ // build debug stats layer tree
798
+ function addDebugLayers (node: Record<string, LayerDebugCounts>, tree: Record<string, LayerDebugCounts>) {
799
+ for (let layer in node) {
800
+ let counts = node[layer];
801
+ addLayerDebugEntry(tree, layer, counts.features, counts.geoms, counts.styles, counts.base);
802
+ if (counts.layers) {
803
+ tree[layer].layers = tree[layer].layers || {};
804
+ addDebugLayers(counts.layers, tree[layer].layers); // process child layers
805
+ }
806
+ }
807
+ }