@pirireis/webglobeplugins 0.1.10 → 0.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.
- package/bearing-line/index.js +0 -0
- package/bearing-line/plugin.js +151 -0
- package/bearing-line/roadmap.md +3 -0
- package/package.json +1 -1
- package/partialrings/buffer-manager.js +89 -0
- package/partialrings/index.js +1 -1
- package/partialrings/plugin.js +22 -28
- package/partialrings/program.js +22 -16
- package/programs/line-on-globe/{program.js → naive.js} +39 -22
- package/programs/rings/distancering/circlepaddingfreeangleprogram.js +1 -1
- package/rangerings/rangerings.js +3 -0
- package/util/account/bufferoffsetmanager.js +17 -4
- package/util/shaderfunctions/geometrytransformations.js +90 -0
- package/wind/plugin.js +7 -4
|
File without changes
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { programCache as ringProgramCache } from '../partialrings/program';
|
|
2
|
+
import { LineOnGlobeCache } from '../programs/line-on-globe/naive';
|
|
3
|
+
|
|
4
|
+
export const RINGPARTIAL_DRAW_MODE = Object.freeze({
|
|
5
|
+
LINE_STRIP: "LINE_STRIP",
|
|
6
|
+
TRIANGLE_FAN: "TRIANGLE_FAN",
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export default class Plugin {
|
|
10
|
+
|
|
11
|
+
constructor(id, { opacity = 1 } = {}) {
|
|
12
|
+
this.id = id;
|
|
13
|
+
this._opacity = opacity;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
setOpacity(opacity) {
|
|
17
|
+
this._opacity = opacity;
|
|
18
|
+
this.globe.DrawRender();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
init(globe, gl) {
|
|
22
|
+
this.gl = gl;
|
|
23
|
+
this.globe = globe;
|
|
24
|
+
this.lineProgram = LineOnGlobeCache.get(globe);
|
|
25
|
+
this.ringProgram = ringProgramCache.get(globe);
|
|
26
|
+
this.lineBufferManager = this.lineProgram.createBufferManager();
|
|
27
|
+
const { bufferManager, vao } = this.ringProgram.getBufferManagerAndVao();
|
|
28
|
+
this.ringBufferManager = bufferManager;
|
|
29
|
+
this.ringVao = vao;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
draw3D() {
|
|
34
|
+
// vao, edgeCount, alphaMultiplier, drawMode,
|
|
35
|
+
this.lineProgram.draw(this.lineBufferManager.vao, this.lineBufferManager.length, this._opacity);
|
|
36
|
+
//bufferManager, vao, edgeCount, alphaMultiplier, drawMode
|
|
37
|
+
this.gl.disable(this.gl.DEPTH_TEST);
|
|
38
|
+
this.ringProgram.draw(this.ringBufferManager.length, this.ringVao, 32, this._opacity * 0.9, RINGPARTIAL_DRAW_MODE.TRIANGLE_FAN);
|
|
39
|
+
this.ringProgram.draw(this.ringBufferManager.length, this.ringVao, 32, this._opacity, RINGPARTIAL_DRAW_MODE.LINE_STRIP);
|
|
40
|
+
this.gl.enable(this.gl.DEPTH_TEST);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
*
|
|
46
|
+
* @param {Array<{key, long, lat, endLong, endLat, bearingAngle, radius, rgba:[4numbers]}>} items
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
insertBulk(items) {
|
|
50
|
+
for (let item of items) {
|
|
51
|
+
const { lat, long, endLat, endLong, radius = null, rgbaMode = null, bearingAngle = 0 } = item;
|
|
52
|
+
item.long = radian(long);
|
|
53
|
+
item.lat = radian(lat);
|
|
54
|
+
item.endLong = radian(endLong);
|
|
55
|
+
item.endLat = radian(endLat);
|
|
56
|
+
if (radius === null) {
|
|
57
|
+
item.radius = 100000;
|
|
58
|
+
}
|
|
59
|
+
if (rgbaMode === null) {
|
|
60
|
+
item.rgbaMode = 0;
|
|
61
|
+
}
|
|
62
|
+
const startAngle = calculateStartAngle(item.long, item.lat, item.endLong, item.endLat);
|
|
63
|
+
|
|
64
|
+
item.startAngle = startAngle;
|
|
65
|
+
const shaderBearingAngle = radian(bearingAngle - 90);
|
|
66
|
+
item.tailAngle = shaderBearingAngle - startAngle;
|
|
67
|
+
}
|
|
68
|
+
this.lineBufferManager.insertBulk(items);
|
|
69
|
+
this.ringBufferManager.insertBulk(items);
|
|
70
|
+
this.globe.DrawRender();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
*
|
|
75
|
+
* @param {Array<{key, long, lat, endLong, endLat, bearingAngle, rgba:[4numbers], colorMode}>} items // TIDI
|
|
76
|
+
*/
|
|
77
|
+
updateBulk(items) { //TODO
|
|
78
|
+
this.lineBufferManager.updateBulk(items);
|
|
79
|
+
for (let item of items) {
|
|
80
|
+
const { long, lat, endLong, endLat } = item;
|
|
81
|
+
item.long = radian(long);
|
|
82
|
+
item.lat = radian(lat);
|
|
83
|
+
item.endLong = radian(endLong);
|
|
84
|
+
item.endLat = radian(endLat);
|
|
85
|
+
const startAngle = calculateStartAngle(item.long, item.lat, item.endLong, item.endLat);
|
|
86
|
+
item.startAngle = startAngle;
|
|
87
|
+
}
|
|
88
|
+
this.ringBufferManager.updateBulk(items);
|
|
89
|
+
this.globe.DrawRender();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
deleteBulk(keys) {
|
|
94
|
+
this.lineBufferManager.deleteBulk(keys);
|
|
95
|
+
this.ringBufferManager.deleteBulk(keys);
|
|
96
|
+
this.globe.DrawRender();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
defrag() {
|
|
101
|
+
this.lineBufferManager.defrag();
|
|
102
|
+
this.ringBufferManager.defrag();
|
|
103
|
+
this.globe.DrawRender();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
*
|
|
108
|
+
* @param {Array<{key, long, lat, endLong, endLat, bearing}>} items // TODO
|
|
109
|
+
*/
|
|
110
|
+
updateCoordinatesBulk(items) { //TODO
|
|
111
|
+
for (let item of items) {
|
|
112
|
+
const { long, lat, endLong, endLat, bearingAngle } = item;
|
|
113
|
+
item.long = radian(long);
|
|
114
|
+
item.lat = radian(lat);
|
|
115
|
+
item.endLong = radian(endLong);
|
|
116
|
+
item.endLat = radian(endLat);
|
|
117
|
+
const startAngle = calculateStartAngle(item.long, item.lat, item.endLong, item.endLat);
|
|
118
|
+
item.startAngle = startAngle;
|
|
119
|
+
item.tailAngle = radian(bearingAngle - 90) - startAngle;
|
|
120
|
+
}
|
|
121
|
+
this.ringBufferManager.updateCenterAndAngleBulk(items);
|
|
122
|
+
this.lineBufferManager.updateCoordinatesBulk(items);
|
|
123
|
+
this.globe.DrawRender();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
//TODO free
|
|
127
|
+
free() {
|
|
128
|
+
if (this.isFreed) return;
|
|
129
|
+
this.lineBufferManager.free();
|
|
130
|
+
this.ringBufferManager.free();
|
|
131
|
+
LineOnGlobeCache.free(this.globe);
|
|
132
|
+
ringProgramCache.free(this.globe);
|
|
133
|
+
this.isFreed = true;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
const radian = (degree) => degree * Math.PI / 180;
|
|
139
|
+
|
|
140
|
+
const integralSec = (angle) => {
|
|
141
|
+
return Math.log(Math.tan(angle / 2 + Math.PI / 4));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const calculateStartAngle = (long, lat, endLong, endLat) => {
|
|
145
|
+
const dLat = (integralSec(endLat) - integralSec(lat)); // Because lines are strectes toward poles.
|
|
146
|
+
const dLong = endLong - long;
|
|
147
|
+
|
|
148
|
+
let angle = -Math.atan2(dLat, dLong);
|
|
149
|
+
return angle;
|
|
150
|
+
}
|
|
151
|
+
|
package/package.json
CHANGED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import BufferOffsetManager from "../util/account/bufferoffsetmanager";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
const ITEM_SIZE = 10;
|
|
6
|
+
export default class BufferManager extends BufferOffsetManager {
|
|
7
|
+
constructor(globe, gl, buffer, { initialCapacity = 10, bufferType = "DYNAMIC_DRAW" } = {}) {
|
|
8
|
+
super(ITEM_SIZE, { capacity: initialCapacity });
|
|
9
|
+
this.globe = globe;
|
|
10
|
+
this.gl = gl;
|
|
11
|
+
this.buffer = buffer;
|
|
12
|
+
this.bufferType = bufferType;
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
16
|
+
gl.bufferData(gl.ARRAY_BUFFER, initialCapacity * ITEM_SIZE * 4, gl[bufferType]);
|
|
17
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
*
|
|
22
|
+
* @param { Array<{key, long, lat, startAngle, tailAngle, radius, rgba[4], rgbaMode }>} rings
|
|
23
|
+
* @returns
|
|
24
|
+
*/
|
|
25
|
+
insertBulk(items) {
|
|
26
|
+
if (items.length === 0) return;
|
|
27
|
+
this.autoExtendBuffer(items.length);
|
|
28
|
+
const { gl, buffer } = this;
|
|
29
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
30
|
+
for (let { key, long, lat, startAngle, tailAngle, rgba, radius, rgbaMode } of items) {
|
|
31
|
+
const offset = this.getOffset(key) | this.nextOffset();
|
|
32
|
+
this.setOffset(key, offset);
|
|
33
|
+
const block = new Float32Array([
|
|
34
|
+
long, lat, startAngle, tailAngle, ...rgba, radius, rgbaMode]);
|
|
35
|
+
gl.bufferSubData(gl.ARRAY_BUFFER, offset, block);
|
|
36
|
+
// 2 1 1 1 4 1 = 10
|
|
37
|
+
}
|
|
38
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
39
|
+
this.globe.DrawRender();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @param {Array<{key, long, lat, startAngle, tailAngle}>} items
|
|
45
|
+
*
|
|
46
|
+
* */
|
|
47
|
+
updateCenterAndAngleBulk(items) {
|
|
48
|
+
const { gl, buffer } = this;
|
|
49
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
50
|
+
for (let { key, long, lat, startAngle, tailAngle } of items) {
|
|
51
|
+
const offset = this.getOffset(key);
|
|
52
|
+
if (offset === null) {
|
|
53
|
+
console.warn(`key ${key} not found`);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const block = new Float32Array([long, lat, startAngle, tailAngle]);
|
|
57
|
+
gl.bufferSubData(gl.ARRAY_BUFFER, offset, block);
|
|
58
|
+
}
|
|
59
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
60
|
+
this.globe.DrawRender();
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
*
|
|
64
|
+
* @param {Array<{key:string, payload:Float32Array}} items
|
|
65
|
+
* @param {PART_OFFSET_LOOPUP} part | long, lat, START_ANGLE, ROTATION_ANGLE, RADIUS, rgba, rgba_MODE
|
|
66
|
+
* @returns
|
|
67
|
+
*/
|
|
68
|
+
updatePartial(items, part) {
|
|
69
|
+
const { gl, buffer } = this;
|
|
70
|
+
this._updatePartial(items, part, gl, buffer);
|
|
71
|
+
this.globe.DrawRender();
|
|
72
|
+
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
deleteBulk(keys) {
|
|
78
|
+
this._deleteBulk(keys);
|
|
79
|
+
this.globe.DrawRender();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
free() {
|
|
86
|
+
this.gl.deleteBuffer(this.buffer);
|
|
87
|
+
this.buffer = null;
|
|
88
|
+
}
|
|
89
|
+
}
|
package/partialrings/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import PartialRing, { RINGPARTIAL_ALPHA_MODE, RINGPARTIAL_DRAW_MODE, PART_OFFSET_LOOPUP } from './plugin';
|
|
2
2
|
|
|
3
|
-
export { PartialRing, RINGPARTIAL_ALPHA_MODE, RINGPARTIAL_DRAW_MODE, PART_OFFSET_LOOPUP };
|
|
3
|
+
export { PartialRing, RINGPARTIAL_ALPHA_MODE, RINGPARTIAL_DRAW_MODE, PART_OFFSET_LOOPUP };
|
package/partialrings/plugin.js
CHANGED
|
@@ -20,12 +20,13 @@ export const RINGPARTIAL_ALPHA_MODE = Object.freeze({
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
export const PART_OFFSET_LOOPUP = Object.freeze({
|
|
23
|
-
|
|
23
|
+
LONG: 0,
|
|
24
|
+
LAT: 1,
|
|
24
25
|
START_ANGLE: 2,
|
|
25
26
|
TAIL_ANGLE: 3,
|
|
26
|
-
|
|
27
|
+
RGBA: 4,
|
|
27
28
|
RADIUS: 8,
|
|
28
|
-
|
|
29
|
+
RGBA_MODE: 9,
|
|
29
30
|
});
|
|
30
31
|
|
|
31
32
|
|
|
@@ -47,8 +48,6 @@ export default class {
|
|
|
47
48
|
const { vao, buffer } = this.program.getVaoBuffer();
|
|
48
49
|
this.vao = vao;
|
|
49
50
|
this.buffer = buffer;
|
|
50
|
-
|
|
51
|
-
|
|
52
51
|
}
|
|
53
52
|
|
|
54
53
|
|
|
@@ -57,7 +56,7 @@ export default class {
|
|
|
57
56
|
|
|
58
57
|
if (LOD < this.startLod || LOD > this.endLod) return;
|
|
59
58
|
this.program.draw(
|
|
60
|
-
this.bufferManager,
|
|
59
|
+
this.bufferManager.length,
|
|
61
60
|
this.vao,
|
|
62
61
|
this.edgeCount,
|
|
63
62
|
this.alphaMultiplier,
|
|
@@ -82,8 +81,8 @@ export default class {
|
|
|
82
81
|
if (endLod !== null) this.endLod = endLod;
|
|
83
82
|
}
|
|
84
83
|
|
|
85
|
-
createBufferMAnager(initialCapacity = 10,
|
|
86
|
-
if (!this.bufferManager) { this.bufferManager = new BufferManager(this.globe, this.gl, this.buffer,
|
|
84
|
+
createBufferMAnager(initialCapacity = 10, bufferType = 'DYNAMIC_DRAW') {
|
|
85
|
+
if (!this.bufferManager) { this.bufferManager = new BufferManager(this.globe, this.gl, this.buffer, { initialCapacity, bufferType, }); }
|
|
87
86
|
return this.bufferManager;
|
|
88
87
|
}
|
|
89
88
|
|
|
@@ -96,13 +95,12 @@ export default class {
|
|
|
96
95
|
|
|
97
96
|
class BufferManager extends BufferOffsetManager {
|
|
98
97
|
|
|
99
|
-
constructor(globe, gl, buffer,
|
|
100
|
-
super(10, { capacity: initialCapacity });
|
|
98
|
+
constructor(globe, gl, buffer, { initialCapacity = 10, bufferType, } = {}) {
|
|
99
|
+
super(10, { capacity: initialCapacity, bufferType, });
|
|
101
100
|
this.globe = globe;
|
|
102
101
|
this.gl = gl;
|
|
103
102
|
this.buffer = buffer;
|
|
104
103
|
this.bufferType = bufferType;
|
|
105
|
-
this.extendRatio = extendRatio;
|
|
106
104
|
|
|
107
105
|
|
|
108
106
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
@@ -112,22 +110,20 @@ class BufferManager extends BufferOffsetManager {
|
|
|
112
110
|
|
|
113
111
|
/**
|
|
114
112
|
*
|
|
115
|
-
* @param { Array<{key,
|
|
113
|
+
* @param { Array<{key, long, lat, startAngle, tailAngle, radius, rgba[4], rgbaMode }>} rings
|
|
116
114
|
* @returns
|
|
117
115
|
*/
|
|
118
|
-
|
|
119
|
-
if (
|
|
120
|
-
|
|
116
|
+
insertBulk(items) {
|
|
117
|
+
if (items.length === 0) return;
|
|
118
|
+
console.log(items)
|
|
119
|
+
this.autoExtendBuffer(items.length);
|
|
121
120
|
const { gl, buffer } = this;
|
|
122
121
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
123
|
-
for (let { key,
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
offset = this.nextOffset();
|
|
127
|
-
this.setOffset(key, offset);
|
|
128
|
-
}
|
|
122
|
+
for (let { key, long, lat, startAngle, tailAngle, rgba, radius, rgbaMode } of items) {
|
|
123
|
+
const offset = this.getOffset(key) | this.nextOffset();
|
|
124
|
+
this.setOffset(key, offset);
|
|
129
125
|
const block = new Float32Array([
|
|
130
|
-
|
|
126
|
+
long, lat, startAngle, tailAngle, ...rgba, radius, rgbaMode]);
|
|
131
127
|
gl.bufferSubData(gl.ARRAY_BUFFER, offset, block);
|
|
132
128
|
// 2 1 1 1 4 1 = 10
|
|
133
129
|
}
|
|
@@ -138,13 +134,13 @@ class BufferManager extends BufferOffsetManager {
|
|
|
138
134
|
|
|
139
135
|
/**
|
|
140
136
|
*
|
|
141
|
-
* @param {Array<{key:string, payload:Float32Array}}
|
|
142
|
-
* @param {PART_OFFSET_LOOPUP} part |
|
|
137
|
+
* @param {Array<{key:string, payload:Float32Array}} items
|
|
138
|
+
* @param {PART_OFFSET_LOOPUP} part | long, lat, START_ANGLE, ROTATION_ANGLE, RADIUS, rgba, rgba_MODE
|
|
143
139
|
* @returns
|
|
144
140
|
*/
|
|
145
|
-
updatePartial(
|
|
141
|
+
updatePartial(items, part) {
|
|
146
142
|
const { gl, buffer } = this;
|
|
147
|
-
this._updatePartial(
|
|
143
|
+
this._updatePartial(items, part, gl, buffer);
|
|
148
144
|
this.globe.DrawRender();
|
|
149
145
|
|
|
150
146
|
}
|
|
@@ -157,8 +153,6 @@ class BufferManager extends BufferOffsetManager {
|
|
|
157
153
|
}
|
|
158
154
|
|
|
159
155
|
|
|
160
|
-
|
|
161
|
-
|
|
162
156
|
free() {
|
|
163
157
|
this.gl.deleteBuffer(this.buffer);
|
|
164
158
|
this.buffer = null;
|
package/partialrings/program.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createProgram, shaderfunctions } from "../util";
|
|
2
2
|
import { CameraUniformBlockTotem, CameraUniformBlockString, noRegisterGlobeProgramCache, globeProgramCache } from "../programs";
|
|
3
|
-
|
|
3
|
+
import BufferManager from "./buffer-manager";
|
|
4
4
|
import {
|
|
5
5
|
POLE,
|
|
6
6
|
PI,
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
mercatorXYTo2DPoint,
|
|
9
9
|
longLatRadToCartesian3D,
|
|
10
10
|
circleLimpFromLongLatRadCenterCartesian3D,
|
|
11
|
-
|
|
11
|
+
circleLimpFromLongLatRadCenterMercatorRealDistance,
|
|
12
12
|
cartesian3DToGLPosition
|
|
13
13
|
|
|
14
14
|
|
|
@@ -35,13 +35,13 @@ const vertexShaderSource = `#version 300 es` +
|
|
|
35
35
|
mercatorXYTo2DPoint +
|
|
36
36
|
longLatRadToCartesian3D +
|
|
37
37
|
circleLimpFromLongLatRadCenterCartesian3D +
|
|
38
|
-
|
|
38
|
+
circleLimpFromLongLatRadCenterMercatorRealDistance +
|
|
39
39
|
cartesian3DToGLPosition + `
|
|
40
40
|
|
|
41
41
|
uniform float edge_count;
|
|
42
42
|
uniform int draw_mode; // %2 => 0: LINE_STRIP, 1: TRIANGLE_FAN
|
|
43
43
|
uniform float plugin_alpha_multiplier;
|
|
44
|
-
|
|
44
|
+
//, lat, startAngle, tailAngle, ...rgba, radius, rgbaMode
|
|
45
45
|
in vec2 center; // long, lat in radian
|
|
46
46
|
in float start_angle; // the start of partial circle from bearing point
|
|
47
47
|
in float tail_angle; // the rotation of the partial circle
|
|
@@ -56,20 +56,17 @@ out vec4 v_color;
|
|
|
56
56
|
void main() {
|
|
57
57
|
if (color_mode == 2.0 || radius == 0.0) { return; }
|
|
58
58
|
|
|
59
|
-
float vertexID;
|
|
59
|
+
float vertexID = float(gl_VertexID);
|
|
60
60
|
float radius_ = radius;
|
|
61
61
|
float alpha = plugin_alpha_multiplier;
|
|
62
62
|
if (draw_mode == 1) { // TRIANGLE_FAN
|
|
63
|
-
vertexID = float(gl_VertexID - 1);
|
|
64
63
|
if (gl_VertexID == 0) {
|
|
65
|
-
radius_ = 0.0;
|
|
64
|
+
radius_ = 0.0;
|
|
66
65
|
if ( color_mode == 1.0 ) { alpha = 0.0; }
|
|
67
66
|
}
|
|
68
|
-
|
|
69
|
-
vertexID = float(gl_VertexID);
|
|
67
|
+
vertexID -= 1.0;
|
|
70
68
|
}
|
|
71
|
-
|
|
72
|
-
float phase = ( vertexID / edge_count);
|
|
69
|
+
float phase = ( vertexID / edge_count);
|
|
73
70
|
|
|
74
71
|
if ( color_mode == 1.0 ) {
|
|
75
72
|
if ( tail_angle < 0.0 ) {
|
|
@@ -83,7 +80,7 @@ void main() {
|
|
|
83
80
|
|
|
84
81
|
float angle;
|
|
85
82
|
if ( tail_angle > 0.0 ) {
|
|
86
|
-
angle = tail_angle * (-phase + 1.0) + start_angle;
|
|
83
|
+
angle = tail_angle * (-phase + 1.0 - 1.0 / edge_count) + start_angle;
|
|
87
84
|
} else {
|
|
88
85
|
angle = tail_angle * phase + start_angle;
|
|
89
86
|
}
|
|
@@ -94,13 +91,14 @@ void main() {
|
|
|
94
91
|
gl_Position = cartesian3DToGLPosition(pos);
|
|
95
92
|
}
|
|
96
93
|
else {
|
|
97
|
-
|
|
94
|
+
|
|
95
|
+
vec2 pos = circleLimpFromLongLatRadCenterMercatorRealDistance(center, radius_, angle);
|
|
98
96
|
v_pos = pos;
|
|
99
97
|
gl_Position = mercatorXYTo2DPoint(pos);
|
|
100
98
|
}
|
|
101
99
|
|
|
102
100
|
|
|
103
|
-
gl_PointSize =
|
|
101
|
+
gl_PointSize = 10.0;
|
|
104
102
|
}`;
|
|
105
103
|
|
|
106
104
|
|
|
@@ -162,7 +160,7 @@ export class Logic {
|
|
|
162
160
|
|
|
163
161
|
|
|
164
162
|
|
|
165
|
-
draw(
|
|
163
|
+
draw(length, vao, edgeCount, alphaMultiplier, drawMode) {
|
|
166
164
|
const { gl, program, cameraBlockTotem, cameraBlockBindingPoint } = this
|
|
167
165
|
|
|
168
166
|
gl.disable(gl.DEPTH_TEST);
|
|
@@ -182,7 +180,7 @@ export class Logic {
|
|
|
182
180
|
const overdraw = drawModeMap[drawMode];
|
|
183
181
|
cameraBlockTotem.bind(cameraBlockBindingPoint);
|
|
184
182
|
gl.bindVertexArray(vao);
|
|
185
|
-
gl.drawArraysInstanced(gl[drawMode], 0, edgeCount + overdraw,
|
|
183
|
+
gl.drawArraysInstanced(gl[drawMode], 0, edgeCount + overdraw, length);
|
|
186
184
|
cameraBlockTotem.unbind(cameraBlockBindingPoint);
|
|
187
185
|
gl.bindVertexArray(null);
|
|
188
186
|
gl.enable(gl.DEPTH_TEST);
|
|
@@ -237,6 +235,14 @@ export class Logic {
|
|
|
237
235
|
buffer,
|
|
238
236
|
}
|
|
239
237
|
}
|
|
238
|
+
|
|
239
|
+
getBufferManagerAndVao({ capacity = 10, bufferType = "DYNAMIC_DRAW" } = {}) {
|
|
240
|
+
const { vao, buffer } = this.getVaoBuffer();
|
|
241
|
+
return {
|
|
242
|
+
bufferManager: new BufferManager(this.globe, this.gl, buffer, { capacity, bufferType }),
|
|
243
|
+
vao
|
|
244
|
+
};
|
|
245
|
+
}
|
|
240
246
|
}
|
|
241
247
|
|
|
242
248
|
export const programCache = Object.freeze({
|
|
@@ -43,10 +43,12 @@ void main() {
|
|
|
43
43
|
|
|
44
44
|
const fragmentShader = `#version 300 es
|
|
45
45
|
precision highp float;
|
|
46
|
+
uniform float opacity;
|
|
46
47
|
in vec4 v_color;
|
|
47
48
|
out vec4 color;
|
|
48
49
|
void main() {
|
|
49
50
|
color = v_color;
|
|
51
|
+
color.a *= opacity;
|
|
50
52
|
}
|
|
51
53
|
`
|
|
52
54
|
|
|
@@ -57,6 +59,7 @@ class Logic {
|
|
|
57
59
|
this.globe = globe;
|
|
58
60
|
this.gl = globe.gl;
|
|
59
61
|
this.program = createProgram(this.gl, vertexShader, fragmentShader);
|
|
62
|
+
this._lastOpacity = 1.0;
|
|
60
63
|
const { gl, program } = this;
|
|
61
64
|
{
|
|
62
65
|
// assign attribute locations
|
|
@@ -65,6 +68,14 @@ class Logic {
|
|
|
65
68
|
gl.bindAttribLocation(program, 2, "color");
|
|
66
69
|
}
|
|
67
70
|
|
|
71
|
+
{
|
|
72
|
+
this._opacityLocation = gl.getUniformLocation(program, "opacity");
|
|
73
|
+
const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
|
|
74
|
+
gl.useProgram(program);
|
|
75
|
+
gl.uniform1f(this._opacityLocation, this._lastOpacity);
|
|
76
|
+
gl.useProgram(currentProgram);
|
|
77
|
+
|
|
78
|
+
}
|
|
68
79
|
|
|
69
80
|
this.cameraBlockBindingPoint = 0;
|
|
70
81
|
const cameraBlockIndex = this.gl.getUniformBlockIndex(this.program, "CameraUniformBlock");
|
|
@@ -75,18 +86,22 @@ class Logic {
|
|
|
75
86
|
}
|
|
76
87
|
|
|
77
88
|
|
|
78
|
-
draw(
|
|
89
|
+
draw(vao, length, opacity) {
|
|
79
90
|
const { gl, program, globe } = this;
|
|
80
91
|
gl.useProgram(program);
|
|
81
92
|
const { cameraBlockTotem, cameraBlockBindingPoint } = this;
|
|
82
93
|
cameraBlockTotem.bind(cameraBlockBindingPoint);
|
|
83
|
-
gl.bindVertexArray(
|
|
94
|
+
gl.bindVertexArray(vao);
|
|
95
|
+
if (opacity !== this._lastOpacity) {
|
|
96
|
+
gl.uniform1f(this._opacityLocation, opacity);
|
|
97
|
+
this._lastOpacity = opacity;
|
|
98
|
+
}
|
|
84
99
|
const drawCount = globe.api_GetCurrentGeometry() === 0 ? GLOBE_MIDPOINT_COUNT : 2;
|
|
85
100
|
gl.disable(gl.DEPTH_TEST);
|
|
86
|
-
gl.drawArraysInstanced(gl.LINE_STRIP, 0, drawCount,
|
|
87
|
-
gl.enable(gl.DEPTH_TEST);
|
|
101
|
+
gl.drawArraysInstanced(gl.LINE_STRIP, 0, drawCount, length);
|
|
88
102
|
gl.bindVertexArray(null);
|
|
89
103
|
cameraBlockTotem.unbind(cameraBlockBindingPoint);
|
|
104
|
+
gl.enable(gl.DEPTH_TEST);
|
|
90
105
|
}
|
|
91
106
|
|
|
92
107
|
|
|
@@ -129,18 +144,19 @@ class BufferManager extends BufferOffsetManger {
|
|
|
129
144
|
|
|
130
145
|
/**
|
|
131
146
|
*
|
|
132
|
-
* @param {Array<{key:string,
|
|
147
|
+
* @param {Array<{key:string, long:number, lat:number, endLong:number, endLat:number, rgba:[4numbers] }} items
|
|
133
148
|
*/
|
|
134
149
|
insertBulk(items) {
|
|
135
150
|
this.autoExtendBuffer(items.length)
|
|
136
151
|
const { gl, buffer, globe } = this;
|
|
137
152
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
138
|
-
for (let { key,
|
|
153
|
+
for (let { key, long, lat, endLong, endLat, rgba } of items) {
|
|
154
|
+
|
|
139
155
|
const payload = new Float32Array([
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
156
|
+
long,
|
|
157
|
+
lat,
|
|
158
|
+
endLong,
|
|
159
|
+
endLat,
|
|
144
160
|
...rgba]);
|
|
145
161
|
const offset = this.getOffset(key) | this.nextOffset();
|
|
146
162
|
gl.bufferSubData(gl.ARRAY_BUFFER, offset, payload);
|
|
@@ -152,17 +168,17 @@ class BufferManager extends BufferOffsetManger {
|
|
|
152
168
|
|
|
153
169
|
/**
|
|
154
170
|
*
|
|
155
|
-
* @param {Array<{key:string,
|
|
171
|
+
* @param {Array<{key:string, long:number, lat:number, endLong:number, endLat:number, rgba:[4numbers] }} items
|
|
156
172
|
*/
|
|
157
173
|
updateBulk(items) {
|
|
158
174
|
const { gl, buffer, globe } = this;
|
|
159
175
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
160
|
-
for (let { key,
|
|
176
|
+
for (let { key, long, lat, endLong, endLat, rgba } of items) {
|
|
161
177
|
const payload = new Float32Array([
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
178
|
+
long,
|
|
179
|
+
lat,
|
|
180
|
+
endLong,
|
|
181
|
+
endLat,
|
|
166
182
|
...rgba]);
|
|
167
183
|
const offset = this.getOffset(key);
|
|
168
184
|
if (offset !== undefined) {
|
|
@@ -177,17 +193,17 @@ class BufferManager extends BufferOffsetManger {
|
|
|
177
193
|
|
|
178
194
|
/**
|
|
179
195
|
*
|
|
180
|
-
* @param {Array<{key:string,
|
|
196
|
+
* @param {Array<{key:string, long:number, lat:number, endLong:number, endLat:number }} items
|
|
181
197
|
*/
|
|
182
198
|
updateCoordinatesBulk(items) {
|
|
183
199
|
const { gl, buffer, globe } = this;
|
|
184
200
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
185
|
-
for (let { key,
|
|
201
|
+
for (let { key, long, lat, endLong, endLat } of items) {
|
|
186
202
|
const payload = new Float32Array([
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
203
|
+
long,
|
|
204
|
+
lat,
|
|
205
|
+
endLong,
|
|
206
|
+
endLat]);
|
|
191
207
|
const offset = this.getOffset(key);
|
|
192
208
|
if (offset !== undefined) {
|
|
193
209
|
gl.bufferSubData(gl.ARRAY_BUFFER, offset, payload);
|
|
@@ -195,6 +211,7 @@ class BufferManager extends BufferOffsetManger {
|
|
|
195
211
|
console.warn("key not found", key);
|
|
196
212
|
}
|
|
197
213
|
}
|
|
214
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
198
215
|
globe.DrawRender();
|
|
199
216
|
}
|
|
200
217
|
|
|
@@ -128,8 +128,8 @@ class Logic {
|
|
|
128
128
|
}
|
|
129
129
|
gl.disable(gl.DEPTH_TEST);
|
|
130
130
|
gl.drawArraysInstanced(gl.LINES, 0, 2, attrBufferManager.length);
|
|
131
|
-
gl.enable(gl.DEPTH_TEST);
|
|
132
131
|
cameraBlockTotem.unbind(cameraBlockBindingPoint);
|
|
132
|
+
gl.enable(gl.DEPTH_TEST);
|
|
133
133
|
gl.bindVertexArray(null);
|
|
134
134
|
|
|
135
135
|
}
|
package/rangerings/rangerings.js
CHANGED
|
@@ -59,6 +59,9 @@ export default class {
|
|
|
59
59
|
this.circleProgramCache?.releaseProgram(this.globe);
|
|
60
60
|
this.PaddingProgramCache?.releaseProgram(this.globe);
|
|
61
61
|
this.PaddingFreeAngleCache?.releaseProgram(this.globe);
|
|
62
|
+
this.gl.deleteVertexArray(this.bufferManager?.vao);
|
|
63
|
+
this.gl.deleteVertexArray(this.paddingBufferManager?.vao);
|
|
64
|
+
this.paddingBufferManager?.free();
|
|
62
65
|
this.bufferManager?.free();
|
|
63
66
|
this.textPlugin?.free();
|
|
64
67
|
this.circleFlatProgram = null;
|
|
@@ -75,6 +75,19 @@ export default class {
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
_deleteBulk(keys) {
|
|
79
|
+
const { gl, buffer } = this;
|
|
80
|
+
const emptyBlock = new Float32Array(this.itemSize).fill(0)
|
|
81
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
82
|
+
for (let key of keys) {
|
|
83
|
+
const offset = this.getOffset(key);
|
|
84
|
+
if (offset !== undefined) {
|
|
85
|
+
this.deleteFromAccount(key);
|
|
86
|
+
gl.bufferSubData(gl.ARRAY_BUFFER, offset, emptyBlock);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
90
|
+
}
|
|
78
91
|
|
|
79
92
|
|
|
80
93
|
offsetMapIterator() { // can be used for defraging the real buffer.
|
|
@@ -90,7 +103,6 @@ export default class {
|
|
|
90
103
|
const itemSize = this.itemSize;
|
|
91
104
|
const itemCount = this.itemCount;
|
|
92
105
|
const capacity = (newCapacity && newCapacity > itemCount) ? newCapacity : itemCount;
|
|
93
|
-
console.log("defrag", itemCount, capacity);
|
|
94
106
|
|
|
95
107
|
const newArray = new Float32Array(itemCount * itemSize);
|
|
96
108
|
|
|
@@ -98,7 +110,6 @@ export default class {
|
|
|
98
110
|
let newOffSet = 0;
|
|
99
111
|
const newOffSetMap = new Map();
|
|
100
112
|
for (const [key, offSet] of this.offSetMap) {
|
|
101
|
-
console.log(key, offSet);
|
|
102
113
|
const itemOffSet = offSet / 4;
|
|
103
114
|
newArray.set(bufferData.slice(itemOffSet, itemOffSet + itemSize), newOffSet);
|
|
104
115
|
// this.offSetMap.set(key, newOffSet * 4);
|
|
@@ -147,8 +158,8 @@ export default class {
|
|
|
147
158
|
*/
|
|
148
159
|
_updatePartial(items, partOffset) {
|
|
149
160
|
const { gl, buffer } = this;
|
|
150
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
151
161
|
const partStart = partOffset * 4;
|
|
162
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
152
163
|
for (let { key, payload } of items) {
|
|
153
164
|
let offset = this.getOffset(key);
|
|
154
165
|
if (offset !== undefined) {
|
|
@@ -183,9 +194,11 @@ export default class {
|
|
|
183
194
|
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
184
195
|
}
|
|
185
196
|
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
|
|
186
200
|
free() {
|
|
187
201
|
this.gl.deleteBuffer(this.buffer);
|
|
188
|
-
this.gl.deleteVertexArray(this.vao);
|
|
189
202
|
this.buffer = null;
|
|
190
203
|
this.vao = null;
|
|
191
204
|
this.gl = null;
|
|
@@ -159,3 +159,93 @@ vec2 circleLimpFromLongLatRadCenterMercatorCompass(vec2 center, float radius, fl
|
|
|
159
159
|
}`;
|
|
160
160
|
|
|
161
161
|
|
|
162
|
+
// Function to interpolate between two Cartesian points using spherical interpolation (slerp)
|
|
163
|
+
export const slerp = `
|
|
164
|
+
vec3 slerp(vec3 A, vec3 B, float t) {
|
|
165
|
+
float cosTheta = dot(A, B);
|
|
166
|
+
float theta = acos(clamp(cosTheta, -1.0, 1.0)); // Angle between the points
|
|
167
|
+
|
|
168
|
+
float sinTheta = sin(theta);
|
|
169
|
+
|
|
170
|
+
// Avoid division by zero // many points falls in to this category
|
|
171
|
+
if (sinTheta < 0.00001) {
|
|
172
|
+
return mix(A, B, t); // Linear interpolation as fallback
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
float factorA = sin((1.0 - t) * theta) / sinTheta;
|
|
176
|
+
float factorB = sin(t * theta) / sinTheta;
|
|
177
|
+
|
|
178
|
+
return factorA * A + factorB * B;
|
|
179
|
+
}
|
|
180
|
+
`;
|
|
181
|
+
|
|
182
|
+
// Function to convert Cartesian coordinates back to spherical (latitude, longitude)
|
|
183
|
+
export const cartesianToSpherical = `
|
|
184
|
+
vec2 cartesianToSpherical(vec3 point) {
|
|
185
|
+
float lat = degrees(asin(point.z)); // Latitude
|
|
186
|
+
float lon = degrees(atan(point.y, point.x)); // Longitude
|
|
187
|
+
|
|
188
|
+
return vec2(lat, lon);
|
|
189
|
+
}`;
|
|
190
|
+
|
|
191
|
+
// Main function to calculate an intermediate point
|
|
192
|
+
|
|
193
|
+
export const interpolateGeographicPoint = slerp + cartesianToSpherical + longLatRadToCartesian3D + `
|
|
194
|
+
vec3 interpolateGeographicPoint(vec2 start, vec2 end, float t) {
|
|
195
|
+
vec3 pointA = longLatRadToCartesian3D(start);
|
|
196
|
+
vec3 pointB = longLatRadToCartesian3D(end);
|
|
197
|
+
vec3 interpolatedPoint = slerp(pointA, pointB, t);
|
|
198
|
+
return interpolatedPoint;
|
|
199
|
+
// return cartesianToSpherical(interpolatedPoint);
|
|
200
|
+
}
|
|
201
|
+
`;
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
export const angleBetweenTwoPointsRadian = `
|
|
206
|
+
float angleBetweenTwoPointsRadian(vec2 start_, vec2 end_) {
|
|
207
|
+
float start_lat = log( tan( ( 1.0 - start_.y ) * PI / 2.0 ) );
|
|
208
|
+
float end_lat = log( tan( ( 1.0 - end_.y ) * PI / 2.0 ) );
|
|
209
|
+
float angle = atan( (end_lat - start_lat )/ (end_.x - start_.x));
|
|
210
|
+
return angle;
|
|
211
|
+
}
|
|
212
|
+
`
|
|
213
|
+
|
|
214
|
+
export const circleCircumferenceInterPolationOf2PointsRadian = `
|
|
215
|
+
float circleCircumferenceInterPolationOf2PointsRadian(vec2 center, vec2 target, float bearing_angle, float ratio) {
|
|
216
|
+
vec2 t = target - center;
|
|
217
|
+
float mainAngle = atan(t.x, t.y);
|
|
218
|
+
float angle = mainAngle - * ratio;
|
|
219
|
+
return angle;
|
|
220
|
+
}
|
|
221
|
+
`
|
|
222
|
+
|
|
223
|
+
export const circumferencePoints = `
|
|
224
|
+
vec2 circumferencePoints(vec2 center, vec2 target, vec2 target2, float phase, float radius) {
|
|
225
|
+
// Calculate vectors from center to target and target2
|
|
226
|
+
vec2 v1 = target - center;
|
|
227
|
+
vec2 v2 = target2 - center;
|
|
228
|
+
|
|
229
|
+
// Normalize the vectors to ensure they are on the unit circle
|
|
230
|
+
v1 = normalize(v1);
|
|
231
|
+
v2 = normalize(v2);
|
|
232
|
+
|
|
233
|
+
// Calculate the angle between the vectors
|
|
234
|
+
float angle1 = atan(v1.y, v1.x);
|
|
235
|
+
float angle2 = atan(v2.y, v2.x);
|
|
236
|
+
|
|
237
|
+
// Ensure the angles are continuous (handle wrap-around at 2π)
|
|
238
|
+
if (angle2 < angle1) {
|
|
239
|
+
angle2 += 2.0 * 3.14159265359; // Add 2π to angle2 if it is smaller
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Interpolate the angle based on the phase
|
|
243
|
+
float interpolatedAngle = mix(angle1, angle2, phase);
|
|
244
|
+
|
|
245
|
+
// Calculate the new point on the circle
|
|
246
|
+
vec2 result = vec2(cos(interpolatedAngle), sin(interpolatedAngle));
|
|
247
|
+
|
|
248
|
+
// Scale back to the original circle radius and shift to center
|
|
249
|
+
return center + radius * result;
|
|
250
|
+
}
|
|
251
|
+
`
|
package/wind/plugin.js
CHANGED
|
@@ -696,9 +696,12 @@ export default class WindPlugin {
|
|
|
696
696
|
|
|
697
697
|
gl.activeTexture(gl.TEXTURE0);
|
|
698
698
|
if (this._doDraw()) {
|
|
699
|
-
gl.
|
|
700
|
-
gl.disable(gl.
|
|
699
|
+
const depthTest = gl.isEnabled(gl.DEPTH_TEST);
|
|
700
|
+
if (depthTest) gl.disable(gl.DEPTH_TEST);
|
|
701
|
+
// if (gl.disable(gl.STENCIL_TEST); //
|
|
701
702
|
this._draw();
|
|
703
|
+
// if (depthTest) gl.enable(gl.DEPTH_TEST); // TODO: stencil
|
|
704
|
+
|
|
702
705
|
}
|
|
703
706
|
|
|
704
707
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
@@ -862,8 +865,8 @@ export default class WindPlugin {
|
|
|
862
865
|
|
|
863
866
|
_resetMachineStates() {
|
|
864
867
|
const { gl, globe } = this;
|
|
865
|
-
gl.disable(gl.DEPTH_TEST);
|
|
866
|
-
gl.disable(gl.STENCIL_TEST);
|
|
868
|
+
// gl.disable(gl.DEPTH_TEST);
|
|
869
|
+
// gl.disable(gl.STENCIL_TEST);
|
|
867
870
|
gl.activeTexture(gl.TEXTURE0);
|
|
868
871
|
gl.viewport(0, 0, globe.api_ScrW(), globe.api_ScrH());
|
|
869
872
|
}
|