@pirireis/webglobeplugins 0.17.0 → 0.17.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.
- package/Math/methods.js +6 -0
- package/Math/tessellation/tile-merger.js +284 -42
- package/Math/tessellation/triangle-tessellation-meta.js +22 -15
- package/investigation-tools/draw/tiles/adapters.js +67 -0
- package/investigation-tools/draw/tiles/tiles.js +128 -0
- package/package.json +1 -1
- package/programs/polygon-on-globe/texture-dem-triangle-test-plugin-triangle.js +155 -31
- package/programs/polygon-on-globe/texture-dem-triangles.js +68 -36
- package/programs/vectorfields/logics/drawrectangleparticles.js +8 -6
- package/programs/vectorfields/logics/drawrectangleparticles1.js +112 -0
- package/semiplugins/shape-on-terrain/arc-plugin.js +9 -0
- package/tracks/point-tracks/plugin.js +1 -0
- package/util/picking/picker-displayer.js +2 -2
- package/util/shaderfunctions/geometrytransformations.js +1 -1
- package/vectorfield/wind/plugin.js +33 -19
- package/write-text/context-text4.js +2 -1
- package/programs/polygon-on-globe/partial-tesselation.js +0 -1
- package/programs/polygon-on-globe/texture-dem-triangle-test-plugin.js +0 -118
- package/util/webglobe/rasteroverlay.js +0 -76
- package/write-text/attached-text-writer.js +0 -95
|
@@ -1,8 +1,80 @@
|
|
|
1
1
|
import { TextureDemTriangles } from "./texture-dem-triangles";
|
|
2
|
-
import {
|
|
2
|
+
import { RADIAN, radianToMercatorXY } from "../../Math/methods";
|
|
3
|
+
import { mergeMeshes } from "../../Math/tessellation/tile-merger";
|
|
4
|
+
import { createTriangleTessellationMeta, getAllPoints, partialTessellation } from "../../Math/tessellation/triangle-tessellation-meta";
|
|
3
5
|
/**
|
|
4
6
|
* Loads a plugin with test data for TextureDemTriangles
|
|
5
7
|
*/
|
|
8
|
+
function test1(zoomLevel, p1, p2, p3) {
|
|
9
|
+
const triangleMeta = createTriangleTessellationMeta(p1, p2, p3);
|
|
10
|
+
const { vec3s, longLats, indices } = getAllPoints(triangleMeta, zoomLevel);
|
|
11
|
+
return { vec3s, longLats, indices };
|
|
12
|
+
}
|
|
13
|
+
function partialTest(bboxZooms, p1, p2, p3) {
|
|
14
|
+
const triangleMeta = createTriangleTessellationMeta(p1, p2, p3);
|
|
15
|
+
return partialTessellation(triangleMeta, bboxZooms, 5);
|
|
16
|
+
}
|
|
17
|
+
function antalyaTestTriangle() {
|
|
18
|
+
const p1 = [30.5391 * RADIAN, 36.9083 * RADIAN];
|
|
19
|
+
const p2 = [32.9271 * RADIAN, 36.9083 * RADIAN];
|
|
20
|
+
const p3 = [31.7331 * RADIAN, 35.8145 * RADIAN];
|
|
21
|
+
const bboxZooms = [
|
|
22
|
+
// 12 zoom level
|
|
23
|
+
{
|
|
24
|
+
bbox: {
|
|
25
|
+
min: [30.5391 * RADIAN, 35.8145 * RADIAN],
|
|
26
|
+
max: [32.9271 * RADIAN, 36.9083 * RADIAN]
|
|
27
|
+
}, zoom: 15
|
|
28
|
+
},
|
|
29
|
+
// 11 zoom level
|
|
30
|
+
// {
|
|
31
|
+
// bbox: {
|
|
32
|
+
// min: [30.5391 * RADIAN, 35.8145 * RADIAN],
|
|
33
|
+
// max: [32.9271 * RADIAN, 36.9083 * RADIAN]
|
|
34
|
+
// }, zoom: 11
|
|
35
|
+
// },
|
|
36
|
+
];
|
|
37
|
+
return partialTest(bboxZooms, p1, p2, p3);
|
|
38
|
+
}
|
|
39
|
+
function loadVec3sLongLatsIndices(gl, bufferInfo, data) {
|
|
40
|
+
// Calculate total sizes
|
|
41
|
+
let totalVec3s = 0;
|
|
42
|
+
let totalLongLats = 0;
|
|
43
|
+
let totalIndices = 0;
|
|
44
|
+
for (const item of data) {
|
|
45
|
+
totalVec3s += item.vec3s.length;
|
|
46
|
+
totalLongLats += item.longLats.length;
|
|
47
|
+
totalIndices += item.indices.length;
|
|
48
|
+
}
|
|
49
|
+
// Pre-allocate arrays
|
|
50
|
+
const vec3s = new Float32Array(totalVec3s);
|
|
51
|
+
const longLats = new Float32Array(totalLongLats);
|
|
52
|
+
const indices = new Uint32Array(totalIndices);
|
|
53
|
+
let vec3Offset = 0;
|
|
54
|
+
let longLatOffset = 0;
|
|
55
|
+
let indexOffset = 0;
|
|
56
|
+
let vertexOffset = 0;
|
|
57
|
+
for (const item of data) {
|
|
58
|
+
// Copy vec3s
|
|
59
|
+
vec3s.set(item.vec3s, vec3Offset);
|
|
60
|
+
vec3Offset += item.vec3s.length;
|
|
61
|
+
// Copy longLats
|
|
62
|
+
longLats.set(item.longLats, longLatOffset);
|
|
63
|
+
longLatOffset += item.longLats.length;
|
|
64
|
+
// Copy and adjust indices
|
|
65
|
+
for (let i = 0; i < item.indices.length; i++) {
|
|
66
|
+
indices[indexOffset + i] = item.indices[i] + vertexOffset;
|
|
67
|
+
}
|
|
68
|
+
indexOffset += item.indices.length;
|
|
69
|
+
vertexOffset += item.vec3s.length / 3; // Each vertex has 3 components
|
|
70
|
+
}
|
|
71
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, bufferInfo.pos3dBufferInfo.buffer);
|
|
72
|
+
gl.bufferData(gl.ARRAY_BUFFER, vec3s, gl.STATIC_DRAW);
|
|
73
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, bufferInfo.longLatBufferInfo.buffer);
|
|
74
|
+
gl.bufferData(gl.ARRAY_BUFFER, longLats, gl.STATIC_DRAW);
|
|
75
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferInfo.elementBufferInfo.buffer);
|
|
76
|
+
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
|
|
77
|
+
}
|
|
6
78
|
const createTestBBOXES = () => {
|
|
7
79
|
const bboxes = [];
|
|
8
80
|
for (let i = 0; i < 6; i++) {
|
|
@@ -10,9 +82,10 @@ const createTestBBOXES = () => {
|
|
|
10
82
|
const west = Math.random() * -1 * Math.PI / 10; // random longitude
|
|
11
83
|
const south = north - Math.PI / 30; // random latitude
|
|
12
84
|
const east = west + Math.PI / 30; // random longitude
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
|
|
85
|
+
const ll = [west, north]; // random northWest
|
|
86
|
+
const ur = [east, south]; // random southEast
|
|
87
|
+
//
|
|
88
|
+
bboxes.push({ ll, ur });
|
|
16
89
|
}
|
|
17
90
|
return bboxes;
|
|
18
91
|
};
|
|
@@ -20,7 +93,7 @@ const demTextureBBOX = createTestBBOXES();
|
|
|
20
93
|
function showTextureBBoxes(bboxes, demData = []) {
|
|
21
94
|
for (let i = 0; i < bboxes.length; i++) {
|
|
22
95
|
const bbox = bboxes[i];
|
|
23
|
-
console.log(`Texture BBOX ${i}:
|
|
96
|
+
console.log(`Texture BBOX ${i}: LL(${(bbox.ll[0] * 180 / Math.PI).toFixed(2)}, ${(bbox.ll[1] * 180 / Math.PI).toFixed(2)}) UR(${(bbox.ur[0] * 180 / Math.PI).toFixed(2)}, ${(bbox.ur[1] * 180 / Math.PI).toFixed(2)})`);
|
|
24
97
|
if (demData.length > i) {
|
|
25
98
|
const dem = demData[i];
|
|
26
99
|
let demStr = "DEM: \n";
|
|
@@ -70,6 +143,7 @@ export class TextureDemTrianglesTestPlugin {
|
|
|
70
143
|
textureDemTriangles = null;
|
|
71
144
|
vao = null;
|
|
72
145
|
drawOptions = null;
|
|
146
|
+
_lastTilesUniqueIdentifier = "";
|
|
73
147
|
bufferInfo = null;
|
|
74
148
|
id;
|
|
75
149
|
uboTriangleStyle = null;
|
|
@@ -139,15 +213,16 @@ export class TextureDemTrianglesTestPlugin {
|
|
|
139
213
|
this.bboxZooms = demTextureBBOX.map((bbox, index) => {
|
|
140
214
|
return {
|
|
141
215
|
bbox: {
|
|
142
|
-
min:
|
|
216
|
+
min: bbox.ll,
|
|
217
|
+
max: bbox.ur,
|
|
143
218
|
}, zoom: index + zoomLevel + 1
|
|
144
219
|
};
|
|
145
220
|
});
|
|
146
|
-
// all world
|
|
221
|
+
// all world - FIX: Convert to radians
|
|
147
222
|
this.bboxZooms.push({
|
|
148
223
|
bbox: {
|
|
149
|
-
min: [-180, -90],
|
|
150
|
-
max: [180, 90]
|
|
224
|
+
min: [-180 * RADIAN, -90 * RADIAN], // ✓ Now radians
|
|
225
|
+
max: [180 * RADIAN, 90 * RADIAN] // ✓ Now radians
|
|
151
226
|
},
|
|
152
227
|
zoom: zoomLevel
|
|
153
228
|
});
|
|
@@ -159,31 +234,17 @@ export class TextureDemTrianglesTestPlugin {
|
|
|
159
234
|
const p1 = [-60 * Math.PI / 180, 60 * Math.PI / 180];
|
|
160
235
|
const p2 = [60 * Math.PI / 180, 60 * Math.PI / 180];
|
|
161
236
|
const p3 = [0, -60 * Math.PI / 180];
|
|
162
|
-
|
|
163
|
-
// const p2_2: LongLatRadian = [20 * Math.PI / 180, 20 * Math.PI / 180];
|
|
164
|
-
// const p3_3: LongLatRadian = [5, -20 * Math.PI / 180];
|
|
165
|
-
// const { vec3s, longLats, indices } = test1(zoomLevel, p1, p2, p3);
|
|
166
|
-
// const {vec3s, longLats, indices} = test1(5, p1_1, p2_2, p3_3);
|
|
167
|
-
const { vec3s, longLats, indices } = partialTest(this.bboxZooms, p1, p2, p3);
|
|
237
|
+
const bigTriangle = partialTest(this.bboxZooms, p1, p2, p3);
|
|
168
238
|
const bufferInfo = this.bufferInfo;
|
|
239
|
+
const antalya = antalyaTestTriangle();
|
|
240
|
+
loadVec3sLongLatsIndices(this.globe.gl, bufferInfo, [
|
|
241
|
+
bigTriangle,
|
|
242
|
+
antalya
|
|
243
|
+
]);
|
|
169
244
|
bufferInfo.drawOptions.drawRange.first = 0;
|
|
170
|
-
bufferInfo.drawOptions.drawRange.count = indices.length;
|
|
245
|
+
bufferInfo.drawOptions.drawRange.count = antalya.indices.length + bigTriangle.indices.length;
|
|
171
246
|
bufferInfo.drawOptionsPoint.drawRange.first = 0;
|
|
172
|
-
bufferInfo.drawOptionsPoint.drawRange.count = longLats.length / 2;
|
|
173
|
-
const gl = this.globe.gl;
|
|
174
|
-
// const longLatArray = createTestLongLatArray();
|
|
175
|
-
// const pos3dArray = createTestPos3dArray(longLatArray);
|
|
176
|
-
// @ts-ignore
|
|
177
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, bufferInfo.pos3dBufferInfo.buffer);
|
|
178
|
-
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vec3s), gl.STATIC_DRAW);
|
|
179
|
-
// @ts-ignore
|
|
180
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, bufferInfo.longLatBufferInfo.buffer);
|
|
181
|
-
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(longLats), gl.STATIC_DRAW);
|
|
182
|
-
// @ts-ignore
|
|
183
|
-
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferInfo.elementBufferInfo.buffer);
|
|
184
|
-
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(indices), gl.STATIC_DRAW);
|
|
185
|
-
this.globe.DrawRender();
|
|
186
|
-
console.log("DrawIInfo", this.bufferInfo);
|
|
247
|
+
bufferInfo.drawOptionsPoint.drawRange.count = (antalya.longLats.length + bigTriangle.longLats.length) / 2;
|
|
187
248
|
}
|
|
188
249
|
setShowDemPoints(show) {
|
|
189
250
|
this.showDemPoints = show;
|
|
@@ -192,6 +253,7 @@ export class TextureDemTrianglesTestPlugin {
|
|
|
192
253
|
if (!this.globe || !this.textureDemTriangles || !this.vao || !this.bufferInfo)
|
|
193
254
|
return;
|
|
194
255
|
const gl = this.globe.gl;
|
|
256
|
+
this._prepareDem();
|
|
195
257
|
gl.frontFace(gl.CW);
|
|
196
258
|
// @ts-ignore
|
|
197
259
|
this.textureDemTriangles.draw(this.vao, this.bufferInfo.drawOptions, this.uboTriangleStyle);
|
|
@@ -201,4 +263,66 @@ export class TextureDemTrianglesTestPlugin {
|
|
|
201
263
|
}
|
|
202
264
|
gl.frontFace(gl.CCW);
|
|
203
265
|
}
|
|
266
|
+
_prepareDem() {
|
|
267
|
+
if (!this.globe || !this.textureDemTriangles)
|
|
268
|
+
return;
|
|
269
|
+
const drawnTiles = this.globe.api_GetDrawedTilesInfo();
|
|
270
|
+
if (this._checkTileChange(drawnTiles))
|
|
271
|
+
return;
|
|
272
|
+
const mergedTiles = mergeMeshes(drawnTiles, 12, 5, 4);
|
|
273
|
+
// let I = 6;
|
|
274
|
+
for (const tile of mergedTiles) {
|
|
275
|
+
const bbox = globeBBoxToXYBBOX(tile.bbox);
|
|
276
|
+
// Validation: Check if values are in expected radian range
|
|
277
|
+
// if (Math.abs(bbox.northWest[0]) > Math.PI * 2 || Math.abs(bbox.northWest[1]) > Math.PI) {
|
|
278
|
+
// console.error(`⚠️ BBOX out of radian range! Raw bbox:`, tile.bbox);
|
|
279
|
+
// }
|
|
280
|
+
if (bbox.ll[0] > bbox.ur[0]) {
|
|
281
|
+
console.warn(`⚠️ BBOX longitudes seem incorrect! ll longitude is greater than ur longitude. Raw bbox:`, bbox);
|
|
282
|
+
}
|
|
283
|
+
if (bbox.ll[1] > bbox.ur[1]) {
|
|
284
|
+
console.warn(`⚠️ BBOX latitudes seem incorrect! ll latitude is greater than ur latitude. Raw bbox:`, bbox);
|
|
285
|
+
}
|
|
286
|
+
// console.log(` BBox LL (${(bbox.ll[0]).toFixed(2)}°, ${(bbox.ll[1]).toFixed(2)}°) UR (${(bbox.ur[0]).toFixed(2)}°, ${(bbox.ur[1]).toFixed(2)}°), Cover: ${tile.coverRatio.x.toFixed(2)}x${tile.coverRatio.y.toFixed(2)}`);
|
|
287
|
+
// console.log(`${I} Cover: ${tile.coverRatio.x.toFixed(2)} ${tile.coverRatio.y.toFixed(2)}`);
|
|
288
|
+
// I--;
|
|
289
|
+
}
|
|
290
|
+
// console.log("...............................")
|
|
291
|
+
this.textureDemTriangles.setDemTextures(mergedTiles.map(t => Array.from(t.mesh)), mergedTiles.map(t => globeBBoxToXYBBOX(t.bbox)), mergedTiles.map(t => ({ x: t.coverRatio.x, y: t.coverRatio.y })));
|
|
292
|
+
}
|
|
293
|
+
_checkTileChange(drawnTiles) {
|
|
294
|
+
let maxLevel = 0;
|
|
295
|
+
let minLevel = Number.MAX_VALUE;
|
|
296
|
+
const tileMap = new Map();
|
|
297
|
+
for (const tile of drawnTiles) {
|
|
298
|
+
if (tile.level > maxLevel) {
|
|
299
|
+
maxLevel = tile.level;
|
|
300
|
+
}
|
|
301
|
+
if (tile.level < minLevel) {
|
|
302
|
+
minLevel = tile.level;
|
|
303
|
+
}
|
|
304
|
+
if (!tileMap.has(tile.level)) {
|
|
305
|
+
tileMap.set(tile.level, []);
|
|
306
|
+
}
|
|
307
|
+
tileMap.get(tile.level).push(tile);
|
|
308
|
+
}
|
|
309
|
+
let tilesUniqueId = "";
|
|
310
|
+
for (let level = minLevel; level <= maxLevel; level++) {
|
|
311
|
+
const tiles = tileMap.get(level);
|
|
312
|
+
if (!tiles)
|
|
313
|
+
continue;
|
|
314
|
+
tilesUniqueId += `L${level}_C${tiles.length}_`;
|
|
315
|
+
}
|
|
316
|
+
if (tilesUniqueId === this._lastTilesUniqueIdentifier)
|
|
317
|
+
return true;
|
|
318
|
+
this._lastTilesUniqueIdentifier = tilesUniqueId;
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
function globeBBoxToXYBBOX(t) {
|
|
323
|
+
// this code scales Y to linear integration
|
|
324
|
+
return {
|
|
325
|
+
ll: radianToMercatorXY([t.ll.x * RADIAN, t.ll.y * RADIAN]), // west longitude, north latitude
|
|
326
|
+
ur: radianToMercatorXY([t.ur.x * RADIAN, t.ur.y * RADIAN]) // east longitude, south latitude
|
|
327
|
+
};
|
|
204
328
|
}
|
|
@@ -25,19 +25,14 @@ ${CameraUniformBlockString}
|
|
|
25
25
|
|
|
26
26
|
${cartesian3DToGLPosition}
|
|
27
27
|
in vec3 a_position;
|
|
28
|
-
in vec2
|
|
28
|
+
in vec2 a_xy;
|
|
29
29
|
uniform sampler2DArray u_demTexture; // <-- changed from array to single
|
|
30
30
|
uniform vec4 u_demTextureBBOX[6];
|
|
31
|
-
|
|
31
|
+
uniform vec2 u_textureDataCoverRatio[6];
|
|
32
|
+
uniform int u_breakLoopIndex;
|
|
32
33
|
|
|
33
34
|
${styleBlockManager.glslCode()}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
// TODO: light directioni
|
|
37
|
-
// out vec3 v_position;
|
|
38
|
-
// out vec3 v_normal;
|
|
39
|
-
// out vec2 v_textureCoord;
|
|
40
|
-
|
|
35
|
+
// Todo: light direction.
|
|
41
36
|
out vec4 v_color;
|
|
42
37
|
|
|
43
38
|
|
|
@@ -46,23 +41,35 @@ ${isPointInBBox}
|
|
|
46
41
|
void main() {
|
|
47
42
|
|
|
48
43
|
float elevation = ${WORLD_RADIUS_3D}; // default elevation at sea level
|
|
44
|
+
float altitude = 0.0;
|
|
49
45
|
v_color = vec4(1.0, 1.0, 1.0, 1.0); // default color white
|
|
46
|
+
|
|
50
47
|
for (int i = 0; i < 6; i++) {
|
|
51
|
-
if (isPointInBBox(
|
|
52
|
-
vec2 uv = (
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
if (isPointInBBox(a_xy, u_demTextureBBOX[i])) {
|
|
49
|
+
vec2 uv = (a_xy - u_demTextureBBOX[i].xy) / (u_demTextureBBOX[i].zw - u_demTextureBBOX[i].xy);
|
|
50
|
+
// uv.y = 1.0 - uv.y; // flip y coordinate
|
|
51
|
+
// rescale and transform uv to fit in the texture data cover bbox
|
|
52
|
+
uv *= u_textureDataCoverRatio[i];
|
|
53
|
+
altitude = texture(u_demTexture, vec3(uv, float(i))).r;
|
|
54
|
+
if (altitude != 0.0) {
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
58
|
}
|
|
59
59
|
if (u_color.a > 0.0) {
|
|
60
60
|
v_color = u_color;
|
|
61
|
+
} else {
|
|
62
|
+
if ( altitude > 0.00001 ) {
|
|
63
|
+
v_color = mix(vec4(1.0, 1.0, 1.0, 1.0), vec4(1.0, 0.2, 0.2, 1.0), altitude / 2.0); // color from white to red based on altitude
|
|
64
|
+
} else {
|
|
65
|
+
// white
|
|
66
|
+
v_color = vec4(1.0, 1.0, 1.0, 0.5);
|
|
67
|
+
}
|
|
61
68
|
}
|
|
62
69
|
v_color.a *= u_opacity;
|
|
63
|
-
vec3 position = a_position * elevation;
|
|
70
|
+
vec3 position = a_position * (elevation + altitude * 2.0);
|
|
64
71
|
gl_Position = cartesian3DToGLPosition(position);
|
|
65
|
-
gl_PointSize =
|
|
72
|
+
gl_PointSize = 6.0; //u_pointSize;
|
|
66
73
|
}
|
|
67
74
|
`;
|
|
68
75
|
const fragmentShaderSource = `#version 300 es
|
|
@@ -75,6 +82,10 @@ void main() {
|
|
|
75
82
|
outColor = v_color;
|
|
76
83
|
}
|
|
77
84
|
`;
|
|
85
|
+
function resCalculation(sourceResolution, mergeCount) {
|
|
86
|
+
return sourceResolution + (mergeCount - 1) * (sourceResolution - 1);
|
|
87
|
+
}
|
|
88
|
+
const RESOLUTION = resCalculation(5, 12); // 5 is tile dimension length, 12 is merge count
|
|
78
89
|
export class TextureDemTriangles {
|
|
79
90
|
globe;
|
|
80
91
|
gl;
|
|
@@ -88,12 +99,14 @@ export class TextureDemTriangles {
|
|
|
88
99
|
locations = {
|
|
89
100
|
attributes: {
|
|
90
101
|
a_position: -1,
|
|
91
|
-
|
|
102
|
+
a_xy: -1,
|
|
92
103
|
},
|
|
93
104
|
uniforms: {
|
|
94
105
|
u_demTexture: -1,
|
|
95
106
|
u_demTextureBBOX: -1,
|
|
107
|
+
u_textureDataCoverRatio: -1,
|
|
96
108
|
u_style: -1,
|
|
109
|
+
u_breakLoopIndex: -1,
|
|
97
110
|
}
|
|
98
111
|
};
|
|
99
112
|
constructor(globe) {
|
|
@@ -104,17 +117,20 @@ export class TextureDemTriangles {
|
|
|
104
117
|
this.cameraUniformBlock.assignBindingPoint(this.program, uniformBindingPoints.camera);
|
|
105
118
|
// get attribute locations
|
|
106
119
|
this.locations.attributes.a_position = this.gl.getAttribLocation(this.program, 'a_position');
|
|
107
|
-
this.locations.attributes.
|
|
120
|
+
this.locations.attributes.a_xy = this.gl.getAttribLocation(this.program, 'a_xy');
|
|
108
121
|
// get uniform locations
|
|
109
122
|
this.locations.uniforms.u_demTexture = this.gl.getUniformLocation(this.program, 'u_demTexture');
|
|
110
123
|
this.locations.uniforms.u_demTextureBBOX = this.gl.getUniformLocation(this.program, 'u_demTextureBBOX');
|
|
124
|
+
this.locations.uniforms.u_textureDataCoverRatio = this.gl.getUniformLocation(this.program, 'u_textureDataCoverRatio');
|
|
125
|
+
this.locations.uniforms.u_breakLoopIndex = this.gl.getUniformLocation(this.program, 'u_breakLoopIndex');
|
|
111
126
|
this.locations.uniforms.u_style = this.gl.getUniformBlockIndex(this.program, 'Style');
|
|
112
127
|
this.gl.uniformBlockBinding(this.program, this.locations.uniforms.u_style, uniformBindingPoints.style);
|
|
113
128
|
// create 3d texture
|
|
114
129
|
const texture = this.gl.createTexture();
|
|
115
130
|
this.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY, texture);
|
|
116
|
-
//
|
|
117
|
-
|
|
131
|
+
// Calculate correct size: tileDimensionLength + (mergeCount - 1) * (tileDimensionLength - 1)
|
|
132
|
+
// For tileDimensionLength=5, mergeCount=8: 5 + 7*4 = RESOLUTION
|
|
133
|
+
this.gl.texStorage3D(this.gl.TEXTURE_2D_ARRAY, 1, this.gl.R32F, RESOLUTION, RESOLUTION, 6);
|
|
118
134
|
// set texture parameters
|
|
119
135
|
const ext = this.gl.getExtension('OES_texture_float_linear');
|
|
120
136
|
console.log('OES_texture_float_linear extension:', ext);
|
|
@@ -129,11 +145,17 @@ export class TextureDemTriangles {
|
|
|
129
145
|
const vao = this.gl.createVertexArray();
|
|
130
146
|
this.gl.bindVertexArray(vao);
|
|
131
147
|
attributeLoader(this.gl, pos3dBufferInfo, this.locations.attributes.a_position, 3);
|
|
132
|
-
attributeLoader(this.gl, longLatBufferInfo, this.locations.attributes.
|
|
148
|
+
attributeLoader(this.gl, longLatBufferInfo, this.locations.attributes.a_xy, 2);
|
|
133
149
|
this.gl.bindVertexArray(null);
|
|
134
150
|
return vao;
|
|
135
151
|
}
|
|
136
|
-
setDemTextures(demTexturesData, demTextureBBOX) {
|
|
152
|
+
setDemTextures(demTexturesData, demTextureBBOX, coverRatio) {
|
|
153
|
+
// Add validation for maximum layers
|
|
154
|
+
const maxLayers = this.gl.getParameter(this.gl.MAX_ARRAY_TEXTURE_LAYERS);
|
|
155
|
+
if (demTexturesData.length > Math.min(maxLayers, 6)) {
|
|
156
|
+
console.error(`Too many DEM textures: ${demTexturesData.length}, max supported: ${Math.min(maxLayers, 6)}`);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
137
159
|
// bind textures to texture units
|
|
138
160
|
const gl = this.gl;
|
|
139
161
|
gl.bindTexture(gl.TEXTURE_2D_ARRAY, this.texture);
|
|
@@ -143,23 +165,33 @@ export class TextureDemTriangles {
|
|
|
143
165
|
// bind and upload each texture to the 3D texture array
|
|
144
166
|
for (let i = 0; i < demTexturesData.length; i++) {
|
|
145
167
|
const data = demTexturesData[i];
|
|
146
|
-
if (data.length ===
|
|
147
|
-
gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, i,
|
|
168
|
+
if (data.length === RESOLUTION * RESOLUTION) { // <-- FIXED
|
|
169
|
+
gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, i, RESOLUTION, RESOLUTION, 1, gl.RED, gl.FLOAT, new Float32Array(data));
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
console.warn(`DEM texture ${i} has incorrect size: ${data.length}, expected: ${RESOLUTION * RESOLUTION}`);
|
|
148
173
|
}
|
|
149
174
|
}
|
|
150
175
|
// set uniform for texture units
|
|
151
176
|
const bboxVec4Array = new Float32Array(6 * 4);
|
|
152
177
|
for (let i = 0; i < demTextureBBOX.length; i++) {
|
|
153
178
|
const bbox = demTextureBBOX[i];
|
|
154
|
-
bboxVec4Array[i * 4 + 0] = bbox.
|
|
155
|
-
bboxVec4Array[i * 4 + 1] = bbox.
|
|
156
|
-
bboxVec4Array[i * 4 + 2] = bbox.
|
|
157
|
-
bboxVec4Array[i * 4 + 3] = bbox.
|
|
179
|
+
bboxVec4Array[i * 4 + 0] = bbox.ll[0];
|
|
180
|
+
bboxVec4Array[i * 4 + 1] = bbox.ll[1];
|
|
181
|
+
bboxVec4Array[i * 4 + 2] = bbox.ur[0];
|
|
182
|
+
bboxVec4Array[i * 4 + 3] = bbox.ur[1];
|
|
158
183
|
}
|
|
159
184
|
const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
|
|
160
185
|
gl.useProgram(this.program);
|
|
161
186
|
gl.uniform4fv(this.locations.uniforms.u_demTextureBBOX, bboxVec4Array);
|
|
187
|
+
if (coverRatio) {
|
|
188
|
+
gl.uniform2fv(this.locations.uniforms.u_textureDataCoverRatio, new Float32Array(coverRatio.flatMap(ratio => [ratio.x, ratio.y])));
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
gl.uniform2fv(this.locations.uniforms.u_textureDataCoverRatio, new Float32Array(12).fill(1.0));
|
|
192
|
+
}
|
|
162
193
|
gl.bindTexture(gl.TEXTURE_2D_ARRAY, null);
|
|
194
|
+
gl.uniform1i(this.locations.uniforms.u_breakLoopIndex, demTexturesData.length);
|
|
163
195
|
gl.useProgram(currentProgram);
|
|
164
196
|
}
|
|
165
197
|
createUBO(bufferReadType = "STATIC_DRAW") {
|
|
@@ -213,10 +245,10 @@ export class TextureDemTriangles {
|
|
|
213
245
|
}
|
|
214
246
|
}
|
|
215
247
|
function drawOnTopBegin(gl) {
|
|
216
|
-
|
|
248
|
+
gl.disable(gl.DEPTH_TEST);
|
|
217
249
|
// gl.enable(gl.POLYGON_OFFSET_FILL);
|
|
218
250
|
// // Use an offset to "nudge" the depth value slightly closer or farther.
|
|
219
|
-
// // Common values are gl.polygonOffset(1.0, 1.0) or gl.polygonOffset(0.
|
|
251
|
+
// // Common values are gl.polygonOffset(1.0, 1.0) or gl.polygonOffset(0.RESOLUTION, 0.RESOLUTION)
|
|
220
252
|
// gl.polygonOffset(1.0, 1.0);
|
|
221
253
|
// gl.depthRange(0.0, 0.0001); // Use near 0.01% of depth range
|
|
222
254
|
// gl.enable(gl.POLYGON_OFFSET_FILL);
|
|
@@ -224,13 +256,13 @@ function drawOnTopBegin(gl) {
|
|
|
224
256
|
// A good starting point is -1.0, -1.0.
|
|
225
257
|
// Negative values "pull" the fragments closer to the camera.
|
|
226
258
|
// gl.polygonOffset(-1.0, -1.0);
|
|
227
|
-
gl.enable(gl.POLYGON_OFFSET_FILL);
|
|
228
|
-
gl.polygonOffset(-1.0, -2.0);
|
|
259
|
+
// gl.enable(gl.POLYGON_OFFSET_FILL);
|
|
260
|
+
// gl.polygonOffset(-1.0, -2.0);
|
|
229
261
|
}
|
|
230
262
|
function drawOnTopEnd(gl) {
|
|
231
|
-
|
|
263
|
+
gl.enable(gl.DEPTH_TEST);
|
|
232
264
|
// gl.disable(gl.POLYGON_OFFSET_FILL);
|
|
233
265
|
// gl.disable(gl.POLYGON_OFFSET_FILL);
|
|
234
266
|
// gl.depthRange(0.0, 1.0); // Restore full depth range
|
|
235
|
-
gl.disable(gl.POLYGON_OFFSET_FILL);
|
|
267
|
+
// gl.disable(gl.POLYGON_OFFSET_FILL);
|
|
236
268
|
}
|
|
@@ -63,10 +63,12 @@ void main(){
|
|
|
63
63
|
outColor = vec4(base_color, 1.0);
|
|
64
64
|
}`;
|
|
65
65
|
class Logic {
|
|
66
|
+
gl;
|
|
67
|
+
program;
|
|
68
|
+
_vector_field_location;
|
|
66
69
|
constructor(gl) {
|
|
67
70
|
this.gl = gl;
|
|
68
|
-
[this.program,
|
|
69
|
-
this._vector_field_location] = this._createProgram();
|
|
71
|
+
[this.program, this._vector_field_location] = this._createProgram();
|
|
70
72
|
// this.decoyBuffer = new DecoyBufferManager(gl);
|
|
71
73
|
}
|
|
72
74
|
_createProgram() {
|
|
@@ -75,13 +77,13 @@ class Logic {
|
|
|
75
77
|
// ubo point
|
|
76
78
|
// const ubo_location = gl.getUniformBlockIndex(program, 'UBO');
|
|
77
79
|
// gl.uniformBlockBinding(program, ubo_location, UBO_BINDING_POINT);
|
|
78
|
-
SeaWaveUbo.assignBindingPoint(gl, program
|
|
80
|
+
SeaWaveUbo.assignBindingPoint(gl, program);
|
|
79
81
|
return [program, gl.getUniformLocation(program, 'u_vector_field')];
|
|
80
82
|
}
|
|
81
83
|
/**
|
|
82
|
-
* @param
|
|
83
|
-
* @param
|
|
84
|
-
* @param
|
|
84
|
+
* @param bufferManager | PingPongBufferManager
|
|
85
|
+
* @param vectorTexture | RG32F texture R: x, G: y
|
|
86
|
+
* @param uboManager | WaveParticalUboManager under ubo.js
|
|
85
87
|
*/
|
|
86
88
|
draw(bufferManager, vectorTexture, uboManager) {
|
|
87
89
|
const { gl, program } = this;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { createProgram } from "../../../util/webglobjectbuilders";
|
|
2
|
+
import { glProgramCache } from "../../programcache";
|
|
3
|
+
import { SeaWaveUbo } from "./ubo-new";
|
|
4
|
+
/**
|
|
5
|
+
* [+] ubo
|
|
6
|
+
*/
|
|
7
|
+
const vertexShaderSource = `#version 300 es
|
|
8
|
+
precision highp float;
|
|
9
|
+
` + SeaWaveUbo.glslCode() + `
|
|
10
|
+
uniform sampler2D u_vector_field;
|
|
11
|
+
in vec2 in_position;
|
|
12
|
+
out vec3 base_color;
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
vec2 read_value(const vec2 uv) {
|
|
16
|
+
vec2 value = texture(u_vector_field, uv).rg;
|
|
17
|
+
if ( value.x == escape_value || value.y == escape_value) {
|
|
18
|
+
return vec2(0.0);
|
|
19
|
+
}
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
vec2 lookup_wind(const vec2 uv) { // gerek kalmayabilir. sampler linear methodu ayni isi yapiyor
|
|
25
|
+
// return texture(u_vector_field, uv).rg; // lower-res hardware filtering
|
|
26
|
+
vec2 res = vec2(textureSize(u_vector_field, 0));
|
|
27
|
+
vec2 px = 1.0 / res;
|
|
28
|
+
vec2 vc = (floor(uv * res)) * px;
|
|
29
|
+
vec2 f = fract(uv * res);
|
|
30
|
+
vec2 tl = read_value(vc).rg;
|
|
31
|
+
vec2 tr = read_value(vc + vec2(px.x, 0)).rg;
|
|
32
|
+
vec2 bl = read_value(vc + vec2(0, px.y)).rg;
|
|
33
|
+
vec2 br = read_value(vc + px).rg;
|
|
34
|
+
|
|
35
|
+
return mix(mix(tl, tr, f.x), mix(bl, br, f.x), f.y);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
void main(){
|
|
40
|
+
vec2 direction_vector = lookup_wind(in_position);
|
|
41
|
+
if (direction_vector.r == 0.0 && direction_vector.g == 0.0) return;
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
vec2 limp;
|
|
45
|
+
if ( 0 == gl_VertexID) { limp = -tail_wing_base_limp; }
|
|
46
|
+
else if ( 1 == gl_VertexID) { limp = vec2( tail_wing_base_limp.x, -tail_wing_base_limp.y); }
|
|
47
|
+
else if ( 2 == gl_VertexID) { limp = tail_wing_base_limp; }
|
|
48
|
+
else { limp = vec2(-tail_wing_base_limp.x, tail_wing_base_limp.y); } // if ( 3 == gl_VertexID)
|
|
49
|
+
|
|
50
|
+
limp = (limp * mat2(
|
|
51
|
+
direction_vector.x, -direction_vector.y,
|
|
52
|
+
direction_vector.y, direction_vector.x)) / draw_texture_size;
|
|
53
|
+
|
|
54
|
+
vec2 pos = in_position * 2.0 - 1.0;
|
|
55
|
+
gl_Position = vec4(pos + limp, 0.0, 1.0);
|
|
56
|
+
base_color = color;
|
|
57
|
+
}`;
|
|
58
|
+
const fragmentShaderSource = `#version 300 es
|
|
59
|
+
precision highp float;
|
|
60
|
+
out vec4 outColor;
|
|
61
|
+
in vec3 base_color;
|
|
62
|
+
void main(){
|
|
63
|
+
outColor = vec4(base_color, 1.0);
|
|
64
|
+
}`;
|
|
65
|
+
class Logic {
|
|
66
|
+
constructor(gl) {
|
|
67
|
+
this.gl = gl;
|
|
68
|
+
[this.program,
|
|
69
|
+
this._vector_field_location] = this._createProgram();
|
|
70
|
+
// this.decoyBuffer = new DecoyBufferManager(gl);
|
|
71
|
+
}
|
|
72
|
+
_createProgram() {
|
|
73
|
+
const gl = this.gl;
|
|
74
|
+
const program = createProgram(gl, vertexShaderSource, fragmentShaderSource);
|
|
75
|
+
// ubo point
|
|
76
|
+
// const ubo_location = gl.getUniformBlockIndex(program, 'UBO');
|
|
77
|
+
// gl.uniformBlockBinding(program, ubo_location, UBO_BINDING_POINT);
|
|
78
|
+
SeaWaveUbo.assignBindingPoint(gl, program, 0);
|
|
79
|
+
return [program, gl.getUniformLocation(program, 'u_vector_field')];
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* @param {*} bufferManager | PingPongBufferManager
|
|
83
|
+
* @param {*} vectorTexture | RG32F texture R: x, G: y
|
|
84
|
+
* @param {*} uboManager | WaveParticalUboManager under ubo.js
|
|
85
|
+
*/
|
|
86
|
+
draw(bufferManager, vectorTexture, uboManager) {
|
|
87
|
+
const { gl, program } = this;
|
|
88
|
+
gl.useProgram(program);
|
|
89
|
+
gl.bindVertexArray(bufferManager.getSourceVao());
|
|
90
|
+
// gl.bindVertexArray(this.decoyBuffer.getSourceVao());
|
|
91
|
+
uboManager.bind();
|
|
92
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
93
|
+
gl.uniform1i(this._vector_field_location, 0);
|
|
94
|
+
gl.bindTexture(gl.TEXTURE_2D, vectorTexture);
|
|
95
|
+
gl.drawArraysInstanced(gl.TRIANGLE_FAN, 0, 4, bufferManager.length);
|
|
96
|
+
gl.drawArraysInstanced(gl.POINTS, 0, 4, bufferManager.length);
|
|
97
|
+
gl.bindVertexArray(null);
|
|
98
|
+
uboManager.unbind();
|
|
99
|
+
}
|
|
100
|
+
free() {
|
|
101
|
+
this.gl.deleteProgram(this.program);
|
|
102
|
+
this.program = null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export const drawRectangleParticlesProgramCache = Object.freeze({
|
|
106
|
+
getProgram: (gl) => {
|
|
107
|
+
return glProgramCache.getProgram(gl, Logic);
|
|
108
|
+
},
|
|
109
|
+
releaseProgram: (gl) => {
|
|
110
|
+
glProgramCache.releaseProgram(gl, Logic);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
@@ -137,6 +137,15 @@ export class ArcOnTerrainPlugin {
|
|
|
137
137
|
this.bufferOrchestrator.deleteBulk(keys, this.bufferManagersMap);
|
|
138
138
|
this.globe.DrawRender();
|
|
139
139
|
}
|
|
140
|
+
deleteAll() {
|
|
141
|
+
if (!this.bufferOrchestrator || !this.bufferManagersMap || !this.globe) {
|
|
142
|
+
console.warn("Buffer orchestrator or buffer manager map is not initialized.");
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
this.bufferOrchestrator.resetWithCapacity(this.bufferManagersMap, this._arcMap.size);
|
|
146
|
+
this._arcMap.clear();
|
|
147
|
+
this.globe.DrawRender();
|
|
148
|
+
}
|
|
140
149
|
updateColors(keyColorCouples, drawRender = true) {
|
|
141
150
|
if (this._freed) {
|
|
142
151
|
console.warn("Plugin is freed, cannot update color");
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BufferOrchestrator, BufferManager, ObjectStore } from "../../util/account/index";
|
|
2
2
|
import { PickerDisplayer } from "../../util/picking/picker-displayer";
|
|
3
3
|
import { PointOnGlobeProgramCache } from "../../programs/point-on-globe/square-pixel-point";
|
|
4
|
+
import { defaultblendfunction } from "../../util/webglobe/gldefaultstates";
|
|
4
5
|
import { wgs84ToCartesian3d, wgs84ToMercator } from "../../Math/methods";
|
|
5
6
|
const _0vec3 = /* @__PURE__ */ [0, 0, 0];
|
|
6
7
|
/**
|
|
@@ -60,8 +60,8 @@ class PickerDisplayer {
|
|
|
60
60
|
}
|
|
61
61
|
// call after drawing the scene with gl picker shader
|
|
62
62
|
drawColorTexture() {
|
|
63
|
-
const { colorTexture } = this;
|
|
64
|
-
|
|
63
|
+
const { gl, colorTexture } = this;
|
|
64
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
65
65
|
this.displayer.draw(colorTexture);
|
|
66
66
|
}
|
|
67
67
|
pickXY(x, y, selectionPointFilling = 1, callback = () => { }) {
|
|
@@ -200,7 +200,7 @@ float realDistanceOnSphereR1(vec2 longLat1, vec2 longLat2) {
|
|
|
200
200
|
`;
|
|
201
201
|
export const isPointInBBox = `
|
|
202
202
|
bool isPointInBBox(vec2 point, vec4 bbox) {
|
|
203
|
-
return point.x
|
|
203
|
+
return point.x >= bbox.x && point.x <= bbox.z && point.y >= bbox.y && point.y <= bbox.w;
|
|
204
204
|
}
|
|
205
205
|
`;
|
|
206
206
|
const pointsOnSphereBetween = `
|