astro-viewer 3.0.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/dist/astroviewer.cjs +3082 -1410
  2. package/dist/astroviewer.js +1 -1
  3. package/dist/astroviewer.min.js +1 -1
  4. package/lib-esm/AstroSphere.d.ts +40 -16
  5. package/lib-esm/AstroSphere.js +359 -93
  6. package/lib-esm/AstroViewer.d.ts +20 -5
  7. package/lib-esm/AstroViewer.js +50 -0
  8. package/lib-esm/Camera.js +28 -14
  9. package/lib-esm/Config.d.ts +2 -0
  10. package/lib-esm/Config.js +15 -1
  11. package/lib-esm/Global.js +12 -0
  12. package/lib-esm/index.d.ts +8 -4
  13. package/lib-esm/index.js +17 -3
  14. package/lib-esm/model/AbstractSkyEntity.d.ts +1 -0
  15. package/lib-esm/model/AbstractSkyEntity.js +12 -0
  16. package/lib-esm/model/AstroGL.js +12 -0
  17. package/lib-esm/model/ColorMaps.js +12 -0
  18. package/lib-esm/model/MetadataColumn.js +12 -0
  19. package/lib-esm/model/MetadataManager.d.ts +1 -0
  20. package/lib-esm/model/MetadataManager.js +16 -1
  21. package/lib-esm/model/Point.d.ts +9 -1
  22. package/lib-esm/model/Point.js +30 -0
  23. package/lib-esm/model/Point2D.js +12 -0
  24. package/lib-esm/model/Source.js +12 -0
  25. package/lib-esm/model/SphereFoV.d.ts +30 -0
  26. package/lib-esm/model/SphereFoV.js +196 -0
  27. package/lib-esm/model/catalogues/CatalogueGL.js +12 -0
  28. package/lib-esm/model/catalogues/CatalogueProps.js +13 -1
  29. package/lib-esm/model/earth/{wmts/WMTSAdapter.d.ts → WMTSAdapter.d.ts} +2 -1
  30. package/lib-esm/model/earth/{wmts/WMTSAdapter.js → WMTSAdapter.js} +12 -0
  31. package/lib-esm/model/earth/XYZAnchestorTile.d.ts +17 -0
  32. package/lib-esm/model/earth/XYZAnchestorTile.js +87 -0
  33. package/lib-esm/model/earth/{types.d.ts → XYZConfig.d.ts} +6 -17
  34. package/lib-esm/model/earth/XYZConfig.js +13 -0
  35. package/lib-esm/model/earth/XYZFoVHelper.d.ts +12 -0
  36. package/lib-esm/model/earth/XYZFoVHelper.js +138 -0
  37. package/lib-esm/model/earth/XYZMap.d.ts +31 -0
  38. package/lib-esm/model/earth/XYZMap.js +208 -0
  39. package/lib-esm/model/earth/XYZMapDescriptor.d.ts +29 -0
  40. package/lib-esm/model/earth/XYZMapDescriptor.js +77 -0
  41. package/lib-esm/model/earth/XYZMeshBuilder.d.ts +1 -1
  42. package/lib-esm/model/earth/XYZMeshBuilder.js +13 -2
  43. package/lib-esm/model/earth/XYZTile.d.ts +20 -21
  44. package/lib-esm/model/earth/XYZTile.js +82 -102
  45. package/lib-esm/model/earth/XYZTileBuffer.d.ts +24 -26
  46. package/lib-esm/model/earth/XYZTileBuffer.js +60 -70
  47. package/lib-esm/model/earth/XYZTileRequestScheduler.d.ts +1 -1
  48. package/lib-esm/model/earth/XYZTileRequestScheduler.js +13 -2
  49. package/lib-esm/model/earth/XYZTypes.d.ts +24 -0
  50. package/lib-esm/model/earth/XYZTypes.js +13 -0
  51. package/lib-esm/model/earth/XYZVisibleTilesManager.d.ts +16 -27
  52. package/lib-esm/model/earth/XYZVisibleTilesManager.js +61 -192
  53. package/lib-esm/model/footprints/Footprint.d.ts +4 -1
  54. package/lib-esm/model/footprints/Footprint.js +30 -2
  55. package/lib-esm/model/footprints/FootprintProps.js +13 -1
  56. package/lib-esm/model/footprints/FootprintSetGL.d.ts +4 -2
  57. package/lib-esm/model/footprints/FootprintSetGL.js +21 -6
  58. package/lib-esm/model/grid/EquatorialGrid.d.ts +2 -1
  59. package/lib-esm/model/grid/EquatorialGrid.js +30 -12
  60. package/lib-esm/model/grid/GridTextHelper.d.ts +10 -19
  61. package/lib-esm/model/grid/GridTextHelper.js +70 -67
  62. package/lib-esm/model/grid/HealpixGrid.d.ts +4 -4
  63. package/lib-esm/model/grid/HealpixGrid.js +24 -8
  64. package/lib-esm/model/grid/LonLatGrid.d.ts +43 -0
  65. package/lib-esm/model/grid/LonLatGrid.js +309 -0
  66. package/lib-esm/model/hips/AllSky.js +12 -0
  67. package/lib-esm/model/hips/AncestorTile.js +12 -0
  68. package/lib-esm/model/hips/FoVHelper.d.ts +5 -2
  69. package/lib-esm/model/hips/FoVHelper.js +52 -3
  70. package/lib-esm/model/hips/HiPS.d.ts +2 -0
  71. package/lib-esm/model/hips/HiPS.js +38 -14
  72. package/lib-esm/model/hips/HiPSConfig.d.ts +13 -0
  73. package/lib-esm/model/hips/HiPSDescriptor.js +12 -0
  74. package/lib-esm/model/hips/Tile.d.ts +1 -0
  75. package/lib-esm/model/hips/Tile.js +15 -0
  76. package/lib-esm/model/hips/TileBuffer.d.ts +5 -0
  77. package/lib-esm/model/hips/TileBuffer.js +61 -0
  78. package/lib-esm/model/hips/VisibleTilesManager.js +12 -0
  79. package/lib-esm/model/tap/TapMetadata.js +12 -0
  80. package/lib-esm/model/tap/TapMetadataList.js +12 -0
  81. package/lib-esm/model/tap/TapRepo.js +12 -0
  82. package/lib-esm/model/terra/TerraFootprintSetGL.d.ts +6 -0
  83. package/lib-esm/model/terra/TerraFootprintSetGL.js +54 -0
  84. package/lib-esm/model/terra/TerraPointSetGL.js +12 -0
  85. package/lib-esm/services/SesameService.js +11 -3
  86. package/lib-esm/services/helpers.js +12 -0
  87. package/lib-esm/services/hipsNodeService.js +12 -0
  88. package/lib-esm/services/parse-hipslist.js +12 -0
  89. package/lib-esm/services/queryCatalogueByFoV.js +13 -1
  90. package/lib-esm/services/queryFootprintSetByFov.js +13 -1
  91. package/lib-esm/services/tapRepoService.js +13 -1
  92. package/lib-esm/services/types.js +12 -0
  93. package/lib-esm/shader/CatalogueShaderProgram.js +12 -0
  94. package/lib-esm/shader/FootprintShaderProgram.js +12 -0
  95. package/lib-esm/shader/GridShaderManager.js +12 -0
  96. package/lib-esm/shader/HiPSShaderProgram.js +12 -0
  97. package/lib-esm/shader/ShaderManager.js +12 -1
  98. package/lib-esm/shader/ShaderManagerMutliHiPS.js +12 -1
  99. package/lib-esm/shader/XYZShaderProgram.d.ts +14 -1
  100. package/lib-esm/shader/XYZShaderProgram.js +127 -2
  101. package/lib-esm/utils/CoordsType.d.ts +2 -1
  102. package/lib-esm/utils/CoordsType.js +13 -0
  103. package/lib-esm/utils/FoVUtils.js +12 -0
  104. package/lib-esm/utils/GeoJSONParser.d.ts +19 -0
  105. package/lib-esm/utils/GeoJSONParser.js +112 -0
  106. package/lib-esm/utils/GeomUtils.js +12 -0
  107. package/lib-esm/utils/MouseHelper.js +12 -0
  108. package/lib-esm/utils/PerspectiveMatrixManager.js +16 -1
  109. package/lib-esm/utils/RayPickingUtils.js +12 -0
  110. package/lib-esm/utils/STCSParser.d.ts +7 -3
  111. package/lib-esm/utils/STCSParser.js +27 -9
  112. package/lib-esm/utils/ShaderUtility.js +13 -1
  113. package/lib-esm/utils/Utils.js +12 -0
  114. package/lib-esm/utils/XYZRayPickingUtils.d.ts +27 -0
  115. package/lib-esm/utils/XYZRayPickingUtils.js +226 -0
  116. package/package.json +2 -2
  117. package/lib-esm/model/FoV.d.ts +0 -62
  118. package/lib-esm/model/FoV.js +0 -274
  119. package/lib-esm/model/earth/XYZAncestorMeshCache.d.ts +0 -10
  120. package/lib-esm/model/earth/XYZAncestorMeshCache.js +0 -31
  121. package/lib-esm/model/earth/XYZLayer.d.ts +0 -31
  122. package/lib-esm/model/earth/XYZLayer.js +0 -231
  123. package/lib-esm/model/earth/XYZTileProvider.d.ts +0 -29
  124. package/lib-esm/model/earth/XYZTileProvider.js +0 -187
  125. package/lib-esm/model/earth/wmts/types.d.ts +0 -1
  126. package/lib-esm/model/earth/wmts/types.js +0 -1
  127. /package/lib-esm/model/{earth/types.js → hips/HiPSConfig.js} +0 -0
