@pirireis/webglobeplugins 0.1.9 → 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 -33
- package/partialrings/program.js +23 -17
- package/programs/line-on-globe/index.js +1 -0
- package/programs/line-on-globe/naive.js +267 -0
- package/programs/rings/distancering/circlepaddingfreeangleprogram.js +1 -1
- package/rangerings/rangerings.js +14 -2
- package/util/account/bufferoffsetmanager.js +31 -3
- package/util/shaderfunctions/geometrytransformations.js +90 -0
- package/wind/plugin.js +7 -4
- package/programs/line-on-globe/program.js +0 -115
|
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
|
}
|
|
@@ -156,13 +152,6 @@ class BufferManager extends BufferOffsetManager {
|
|
|
156
152
|
this.globe.DrawRender();
|
|
157
153
|
}
|
|
158
154
|
|
|
159
|
-
_autoExtendBuffer(payloadSize) {
|
|
160
|
-
const { gl, buffer, bufferType, extendRatio } = this;
|
|
161
|
-
if (payloadSize <= this.spaceLeft) return;
|
|
162
|
-
const newCapacity = Math.ceil((payloadSize + this.length) * extendRatio);
|
|
163
|
-
this.extendBuffer(gl, buffer, bufferType, newCapacity);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
155
|
|
|
167
156
|
free() {
|
|
168
157
|
this.gl.deleteBuffer(this.buffer);
|
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,9 +235,17 @@ 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({
|
|
243
249
|
get: (globe) => noRegisterGlobeProgramCache.getProgram(globe, Logic),
|
|
244
|
-
|
|
250
|
+
release: (globe) => noRegisterGlobeProgramCache.releaseProgram(globe, Logic)
|
|
245
251
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { LineOnGlobeCache } from './program.js';
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { CameraUniformBlockString, CameraUniformBlockTotem } from "../totems";
|
|
2
|
+
import { longLatRadToMercator, longLatRadToCartesian3D, cartesian3DToGLPosition, mercatorXYTo2DPoint } from "../../util/shaderfunctions/geometrytransformations";
|
|
3
|
+
import { createProgram } from "../../util";
|
|
4
|
+
import { noRegisterGlobeProgramCache, globeProgramCache } from "../programcache";
|
|
5
|
+
import BufferOffsetManger from "../../util/account/bufferoffsetmanager";
|
|
6
|
+
const Radian = Math.PI / 180.0;
|
|
7
|
+
const GLOBE_MIDPOINT_COUNT = 100;
|
|
8
|
+
const ITEM_SIZE = 8;
|
|
9
|
+
|
|
10
|
+
const vertexShader = `#version 300 es
|
|
11
|
+
precision highp float;
|
|
12
|
+
${CameraUniformBlockString}
|
|
13
|
+
${longLatRadToMercator}
|
|
14
|
+
${longLatRadToCartesian3D}
|
|
15
|
+
${cartesian3DToGLPosition}
|
|
16
|
+
${mercatorXYTo2DPoint}
|
|
17
|
+
|
|
18
|
+
in vec2 start_position;
|
|
19
|
+
in vec2 end_position;
|
|
20
|
+
in vec4 color;
|
|
21
|
+
out vec4 v_color;
|
|
22
|
+
|
|
23
|
+
void main() {
|
|
24
|
+
|
|
25
|
+
vec2 longLat;
|
|
26
|
+
if (is3D) {
|
|
27
|
+
float interpolation = float(gl_VertexID) / ${GLOBE_MIDPOINT_COUNT}.0;
|
|
28
|
+
longLat = mix(start_position, end_position, interpolation);
|
|
29
|
+
vec3 cartesian = longLatRadToCartesian3D(longLat);
|
|
30
|
+
gl_Position = cartesian3DToGLPosition(cartesian);
|
|
31
|
+
} else {
|
|
32
|
+
if ( gl_VertexID == 0 ) {
|
|
33
|
+
longLat = start_position;
|
|
34
|
+
} else {
|
|
35
|
+
longLat = end_position;
|
|
36
|
+
}
|
|
37
|
+
vec2 mercator = longLatRadToMercator(longLat);
|
|
38
|
+
gl_Position = mercatorXYTo2DPoint(mercator);
|
|
39
|
+
}
|
|
40
|
+
v_color = color;
|
|
41
|
+
}
|
|
42
|
+
`
|
|
43
|
+
|
|
44
|
+
const fragmentShader = `#version 300 es
|
|
45
|
+
precision highp float;
|
|
46
|
+
uniform float opacity;
|
|
47
|
+
in vec4 v_color;
|
|
48
|
+
out vec4 color;
|
|
49
|
+
void main() {
|
|
50
|
+
color = v_color;
|
|
51
|
+
color.a *= opacity;
|
|
52
|
+
}
|
|
53
|
+
`
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class Logic {
|
|
57
|
+
|
|
58
|
+
constructor(globe) {
|
|
59
|
+
this.globe = globe;
|
|
60
|
+
this.gl = globe.gl;
|
|
61
|
+
this.program = createProgram(this.gl, vertexShader, fragmentShader);
|
|
62
|
+
this._lastOpacity = 1.0;
|
|
63
|
+
const { gl, program } = this;
|
|
64
|
+
{
|
|
65
|
+
// assign attribute locations
|
|
66
|
+
gl.bindAttribLocation(program, 0, "start_position");
|
|
67
|
+
gl.bindAttribLocation(program, 1, "end_position");
|
|
68
|
+
gl.bindAttribLocation(program, 2, "color");
|
|
69
|
+
}
|
|
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
|
+
}
|
|
79
|
+
|
|
80
|
+
this.cameraBlockBindingPoint = 0;
|
|
81
|
+
const cameraBlockIndex = this.gl.getUniformBlockIndex(this.program, "CameraUniformBlock");
|
|
82
|
+
this.cameraBlockTotem = globeProgramCache.getProgram(globe, CameraUniformBlockTotem);
|
|
83
|
+
gl.uniformBlockBinding(this.program, cameraBlockIndex, this.cameraBlockBindingPoint);
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
draw(vao, length, opacity) {
|
|
90
|
+
const { gl, program, globe } = this;
|
|
91
|
+
gl.useProgram(program);
|
|
92
|
+
const { cameraBlockTotem, cameraBlockBindingPoint } = this;
|
|
93
|
+
cameraBlockTotem.bind(cameraBlockBindingPoint);
|
|
94
|
+
gl.bindVertexArray(vao);
|
|
95
|
+
if (opacity !== this._lastOpacity) {
|
|
96
|
+
gl.uniform1f(this._opacityLocation, opacity);
|
|
97
|
+
this._lastOpacity = opacity;
|
|
98
|
+
}
|
|
99
|
+
const drawCount = globe.api_GetCurrentGeometry() === 0 ? GLOBE_MIDPOINT_COUNT : 2;
|
|
100
|
+
gl.disable(gl.DEPTH_TEST);
|
|
101
|
+
gl.drawArraysInstanced(gl.LINE_STRIP, 0, drawCount, length);
|
|
102
|
+
gl.bindVertexArray(null);
|
|
103
|
+
cameraBlockTotem.unbind(cameraBlockBindingPoint);
|
|
104
|
+
gl.enable(gl.DEPTH_TEST);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
createBufferManager({ capacity = 10, bufferType = "DYNAMIC_DRAW" } = {}) {
|
|
109
|
+
return new BufferManager(this.globe, { capacity, bufferType });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class BufferManager extends BufferOffsetManger {
|
|
115
|
+
|
|
116
|
+
constructor(globe, { capacity = 10, bufferType = "DYNAMIC_DRAW" } = {}) {
|
|
117
|
+
super(ITEM_SIZE, { capacity, bufferType });
|
|
118
|
+
this.globe = globe
|
|
119
|
+
this.gl = globe.gl;
|
|
120
|
+
this.buffer = this.gl.createBuffer();
|
|
121
|
+
|
|
122
|
+
const { gl, buffer } = this;
|
|
123
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
124
|
+
gl.bufferData(gl.ARRAY_BUFFER, capacity * ITEM_SIZE * 4, gl[bufferType]);
|
|
125
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
126
|
+
|
|
127
|
+
this.vao = gl.createVertexArray();
|
|
128
|
+
{
|
|
129
|
+
gl.bindVertexArray(this.vao);
|
|
130
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
131
|
+
gl.enableVertexAttribArray(0);
|
|
132
|
+
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, ITEM_SIZE * 4, 0);
|
|
133
|
+
gl.enableVertexAttribArray(1);
|
|
134
|
+
gl.vertexAttribPointer(1, 2, gl.FLOAT, false, ITEM_SIZE * 4, 8);
|
|
135
|
+
gl.enableVertexAttribArray(2);
|
|
136
|
+
gl.vertexAttribPointer(2, 4, gl.FLOAT, false, ITEM_SIZE * 4, 16);
|
|
137
|
+
gl.vertexAttribDivisor(0, 1);
|
|
138
|
+
gl.vertexAttribDivisor(1, 1);
|
|
139
|
+
gl.vertexAttribDivisor(2, 1);
|
|
140
|
+
gl.bindVertexArray(null);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
*
|
|
147
|
+
* @param {Array<{key:string, long:number, lat:number, endLong:number, endLat:number, rgba:[4numbers] }} items
|
|
148
|
+
*/
|
|
149
|
+
insertBulk(items) {
|
|
150
|
+
this.autoExtendBuffer(items.length)
|
|
151
|
+
const { gl, buffer, globe } = this;
|
|
152
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
153
|
+
for (let { key, long, lat, endLong, endLat, rgba } of items) {
|
|
154
|
+
|
|
155
|
+
const payload = new Float32Array([
|
|
156
|
+
long,
|
|
157
|
+
lat,
|
|
158
|
+
endLong,
|
|
159
|
+
endLat,
|
|
160
|
+
...rgba]);
|
|
161
|
+
const offset = this.getOffset(key) | this.nextOffset();
|
|
162
|
+
gl.bufferSubData(gl.ARRAY_BUFFER, offset, payload);
|
|
163
|
+
this.setOffset(key, offset);
|
|
164
|
+
}
|
|
165
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
166
|
+
globe.DrawRender();
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
*
|
|
171
|
+
* @param {Array<{key:string, long:number, lat:number, endLong:number, endLat:number, rgba:[4numbers] }} items
|
|
172
|
+
*/
|
|
173
|
+
updateBulk(items) {
|
|
174
|
+
const { gl, buffer, globe } = this;
|
|
175
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
176
|
+
for (let { key, long, lat, endLong, endLat, rgba } of items) {
|
|
177
|
+
const payload = new Float32Array([
|
|
178
|
+
long,
|
|
179
|
+
lat,
|
|
180
|
+
endLong,
|
|
181
|
+
endLat,
|
|
182
|
+
...rgba]);
|
|
183
|
+
const offset = this.getOffset(key);
|
|
184
|
+
if (offset !== undefined) {
|
|
185
|
+
gl.bufferSubData(gl.ARRAY_BUFFER, offset, payload);
|
|
186
|
+
} else {
|
|
187
|
+
console.warn("key not found", key);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
191
|
+
globe.DrawRender();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
*
|
|
196
|
+
* @param {Array<{key:string, long:number, lat:number, endLong:number, endLat:number }} items
|
|
197
|
+
*/
|
|
198
|
+
updateCoordinatesBulk(items) {
|
|
199
|
+
const { gl, buffer, globe } = this;
|
|
200
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
201
|
+
for (let { key, long, lat, endLong, endLat } of items) {
|
|
202
|
+
const payload = new Float32Array([
|
|
203
|
+
long,
|
|
204
|
+
lat,
|
|
205
|
+
endLong,
|
|
206
|
+
endLat]);
|
|
207
|
+
const offset = this.getOffset(key);
|
|
208
|
+
if (offset !== undefined) {
|
|
209
|
+
gl.bufferSubData(gl.ARRAY_BUFFER, offset, payload);
|
|
210
|
+
} else {
|
|
211
|
+
console.warn("key not found", key);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
215
|
+
globe.DrawRender();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
*
|
|
221
|
+
* @param {Array<{key:string, rgba:[4numbers] }} items
|
|
222
|
+
*/
|
|
223
|
+
updateColorBulk(items) {
|
|
224
|
+
const { gl, buffer, globe } = this;
|
|
225
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
226
|
+
for (let { key, rgba } of items) {
|
|
227
|
+
const payload = new Float32Array([...rgba]);
|
|
228
|
+
const offset = this.getOffset(key);
|
|
229
|
+
if (offset !== undefined) {
|
|
230
|
+
gl.bufferSubData(gl.ARRAY_BUFFER, offset + 16, payload);
|
|
231
|
+
} else {
|
|
232
|
+
console.warn("key not found", key);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
236
|
+
globe.DrawRender();
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
*
|
|
242
|
+
* @param {Array<string>} keys
|
|
243
|
+
*/
|
|
244
|
+
deleteBulk(keys) {
|
|
245
|
+
const { gl, buffer, globe } = this;
|
|
246
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
247
|
+
const emptyBlock = new Float32Array(ITEM_SIZE).fill(0);
|
|
248
|
+
for (let key of keys) {
|
|
249
|
+
const offset = this.getOffset(key);
|
|
250
|
+
if (offset !== undefined) {
|
|
251
|
+
this.deleteFromAccount(key);
|
|
252
|
+
gl.bufferSubData(gl.ARRAY_BUFFER, offset, emptyBlock);
|
|
253
|
+
} else {
|
|
254
|
+
console.warn("key not found", key);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
258
|
+
globe.DrawRender();
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
export const LineOnGlobeCache = Object.freeze({
|
|
264
|
+
get: (globe) => { return noRegisterGlobeProgramCache.getProgram(globe, Logic) },
|
|
265
|
+
free: (globe) => { return noRegisterGlobeProgramCache.releaseProgram(globe, Logic) }
|
|
266
|
+
});
|
|
267
|
+
|
|
@@ -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
|
@@ -31,6 +31,9 @@ export default class {
|
|
|
31
31
|
this.circleEdgeCount = 360;
|
|
32
32
|
this._onedegreepaddingOn = oneDegreePadding;
|
|
33
33
|
this.bufferManager = null;
|
|
34
|
+
|
|
35
|
+
this._deleteCounter = 0;
|
|
36
|
+
this._deleteThreshold = 10;
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
|
|
@@ -56,6 +59,9 @@ export default class {
|
|
|
56
59
|
this.circleProgramCache?.releaseProgram(this.globe);
|
|
57
60
|
this.PaddingProgramCache?.releaseProgram(this.globe);
|
|
58
61
|
this.PaddingFreeAngleCache?.releaseProgram(this.globe);
|
|
62
|
+
this.gl.deleteVertexArray(this.bufferManager?.vao);
|
|
63
|
+
this.gl.deleteVertexArray(this.paddingBufferManager?.vao);
|
|
64
|
+
this.paddingBufferManager?.free();
|
|
59
65
|
this.bufferManager?.free();
|
|
60
66
|
this.textPlugin?.free();
|
|
61
67
|
this.circleFlatProgram = null;
|
|
@@ -157,8 +163,14 @@ export default class {
|
|
|
157
163
|
this.bufferManager.removeCenters(centerIds);
|
|
158
164
|
this.paddingBufferManager.removeCenters(centerIds);
|
|
159
165
|
this.textPlugin?.removeCenters(centerIds);
|
|
160
|
-
|
|
161
|
-
|
|
166
|
+
this._deleteCounter += centerIds.length;
|
|
167
|
+
if (this._deleteCounter > this._deleteThreshold) {
|
|
168
|
+
// this is naive since we are not checking the actual deletion
|
|
169
|
+
// but it works
|
|
170
|
+
this._deleteCounter = 0;
|
|
171
|
+
this.bufferManager.defrag();
|
|
172
|
+
this.paddingBufferManager.defrag();
|
|
173
|
+
}
|
|
162
174
|
this.globe.DrawRender();
|
|
163
175
|
|
|
164
176
|
}
|
|
@@ -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.
|
|
@@ -91,7 +104,6 @@ export default class {
|
|
|
91
104
|
const itemCount = this.itemCount;
|
|
92
105
|
const capacity = (newCapacity && newCapacity > itemCount) ? newCapacity : itemCount;
|
|
93
106
|
|
|
94
|
-
|
|
95
107
|
const newArray = new Float32Array(itemCount * itemSize);
|
|
96
108
|
|
|
97
109
|
const bufferData = this._getBufferData();
|
|
@@ -112,9 +124,16 @@ export default class {
|
|
|
112
124
|
|
|
113
125
|
this._capacity = capacity;
|
|
114
126
|
this.tombstoneOffSet = [];
|
|
127
|
+
this._length = itemCount;
|
|
115
128
|
this.offSetMap = newOffSetMap;
|
|
116
129
|
}
|
|
117
130
|
|
|
131
|
+
autoExtendBuffer(payloadSize) {
|
|
132
|
+
if (payloadSize <= this.spaceLeft) return;
|
|
133
|
+
const newCapacity = Math.ceil((payloadSize + this.length));
|
|
134
|
+
this.extendBuffer(newCapacity);
|
|
135
|
+
}
|
|
136
|
+
|
|
118
137
|
|
|
119
138
|
extendBuffer(newCapacity) {
|
|
120
139
|
const { gl, buffer, bufferType } = this;
|
|
@@ -139,8 +158,8 @@ export default class {
|
|
|
139
158
|
*/
|
|
140
159
|
_updatePartial(items, partOffset) {
|
|
141
160
|
const { gl, buffer } = this;
|
|
142
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
143
161
|
const partStart = partOffset * 4;
|
|
162
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
144
163
|
for (let { key, payload } of items) {
|
|
145
164
|
let offset = this.getOffset(key);
|
|
146
165
|
if (offset !== undefined) {
|
|
@@ -161,7 +180,6 @@ export default class {
|
|
|
161
180
|
}
|
|
162
181
|
|
|
163
182
|
|
|
164
|
-
|
|
165
183
|
_removeFromBuffer(keys) {
|
|
166
184
|
const { gl, buffer } = this;
|
|
167
185
|
const emptyBlock = new Float32Array(this.itemSize).fill(0)
|
|
@@ -175,6 +193,16 @@ export default class {
|
|
|
175
193
|
}
|
|
176
194
|
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
177
195
|
}
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
free() {
|
|
201
|
+
this.gl.deleteBuffer(this.buffer);
|
|
202
|
+
this.buffer = null;
|
|
203
|
+
this.vao = null;
|
|
204
|
+
this.gl = null;
|
|
205
|
+
}
|
|
178
206
|
}
|
|
179
207
|
|
|
180
208
|
|
|
@@ -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
|
}
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { CameraUniformBlockString, CameraUniformBlockTotem } from "../totems";
|
|
2
|
-
import { longLatRadToMercator, longLatRadToCartesian3D, cartesian3DToGLPosition, mercatorXYTo2DPoint } from "../shaderfunctions/geometrytransformations";
|
|
3
|
-
import { createProgram } from "../webgl/program";
|
|
4
|
-
import { noRegisterGlobeProgramCache, globeProgramCache } from "../programcache";
|
|
5
|
-
import { BufferOffsetManger } from "../../util/account";
|
|
6
|
-
|
|
7
|
-
const GLOBE_MIDPOINT_COUNT = 100;
|
|
8
|
-
const ITEM_SIZE = 8;
|
|
9
|
-
|
|
10
|
-
const vertexShader = `#version 300 es
|
|
11
|
-
precision highp float;
|
|
12
|
-
${CameraUniformBlockString}
|
|
13
|
-
${longLatRadToMercator}
|
|
14
|
-
${longLatRadToCartesian3D}
|
|
15
|
-
${cartesian3DToGLPosition}
|
|
16
|
-
${mercatorXYTo2DPoint}
|
|
17
|
-
|
|
18
|
-
in vec2 start_position;
|
|
19
|
-
in vec2 end_position;
|
|
20
|
-
in vec4 color;
|
|
21
|
-
out vec4 v_color;
|
|
22
|
-
|
|
23
|
-
void main() {
|
|
24
|
-
|
|
25
|
-
vec2 longLat;
|
|
26
|
-
if (is3D) {
|
|
27
|
-
float interpolation = float(gl_VertexID) / ${GLOBE_MIDPOINT_COUNT}.0;
|
|
28
|
-
longLat = mix(start_position, end_position, interpolation)
|
|
29
|
-
vec3 cartesian = longLatRadToMercator(longLat);
|
|
30
|
-
gl_Position = cartesian3DToGLPosition(cartesian);
|
|
31
|
-
} else {
|
|
32
|
-
if ( gl_VertexID == 0 ) {
|
|
33
|
-
longLat = start_position;
|
|
34
|
-
} else {
|
|
35
|
-
longLat = end_position;
|
|
36
|
-
}
|
|
37
|
-
vec2 mercator = longLatRadToMercator(longLat);
|
|
38
|
-
gl_Position = mercatorXYTo2DPoint(mercator);
|
|
39
|
-
}
|
|
40
|
-
v_color = color;
|
|
41
|
-
}
|
|
42
|
-
`
|
|
43
|
-
|
|
44
|
-
const fragmentShader = `#version 300 es
|
|
45
|
-
precision highp float;
|
|
46
|
-
in vec4 v_color;
|
|
47
|
-
out vec4 color;
|
|
48
|
-
void main() {
|
|
49
|
-
color = v_color;
|
|
50
|
-
}
|
|
51
|
-
`
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
class Logic {
|
|
55
|
-
|
|
56
|
-
constructor(globe) {
|
|
57
|
-
this.globe = globe;
|
|
58
|
-
this.gl = gl;
|
|
59
|
-
this.program = createProgram(gl, vertexShader, fragmentShader);
|
|
60
|
-
const { gl, program } = this;
|
|
61
|
-
{
|
|
62
|
-
// assign attribute locations
|
|
63
|
-
gl.bindAttribLocation(program, 0, "start_position");
|
|
64
|
-
gl.bindAttribLocation(program, 1, "end_position");
|
|
65
|
-
gl.bindAttribLocation(program, 2, "color");
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
this.cameraBlockBindingPoint = 0;
|
|
71
|
-
const cameraBlockIndex = this.gl.getUniformBlockIndex(this.program, "CameraUniformBlock");
|
|
72
|
-
this.cameraBlockTotem = globeProgramCache.getProgram(globe, CameraUniformBlockTotem);
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
draw(bufferManager) {
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
class BufferManager extends BufferOffsetManger {
|
|
87
|
-
|
|
88
|
-
constructor(gl, { capacity = 10, bufferType = "DYNAMIC_DRAW" } = {}) {
|
|
89
|
-
super(ITEM_SIZE, { capacity, bufferType });
|
|
90
|
-
this.gl = gl;
|
|
91
|
-
this.buffer = gl.createBuffer();
|
|
92
|
-
|
|
93
|
-
const { gl, buffer } = this;
|
|
94
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
95
|
-
gl.bufferData(gl.ARRAY_BUFFER, _capacity * ITEM_SIZE * 4, gl[bufferType]);
|
|
96
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
97
|
-
|
|
98
|
-
this.vao = gl.createVertexArray();
|
|
99
|
-
{
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
insertBulk(items) {
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
export const programCache = Object.freeze({
|
|
112
|
-
get: (globe) => { return noRegisterGlobeProgramCache.getProgram(globe, Logic) },
|
|
113
|
-
release: (globe) => { noRegisterGlobeProgramCache.releaseProgram(globe, Logic) }
|
|
114
|
-
});
|
|
115
|
-
|