@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,116 @@
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 {Matrix3, Matrix4} from '@math.gl/core';
7
+ import type {HostProjection} from '../types';
8
+
9
+ export type Matrix = Float32Array | Float64Array;
10
+ export type Vector = number[] | Float32Array | Float64Array;
11
+ export type CameraType = 'external' | 'isometric' | 'flat' | 'perspective';
12
+ export type CameraConfiguration = {
13
+ type?: CameraType;
14
+ position?: number[];
15
+ zoom?: number;
16
+ focal_length?: number | number[][];
17
+ fov?: number | number[][];
18
+ vanishing_point?: number[];
19
+ axis?: {x: number; y: number} | number[];
20
+ };
21
+ export type CameraView = {
22
+ /** Host geographic projection; omitted by classic planar cameras. */
23
+ projection?: HostProjection;
24
+ setView(view: {lng?: number; lat?: number; zoom?: number}): void;
25
+ scene: {requestRedraw(): void};
26
+ size: {
27
+ css: {width: number; height: number};
28
+ meters: {x: number; y: number};
29
+ };
30
+ aspect: number;
31
+ meters_per_pixel: number;
32
+ zoom: number;
33
+ center: {meters: {x: number; y: number}};
34
+ };
35
+ export type Program = {uniform(type: string, name: string, value: Vector | Matrix): void};
36
+ export type UniformBuffer = {setUniforms(uniforms: Record<string, Vector | Matrix | number | boolean>): void};
37
+ export type MatrixSet = {
38
+ model_view32: Matrix;
39
+ model: Matrix;
40
+ normal32: Matrix;
41
+ inverse_normal32: Matrix;
42
+ };
43
+
44
+ // Abstract base class
45
+ export default class Camera {
46
+ readonly view: CameraView;
47
+ readonly position?: number[];
48
+ readonly zoom?: number;
49
+ private readonly matrix3 = new Matrix3();
50
+ protected readonly matrix4 = new Matrix4();
51
+ type?: CameraType;
52
+ view_matrix: Matrix = new Float64Array(16);
53
+ projection_matrix: Matrix = new Float32Array(16);
54
+ position_meters: Vector = [0, 0, 0];
55
+
56
+ constructor(name: string, view: CameraView, options: CameraConfiguration = {}) {
57
+ this.view = view;
58
+ this.position = options.position;
59
+ this.zoom = options.zoom;
60
+ }
61
+
62
+ // Update method called once per frame
63
+ update(): void {
64
+ }
65
+
66
+ // Called once per frame per program (e.g. for main render pass, then for each additional pass for feature selection, etc.)
67
+ setupProgram(/*program*/ _program?: Program, _uniformBuffer?: UniformBuffer): void {
68
+ }
69
+
70
+ // Sync camera position/zoom to scene view
71
+ updateView (): void {
72
+ if (this.position || this.zoom) {
73
+ let view: {lng?: number; lat?: number; zoom?: number} = {};
74
+ if (this.position) {
75
+ view = { lng: this.position[0], lat: this.position[1], zoom: this.position[2] };
76
+ }
77
+ if (this.zoom) {
78
+ view.zoom = this.zoom;
79
+ }
80
+ this.view.setView(view);
81
+ }
82
+ }
83
+
84
+ // Set model-view and normal matrices
85
+ setupMatrices (matrices: MatrixSet, program: Program, uniform_buffer?: UniformBuffer): void {
86
+ // Model view matrix - transform tile space into view space (meters, relative to camera)
87
+ this.matrix4.copy(this.view_matrix).multiplyRight(matrices.model).toArray(matrices.model_view32);
88
+
89
+ // Normal matrices - transforms surface normals into view space
90
+ const normal_matrix = this.matrix3.set(
91
+ matrices.model_view32[0], matrices.model_view32[1], matrices.model_view32[2],
92
+ matrices.model_view32[4], matrices.model_view32[5], matrices.model_view32[6],
93
+ matrices.model_view32[8], matrices.model_view32[9], matrices.model_view32[10]
94
+ );
95
+ if (normal_matrix.determinant() !== 0) {
96
+ normal_matrix.invert().transpose().toArray(matrices.normal32);
97
+ normal_matrix.copy(matrices.normal32);
98
+ if (normal_matrix.determinant() !== 0) {
99
+ normal_matrix.invert().toArray(matrices.inverse_normal32);
100
+ }
101
+ }
102
+ if (uniform_buffer) {
103
+ uniform_buffer.setUniforms({
104
+ u_modelView: matrices.model_view32,
105
+ u_normalMatrix: matrices.normal32,
106
+ u_inverseNormalMatrix: matrices.inverse_normal32
107
+ });
108
+ }
109
+ else {
110
+ program.uniform('Matrix4fv', 'u_modelView', matrices.model_view32);
111
+ program.uniform('Matrix3fv', 'u_normalMatrix', matrices.normal32);
112
+ program.uniform('Matrix3fv', 'u_inverseNormalMatrix', matrices.inverse_normal32);
113
+ }
114
+ }
115
+
116
+ }
@@ -0,0 +1,20 @@
1
+ // tangram-layers
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import CoreScene from './scene';
6
+ import Camera from './camera';
7
+ import type {RendererOptions, SceneDefinition} from '../types';
8
+
9
+ /** Standalone Scene with classic camera construction; host renderers use CoreScene. */
10
+ export default class Scene extends CoreScene {
11
+ /** Constructs a standalone scene without changing explicitly external camera mode. */
12
+ constructor(config: SceneDefinition, options: RendererOptions = {}) {
13
+ super(config, {...options, cameraFactory: Camera.create});
14
+ }
15
+
16
+ /** Creates a scene with Tangram's perspective, isometric, and flat cameras. */
17
+ static create(config: SceneDefinition, options: RendererOptions = {}): Scene {
18
+ return new Scene(config, options);
19
+ }
20
+ }
@@ -0,0 +1,101 @@
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 ShaderProgram from '../gl/shader_program';
7
+ import Camera, {type CameraView, type CameraConfiguration, type Matrix, type Vector, type Program, type UniformBuffer} from './camera_base';
8
+ import type {Matrix4 as HostMatrix} from '../types';
9
+
10
+ /**
11
+ Camera whose view and projection matrices are supplied by an embedding renderer.
12
+
13
+ This lets hosts such as deck.gl remain authoritative for camera projection while
14
+ Tangram continues to manage scene loading, tile selection, and drawing.
15
+ */
16
+ export default class ExternalCamera extends Camera {
17
+ readonly vanishing_point: number[];
18
+
19
+ constructor(name: string, view: CameraView, options: CameraConfiguration = {}) {
20
+ super(name, view, options);
21
+ this.type = 'external';
22
+ this.position_meters = [0, 0, 0];
23
+ this.vanishing_point = [0, 0];
24
+ this.view_matrix = new Float64Array(16);
25
+ this.projection_matrix = new Float32Array(16);
26
+ this.matrix4.identity().toArray(this.view_matrix);
27
+ this.matrix4.identity().toArray(this.projection_matrix);
28
+
29
+ ShaderProgram.replaceBlock('camera', `
30
+ uniform mat4 u_projection;
31
+ uniform vec3 u_eye;
32
+ uniform vec2 u_vanishing_point;
33
+
34
+ void cameraProjection (inout vec4 position) {
35
+ position = u_projection * position;
36
+ }`
37
+ );
38
+ }
39
+
40
+ setMatrices({view, projection, position = [0, 0, 0]}: {view: HostMatrix; projection: HostMatrix; position?: ArrayLike<number>}): boolean {
41
+ if (!view || view.length !== 16 || !projection || projection.length !== 16) {
42
+ throw new Error('ExternalCamera requires 4x4 view and projection matrices');
43
+ }
44
+ const changed = !matrixEquals(this.view_matrix, view) ||
45
+ !matrixEquals(this.projection_matrix, projection) ||
46
+ !vectorEquals(this.position_meters, position);
47
+ if (!changed) {
48
+ return false;
49
+ }
50
+ this.view_matrix.set(view);
51
+ this.projection_matrix.set(projection);
52
+ this.position_meters = Array.from(position);
53
+ this.view.scene.requestRedraw();
54
+ return true;
55
+ }
56
+
57
+ setupProgram(program: Program, uniform_buffer?: UniformBuffer): void {
58
+ if (uniform_buffer) {
59
+ uniform_buffer.setUniforms({
60
+ u_projection: this.projection_matrix,
61
+ u_eye: this.position_meters,
62
+ u_vanishing_point: this.vanishing_point
63
+ });
64
+ }
65
+ else {
66
+ program.uniform('Matrix4fv', 'u_projection', this.projection_matrix);
67
+ program.uniform('3fv', 'u_eye', this.position_meters);
68
+ program.uniform('2fv', 'u_vanishing_point', this.vanishing_point);
69
+ }
70
+ }
71
+
72
+ /** Keep globe directional lights in common space; planar lights remain view-relative. */
73
+ transformVector(vector: Vector): number[] {
74
+ if (this.view.projection?.type === 'globe') {
75
+ const length = Math.hypot(...vector);
76
+ return length === 0 ? Array.from(vector) : Array.from(vector, value => value / length);
77
+ }
78
+ const matrix = this.view_matrix;
79
+ const transformed = [
80
+ matrix[0] * vector[0] + matrix[4] * vector[1] + matrix[8] * vector[2],
81
+ matrix[1] * vector[0] + matrix[5] * vector[1] + matrix[9] * vector[2],
82
+ matrix[2] * vector[0] + matrix[6] * vector[1] + matrix[10] * vector[2]
83
+ ];
84
+ const length = Math.hypot(...transformed);
85
+ return length === 0 ? transformed : transformed.map(value => value / length);
86
+ }
87
+
88
+ }
89
+
90
+ function matrixEquals(left: Matrix, right: ArrayLike<number>): boolean {
91
+ for (let index = 0; index < 16; index++) {
92
+ if (left[index] !== right[index]) {
93
+ return false;
94
+ }
95
+ }
96
+ return true;
97
+ }
98
+
99
+ function vectorEquals(left: Vector, right: ArrayLike<number>): boolean {
100
+ return left.length === right.length && left.every((value, index) => value === right[index]);
101
+ }
@@ -0,0 +1,120 @@
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 { getPropertyPathTarget } from '../utils/props';
8
+
9
+ // prefix used to identify global property references
10
+ const GLOBAL_PREFIX = 'global.';
11
+ const GLOBAL_PREFIX_LENGTH = GLOBAL_PREFIX.length;
12
+
13
+ // name of 'hidden' (non-enumerable) property used to track global property references on an object
14
+ const GLOBAL_REGISTRY = '__global_prop';
15
+
16
+ /** Authored globals may contain scalars, functions, arrays, or opaque application values. */
17
+ type GlobalObject = Record<string, unknown>;
18
+ /** Non-enumerable provenance attached to objects/arrays after substitution. */
19
+ type GlobalTarget = Record<PropertyKey, unknown> & {
20
+ [GLOBAL_REGISTRY]?: Record<PropertyKey, string>;
21
+ };
22
+
23
+ // Property name references a global property?
24
+ /** Identify URL/global-reference strings while retaining omitted resource values. */
25
+ export function isGlobalReference (val: string | null | undefined): boolean {
26
+ return val?.slice(0, GLOBAL_PREFIX_LENGTH) === GLOBAL_PREFIX;
27
+ }
28
+
29
+ // Has object property been substitued with a value from a global reference?
30
+ // Property provided as a single-depth string name, or nested path array (`a.b.c` => ['a', 'b', 'c'])
31
+ /** Inspect substitution provenance for a named property or nested object/array path. */
32
+ export function isGlobalSubstitution (object: object, prop_or_path: string | (string | number)[]): boolean {
33
+ const path = Array.isArray(prop_or_path) ? prop_or_path : [prop_or_path];
34
+ const target = getPropertyPathTarget(object, path) as GlobalTarget | undefined;
35
+ const prop = path[path.length - 1];
36
+ return target?.[GLOBAL_REGISTRY]?.[prop] !== undefined;
37
+ }
38
+
39
+ // Flatten nested global properties for simpler string look-ups
40
+ /** Flatten global records without discarding their original nested values. */
41
+ export function flattenGlobalProperties (obj: GlobalObject, prefix: string | null = null, globals: GlobalObject = {}): GlobalObject {
42
+ prefix = prefix ? (prefix + '.') : GLOBAL_PREFIX;
43
+
44
+ for (const p in obj) {
45
+ const key = prefix + p;
46
+ const val = obj[p];
47
+ globals[key] = val;
48
+
49
+ if (typeof val === 'object' && !Array.isArray(val)) {
50
+ flattenGlobalProperties(val as GlobalObject, key, globals);
51
+ }
52
+ }
53
+ return globals;
54
+ }
55
+
56
+ // Find and apply new global properties (and re-apply old ones)
57
+ /** Reapply globals using hidden provenance, retaining the input object's identity and type. */
58
+ export function applyGlobalProperties<Value>(globals: GlobalObject, obj: Value, target?: object, key?: string | number): Value {
59
+ let prop: string | undefined;
60
+ const targetRecord = target as GlobalTarget | undefined;
61
+
62
+ // Check for previously applied global substitution
63
+ if (targetRecord?.[GLOBAL_REGISTRY]?.[key!]) {
64
+ prop = targetRecord[GLOBAL_REGISTRY][key!];
65
+ }
66
+ // Check string for new global substitution
67
+ else if (typeof obj === 'string' && obj.slice(0, GLOBAL_PREFIX_LENGTH) === GLOBAL_PREFIX) {
68
+ prop = obj;
69
+ }
70
+
71
+ // Found global property to substitute
72
+ if (prop) {
73
+ // Mark property as global substitution
74
+ if (targetRecord![GLOBAL_REGISTRY] == null) {
75
+ Object.defineProperty(targetRecord!, GLOBAL_REGISTRY, { value: {} });
76
+ }
77
+ targetRecord![GLOBAL_REGISTRY]![key!] = prop;
78
+
79
+ // Get current global value
80
+ let val = globals[prop];
81
+ let stack: string[] | undefined;
82
+ while (typeof val === 'string' && val.slice(0, GLOBAL_PREFIX_LENGTH) === GLOBAL_PREFIX) {
83
+ // handle globals that refer to other globals, detecting any cyclical references
84
+ stack = stack || [prop];
85
+ if (stack.indexOf(val) > -1) {
86
+ log({ level: 'warn', once: true }, 'Global properties: cyclical reference detected', stack);
87
+ val = null;
88
+ break;
89
+ }
90
+ stack.push(val);
91
+ val = globals[val];
92
+ }
93
+
94
+ // Create getter/setter
95
+ Object.defineProperty(targetRecord!, key!, {
96
+ enumerable: true,
97
+ get: function () {
98
+ return val; // return substituted value
99
+ },
100
+ set: function (v: unknown) {
101
+ // clear the global substitution and remove the getter/setter
102
+ delete targetRecord![GLOBAL_REGISTRY]![key!];
103
+ delete targetRecord![key!];
104
+ targetRecord![key!] = v; // save the new value
105
+ }
106
+ });
107
+ }
108
+ // Loop through object keys or array indices
109
+ else if (Array.isArray(obj)) {
110
+ for (let p = 0; p < obj.length; p++) {
111
+ applyGlobalProperties(globals, obj[p], obj, p);
112
+ }
113
+ }
114
+ else if (typeof obj === 'object') {
115
+ for (const p in obj) {
116
+ applyGlobalProperties(globals, obj[p], obj as object, p);
117
+ }
118
+ }
119
+ return obj;
120
+ }
@@ -0,0 +1,139 @@
1
+ // tangram-layers
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import {Matrix4} from '@math.gl/core';
6
+ import type {HostCamera} from '../types';
7
+ import type {Bounds} from '../utils/geo';
8
+
9
+ type Point = [number, number];
10
+
11
+ /**
12
+ * Intersects all twelve edges of a finite host frustum with EPSG:3857 ground.
13
+ * Optional meter-space limits clip the resulting convex polygon before bounds
14
+ * are calculated. Null means no ground area, not an unknown footprint.
15
+ * Matrices use column-major OpenGL clip coordinates, also on the WebGPU path.
16
+ */
17
+ export function calculatePlanarGroundBounds(camera: HostCamera, limits?: Bounds): Bounds | null {
18
+ return calculatePlanarVolumeBounds(camera, [0, 0], limits);
19
+ }
20
+
21
+ /**
22
+ * Bounds the finite frustum intersected with a closed elevation slab. Heights
23
+ * are physical meters; XY uses EPSG:3857 meters. This conservative candidate
24
+ * footprint includes elevated-only geometry, not terrain surface intersections.
25
+ * Optional horizontal limits clip the convex footprint, not its bounding box.
26
+ */
27
+ export function calculatePlanarVolumeBounds(camera: HostCamera,
28
+ elevationRange: readonly [number, number], limits?: Bounds): Bounds | null {
29
+ const [minimumElevation, maximumElevation] = elevationRange;
30
+ if (elevationRange.length !== 2 || !Number.isFinite(minimumElevation) ||
31
+ !Number.isFinite(maximumElevation) || minimumElevation > maximumElevation) {
32
+ throw new Error('Elevation range requires two finite ordered heights');
33
+ }
34
+ if (camera.view.length !== 16 || camera.projection.length !== 16 ||
35
+ !Array.from(camera.view).every(Number.isFinite) || !Array.from(camera.projection).every(Number.isFinite)) {
36
+ throw new Error('Ground footprint requires finite camera matrices');
37
+ }
38
+ if (limits && (![limits.sw.x, limits.sw.y, limits.ne.x, limits.ne.y].every(Number.isFinite) ||
39
+ limits.sw.x > limits.ne.x || limits.sw.y > limits.ne.y)) {
40
+ throw new Error('Ground footprint limits must be finite ordered bounds');
41
+ }
42
+ const inverse = new Matrix4().copy(camera.projection).multiplyRight(camera.view);
43
+ if (!Number.isFinite(inverse.determinant()) || inverse.determinant() === 0) {
44
+ throw new Error('Ground footprint camera is singular');
45
+ }
46
+ inverse.invert();
47
+ const corners: number[][] = [];
48
+ for (const depth of [-1, 1]) {
49
+ for (const vertical of [-1, 1]) {
50
+ for (const horizontal of [-1, 1]) {
51
+ const homogeneous = inverse.transform([horizontal, vertical, depth, 1]);
52
+ const point = Array.from(homogeneous).slice(0, 3).map(value => value / homogeneous[3]);
53
+ if (!point.every(Number.isFinite) || homogeneous[3] <= 0) {
54
+ throw new Error('Ground footprint requires a finite near and far frustum');
55
+ }
56
+ corners.push(point);
57
+ }
58
+ }
59
+ }
60
+ const points: Point[] = corners.filter(point => point[2] >= minimumElevation &&
61
+ point[2] <= maximumElevation).map(point => [point[0], point[1]]);
62
+ for (let index = 0; index < corners.length; index++) {
63
+ for (const bit of [1, 2, 4]) {
64
+ const adjacent = index ^ bit;
65
+ if (adjacent < index) continue;
66
+ const start = corners[index];
67
+ const end = corners[adjacent];
68
+ for (const elevation of [minimumElevation, maximumElevation]) {
69
+ if (start[2] === elevation) points.push([start[0], start[1]]);
70
+ if (end[2] === elevation) points.push([end[0], end[1]]);
71
+ if ((start[2] < elevation && end[2] > elevation) ||
72
+ (start[2] > elevation && end[2] < elevation)) {
73
+ const parameter = (elevation - start[2]) / (end[2] - start[2]);
74
+ points.push([start[0] + parameter * (end[0] - start[0]),
75
+ start[1] + parameter * (end[1] - start[1])]);
76
+ }
77
+ }
78
+ }
79
+ }
80
+ let polygon = convexHull(points);
81
+ if (polygon.length < 3) return null;
82
+ if (limits) {
83
+ polygon = clipPolygon(polygon, 0, limits.sw.x, true);
84
+ polygon = clipPolygon(polygon, 0, limits.ne.x, false);
85
+ polygon = clipPolygon(polygon, 1, limits.sw.y, true);
86
+ polygon = clipPolygon(polygon, 1, limits.ne.y, false);
87
+ }
88
+ if (polygon.length < 3) return null;
89
+ // Use a local origin to avoid cancellation for meter coordinates near the antimeridian.
90
+ const origin = polygon[0];
91
+ const twiceArea = polygon.reduce((area, point, index) => {
92
+ const next = polygon[(index + 1) % polygon.length];
93
+ return area + (point[0] - origin[0]) * (next[1] - origin[1]) -
94
+ (point[1] - origin[1]) * (next[0] - origin[0]);
95
+ }, 0);
96
+ if (twiceArea === 0) return null;
97
+ const bounds = {
98
+ sw: {x: Math.min(...polygon.map(point => point[0])), y: Math.min(...polygon.map(point => point[1]))},
99
+ ne: {x: Math.max(...polygon.map(point => point[0])), y: Math.max(...polygon.map(point => point[1]))}
100
+ };
101
+ return bounds.ne.x > bounds.sw.x && bounds.ne.y > bounds.sw.y ? bounds : null;
102
+ }
103
+
104
+ /** Monotone-chain hull removes duplicate/interior projected frustum corners. */
105
+ function convexHull(points: Point[]): Point[] {
106
+ const sorted = points.sort((left, right) => left[0] - right[0] || left[1] - right[1])
107
+ .filter((point, index, list) => index === 0 || point[0] !== list[index - 1][0] || point[1] !== list[index - 1][1]);
108
+ const cross = (origin: Point, first: Point, second: Point): number =>
109
+ (first[0] - origin[0]) * (second[1] - origin[1]) - (first[1] - origin[1]) * (second[0] - origin[0]);
110
+ const half = (list: Point[]): Point[] => {
111
+ const hull: Point[] = [];
112
+ for (const point of list) {
113
+ while (hull.length >= 2 && cross(hull[hull.length - 2], hull[hull.length - 1], point) <= 0) hull.pop();
114
+ hull.push(point);
115
+ }
116
+ return hull;
117
+ };
118
+ const lower = half(sorted), upper = half([...sorted].reverse());
119
+ return [...lower.slice(0, -1), ...upper.slice(0, -1)];
120
+ }
121
+
122
+ /** Clips a convex ground polygon against one axis-aligned half-plane. */
123
+ function clipPolygon(polygon: Point[], axis: 0 | 1, boundary: number, keepGreater: boolean): Point[] {
124
+ const result: Point[] = [];
125
+ const inside = (point: Point) => keepGreater ? point[axis] >= boundary : point[axis] <= boundary;
126
+ for (let index = 0; index < polygon.length; index++) {
127
+ const start = polygon[index];
128
+ const end = polygon[(index + 1) % polygon.length];
129
+ if (inside(start)) result.push(start);
130
+ if (inside(start) !== inside(end)) {
131
+ const parameter = (boundary - start[axis]) / (end[axis] - start[axis]);
132
+ const point: Point = [start[0] + parameter * (end[0] - start[0]),
133
+ start[1] + parameter * (end[1] - start[1])];
134
+ point[axis] = boundary;
135
+ result.push(point);
136
+ }
137
+ }
138
+ return result;
139
+ }