@@ -0,0 +1,208 @@
1
+ /*
2
+ * AstroViewer
3
+ * Copyright (C) Fabrizio Giordano
4
+ * SPDX-License-Identifier: LicenseRef-AstroViewer-Dual-License
5
+ *
6
+ * This file is part of AstroViewer.
7
+ * AstroViewer is distributed under a dual-license model.
8
+ * Commercial use requires a separate commercial license.
9
+ * Non-commercial use is governed by LICENSE-NONCOMMERCIAL.md.
10
+ *
11
+ * See LICENSE.md, LICENSE-COMMERCIAL.md, and LICENSE-NONCOMMERCIAL.md for details.
12
+ */
13
+ import { AbstractSkyEntity } from "../AbstractSkyEntity.js";
14
+ import { XYZVisibleTilesManager } from "./XYZVisibleTilesManager.js";
15
+ import { xyzFovHelper } from "./XYZFoVHelper.js";
16
+ import { ColorMaps } from "../ColorMaps.js";
17
+ import { LatLonGrid } from "../grid/LonLatGrid.js";
18
+ import { XYZShaderProgram } from "../../shader/XYZShaderProgram.js";
19
+ import { XYZTileBuffer } from "./XYZTileBuffer.js";
20
+ import { XYZAnchestorTile } from "./XYZAnchestorTile.js";
21
+ import { XYZMeshBuilder } from "./XYZMeshBuilder.js";
22
+ export class XYZMap extends AbstractSkyEntity {
23
+ _xyzShaderProgram;
24
+ _descriptor;
25
+ _visibleTilesManager;
26
+ _tileBuffer;
27
+ _meshBuilder;
28
+ _baseurl;
29
+ _zoom;
30
+ _latLonGrid;
31
+ _colorMapIdx = 0;
32
+ _colorMap = ColorMaps['native'];
33
+ constructor(radius, position, xrad, yrad, descriptor, webgl) {
34
+ super(radius, position, xrad, yrad, descriptor.name, webgl, false);
35
+ this._descriptor = descriptor;
36
+ this._xyzShaderProgram = new XYZShaderProgram(webgl);
37
+ this._meshBuilder = new XYZMeshBuilder();
38
+ this._tileBuffer = new XYZTileBuffer(1);
39
+ this.initGL(webgl);
40
+ this._latLonGrid = new LatLonGrid(radius, position, xrad, yrad, 'LatLonGrid', this._webgl);
41
+ this._visibleTilesManager = new XYZVisibleTilesManager();
42
+ this._baseurl = descriptor.url;
43
+ this.initShaders();
44
+ const fov = 180;
45
+ this._zoom = xyzFovHelper.getZoom(fov);
46
+ }
47
+ changeColorMap(colorMap) {
48
+ this._colorMap = colorMap;
49
+ switch (colorMap.name) {
50
+ case 'grayscale':
51
+ this._colorMapIdx = 1;
52
+ this._colorMap = ColorMaps['grayscale'];
53
+ break;
54
+ case 'planck':
55
+ this._colorMapIdx = 2;
56
+ this._colorMap = ColorMaps['planck'];
57
+ break;
58
+ case 'cmb':
59
+ this._colorMapIdx = 3;
60
+ this._colorMap = ColorMaps['cmb'];
61
+ break;
62
+ case 'rainbow':
63
+ this._colorMapIdx = 4;
64
+ this._colorMap = ColorMaps['rainbow'];
65
+ break;
66
+ case 'eosb':
67
+ this._colorMapIdx = 5;
68
+ this._colorMap = ColorMaps['eosb'];
69
+ break;
70
+ case 'cubehelix':
71
+ this._colorMapIdx = 6;
72
+ this._colorMap = ColorMaps['cubehelix'];
73
+ break;
74
+ case 'hot':
75
+ this._colorMapIdx = 7;
76
+ this._colorMap = ColorMaps['hot'];
77
+ break;
78
+ case 'gray':
79
+ this._colorMapIdx = 8;
80
+ this._colorMap = ColorMaps['gray'];
81
+ break;
82
+ case 'native':
83
+ this._colorMapIdx = 0;
84
+ this._colorMap = ColorMaps['native'];
85
+ break;
86
+ default:
87
+ this._colorMapIdx = 9;
88
+ this._colorMap = colorMap;
89
+ }
90
+ }
91
+ initShaders() {
92
+ this._xyzShaderProgram.enableProgram();
93
+ }
94
+ isLonLatGridVisible() {
95
+ return this._latLonGrid.isVisible();
96
+ }
97
+ toggleLonLatGrid() {
98
+ return this._latLonGrid.toggleShowGrid();
99
+ }
100
+ getFoV() {
101
+ return this._latLonGrid.getFoV();
102
+ }
103
+ refresh(input) {
104
+ const fov = this._latLonGrid.refreshFoV(input);
105
+ // this._zoom = this.resolveVisibleZoom(fov)
106
+ this._zoom = xyzFovHelper.getZoom(fov);
107
+ }
108
+ draw(input) {
109
+ const vMatrix = input.camera.getCameraMatrix();
110
+ if (!vMatrix)
111
+ return;
112
+ const pMatrix = input.pMatrix;
113
+ if (!pMatrix)
114
+ return;
115
+ this.refresh(input);
116
+ const mMatrix = this.getModelMatrix();
117
+ this._xyzShaderProgram.setRuntimeColorMap(this._colorMap);
118
+ const tileSelection = this._visibleTilesManager.computeVisibleTiles(this._zoom, this, this._webgl, input.camera, input.pMatrix);
119
+ const visibleTiles = tileSelection.visibleTiles;
120
+ const ancestorsMap = tileSelection.ancestorsMap;
121
+ const tileKeys = this._tileBuffer.ensureTiles(this.getTilesToEnsure(visibleTiles, ancestorsMap), (coord) => this.createTile(coord));
122
+ this._tileBuffer.evictCached(this._descriptor.maxCachedTiles);
123
+ for (const tileKey of tileKeys) {
124
+ const tile = this._tileBuffer.getActiveTile(tileKey);
125
+ if (!tile || tile.coord.z !== tileSelection.currentZoom) {
126
+ continue;
127
+ }
128
+ const drawn = tile.draw(pMatrix, vMatrix, mMatrix, this._colorMapIdx);
129
+ if (drawn) {
130
+ continue;
131
+ }
132
+ const ancestorTile = this.findBestAvailableAncestor(tile.coord);
133
+ ancestorTile?.draw(tileSelection.currentZoom, [tile.coord], ancestorsMap, pMatrix, vMatrix, mMatrix, this._colorMapIdx);
134
+ }
135
+ this._latLonGrid.draw(input);
136
+ }
137
+ createTile(coord) {
138
+ return new XYZAnchestorTile(coord, this.resolveTileUrl(coord), this._webgl, this._xyzShaderProgram, this._meshBuilder, this._descriptor.segmentsPerSide);
139
+ }
140
+ getTilesToEnsure(visibleTiles, ancestorsMap) {
141
+ const tilesByKey = new Map();
142
+ for (const tile of visibleTiles) {
143
+ tilesByKey.set(this.tileKey(tile), tile);
144
+ }
145
+ for (const ancestor of ancestorsMap.values()) {
146
+ tilesByKey.set(this.tileKey(ancestor), ancestor);
147
+ }
148
+ return Array.from(tilesByKey.values());
149
+ }
150
+ findBestAvailableAncestor(targetTile) {
151
+ for (let z = targetTile.z - 1; z >= 0; z--) {
152
+ const dz = targetTile.z - z;
153
+ const ancestorCoord = {
154
+ z,
155
+ x: targetTile.x >> dz,
156
+ y: targetTile.y >> dz,
157
+ };
158
+ const ancestorTile = this._tileBuffer.getAnyTile(this.tileKey(ancestorCoord));
159
+ if (ancestorTile?.ready) {
160
+ return ancestorTile;
161
+ }
162
+ }
163
+ return null;
164
+ }
165
+ resolveTileUrl(tile) {
166
+ const urlResolver = this._descriptor.urlResolver;
167
+ if (urlResolver) {
168
+ return urlResolver(tile);
169
+ }
170
+ const dim = 2 ** tile.z;
171
+ const y = this._descriptor.flipY ? dim - 1 - tile.y : tile.y;
172
+ const subdomains = this._descriptor.subdomains;
173
+ const subdomain = subdomains.length > 0
174
+ ? subdomains[Math.abs(tile.x + tile.y + tile.z) % subdomains.length]
175
+ : '';
176
+ return this._baseurl
177
+ .replace(/\{z\}/g, String(tile.z))
178
+ .replace(/\{x\}/g, String(tile.x))
179
+ .replace(/\{y\}/g, String(y))
180
+ .replace(/\{s\}/g, subdomain ?? '');
181
+ }
182
+ getDebugStats() {
183
+ const activeTiles = Array.from(this._tileBuffer.activeTiles.values(), (entry) => entry.tile);
184
+ const cachedTiles = Array.from(this._tileBuffer.cachedTiles.values(), (entry) => entry.tile);
185
+ const allTiles = [...activeTiles, ...cachedTiles];
186
+ const selection = this._visibleTilesManager.selection;
187
+ return {
188
+ cacheSize: this._tileBuffer.size,
189
+ visibleTileCount: selection.visibleTiles.length,
190
+ currentTileCount: activeTiles.filter((tile) => tile.coord.z === selection.currentZoom).length,
191
+ fallbackTileCount: selection.ancestorsMap.size,
192
+ coreTileCount: selection.visibleTiles.length,
193
+ coverageTileCount: selection.visibleTiles.length,
194
+ readyTileCount: allTiles.filter((tile) => tile.ready).length,
195
+ loadingTileCount: allTiles.filter((tile) => tile.loading).length,
196
+ coolingDownTileCount: 0,
197
+ currentZoom: selection.currentZoom,
198
+ tileSelectionKey: selection.key,
199
+ isSettling: false,
200
+ coarseTileCount: selection.ancestorsMap.size,
201
+ hasPendingSelection: false,
202
+ pendingSelectionKey: null,
203
+ };
204
+ }
205
+ tileKey(tile) {
206
+ return `${tile.z}/${tile.x}/${tile.y}`;
207
+ }
208
+ }
@@ -0,0 +1,29 @@
1
+ import type { XYZTileCoord } from './XYZTypes.js';
2
+ export declare class XYZMapDescriptor {
3
+ _name: string;
4
+ _url: string;
5
+ _urlResolver?: (tile: XYZTileCoord) => string;
6
+ _minZoom?: number;
7
+ _maxZoom?: number;
8
+ _segmentsPerSide?: number;
9
+ _tileSize?: number;
10
+ _maxCachedTiles?: number;
11
+ _interactionDebounceMs?: number;
12
+ _subdomains?: string[];
13
+ _attribution?: string;
14
+ _flipY?: boolean;
15
+ _maxConcurrentLoads?: number;
16
+ constructor(name: string, url: string, minZoom?: number, maxZoom?: number, segmentsPerSide?: number, maxCachedTiles?: number, maxConcurrentLoads?: number, urlResolver?: (tile: XYZTileCoord) => string);
17
+ get url(): string;
18
+ get urlResolver(): ((tile: XYZTileCoord) => string) | undefined;
19
+ get name(): string;
20
+ get minZoom(): number;
21
+ get maxZoom(): number;
22
+ get segmentsPerSide(): number;
23
+ get maxCachedTiles(): number;
24
+ get interactionDebounceMs(): number;
25
+ get subdomains(): string[];
26
+ get attribution(): string;
27
+ get flipY(): boolean;
28
+ get maxConcurrentLoads(): number;
29
+ }
@@ -0,0 +1,77 @@
1
+ /*
2
+ * AstroViewer
3
+ * Copyright (C) Fabrizio Giordano
4
+ * SPDX-License-Identifier: LicenseRef-AstroViewer-Dual-License
5
+ *
6
+ * This file is part of AstroViewer.
7
+ * AstroViewer is distributed under a dual-license model.
8
+ * Commercial use requires a separate commercial license.
9
+ * Non-commercial use is governed by LICENSE-NONCOMMERCIAL.md.
10
+ *
11
+ * See LICENSE.md, LICENSE-COMMERCIAL.md, and LICENSE-NONCOMMERCIAL.md for details.
12
+ */
13
+ export class XYZMapDescriptor {
14
+ _name;
15
+ _url;
16
+ _urlResolver;
17
+ _minZoom;
18
+ _maxZoom;
19
+ _segmentsPerSide;
20
+ _tileSize;
21
+ _maxCachedTiles;
22
+ _interactionDebounceMs;
23
+ _subdomains;
24
+ _attribution;
25
+ _flipY;
26
+ _maxConcurrentLoads;
27
+ constructor(name, url, minZoom = 0, maxZoom = 8, segmentsPerSide = 16, maxCachedTiles = 384, maxConcurrentLoads = 8, urlResolver) {
28
+ this._name = name;
29
+ this._url = url;
30
+ this._urlResolver = urlResolver;
31
+ this._minZoom = minZoom;
32
+ this._maxZoom = maxZoom;
33
+ this._segmentsPerSide = segmentsPerSide;
34
+ this._maxCachedTiles = maxCachedTiles;
35
+ this._interactionDebounceMs = 100;
36
+ this._subdomains = ['a', 'b', 'c'];
37
+ this._attribution = '';
38
+ this._flipY = false;
39
+ this._maxConcurrentLoads = maxConcurrentLoads;
40
+ }
41
+ get url() {
42
+ return this._url;
43
+ }
44
+ get urlResolver() {
45
+ return this._urlResolver;
46
+ }
47
+ get name() {
48
+ return this._name;
49
+ }
50
+ get minZoom() {
51
+ return this._minZoom;
52
+ }
53
+ get maxZoom() {
54
+ return this._maxZoom;
55
+ }
56
+ get segmentsPerSide() {
57
+ return this._segmentsPerSide;
58
+ }
59
+ get maxCachedTiles() {
60
+ return this._maxCachedTiles;
61
+ }
62
+ get interactionDebounceMs() {
63
+ return this._interactionDebounceMs;
64
+ }
65
+ get subdomains() {
66
+ return this._subdomains;
67
+ }
68
+ get attribution() {
69
+ return this._attribution;
70
+ }
71
+ get flipY() {
72
+ return this._flipY;
73
+ }
74
+ get maxConcurrentLoads() {
75
+ return this._maxConcurrentLoads;
76
+ }
77
+ }
@@ -1,4 +1,4 @@
1
- import type { XYZTileCoord, XYZTileMesh, XYZTileGpuMesh } from './types.js';
1
+ import type { XYZTileCoord, XYZTileGpuMesh, XYZTileMesh } from './XYZTypes.js';
2
2
  export declare class XYZMeshBuilder {
3
3
  buildTileMesh(tile: XYZTileCoord, segmentsPerSide?: number): XYZTileMesh;
4
4
  buildAncestorMesh(targetTile: XYZTileCoord, ancestorTile: XYZTileCoord, segmentsPerSide?: number): XYZTileMesh;
@@ -1,3 +1,15 @@
1
+ /*
2
+ * AstroViewer
3
+ * Copyright (C) Fabrizio Giordano
4
+ * SPDX-License-Identifier: LicenseRef-AstroViewer-Dual-License
5
+ *
6
+ * This file is part of AstroViewer.
7
+ * AstroViewer is distributed under a dual-license model.
8
+ * Commercial use requires a separate commercial license.
9
+ * Non-commercial use is governed by LICENSE-NONCOMMERCIAL.md.
10
+ *
11
+ * See LICENSE.md, LICENSE-COMMERCIAL.md, and LICENSE-NONCOMMERCIAL.md for details.
12
+ */
1
13
  import { sphericalToCartesian } from '../../utils/Utils.js';
2
14
  const MAX_MERCATOR_LAT = 85.0511287798066;
3
15
  function mercatorYToLatDeg(yNormalized) {
@@ -35,8 +47,7 @@ export class XYZMeshBuilder {
35
47
  uvs[uv++] = 1 - v;
36
48
  }
37
49
  }
38
- const triangleCount = segments * segments * 2;
39
- const rawIndices = new Uint32Array(triangleCount * 3);
50
+ const rawIndices = new Uint32Array(segments * segments * 2 * 3);
40
51
  let i = 0;
41
52
  for (let row = 0; row < segments; row++) {
42
53
  for (let col = 0; col < segments; col++) {
@@ -1,39 +1,38 @@
1
1
  import { XYZShaderProgram } from '../../shader/XYZShaderProgram.js';
2
- import type { XYZTileCoord, XYZTileGpuMesh, XYZTileMesh } from './types.js';
3
- export declare class XYZTile {
2
+ import type { XYZBufferedTile } from './XYZTileBuffer.js';
3
+ import { XYZMeshBuilder } from './XYZMeshBuilder.js';
4
+ import type { XYZTileCoord, XYZTileGpuMesh } from './XYZTypes.js';
5
+ type Mat4 = Float32Array;
6
+ export declare class XYZTile implements XYZBufferedTile {
4
7
  private _coord;
5
8
  private _url;
6
9
  private _webgl;
7
10
  private _shaderProgram;
8
- private _positionBuffer;
9
- private _uvBuffer;
10
- private _indexBuffer;
11
+ private _meshBuilder;
12
+ private _gpuMesh;
11
13
  private _texture;
12
- private _indices;
13
- private _indexType;
14
+ private _image?;
14
15
  private _ready;
15
- private _aborted;
16
16
  private _loading;
17
+ private _aborted;
17
18
  private _failedUntil;
18
19
  private _lastUsedAt;
19
20
  private _createdAt;
20
- private _image?;
21
- private _objectUrl;
22
- constructor(coord: XYZTileCoord, url: string, mesh: XYZTileMesh, webgl: WebGL2RenderingContext, shaderProgram: XYZShaderProgram);
23
- get ready(): boolean;
21
+ constructor(coord: XYZTileCoord, url: string, webgl: WebGL2RenderingContext, shaderProgram: XYZShaderProgram, meshBuilder?: XYZMeshBuilder, segmentsPerSide?: number);
24
22
  get coord(): XYZTileCoord;
25
- get failedUntil(): number;
23
+ get ready(): boolean;
26
24
  get loading(): boolean;
25
+ get failedUntil(): number;
27
26
  get lastUsedAt(): number;
28
27
  get createdAt(): number;
29
28
  touch(): void;
30
- primeLoad(priority?: number): void;
31
- private loadTexture;
32
- private loadImageFromBlob;
33
- private onImageLoaded;
34
- draw(pMatrix: Float32Array, vMatrix: Float32Array, mMatrix: Float32Array, priority?: number, allowLoad?: boolean): void;
35
- drawRemapped(mesh: XYZTileGpuMesh, pMatrix: Float32Array, vMatrix: Float32Array, mMatrix: Float32Array): void;
36
- private drawWithGpuMesh;
29
+ private initImage;
30
+ private imageLoaded;
31
+ private textureLoaded;
32
+ draw(pMatrix: Mat4, vMatrix: Mat4, mMatrix: Mat4, colorMapIdx: number): boolean;
33
+ drawRemapped(mesh: XYZTileGpuMesh, pMatrix: Mat4, vMatrix: Mat4, mMatrix: Mat4, colorMapIdx: number): boolean;
37
34
  dispose(): void;
38
- private revokeObjectUrl;
35
+ private drawWithGpuMesh;
36
+ private get key();
39
37
  }
38
+ export {};
@@ -1,52 +1,53 @@
1
- import { xyzTileRequestScheduler, XYZTileRequestError } from './XYZTileRequestScheduler.js';
1
+ /*
2
+ * AstroViewer
3
+ * Copyright (C) Fabrizio Giordano
4
+ * SPDX-License-Identifier: LicenseRef-AstroViewer-Dual-License
5
+ *
6
+ * This file is part of AstroViewer.
7
+ * AstroViewer is distributed under a dual-license model.
8
+ * Commercial use requires a separate commercial license.
9
+ * Non-commercial use is governed by LICENSE-NONCOMMERCIAL.md.
10
+ *
11
+ * See LICENSE.md, LICENSE-COMMERCIAL.md, and LICENSE-NONCOMMERCIAL.md for details.
12
+ */
13
+ import { XYZMeshBuilder } from './XYZMeshBuilder.js';
2
14
  export class XYZTile {
3
15
  _coord;
4
16
  _url;
5
17
  _webgl;
6
18
  _shaderProgram;
7
- _positionBuffer;
8
- _uvBuffer;
9
- _indexBuffer;
19
+ _meshBuilder;
20
+ _gpuMesh;
10
21
  _texture = null;
11
- _indices;
12
- _indexType;
22
+ _image;
13
23
  _ready = false;
14
- _aborted = false;
15
24
  _loading = false;
25
+ _aborted = false;
16
26
  _failedUntil = 0;
17
27
  _lastUsedAt = 0;
18
28
  _createdAt = Date.now();
19
- _image;
20
- _objectUrl = null;
21
- constructor(coord, url, mesh, webgl, shaderProgram) {
29
+ constructor(coord, url, webgl, shaderProgram, meshBuilder = new XYZMeshBuilder(), segmentsPerSide = 16) {
22
30
  this._coord = coord;
23
31
  this._url = url;
24
32
  this._webgl = webgl;
25
33
  this._shaderProgram = shaderProgram;
26
- this._positionBuffer = webgl.createBuffer();
27
- this._uvBuffer = webgl.createBuffer();
28
- this._indexBuffer = webgl.createBuffer();
29
- this._indices = mesh.indices;
30
- this._indexType = mesh.indices instanceof Uint32Array ? webgl.UNSIGNED_INT : webgl.UNSIGNED_SHORT;
31
- webgl.bindBuffer(webgl.ARRAY_BUFFER, this._positionBuffer);
32
- webgl.bufferData(webgl.ARRAY_BUFFER, mesh.positions, webgl.STATIC_DRAW);
33
- webgl.bindBuffer(webgl.ARRAY_BUFFER, this._uvBuffer);
34
- webgl.bufferData(webgl.ARRAY_BUFFER, mesh.uvs, webgl.STATIC_DRAW);
35
- webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);
36
- webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER, mesh.indices, webgl.STATIC_DRAW);
37
- }
38
- get ready() {
39
- return this._ready;
34
+ this._meshBuilder = meshBuilder;
35
+ const mesh = this._meshBuilder.buildTileMesh(coord, segmentsPerSide);
36
+ this._gpuMesh = this._meshBuilder.uploadMesh(mesh, this._webgl);
37
+ this.initImage();
40
38
  }
41
39
  get coord() {
42
40
  return this._coord;
43
41
  }
44
- get failedUntil() {
45
- return this._failedUntil;
42
+ get ready() {
43
+ return this._ready;
46
44
  }
47
45
  get loading() {
48
46
  return this._loading;
49
47
  }
48
+ get failedUntil() {
49
+ return this._failedUntil;
50
+ }
50
51
  get lastUsedAt() {
51
52
  return this._lastUsedAt;
52
53
  }
@@ -56,10 +57,7 @@ export class XYZTile {
56
57
  touch() {
57
58
  this._lastUsedAt = Date.now();
58
59
  }
59
- primeLoad(priority = 0) {
60
- this.loadTexture(priority);
61
- }
62
- loadTexture(priority = 0) {
60
+ initImage() {
63
61
  if (this._loading || this._ready || this._aborted) {
64
62
  return;
65
63
  }
@@ -68,80 +66,88 @@ export class XYZTile {
68
66
  return;
69
67
  }
70
68
  this._loading = true;
71
- xyzTileRequestScheduler.load(this._url, priority)
72
- .then((blob) => this.loadImageFromBlob(blob))
73
- .catch((error) => {
74
- this._loading = false;
75
- this._ready = false;
76
- const cooldownMs = error instanceof XYZTileRequestError ? error.cooldownMs : 10000;
77
- this._failedUntil = Date.now() + cooldownMs;
78
- });
79
- }
80
- loadImageFromBlob(blob) {
81
69
  const image = new Image();
82
70
  this._image = image;
83
- this._objectUrl = URL.createObjectURL(blob);
84
- image.onload = () => this.onImageLoaded();
71
+ image.crossOrigin = 'anonymous';
72
+ image.onload = () => this.imageLoaded();
85
73
  image.onerror = () => {
86
- this._loading = false;
87
74
  this._ready = false;
88
- this._failedUntil = Date.now() + 30000;
89
- this.revokeObjectUrl();
75
+ this._loading = false;
76
+ this._failedUntil = Date.now() + 30_000;
90
77
  };
91
- image.src = this._objectUrl;
78
+ image.src = this._url;
92
79
  }
93
- onImageLoaded() {
80
+ imageLoaded() {
94
81
  if (!this._image || this._aborted) {
95
82
  return;
96
83
  }
84
+ this.textureLoaded(this._image);
85
+ this._loading = false;
86
+ this._failedUntil = 0;
87
+ this._ready = true;
88
+ }
89
+ textureLoaded(image) {
97
90
  const gl = this._webgl;
91
+ this._shaderProgram.enableProgram();
98
92
  const texture = gl.createTexture();
99
93
  if (!texture) {
100
- throw new Error('Could not create XYZ texture');
94
+ throw new Error(`Could not create XYZ texture for ${this.key}`);
101
95
  }
102
96
  this._texture = texture;
103
97
  gl.activeTexture(gl.TEXTURE0);
104
- gl.bindTexture(gl.TEXTURE_2D, texture);
105
98
  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
106
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image);
99
+ gl.bindTexture(gl.TEXTURE_2D, texture);
100
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
107
101
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
108
102
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
109
103
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
110
104
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
111
- this._loading = false;
112
- this._failedUntil = 0;
113
- this._ready = true;
114
- this.revokeObjectUrl();
115
105
  }
116
- draw(pMatrix, vMatrix, mMatrix, priority = 0, allowLoad = true) {
106
+ draw(pMatrix, vMatrix, mMatrix, colorMapIdx) {
117
107
  this.touch();
118
- if (!this._ready && allowLoad) {
119
- this.loadTexture(priority);
120
- }
121
- if (!this._ready || !this._texture) {
122
- return;
108
+ if (!this._ready || !this._texture || this._aborted) {
109
+ return false;
123
110
  }
124
- this.drawWithGpuMesh({
125
- positionBuffer: this._positionBuffer,
126
- uvBuffer: this._uvBuffer,
127
- indexBuffer: this._indexBuffer,
128
- indexCount: this._indices.length,
129
- indexType: this._indexType,
130
- }, pMatrix, vMatrix, mMatrix);
131
- }
132
- drawRemapped(mesh, pMatrix, vMatrix, mMatrix) {
111
+ this.drawWithGpuMesh(this._gpuMesh, pMatrix, vMatrix, mMatrix, colorMapIdx);
112
+ return true;
113
+ }
114
+ drawRemapped(mesh, pMatrix, vMatrix, mMatrix, colorMapIdx) {
133
115
  this.touch();
134
- if (!this._ready || !this._texture) {
135
- return;
116
+ if (!this._ready || !this._texture || this._aborted) {
117
+ return false;
136
118
  }
137
- this.drawWithGpuMesh(mesh, pMatrix, vMatrix, mMatrix);
119
+ this.drawWithGpuMesh(mesh, pMatrix, vMatrix, mMatrix, colorMapIdx);
120
+ return true;
121
+ }
122
+ dispose() {
123
+ const gl = this._webgl;
124
+ if (this._texture) {
125
+ gl.deleteTexture(this._texture);
126
+ this._texture = null;
127
+ }
128
+ if (this._gpuMesh.positionBuffer) {
129
+ gl.deleteBuffer(this._gpuMesh.positionBuffer);
130
+ this._gpuMesh.positionBuffer = null;
131
+ }
132
+ if (this._gpuMesh.uvBuffer) {
133
+ gl.deleteBuffer(this._gpuMesh.uvBuffer);
134
+ this._gpuMesh.uvBuffer = null;
135
+ }
136
+ if (this._gpuMesh.indexBuffer) {
137
+ gl.deleteBuffer(this._gpuMesh.indexBuffer);
138
+ this._gpuMesh.indexBuffer = null;
139
+ }
140
+ this._image = undefined;
141
+ this._ready = false;
142
+ this._loading = false;
143
+ this._aborted = true;
138
144
  }
139
- drawWithGpuMesh(mesh, pMatrix, vMatrix, mMatrix) {
145
+ drawWithGpuMesh(mesh, pMatrix, vMatrix, mMatrix, colorMapIdx) {
140
146
  if (!this._texture) {
141
147
  return;
142
148
  }
143
149
  const gl = this._webgl;
144
- this._shaderProgram.enableShaders(pMatrix, vMatrix, mMatrix);
150
+ this._shaderProgram.enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx);
145
151
  gl.bindBuffer(gl.ARRAY_BUFFER, mesh.positionBuffer);
146
152
  gl.vertexAttribPointer(this._shaderProgram.locations.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
147
153
  gl.enableVertexAttribArray(this._shaderProgram.locations.vertexPositionAttribute);
@@ -155,33 +161,7 @@ export class XYZTile {
155
161
  gl.disableVertexAttribArray(this._shaderProgram.locations.vertexPositionAttribute);
156
162
  gl.disableVertexAttribArray(this._shaderProgram.locations.textureCoordAttribute);
157
163
  }
158
- dispose() {
159
- const gl = this._webgl;
160
- if (this._texture) {
161
- gl.deleteTexture(this._texture);
162
- this._texture = null;
163
- }
164
- if (this._positionBuffer) {
165
- gl.deleteBuffer(this._positionBuffer);
166
- this._positionBuffer = null;
167
- }
168
- if (this._uvBuffer) {
169
- gl.deleteBuffer(this._uvBuffer);
170
- this._uvBuffer = null;
171
- }
172
- if (this._indexBuffer) {
173
- gl.deleteBuffer(this._indexBuffer);
174
- this._indexBuffer = null;
175
- }
176
- this._image = undefined;
177
- this.revokeObjectUrl();
178
- this._loading = false;
179
- this._ready = false;
180
- }
181
- revokeObjectUrl() {
182
- if (this._objectUrl) {
183
- URL.revokeObjectURL(this._objectUrl);
184
- this._objectUrl = null;
185
- }
164
+ get key() {
165
+ return `${this._coord.z}/${this._coord.x}/${this._coord.y}`;
186
166
  }
187
167
  }