@pirireis/webglobeplugins 0.7.5 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Math/methods.js +27 -0
- package/package.json +1 -1
- package/point-heat-map/point-to-heat-map-flow.js +3 -2
- package/point-tracks/plugin.js +256 -22
- package/programs/line-on-globe/lines-color-instanced-flat.js +0 -1
- package/programs/point-on-globe/square-pixel-point.js +50 -17
- package/rangerings/plugin.js +2 -1
- package/util/account/single-attribute-buffer-management/index.js +2 -2
- package/util/account/single-attribute-buffer-management/object-store.js +62 -0
- package/util/geometry/index.js +1 -16
- package/util/picking/fence.js +46 -0
- package/util/picking/picker-displayer.js +177 -0
- package/util/programs/draw-texture-on-canvas.js +5 -6
- package/util/webglobjectbuilders.js +16 -1
- package/util/geometry/geodatafromtexture.js +0 -52
package/Math/methods.js
CHANGED
|
@@ -147,6 +147,31 @@ const wgs84ToUnitVector = (coordinates) => {
|
|
|
147
147
|
return [x, y, z];
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
+
/**
|
|
151
|
+
* @param {number} long wgs84
|
|
152
|
+
* @param {number} lat wgs84
|
|
153
|
+
* @param {number} height
|
|
154
|
+
* @returns {vec3} cartesian3D
|
|
155
|
+
*/
|
|
156
|
+
const wgs84ToCartesian3d = (long, lat, height) => {
|
|
157
|
+
const longRad = long * RADIANS;
|
|
158
|
+
const latRad = lat * RADIANS;
|
|
159
|
+
const x = Math.cos(latRad) * Math.cos(longRad);
|
|
160
|
+
const y = Math.cos(latRad) * Math.sin(longRad);
|
|
161
|
+
const z = Math.sin(latRad);
|
|
162
|
+
const radius = WORLD_RADIUS_3D + height;
|
|
163
|
+
return [x * radius, y * radius, z * radius];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* @param {number} long
|
|
168
|
+
* @param {number} lat
|
|
169
|
+
* @returns {vec2} mercator
|
|
170
|
+
*/
|
|
171
|
+
const wgs84ToMercator = (long, lat) => {
|
|
172
|
+
return [WORLD_RADIUS_MERCATOR * long * RADIANS, WORLD_RADIUS_MERCATOR * Math.log(Math.tan(Math.PI / 4 + lat * RADIANS / 2))];
|
|
173
|
+
}
|
|
174
|
+
|
|
150
175
|
|
|
151
176
|
/**
|
|
152
177
|
* @param {vec3} cartesian
|
|
@@ -190,6 +215,8 @@ export {
|
|
|
190
215
|
sphericalLinearInterpolation_Mercator,
|
|
191
216
|
sphericalLinearInterpolation_Cartesian3d,
|
|
192
217
|
wgs84ToUnitVector,
|
|
218
|
+
wgs84ToCartesian3d,
|
|
219
|
+
wgs84ToMercator,
|
|
193
220
|
cartesian3dToUnitVectorWithHeight,
|
|
194
221
|
pixelXYLenghtToUnitVectorWithHeight
|
|
195
222
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { densityToLegendProgramCache } from "../programs/data2legend/density-to-legend";
|
|
2
2
|
import { pointToDensityTextureCache } from "../programs/data2legend/point-to-density-texture";
|
|
3
|
-
import { textureOnCanvasProgramCache } from "../util/programs/draw-texture-on-canvas";
|
|
3
|
+
// import { textureOnCanvasProgramCache } from "../util/programs/draw-texture-on-canvas";
|
|
4
4
|
import { defaultblendfunction } from "../util/webglobe/gldefaultstates";
|
|
5
5
|
class PointHeatmapFlow {
|
|
6
6
|
|
|
@@ -13,7 +13,7 @@ class PointHeatmapFlow {
|
|
|
13
13
|
this.gl = globe.gl;
|
|
14
14
|
this.pointToDensityProgram = pointToDensityTextureCache.get(globe);
|
|
15
15
|
this.densityToLegendProgram = densityToLegendProgramCache.get(globe);
|
|
16
|
-
// this.testTextureProgram = textureOnCanvasProgramCache.get(globe);
|
|
16
|
+
// this.testTextureProgram = textureOnCanvasProgramCache.get(globe.gl);
|
|
17
17
|
this._lookInfo = globe.api_GetCurrentLookInfo();
|
|
18
18
|
const { gl } = this;
|
|
19
19
|
{
|
|
@@ -143,6 +143,7 @@ class PointHeatmapFlow {
|
|
|
143
143
|
this._isFreed = true;
|
|
144
144
|
densityToLegendProgramCache.release(this.globe);
|
|
145
145
|
pointToDensityTextureCache.release(this.globe);
|
|
146
|
+
// textureOnCanvasProgramCache.release(this.gl);
|
|
146
147
|
this.gl.deleteTexture(this.densityTexture);
|
|
147
148
|
this.gl.deleteFramebuffer(this.framebuffer);
|
|
148
149
|
this.gl.deleteBuffer(this.buffer);
|
package/point-tracks/plugin.js
CHANGED
|
@@ -1,20 +1,49 @@
|
|
|
1
|
-
import { BufferOrchestrator, BufferManager } from "../util/account";
|
|
1
|
+
import { BufferOrchestrator, BufferManager, ObjectStore } from "../util/account";
|
|
2
2
|
|
|
3
|
+
import { PickerDisplayer } from "../util/picking/picker-displayer";
|
|
4
|
+
import { pointOnGlobeProgramCache } from "../programs/point-on-globe/square-pixel-point";
|
|
5
|
+
|
|
6
|
+
import { wgs84ToCartesian3d, wgs84ToMercator } from "../Math/methods";
|
|
7
|
+
import { hover } from "@testing-library/user-event/dist/hover";
|
|
3
8
|
|
|
4
9
|
/**
|
|
5
10
|
*
|
|
6
11
|
* @typedef { long ,lat, height, ID } Point
|
|
7
|
-
* @typedef {Array<Point>, rgba,
|
|
12
|
+
* @typedef {Array<Point>, rgba, trackID} Track
|
|
8
13
|
*/
|
|
9
14
|
|
|
15
|
+
// TODO: redraw after insert and delete operations
|
|
16
|
+
|
|
10
17
|
class PointTracksPlugin {
|
|
11
18
|
|
|
12
|
-
constructor(id, { } = {}) {
|
|
19
|
+
constructor(id, { pointSize = 2, hoveredPointSize = 4, selectionPointFilling = 4, opacity = 1.0 } = {}) {
|
|
13
20
|
this.id = id;
|
|
14
21
|
this._isFreed = false;
|
|
15
|
-
|
|
22
|
+
|
|
23
|
+
this._pointProgram = null
|
|
24
|
+
this._vao = null;
|
|
25
|
+
this._bufferManagersMap = null;
|
|
26
|
+
this._bufferOrchestrator = null;
|
|
27
|
+
|
|
28
|
+
this._pickerDisplayer = null
|
|
29
|
+
this._selectedID = -1;
|
|
30
|
+
this._selectedObj = null;
|
|
31
|
+
|
|
32
|
+
this._tracksToPointsMap = new Map(); // one to many
|
|
33
|
+
|
|
34
|
+
this._opacity = opacity;
|
|
35
|
+
this.pointSizes = {
|
|
36
|
+
pointSize,
|
|
37
|
+
selectionPointFilling,
|
|
38
|
+
hoveredPointSize
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
this._lastWH = { w: 0, h: 0 };
|
|
16
43
|
|
|
17
44
|
this.program = null
|
|
45
|
+
// selectionPointFilling will be used to create a selection buffer and the iteration
|
|
46
|
+
|
|
18
47
|
}
|
|
19
48
|
|
|
20
49
|
|
|
@@ -22,59 +51,264 @@ class PointTracksPlugin {
|
|
|
22
51
|
|
|
23
52
|
this.globe = globe;
|
|
24
53
|
this.gl = gl;
|
|
25
|
-
|
|
54
|
+
this._pickerDisplayer = new PickerDisplayer(globe);
|
|
55
|
+
this._pointProgram = pointOnGlobeProgramCache.get(globe);
|
|
26
56
|
this._initBufferManagers();
|
|
27
57
|
}
|
|
28
58
|
|
|
29
|
-
_initBufferManagers() {
|
|
30
|
-
|
|
31
59
|
|
|
60
|
+
_initBufferManagers() {
|
|
32
61
|
const { gl } = this;
|
|
33
62
|
const initialCapacity = 10;
|
|
34
|
-
|
|
63
|
+
const bufferType = "DYNAMIC_DRAW";
|
|
35
64
|
this._bufferOrchestrator = new BufferOrchestrator({ initialCapacity });
|
|
36
65
|
this._bufferManagersMap = new Map(
|
|
37
66
|
[
|
|
38
|
-
["pos3D",
|
|
39
|
-
|
|
40
|
-
|
|
67
|
+
["pos3D", {
|
|
68
|
+
bufferManager: new BufferManager(gl, 3, { bufferType, initialCapacity }),
|
|
69
|
+
adaptor: (item) => new Float32Array(wgs84ToCartesian3d(item.long, item.lat, item.height))
|
|
70
|
+
}],
|
|
71
|
+
["pos2D", {
|
|
72
|
+
bufferManager: new BufferManager(gl, 2, { bufferType, initialCapacity }),
|
|
73
|
+
adaptor: (item) => new Float32Array(wgs84ToMercator(item.long, item.lat))
|
|
74
|
+
}],
|
|
75
|
+
["rgba", {
|
|
76
|
+
bufferManager: new BufferManager(gl, 4, { bufferType, initialCapacity }),
|
|
77
|
+
adaptor: (item) => item.rgba
|
|
78
|
+
}],
|
|
79
|
+
["objectStore", {
|
|
80
|
+
bufferManager: new ObjectStore({ initialCapacity }),
|
|
81
|
+
adaptor: (item) => {
|
|
82
|
+
return {
|
|
83
|
+
trackID: item.trackID, pointID: item.pointID
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}]
|
|
41
87
|
]
|
|
42
88
|
);
|
|
43
89
|
|
|
44
|
-
this._vao = this.
|
|
45
|
-
this._bufferManagersMap.get("pos3D"),
|
|
46
|
-
this._bufferManagersMap.get("pos2D"),
|
|
47
|
-
this._bufferManagersMap.get("rgba"),
|
|
90
|
+
this._vao = this._pointProgram.createVAO(
|
|
91
|
+
this._bufferManagersMap.get("pos3D").bufferManager.buffer,
|
|
92
|
+
this._bufferManagersMap.get("pos2D").bufferManager.buffer,
|
|
93
|
+
this._bufferManagersMap.get("rgba").bufferManager.buffer,
|
|
48
94
|
);
|
|
95
|
+
}
|
|
49
96
|
|
|
50
97
|
|
|
98
|
+
setPointSize(size) {
|
|
99
|
+
this.pointSizes.pointSize = size;
|
|
100
|
+
this.globe?.DrawRender();
|
|
51
101
|
}
|
|
52
102
|
|
|
103
|
+
setSelectionPointFilling(size) {
|
|
104
|
+
this.pointSizes.selectionPointFilling = size;
|
|
105
|
+
this.globe?.DrawRender();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
setHoveredPointSize(size) {
|
|
109
|
+
this.pointSizes.hoveredPointSize = size;
|
|
110
|
+
this.globe?.DrawRender();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
setOpacity(opacity) {
|
|
114
|
+
if (opacity < 0 || opacity > 1) return;
|
|
115
|
+
this._opacity = opacity;
|
|
116
|
+
this.globe?.DrawRender();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
getCurrentSelection() {
|
|
120
|
+
return this._selectedObj;
|
|
121
|
+
}
|
|
53
122
|
|
|
54
123
|
|
|
55
124
|
/**
|
|
56
125
|
*
|
|
126
|
+
* @param {*} x screen x
|
|
127
|
+
* @param {*} y screen y
|
|
128
|
+
* @param {*} callback callback on selection
|
|
129
|
+
*/
|
|
130
|
+
screenSelection(x, y, callback) {
|
|
131
|
+
const { pointSizes, _pickerDisplayer } = this;
|
|
132
|
+
const objectStore = this._bufferManagersMap.get("objectStore").bufferManager;
|
|
133
|
+
const wrapper = (selectedIDsSet) => {
|
|
134
|
+
const selectedIDs = Array.from(selectedIDsSet);
|
|
135
|
+
if (selectedIDs.length === 0) {
|
|
136
|
+
this._selectedObj = null;
|
|
137
|
+
this._selectedID = -1;
|
|
138
|
+
callback([]);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const selectedPoints = [];
|
|
142
|
+
for (let i = 0; i < selectedIDs.length; i++) {
|
|
143
|
+
const id = selectedIDs[i];
|
|
144
|
+
if (i === 0) {
|
|
145
|
+
this._selectedID = id;
|
|
146
|
+
this._selectedObj = objectStore.get(id);
|
|
147
|
+
}
|
|
148
|
+
const obj = objectStore.get(id);
|
|
149
|
+
selectedPoints.push(obj);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
callback(selectedPoints);
|
|
153
|
+
}
|
|
154
|
+
_pickerDisplayer.pickXY(x, y, pointSizes.selectionPointFilling, wrapper);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
/**
|
|
57
159
|
* @param {Array<Track>} tracks
|
|
58
|
-
*
|
|
59
160
|
* @returns
|
|
60
161
|
*/
|
|
61
162
|
insertBulk(tracks) {
|
|
62
|
-
|
|
163
|
+
this._fillTracksToPointsMap(tracks);
|
|
164
|
+
const flattenedPoints = tracks.map(trackToFlatPoints).flat();
|
|
165
|
+
const currentLoad = this._bufferOrchestrator.length;
|
|
166
|
+
if (currentLoad + flattenedPoints.length >= 2147483647) {
|
|
167
|
+
throw new Error("Too many points, Point count cannot exceed 2147483647");
|
|
168
|
+
}
|
|
169
|
+
const { _bufferManagersMap, _bufferOrchestrator } = this;
|
|
170
|
+
console.log("point tracks plugin insert bulk", flattenedPoints);
|
|
171
|
+
_bufferOrchestrator.insertBulk(flattenedPoints, _bufferManagersMap);
|
|
172
|
+
this.globe?.DrawRender();
|
|
173
|
+
|
|
174
|
+
}
|
|
175
|
+
|
|
63
176
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
177
|
+
/**
|
|
178
|
+
* @param {string} trackID
|
|
179
|
+
*/
|
|
180
|
+
deleteTrack(trackID) {
|
|
181
|
+
const pointSet = this._tracksToPointsMap.get(trackID);
|
|
182
|
+
const points = Array.from(pointSet);
|
|
183
|
+
const { _bufferOrchestrator, _bufferManagersMap } = this;
|
|
184
|
+
_bufferOrchestrator.deleteBulk(
|
|
185
|
+
points.map((pointID) => keyMethod(trackID, pointID)),
|
|
186
|
+
_bufferManagersMap
|
|
187
|
+
);
|
|
188
|
+
this._tracksToPointsMap.delete(trackID);
|
|
189
|
+
this._redraw = true;
|
|
190
|
+
this.globe?.DrawRender();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* @param {string} trackID
|
|
196
|
+
* @param {Array<string>} pointIDs
|
|
197
|
+
*/
|
|
198
|
+
deletePoints(trackID, pointIDs) {
|
|
199
|
+
const { _bufferOrchestrator, _bufferManagersMap } = this;
|
|
200
|
+
_bufferOrchestrator.deleteBulk(
|
|
201
|
+
pointIDs.map((pointID) => keyMethod(trackID, pointID)),
|
|
202
|
+
_bufferManagersMap
|
|
203
|
+
);
|
|
204
|
+
this._deletePointsFromTracksMap(trackID, pointIDs);
|
|
205
|
+
this.globe?.DrawRender();
|
|
68
206
|
}
|
|
69
207
|
|
|
208
|
+
// GLOBE API METHODS
|
|
70
209
|
|
|
71
210
|
free() {
|
|
72
211
|
if (this._isFreed) return;
|
|
73
212
|
this._isFreed = true;
|
|
213
|
+
this._pickerDisplayer.free();
|
|
214
|
+
pointOnGlobeProgramCache.release(this.globe);
|
|
215
|
+
this._bufferManagersMap.forEach(
|
|
216
|
+
({ bufferManager, adaptor }) => bufferManager.free()
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
draw3D() {
|
|
222
|
+
const { gl, _pointProgram, _pickerDisplayer, _bufferOrchestrator, _vao } = this;
|
|
223
|
+
this.resize();
|
|
224
|
+
|
|
225
|
+
_pickerDisplayer.bindFBO();
|
|
226
|
+
_pickerDisplayer.clearTextures();
|
|
227
|
+
_pointProgram.draw(_vao, _bufferOrchestrator.length,
|
|
228
|
+
{
|
|
229
|
+
hoveredID: this._selectedID,
|
|
230
|
+
opacity: this._opacity,
|
|
231
|
+
pointSize: this.pointSizes.pointSize,
|
|
232
|
+
hoveredPointSize: this.pointSizes.hoveredPointSize
|
|
233
|
+
|
|
234
|
+
});
|
|
235
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
236
|
+
|
|
237
|
+
_pickerDisplayer.drawColorTexture();
|
|
238
|
+
this._selfSelect();
|
|
74
239
|
}
|
|
75
240
|
|
|
76
241
|
|
|
242
|
+
resize() {
|
|
243
|
+
const w = this.globe.api_ScrW();
|
|
244
|
+
const h = this.globe.api_ScrH();
|
|
245
|
+
if (w === this._lastWH.w && h === this._lastWH.h) return;
|
|
246
|
+
console.log("point tracks plugin resize", w, h);
|
|
247
|
+
|
|
248
|
+
this._lastWH.w = w;
|
|
249
|
+
this._lastWH.h = h;
|
|
250
|
+
this._pickerDisplayer.resize();
|
|
251
|
+
this.globe?.DrawRender();
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// IMPLICIT METHODS
|
|
255
|
+
|
|
256
|
+
_fillTracksToPointsMap(tracks) {
|
|
257
|
+
for (const track of tracks) {
|
|
258
|
+
const trackID = track.trackID;
|
|
259
|
+
const points = track.points;
|
|
260
|
+
if (!this._tracksToPointsMap.has(trackID)) {
|
|
261
|
+
this._tracksToPointsMap.set(trackID, new Set());
|
|
262
|
+
}
|
|
263
|
+
const pointSet = this._tracksToPointsMap.get(trackID);
|
|
264
|
+
for (let p = 0; p < points.length; p++) {
|
|
265
|
+
const pointID = points[p].ID;
|
|
266
|
+
pointSet.add(pointID);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
_deletePointsFromTracksMap(trackID, pointIDs) {
|
|
272
|
+
const trackSet = this._tracksToPointsMap.get(trackID);
|
|
273
|
+
for (const pointID of pointIDs) {
|
|
274
|
+
trackSet.delete(pointID);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
_selfSelect() {
|
|
280
|
+
const { globe } = this;
|
|
281
|
+
const pos = globe.api_GetMousePos();
|
|
282
|
+
const x = pos.canvasX;
|
|
283
|
+
const y = globe.api_ScrH() - pos.canvasY;
|
|
284
|
+
this.screenSelection(x, y, (selectedPoints) => {
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
const trackToFlatPoints = (track) => {
|
|
292
|
+
|
|
293
|
+
const trackID = track.trackID;
|
|
294
|
+
const points = track.points;
|
|
295
|
+
const rgba = new Float32Array(track.rgba);
|
|
296
|
+
const flatPoints = [];
|
|
297
|
+
for (const point of points) {
|
|
298
|
+
flatPoints.push({
|
|
299
|
+
key: keyMethod(trackID, point.ID),
|
|
300
|
+
long: point.long,
|
|
301
|
+
lat: point.lat,
|
|
302
|
+
height: point.height,
|
|
303
|
+
pointID: point.ID,
|
|
304
|
+
rgba,
|
|
305
|
+
trackID
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
return flatPoints;
|
|
309
|
+
}
|
|
77
310
|
|
|
311
|
+
const keyMethod = (trackID, pointID) => `${trackID}_${pointID}`;
|
|
78
312
|
|
|
79
313
|
|
|
80
|
-
}
|
|
314
|
+
export { PointTracksPlugin, keyMethod }
|
|
@@ -11,14 +11,16 @@ ${cartesian3DToGLPosition}
|
|
|
11
11
|
precision highp float;
|
|
12
12
|
precision highp int;
|
|
13
13
|
|
|
14
|
-
uniform int
|
|
14
|
+
uniform int hovered_vertexID; // can be removed
|
|
15
15
|
|
|
16
16
|
in vec3 pos3D;
|
|
17
17
|
in vec2 pos2D;
|
|
18
18
|
in vec4 rgba;
|
|
19
19
|
|
|
20
|
+
uniform float pointSize;
|
|
21
|
+
uniform float hoveredPointSize;
|
|
20
22
|
|
|
21
|
-
flat out highp int
|
|
23
|
+
flat out highp int vVertexID;
|
|
22
24
|
|
|
23
25
|
|
|
24
26
|
out vec4 v_rgba;
|
|
@@ -31,29 +33,30 @@ void main() {
|
|
|
31
33
|
else{
|
|
32
34
|
gl_Position = mercatorXYToGLPosition(pos2D);
|
|
33
35
|
}
|
|
34
|
-
if (
|
|
35
|
-
gl_PointSize =
|
|
36
|
+
if (hovered_vertexID == gl_VertexID) {
|
|
37
|
+
gl_PointSize = hoveredPointSize;
|
|
36
38
|
} else {
|
|
37
|
-
gl_PointSize =
|
|
39
|
+
gl_PointSize = pointSize;
|
|
40
|
+
}
|
|
38
41
|
v_rgba = rgba;
|
|
42
|
+
vVertexID = gl_VertexID;
|
|
39
43
|
}`;
|
|
40
44
|
|
|
41
45
|
const fs = `#version 300 es
|
|
42
46
|
precision highp float;
|
|
43
47
|
|
|
44
|
-
uniform opacity;
|
|
45
|
-
|
|
46
|
-
flat in highp int vInstanceID;
|
|
48
|
+
uniform float opacity;
|
|
47
49
|
|
|
50
|
+
flat in highp int vVertexID;
|
|
48
51
|
in vec4 v_rgba;
|
|
49
52
|
|
|
50
53
|
layout(location = 0) out vec4 fragColor;
|
|
51
|
-
layout(location = 1) out int
|
|
54
|
+
layout(location = 1) out int vertexID;
|
|
52
55
|
|
|
53
56
|
void main() {
|
|
57
|
+
vertexID = vVertexID;
|
|
54
58
|
fragColor = v_rgba;
|
|
55
59
|
fragColor.a *= opacity;
|
|
56
|
-
instanceID = vInstanceID;
|
|
57
60
|
}`;
|
|
58
61
|
|
|
59
62
|
|
|
@@ -68,8 +71,26 @@ class PointOnGlobeProgram {
|
|
|
68
71
|
|
|
69
72
|
const { gl, program } = this;
|
|
70
73
|
|
|
74
|
+
|
|
71
75
|
this.uniforms = {
|
|
72
76
|
opacity: gl.getUniformLocation(program, "opacity"),
|
|
77
|
+
hovered_vertexID: gl.getUniformLocation(program, "hovered_vertexID"),
|
|
78
|
+
hoveredPointSize: gl.getUniformLocation(program, "hoveredPointSize"),
|
|
79
|
+
pointSize: gl.getUniformLocation(program, "pointSize"),
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
{ // assign opacity
|
|
83
|
+
this._lastOpacity = 1.0;
|
|
84
|
+
this._lastPointSize = 2.0;
|
|
85
|
+
this._lastHoveredPointSize = 4.0;
|
|
86
|
+
this._lastHoveredID = -1;
|
|
87
|
+
const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
|
|
88
|
+
gl.useProgram(program);
|
|
89
|
+
gl.uniform1f(this.uniforms.opacity, this._lastOpacity);
|
|
90
|
+
gl.uniform1f(this.uniforms.pointSize, this._lastPointSize);
|
|
91
|
+
gl.uniform1f(this.uniforms.hoveredPointSize, this._lastHoveredPointSize);
|
|
92
|
+
gl.uniform1i(this.uniforms.hovered_vertexID, this._lastHoveredID);
|
|
93
|
+
gl.useProgram(currentProgram);
|
|
73
94
|
}
|
|
74
95
|
|
|
75
96
|
{ // assign attribute locations
|
|
@@ -113,23 +134,35 @@ class PointOnGlobeProgram {
|
|
|
113
134
|
return vao;
|
|
114
135
|
}
|
|
115
136
|
|
|
116
|
-
|
|
137
|
+
|
|
138
|
+
draw(vao, length, { opacity = 1.0, hoveredID = -1, pointSize = 2.0, hoveredPointSize = 4.0 } = {}) {
|
|
117
139
|
if (length === 0 || opacity === 0) return;
|
|
118
140
|
const { gl, program, uniforms } = this;
|
|
119
141
|
gl.useProgram(program);
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
142
|
+
if (this._lastOpacity !== opacity) {
|
|
143
|
+
gl.uniform1f(uniforms.opacity, opacity);
|
|
144
|
+
this._lastOpacity = opacity;
|
|
145
|
+
}
|
|
146
|
+
if (this._lastPointSize !== pointSize) {
|
|
147
|
+
gl.uniform1f(uniforms.pointSize, pointSize);
|
|
148
|
+
this._lastPointSize = pointSize;
|
|
149
|
+
}
|
|
150
|
+
if (this._lastHoveredPointSize !== hoveredPointSize) {
|
|
151
|
+
gl.uniform1f(uniforms.hoveredPointSize, hoveredPointSize);
|
|
152
|
+
this._lastHoveredPointSize = hoveredPointSize;
|
|
126
153
|
}
|
|
154
|
+
if (this._lastHoveredID !== hoveredID) {
|
|
155
|
+
gl.uniform1i(uniforms.hovered_vertexID, hoveredID);
|
|
156
|
+
this._lastHoveredID = hoveredID;
|
|
157
|
+
}
|
|
158
|
+
gl.bindVertexArray(vao);
|
|
127
159
|
this.cameraBlockTotem.bind(this.cameraBlockBingingPoint);
|
|
128
160
|
gl.drawArrays(gl.POINTS, 0, length);
|
|
129
161
|
this.cameraBlockTotem.unbind(this.cameraBlockBingingPoint);
|
|
130
162
|
gl.bindVertexArray(null);
|
|
131
163
|
}
|
|
132
164
|
|
|
165
|
+
|
|
133
166
|
free() {
|
|
134
167
|
if (this._isFreed) return;
|
|
135
168
|
const { gl, globe } = this;
|
package/rangerings/plugin.js
CHANGED
|
@@ -101,7 +101,8 @@ class RangeRings {
|
|
|
101
101
|
this._ringAccount.updateCentersCoordinate(items);
|
|
102
102
|
const { globe,
|
|
103
103
|
bufferOrchestrator, bufferManagersCompMap,
|
|
104
|
-
paddingBufferOrchestrator,
|
|
104
|
+
paddingBufferOrchestrator,
|
|
105
|
+
bufferManagersCompMapPadding
|
|
105
106
|
} = this;
|
|
106
107
|
for (const { centerID } of items) {
|
|
107
108
|
const datas = this.__reconstructCentralRings(centerID);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { BufferOrchestrator } from "./buffer-orchestrator";
|
|
2
2
|
import { BufferManager } from "./buffer-manager";
|
|
3
|
-
|
|
4
|
-
export { BufferOrchestrator, BufferManager };
|
|
3
|
+
import { ObjectStore } from "./object-store";
|
|
4
|
+
export { BufferOrchestrator, BufferManager, ObjectStore };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
|
|
2
|
+
export class ObjectStore {
|
|
3
|
+
constructor({ initialCapcity = 10 } = {}) {
|
|
4
|
+
this._container = this._createEmptyList(initialCapcity);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
resetWithCapacity(capacity) {
|
|
9
|
+
this._container = this._createEmptyList(capacity);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
deleteBulk(offsets) {
|
|
14
|
+
for (let i = 0; i < offsets.length; i++) {
|
|
15
|
+
const offset = offsets[i];
|
|
16
|
+
if (offset !== undefined) {
|
|
17
|
+
this._container[offset] = null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
insertBulk(objects, offsets) {
|
|
24
|
+
for (let i = 0; i < objects.length; i++) {
|
|
25
|
+
const object = objects[i];
|
|
26
|
+
const offset = offsets[i];
|
|
27
|
+
if (offset !== undefined) {
|
|
28
|
+
this._container[offset] = object;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
defrag(offsetValues, occupiedCapacity, newCapacity) {
|
|
34
|
+
|
|
35
|
+
const hold = this._createEmptyList(newCapacity);
|
|
36
|
+
for (let i = 0; i < offsetValues.length; i++) {
|
|
37
|
+
const offset = offsetValues[i];
|
|
38
|
+
if (offset !== undefined) {
|
|
39
|
+
hold[i] = this._container[offset];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
this._container = hold;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
extendBuffer(occupiedCapacity, newCapacity) {
|
|
46
|
+
const oldCapacity = this._container.length;
|
|
47
|
+
this._container = this._container.concat(this._createEmptyList(newCapacity - oldCapacity));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
_createEmptyList(size) {
|
|
51
|
+
return new Array(size).fill(null);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
get(index) {
|
|
55
|
+
return this._container[index];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
free() {
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
}
|
package/util/geometry/index.js
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
const PI_BY_180 = Math.PI / 180;
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
1
|
export function latLongToPixelXY(latitude, longitude) {
|
|
7
2
|
return {
|
|
8
3
|
x: (longitude + 180) / 360,
|
|
@@ -10,16 +5,6 @@ export function latLongToPixelXY(latitude, longitude) {
|
|
|
10
5
|
};
|
|
11
6
|
}
|
|
12
7
|
|
|
13
|
-
|
|
14
|
-
// export function latLongToRadiansTwist(latitude, longitude) {
|
|
15
|
-
|
|
16
|
-
// return {
|
|
17
|
-
// y: (90 - latitude) * PI_BY_180,
|
|
18
|
-
// x: longitude * PI_BY_180
|
|
19
|
-
// };
|
|
20
|
-
// }
|
|
21
|
-
|
|
22
|
-
|
|
23
8
|
/**
|
|
24
9
|
* createBBoxMatrix( minX, maxX, minY, maxY)
|
|
25
10
|
* use this matrix to transform a point from 0 to 1 range to the bounding box
|
|
@@ -41,4 +26,4 @@ export function latLongBboxtoPixelXYBbox(minX, minY, maxX, maxY) {
|
|
|
41
26
|
}
|
|
42
27
|
|
|
43
28
|
|
|
44
|
-
export { GeoDataFromTexture } from './geodatafromtexture';
|
|
29
|
+
// export { GeoDataFromTexture } from './geodatafromtexture';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const fence = (gl) => new Promise((resolve, reject) => {
|
|
2
|
+
// This will create a fence. If this follows a `readPixels()` call, then it
|
|
3
|
+
// will signal to WebGL that the read instruction should be asynchronous.
|
|
4
|
+
// This means JS can continue to work on other tasks while the read instruction
|
|
5
|
+
// completes.
|
|
6
|
+
const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
|
|
7
|
+
gl.flush();
|
|
8
|
+
|
|
9
|
+
// There are TWO possible ways to check on the status of a WebGLSync object.
|
|
10
|
+
|
|
11
|
+
// 1. This will check it using clientWaitSync()
|
|
12
|
+
const checkStatus_v1 = () => {
|
|
13
|
+
const status = gl.clientWaitSync(sync, 0, 0);
|
|
14
|
+
|
|
15
|
+
// There are four possible values for status:
|
|
16
|
+
// a. ALREADY_SIGNALED and CONDITION_SATISFIED (done)
|
|
17
|
+
// b. TIMEOUT_EXPIRED (check again later)
|
|
18
|
+
// c. WAIT_FAILED (there was an error)
|
|
19
|
+
if (status === gl.TIMEOUT_EXPIRED) {
|
|
20
|
+
setTimeout(checkStatus_v1, 1);
|
|
21
|
+
} else if (status === gl.ALREADY_SIGNALED || status === gl.CONDITION_SATISFIED) {
|
|
22
|
+
gl.deleteSync(sync);
|
|
23
|
+
resolve();
|
|
24
|
+
} else {
|
|
25
|
+
gl.deleteSync(sync);
|
|
26
|
+
reject(new Error('Fence did not resolve normally for some reason'));
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// 2. This will check with getSyncParameter(s, gl.SYNC_STATUS)
|
|
31
|
+
const checkStatus_v2 = () => {
|
|
32
|
+
const status = gl.getSyncParameter(sync, gl.SYNC_STATUS);
|
|
33
|
+
|
|
34
|
+
// There are only two possible values for status: SIGNALED and UNSIGNALED
|
|
35
|
+
// Note that there is no `error` signal, so there is no reason to use `reject()` here
|
|
36
|
+
if (status === gl.SIGNALED) {
|
|
37
|
+
gl.deleteSync(sync);
|
|
38
|
+
resolve();
|
|
39
|
+
} else {
|
|
40
|
+
setTimeout(checkStatus_v2, 1);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
setTimeout(checkStatus_v2, 1);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
export { fence };
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* add implicit texture display program for color
|
|
3
|
+
* add fence on query return and return id.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { textureOnCanvasProgramCache } from "../programs/draw-texture-on-canvas";
|
|
7
|
+
import { fence } from "./fence";
|
|
8
|
+
|
|
9
|
+
const ESCAPE_VALUE = -1;
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class PickerDisplayer {
|
|
13
|
+
constructor(globe) {
|
|
14
|
+
this.globe = globe;
|
|
15
|
+
this.gl = globe.gl;
|
|
16
|
+
const gl = this.gl;
|
|
17
|
+
this.colorTexture = gl.createTexture(); // bind to color attachment 0
|
|
18
|
+
this.indexTexture = gl.createTexture(); // bind to color attachment 1
|
|
19
|
+
this.fbo = gl.createFramebuffer();
|
|
20
|
+
|
|
21
|
+
this._pbo = undefined;
|
|
22
|
+
this._pboSize = 0;
|
|
23
|
+
this.resize();
|
|
24
|
+
|
|
25
|
+
this.displayer = textureOnCanvasProgramCache.get(this.gl);
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
resize(width = null, height = null) {
|
|
30
|
+
if (width === null || height === null) {
|
|
31
|
+
width = this.globe.api_ScrW();
|
|
32
|
+
height = this.globe.api_ScrH();
|
|
33
|
+
}
|
|
34
|
+
console.log("resize picker displayer", width, height);
|
|
35
|
+
const { gl, colorTexture, indexTexture } = this;
|
|
36
|
+
|
|
37
|
+
gl.deleteTexture(colorTexture);
|
|
38
|
+
gl.deleteTexture(indexTexture);
|
|
39
|
+
const colorTextureNew = gl.createTexture();
|
|
40
|
+
gl.bindTexture(gl.TEXTURE_2D, colorTextureNew);
|
|
41
|
+
gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, width, height);
|
|
42
|
+
const indexTextureNew = gl.createTexture();
|
|
43
|
+
gl.bindTexture(gl.TEXTURE_2D, indexTextureNew);
|
|
44
|
+
// gl.texStorage2D(gl.TEXTURE_2D, 1, gl.R16I, width, height);
|
|
45
|
+
gl.texStorage2D(gl.TEXTURE_2D, 1, gl.R32I, width, height);
|
|
46
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
47
|
+
|
|
48
|
+
this.colorTexture = colorTextureNew;
|
|
49
|
+
this.indexTexture = indexTextureNew;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
clearTextures() {
|
|
54
|
+
const { gl, colorTexture, indexTexture } = this;
|
|
55
|
+
gl.activeTexture(gl.TEXTURE1);
|
|
56
|
+
gl.bindTexture(gl.TEXTURE_2D, indexTexture);
|
|
57
|
+
gl.clearBufferiv(gl.COLOR, 1, new Int32Array([-1, -1, -1, -1]));
|
|
58
|
+
|
|
59
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
60
|
+
gl.bindTexture(gl.TEXTURE_2D, colorTexture);
|
|
61
|
+
gl.clearBufferfv(gl.COLOR, 0, new Float32Array([0, 0, 0, 0]));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
// call before drawing the scene with gl picker shader
|
|
66
|
+
bindFBO() {
|
|
67
|
+
const { gl, colorTexture, indexTexture, fbo } = this;
|
|
68
|
+
gl.activeTexture(gl.TEXTURE1);
|
|
69
|
+
gl.bindTexture(gl.TEXTURE_2D, indexTexture);
|
|
70
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
71
|
+
gl.bindTexture(gl.TEXTURE_2D, colorTexture);
|
|
72
|
+
{ // bind framebuffer
|
|
73
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
|
|
74
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.colorTexture, 0);
|
|
75
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, this.indexTexture, 0);
|
|
76
|
+
gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1]);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
// call after drawing the scene with gl picker shader
|
|
82
|
+
drawColorTexture() {
|
|
83
|
+
const { colorTexture } = this;
|
|
84
|
+
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);
|
|
85
|
+
this.displayer.draw(colorTexture);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
pickXY(x, y, selectionPointFilling = 1, callback = () => { }) {
|
|
90
|
+
const size = Math.pow(1 + 2 * selectionPointFilling, 2);
|
|
91
|
+
this._pick(size,
|
|
92
|
+
x - selectionPointFilling,
|
|
93
|
+
y - selectionPointFilling,
|
|
94
|
+
1 + 2 * selectionPointFilling,
|
|
95
|
+
1 + 2 * selectionPointFilling,
|
|
96
|
+
callback);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
pickBbox(left, top, right, bottom, callback) {
|
|
101
|
+
const size = (right - left) * (bottom - top) * 4;
|
|
102
|
+
this._pick(size, left, top, right - left, bottom - top, callback);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
_pick(size, startX, startY, lengthX, lengthY, callback) {
|
|
107
|
+
if (this._inProgress) return false;
|
|
108
|
+
this._inProgress = true;
|
|
109
|
+
|
|
110
|
+
this._initHoldBuffer(size * 4);
|
|
111
|
+
const { gl, _pbo } = this;
|
|
112
|
+
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, _pbo);
|
|
113
|
+
this.bindFBO();
|
|
114
|
+
gl.readBuffer(gl.COLOR_ATTACHMENT1); // This is the attachment we want to read
|
|
115
|
+
gl.readPixels( // This will read the pixels to the buffer asynchronously
|
|
116
|
+
startX, startY, lengthX, lengthY,
|
|
117
|
+
gl.RED_INTEGER, gl.INT,
|
|
118
|
+
0
|
|
119
|
+
);
|
|
120
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
121
|
+
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
|
|
122
|
+
fence(this.gl).then(() => {
|
|
123
|
+
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, _pbo);
|
|
124
|
+
// const data = new Int16Array(size);
|
|
125
|
+
const data = new Int32Array(size);
|
|
126
|
+
gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, data);
|
|
127
|
+
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
|
|
128
|
+
const result = this._pickFromBuffer(data, size);
|
|
129
|
+
callback(result);
|
|
130
|
+
// gl.deleteBuffer(pbo);
|
|
131
|
+
this._inProgress = false
|
|
132
|
+
}
|
|
133
|
+
);
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
_pickFromBuffer(array, size) {
|
|
139
|
+
const selectedObjects = new Set();
|
|
140
|
+
for (let i = 0; i < size; i += 1) {
|
|
141
|
+
const id = array[i];
|
|
142
|
+
if (id !== ESCAPE_VALUE) {
|
|
143
|
+
selectedObjects.add(id);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return selectedObjects;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
_initHoldBuffer(size) {
|
|
151
|
+
if (this._pbo && this._pboSize >= size) {
|
|
152
|
+
return
|
|
153
|
+
}
|
|
154
|
+
const { gl } = this;
|
|
155
|
+
const pbo = gl.createBuffer();
|
|
156
|
+
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, pbo);
|
|
157
|
+
gl.bufferData(gl.PIXEL_PACK_BUFFER, size, gl.STREAM_READ);
|
|
158
|
+
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
|
|
159
|
+
this._pboSize = size;
|
|
160
|
+
if (this._pbo !== undefined) {
|
|
161
|
+
gl.deleteBuffer(this._pbo);
|
|
162
|
+
}
|
|
163
|
+
this._pbo = pbo;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
free() {
|
|
168
|
+
const { gl, colorTexture, indexTexture, fbo } = this;
|
|
169
|
+
gl.deleteTexture(colorTexture);
|
|
170
|
+
gl.deleteTexture(indexTexture);
|
|
171
|
+
gl.deleteFramebuffer(fbo);
|
|
172
|
+
textureOnCanvasProgramCache.release(this.gl);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
export { PickerDisplayer };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createProgram } from "../webglobjectbuilders";
|
|
2
|
-
import {
|
|
2
|
+
import { glProgramCache } from "../../programs";
|
|
3
3
|
// import { CameraUniformBlockTotemCache, CameraUniformBlockString } from "../../programs/totems";
|
|
4
4
|
|
|
5
5
|
|
|
@@ -30,9 +30,8 @@ void main() {
|
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
class TextureOnCanvasProgram {
|
|
33
|
-
constructor(
|
|
34
|
-
this.
|
|
35
|
-
this.gl = globe.gl;
|
|
33
|
+
constructor(gl) {
|
|
34
|
+
this.gl = gl;
|
|
36
35
|
|
|
37
36
|
this.vao = this.gl.createVertexArray();
|
|
38
37
|
this.buffer = this.gl.createBuffer();
|
|
@@ -95,8 +94,8 @@ class TextureOnCanvasProgram {
|
|
|
95
94
|
}
|
|
96
95
|
|
|
97
96
|
const textureOnCanvasProgramCache = Object.freeze({
|
|
98
|
-
get: (
|
|
99
|
-
release: (
|
|
97
|
+
get: (gl) => glProgramCache.getProgram(gl, TextureOnCanvasProgram),
|
|
98
|
+
release: (gl) => glProgramCache.releaseProgram(gl, TextureOnCanvasProgram)
|
|
100
99
|
});
|
|
101
100
|
|
|
102
101
|
|
|
@@ -1,11 +1,26 @@
|
|
|
1
1
|
|
|
2
|
+
// export function createShader(gl, type, source) {
|
|
3
|
+
// const shader = gl.createShader(type);
|
|
4
|
+
// gl.shaderSource(shader, source);
|
|
5
|
+
|
|
6
|
+
// gl.compileShader(shader);
|
|
7
|
+
// if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
8
|
+
// throw new Error(gl.getShaderInfoLog(shader));
|
|
9
|
+
// }
|
|
10
|
+
|
|
11
|
+
// return shader;
|
|
12
|
+
// }
|
|
13
|
+
|
|
2
14
|
export function createShader(gl, type, source) {
|
|
3
15
|
const shader = gl.createShader(type);
|
|
4
16
|
gl.shaderSource(shader, source);
|
|
5
17
|
|
|
6
18
|
gl.compileShader(shader);
|
|
7
19
|
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
8
|
-
|
|
20
|
+
const errorLog = gl.getShaderInfoLog(shader);
|
|
21
|
+
const shaderType = type === gl.VERTEX_SHADER ? 'VERTEX_SHADER' : 'FRAGMENT_SHADER';
|
|
22
|
+
const sourceWithLineNumbers = source.split('\n').map((line, i) => `${i + 1}: ${line}`).join('\n');
|
|
23
|
+
throw new Error(`Error compiling ${shaderType}:\n${errorLog}\nSource:\n${sourceWithLineNumbers}`);
|
|
9
24
|
}
|
|
10
25
|
|
|
11
26
|
return shader;
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
export class GeoDataFromTexture {
|
|
2
|
-
/**
|
|
3
|
-
* @param {Array} bbox - [minLong, minLat, maxLong, maxLat]
|
|
4
|
-
* @param {Array} textureData - array of data
|
|
5
|
-
* @param {Number} width - width of the texture
|
|
6
|
-
* @param {Number} height - height of the texture
|
|
7
|
-
* */
|
|
8
|
-
constructor(bbox, textureData, width, height) {
|
|
9
|
-
this.bbox = null;
|
|
10
|
-
this.textureData = textureData;
|
|
11
|
-
this.width = width;
|
|
12
|
-
this.height = height;
|
|
13
|
-
this.setBBox(bbox);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
setBBox(bbox) {
|
|
17
|
-
this.bbox = bbox;
|
|
18
|
-
this._longRatio = (this.bbox[2] - this.bbox[0]) / this.width;
|
|
19
|
-
|
|
20
|
-
this._latRatio = (this.bbox[3] - this.bbox[1]) / this.height;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
setTextureData(textureData) {
|
|
24
|
-
this.textureData = textureData;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
getFloored(lat, long) {
|
|
28
|
-
const x = (long - this.bbox[0]) / this._longRatio;
|
|
29
|
-
const y = (lat - this.bbox[1]) / this._latRatio;
|
|
30
|
-
//console.log(x + " = (" + long + " - " + this.bbox[0] + ") / " + this._longRatio);
|
|
31
|
-
//console.log(y + " = (" + lat + " - " + this.bbox[1] + ") / " + this._latRatio);
|
|
32
|
-
const index = Math.floor(y) * this.width + Math.floor(x);
|
|
33
|
-
//console.log({ index, x, y, w: this.width, h: this.height, "total": this.width * this.height });
|
|
34
|
-
return this.textureData[index];
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
getInterpolated(lat, long) {
|
|
38
|
-
// this has bug for the last row and column
|
|
39
|
-
const x = (long - this.bbox[0]) / (this.bbox[2] - this.bbox[0]);
|
|
40
|
-
const y = (lat - this.bbox[1]) / (this.bbox[3] - this.bbox[1]);
|
|
41
|
-
const xIndex = Math.floor(x * this.width);
|
|
42
|
-
const yIndex = Math.floor(y * this.height);
|
|
43
|
-
const xRatio = x * this.width - xIndex;
|
|
44
|
-
const yRatio = y * this.height - yIndex;
|
|
45
|
-
const index = yIndex * this.width + xIndex;
|
|
46
|
-
const data = this.textureData[index];
|
|
47
|
-
const data1 = this.textureData[index + 1];
|
|
48
|
-
const data2 = this.textureData[index + this.width];
|
|
49
|
-
const data3 = this.textureData[index + this.width + 1];
|
|
50
|
-
return data * (1 - xRatio) * (1 - yRatio) + data1 * xRatio * (1 - yRatio) + data2 * (1 - xRatio) * yRatio + data3 * xRatio * yRatio;
|
|
51
|
-
}
|
|
52
|
-
}
|