@pirireis/webglobeplugins 0.15.2-3.alpha → 0.15.2-alpha
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/arc-generate-points copy.js +366 -0
- package/Math/arc.js +2 -1
- package/Math/circle-cdf-points.js +170 -1
- package/Math/circle.js +25 -0
- package/Math/globe-util/horizon-plane.js +112 -0
- package/Math/methods.js +2 -2
- package/Math/vec3.js +2 -6
- package/altitude-locator/draw-subset-obj.js +16 -0
- package/altitude-locator/plugin.js +1 -1
- package/bearing-line/plugin.js +2 -3
- package/package.json +1 -1
- package/point-tracks/plugin.js +22 -82
- package/programs/line-on-globe/lines-color-instanced-flat.js +1 -0
- package/programs/line-on-globe/linestrip/linestrip.js +28 -2
- package/programs/line-on-globe/paddings/paddings.js +1 -0
- package/programs/point-on-globe/element-globe-surface-glow.js +1 -0
- package/programs/rings/partial-ring/piece-of-pie copy.js +286 -0
- package/programs/totems/camerauniformblock.js +0 -7
- package/programs/totems/canvas-webglobe-info.js +9 -9
- package/range-tools-on-terrain/bearing-line/adapters.js +5 -8
- package/range-tools-on-terrain/bearing-line/plugin.js +20 -95
- package/range-tools-on-terrain/circle-line-chain/adapters.js +8 -15
- package/range-tools-on-terrain/circle-line-chain/chain-list-map.js +15 -32
- package/range-tools-on-terrain/circle-line-chain/plugin.js +15 -75
- package/range-tools-on-terrain/range-ring/adapters.js +6 -74
- package/range-tools-on-terrain/range-ring/plugin.js +7 -222
- package/range-tools-on-terrain/range-ring/types.js +1 -9
- package/semiplugins/lightweight/line-plugin.js +47 -65
- package/semiplugins/lightweight/piece-of-pie-plugin.js +18 -44
- package/semiplugins/shape-on-terrain/arc-plugin.js +100 -197
- package/semiplugins/shape-on-terrain/circle-plugin.js +90 -209
- package/semiplugins/shape-on-terrain/derived/padding-plugin.js +101 -0
- package/semiplugins/shape-on-terrain/one-degree-padding.js +85 -0
- package/util/account/single-attribute-buffer-management/buffer-manager.js +0 -10
- package/util/account/single-attribute-buffer-management/buffer-orchestrator.js +8 -145
- package/util/account/single-attribute-buffer-management/object-store.js +0 -7
- package/util/build-strategy/static-dynamic.js +1 -11
- package/util/check/typecheck.js +0 -12
- package/util/geometry/index.js +1 -2
- package/programs/totems/globe-changes.js +0 -59
- package/semiplugins/interface.js +0 -1
- package/semiplugins/shape-on-terrain/padding-1-degree.js +0 -538
- package/util/account/single-attribute-buffer-management/buffer-orchestrator1.js +0 -159
- package/util/frame-counter-trigger.js +0 -84
- package/write-text/context-text4.js +0 -140
|
@@ -9,7 +9,6 @@ import { globe3Dcoordinates, globe2Dcoordinates } from "../../Math/methods";
|
|
|
9
9
|
import { StaticDynamicStrategy, StaticDynamicState } from "../../util/build-strategy/static-dynamic";
|
|
10
10
|
import { WORLD_RADIUS_3D, WORLD_RADIUS_MERCATOR } from "../../Math/constants";
|
|
11
11
|
import { opacityCheck } from "../../util/check/typecheck";
|
|
12
|
-
import { FrameCounterTrigger } from "../../util/frame-counter-trigger";
|
|
13
12
|
const ACTIVATE_DYNAMIC_STRATEGY_AT_LEVEL = 8;
|
|
14
13
|
const CIRCLE_POINTS_COUNT_HALF = 65; // Half of the points plus one for the reflection
|
|
15
14
|
const CIRCLE_POINTS_COUNT = CIRCLE_POINTS_COUNT_HALF * 2 - 1; // Number of points to approximate the circle
|
|
@@ -59,47 +58,45 @@ export class CircleOnTerrainPlugin {
|
|
|
59
58
|
globe = null;
|
|
60
59
|
gl = null;
|
|
61
60
|
lineProgram = null;
|
|
62
|
-
|
|
61
|
+
bufferManagerMap = new Map();
|
|
63
62
|
bufferOrchestrator = new BufferOrchestrator();
|
|
64
63
|
circleMap = new Map();
|
|
65
64
|
_cameraUniformBlock = null;
|
|
66
|
-
|
|
65
|
+
_isFree = false;
|
|
67
66
|
_circleUBOHandler = null;
|
|
68
67
|
_opacity = 1;
|
|
69
68
|
_vao = null;
|
|
70
69
|
_dobuild = true; // This is used to trigger the build of circles when the camera position changes.
|
|
71
|
-
_frameCounterTrigger = null;
|
|
72
70
|
_staticDynamicStrategy = null;
|
|
73
|
-
|
|
71
|
+
_styleOptions = {
|
|
74
72
|
variativeColorsOn: false,
|
|
75
73
|
defaultColor: [0.1, 0.1, 0.1, 1], // Default color in RGBA format
|
|
76
|
-
defaultHeightFromGroundIn3D: 30.0
|
|
77
|
-
isMSL: false
|
|
74
|
+
defaultHeightFromGroundIn3D: 30.0
|
|
78
75
|
};
|
|
79
|
-
|
|
80
|
-
constructor(id, styleOptions = null) {
|
|
76
|
+
constructor(id, styleOptions = {}) {
|
|
81
77
|
this.id = id;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
78
|
+
this._styleOptions = { ...this._styleOptions, ...styleOptions };
|
|
79
|
+
this._styleOptions.defaultColor = new Float32Array(this._styleOptions.defaultColor);
|
|
85
80
|
}
|
|
86
81
|
init(globe, gl) {
|
|
87
82
|
this.globe = globe;
|
|
88
83
|
this.gl = gl;
|
|
89
84
|
// Initialize the program cache for line strip rendering.
|
|
85
|
+
this._staticDynamicStrategy = new StaticDynamicStrategy(globe, ACTIVATE_DYNAMIC_STRATEGY_AT_LEVEL);
|
|
90
86
|
this.lineProgram = LineStripProgramCache.get(globe);
|
|
87
|
+
// const g3D = globe3Dcoordinates(globe, 30);
|
|
91
88
|
const g2D = globe2Dcoordinates(globe);
|
|
92
89
|
// Initialize with a reasonable initial capacity to prevent buffer size issues
|
|
93
90
|
const initialCapacity = 100; // Start with capacity for 100 circles
|
|
94
|
-
this.
|
|
91
|
+
this.bufferManagerMap.set("position3d", {
|
|
95
92
|
bufferManager: new BufferManager(gl, (CIRCLE_POINTS_COUNT + 1) * 3, { initialCapacity }), // plus 1 is for butting linestrips
|
|
96
93
|
adaptor: (item) => {
|
|
97
|
-
const { longLatArr, height = this.
|
|
98
|
-
const result = globe3Dcoordinates(globe, longLatArr,
|
|
94
|
+
const { longLatArr, height = this._styleOptions.defaultHeightFromGroundIn3D } = item;
|
|
95
|
+
const result = globe3Dcoordinates(globe, height)(longLatArr, { paddingCount: 1, paddingValue: NaN });
|
|
99
96
|
return result;
|
|
100
97
|
}
|
|
101
98
|
});
|
|
102
|
-
this.
|
|
99
|
+
this.bufferManagerMap.set("position2d", {
|
|
103
100
|
bufferManager: new BufferManager(gl, (CIRCLE_POINTS_COUNT + 1) * 2, { initialCapacity }),
|
|
104
101
|
adaptor: (item) => {
|
|
105
102
|
const { longLatArr } = item;
|
|
@@ -107,8 +104,8 @@ export class CircleOnTerrainPlugin {
|
|
|
107
104
|
return result;
|
|
108
105
|
}
|
|
109
106
|
});
|
|
110
|
-
if (this.
|
|
111
|
-
this.
|
|
107
|
+
if (this._styleOptions.variativeColorsOn) {
|
|
108
|
+
this.bufferManagerMap.set("color", {
|
|
112
109
|
bufferManager: new BufferManager(gl, (CIRCLE_POINTS_COUNT + 1) * 4, { initialCapacity }),
|
|
113
110
|
adaptor: (item) => {
|
|
114
111
|
if (item.color) {
|
|
@@ -118,109 +115,50 @@ export class CircleOnTerrainPlugin {
|
|
|
118
115
|
}
|
|
119
116
|
else {
|
|
120
117
|
for (let i = 0; i < CIRCLE_POINTS_COUNT; i++) {
|
|
121
|
-
_colorArray.set(this.
|
|
118
|
+
_colorArray.set(this._styleOptions.defaultColor, i * 4);
|
|
122
119
|
}
|
|
123
120
|
}
|
|
124
121
|
return _colorArray;
|
|
125
122
|
}
|
|
126
123
|
});
|
|
127
124
|
}
|
|
128
|
-
this._vao = this.lineProgram.createVAO(createBufferAndReadInfo(this.
|
|
129
|
-
createBufferAndReadInfo(this.
|
|
125
|
+
this._vao = this.lineProgram.createVAO(createBufferAndReadInfo(this.bufferManagerMap.get("position3d")?.bufferManager.buffer), createBufferAndReadInfo(this.bufferManagerMap.get("position2d")?.bufferManager.buffer), this._styleOptions.variativeColorsOn ?
|
|
126
|
+
createBufferAndReadInfo(this.bufferManagerMap.get("color")?.bufferManager.buffer) : null);
|
|
130
127
|
this._circleUBOHandler = this.lineProgram.createUBO();
|
|
131
|
-
this.setDefaultColor(this._options.defaultColor);
|
|
132
128
|
this._cameraUniformBlock = CameraUniformBlockTotemCache.get(globe);
|
|
133
|
-
this._staticDynamicStrategy = new StaticDynamicStrategy(globe, ACTIVATE_DYNAMIC_STRATEGY_AT_LEVEL, () => {
|
|
134
|
-
this.__buildStaticCircles();
|
|
135
|
-
});
|
|
136
|
-
this._frameCounterTrigger = new FrameCounterTrigger(globe, 15, 1000, (globeChanges) => {
|
|
137
|
-
if (this._freed)
|
|
138
|
-
return;
|
|
139
|
-
this._buildCircles();
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
increaseSpace(amount) {
|
|
143
|
-
if (this._freed) {
|
|
144
|
-
console.warn("Plugin is freed, cannot increase space");
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
if (this.globe === null) {
|
|
148
|
-
console.warn("Globe is not initialized.");
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
if (typeof amount !== "number" || amount <= 0) {
|
|
152
|
-
console.warn("Invalid amount, must be a positive number");
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
this.bufferOrchestrator.ensureSpace(amount, this.bufferManagersMap);
|
|
156
129
|
}
|
|
157
130
|
insertBulk(circles) {
|
|
158
|
-
if (this.
|
|
131
|
+
if (this._isFree)
|
|
159
132
|
return;
|
|
160
133
|
if (!this.globe || !this.gl || !this.lineProgram || !this.bufferOrchestrator ||
|
|
161
|
-
!this.
|
|
134
|
+
!this.bufferManagerMap || !this._vao || !this._circleUBOHandler) {
|
|
162
135
|
throw new Error("Plugin not initialized properly");
|
|
163
136
|
}
|
|
164
|
-
|
|
165
|
-
|
|
137
|
+
//
|
|
138
|
+
const fillStaticKeys = [];
|
|
166
139
|
for (const circleInput of circles) {
|
|
167
140
|
if (!circleInput.key || !circleInput.center || !circleInput.radius) {
|
|
168
141
|
console.warn(`CircleOnTerrainPlugin: Circle input is missing required properties: ${circleInput.radius} or ${circleInput.center} or ${circleInput.key}`);
|
|
169
142
|
continue;
|
|
170
143
|
}
|
|
171
|
-
|
|
172
|
-
console.warn(`CircleOnTerrainPlugin: Circle ${circleInput.key} has non-positive radius ${circleInput.radius}. Skipping.`);
|
|
173
|
-
continue;
|
|
174
|
-
}
|
|
175
|
-
keys.push(circleInput.key);
|
|
176
|
-
if (!this.circleMap.has(circleInput.key)) {
|
|
177
|
-
newItemCount++;
|
|
178
|
-
}
|
|
144
|
+
fillStaticKeys.push(circleInput.key);
|
|
179
145
|
const circleForAzimuthCalc = CircleMethods.createCircleClosestAzimuthAngleProperties(circleInput);
|
|
180
146
|
this.circleMap.set(circleInput.key, [circleInput, circleForAzimuthCalc]);
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
this._buildCircles(keys);
|
|
184
|
-
if (this._options.variativeColorsOn) {
|
|
185
|
-
this.__fillColor(keys);
|
|
186
|
-
}
|
|
187
|
-
this.globe.DrawRender();
|
|
188
|
-
}
|
|
189
|
-
updateColors(keyColorCouples, drawRender = true) {
|
|
190
|
-
if (this._freed) {
|
|
191
|
-
console.warn("Plugin is freed, cannot increase space");
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
if (this.globe === null) {
|
|
195
|
-
console.warn("Globe is not initialized.");
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
if (this._options.variativeColorsOn === false) {
|
|
199
|
-
console.warn("VariativeColors are not enabled");
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
for (const { key, color } of keyColorCouples) {
|
|
203
|
-
const [circleInput] = this.circleMap.get(key) || [];
|
|
204
|
-
if (circleInput) {
|
|
205
|
-
circleInput.color = color;
|
|
206
|
-
this.__fillColor([key]);
|
|
207
|
-
}
|
|
208
|
-
else {
|
|
209
|
-
console.warn(`Circle key ${key} not found in circleMap.`);
|
|
147
|
+
if (this._staticDynamicStrategy?.getState() !== StaticDynamicState.DYNAMIC) {
|
|
148
|
+
fillStaticKeys.push(circleInput.key);
|
|
210
149
|
}
|
|
211
150
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
151
|
+
this.__buildStaticCircles(fillStaticKeys);
|
|
152
|
+
this.globe.DrawRender();
|
|
215
153
|
}
|
|
216
154
|
deleteBulk(keys) {
|
|
217
|
-
if (this.
|
|
155
|
+
if (this._isFree)
|
|
218
156
|
return;
|
|
219
157
|
if (!this.globe || !this.gl || !this.lineProgram || !this.bufferOrchestrator ||
|
|
220
|
-
!this.
|
|
158
|
+
!this.bufferManagerMap || !this._vao || !this._circleUBOHandler) {
|
|
221
159
|
throw new Error("Plugin not initialized properly");
|
|
222
160
|
}
|
|
223
|
-
this.bufferOrchestrator.deleteBulk(keys, this.
|
|
161
|
+
this.bufferOrchestrator.deleteBulk(keys, this.bufferManagerMap);
|
|
224
162
|
for (const key of keys) {
|
|
225
163
|
if (this.circleMap.has(key)) {
|
|
226
164
|
this.circleMap.delete(key);
|
|
@@ -230,104 +168,47 @@ export class CircleOnTerrainPlugin {
|
|
|
230
168
|
}
|
|
231
169
|
}
|
|
232
170
|
}
|
|
233
|
-
setPluginOpacity(opacity
|
|
171
|
+
setPluginOpacity(opacity) {
|
|
234
172
|
if (!this.globe || !this.gl) {
|
|
235
173
|
console.warn("Globe or WebGL context is not initialized.");
|
|
236
174
|
return;
|
|
237
175
|
}
|
|
238
176
|
opacityCheck(opacity);
|
|
239
177
|
this._opacity = opacity;
|
|
240
|
-
|
|
241
|
-
this.globe.DrawRender();
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
setElevationMode(mode) {
|
|
245
|
-
switch (mode) {
|
|
246
|
-
case "msl":
|
|
247
|
-
this._options.isMSL = true;
|
|
248
|
-
break;
|
|
249
|
-
case "agl":
|
|
250
|
-
this._options.isMSL = false;
|
|
251
|
-
break;
|
|
252
|
-
default:
|
|
253
|
-
throw new Error(`Unknown elevation mode: ${mode}`);
|
|
254
|
-
}
|
|
255
|
-
this._buildCircles();
|
|
256
|
-
this.globe?.DrawRender();
|
|
178
|
+
this.globe.DrawRender();
|
|
257
179
|
}
|
|
258
|
-
setDefaultColor(color
|
|
180
|
+
setDefaultColor(color) {
|
|
259
181
|
if (!this.globe || !this.gl) {
|
|
260
182
|
console.warn("Globe or WebGL context is not initialized.");
|
|
261
183
|
return;
|
|
262
184
|
}
|
|
263
185
|
this._circleUBOHandler?.updateSingle("u_color", new Float32Array(color));
|
|
264
|
-
if (drawRender) {
|
|
265
|
-
this.globe.DrawRender();
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
updateCoordinates(items) {
|
|
269
|
-
if (this._freed) {
|
|
270
|
-
console.warn("CircleOnTerrainPlugin is freed, cannot update coordinates");
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
if (this.globe === null) {
|
|
274
|
-
console.warn("Globe is not initialized, cannot update coordinates");
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
277
|
-
const updateKeys = [];
|
|
278
|
-
for (const item of items) {
|
|
279
|
-
const { key, center, radius } = item;
|
|
280
|
-
const [circleInput] = this.circleMap.get(key) || [];
|
|
281
|
-
if (circleInput) {
|
|
282
|
-
circleInput.center = center;
|
|
283
|
-
circleInput.radius = radius;
|
|
284
|
-
updateKeys.push(key);
|
|
285
|
-
}
|
|
286
|
-
else {
|
|
287
|
-
console.warn(`Circle key ${key} not found in circleMap.`);
|
|
288
|
-
continue;
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
this._buildCircles(updateKeys);
|
|
292
186
|
this.globe.DrawRender();
|
|
293
187
|
}
|
|
294
188
|
// IMPLICIT METHODS
|
|
295
|
-
|
|
296
|
-
if (!this._options.variativeColorsOn)
|
|
297
|
-
return;
|
|
298
|
-
const wrapper = [null];
|
|
299
|
-
for (const key of subSetIDs) {
|
|
300
|
-
const [circleInput, circleForAzimuthCalc] = this.circleMap.get(key) || [];
|
|
301
|
-
if (circleInput) {
|
|
302
|
-
wrapper[0] = circleInput;
|
|
303
|
-
this.bufferOrchestrator.insertBulk(wrapper, this.bufferManagersMap, ["color"]);
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
_buildCircles(subSetIDs = null) {
|
|
189
|
+
_buildCircles() {
|
|
308
190
|
// @ts-ignore
|
|
309
191
|
this._staticDynamicStrategy?.updateState();
|
|
310
192
|
const state = this._staticDynamicStrategy?.getState();
|
|
311
|
-
if (state === StaticDynamicState.
|
|
312
|
-
this.
|
|
193
|
+
if (state === StaticDynamicState.TO_STATIC) {
|
|
194
|
+
this.__buildStaticCircles();
|
|
313
195
|
}
|
|
314
|
-
else if (
|
|
315
|
-
this.
|
|
196
|
+
else if (state === StaticDynamicState.DYNAMIC) {
|
|
197
|
+
this.__buildCircles();
|
|
316
198
|
}
|
|
317
199
|
}
|
|
318
|
-
|
|
319
|
-
const { globe, gl, _cameraUniformBlock, lineProgram, bufferOrchestrator,
|
|
200
|
+
__buildCircles() {
|
|
201
|
+
const { globe, gl, _cameraUniformBlock, lineProgram, bufferOrchestrator, bufferManagerMap, circleMap } = this;
|
|
320
202
|
if (!globe || !gl || !_cameraUniformBlock || !lineProgram ||
|
|
321
|
-
!bufferOrchestrator || !
|
|
203
|
+
!bufferOrchestrator || !bufferManagerMap || !circleMap)
|
|
322
204
|
throw new Error("Plugin not initialized properly");
|
|
323
205
|
// unoptimized.. resets all circles.
|
|
324
|
-
// bufferOrchestrator.resetWithCapacity(
|
|
206
|
+
// bufferOrchestrator.resetWithCapacity(bufferManagerMap, circleMap.size);
|
|
325
207
|
// Prepare the data for the buffers
|
|
326
208
|
const data = [{
|
|
327
209
|
key: "",
|
|
328
210
|
longLatArr: [],
|
|
329
|
-
height: null
|
|
330
|
-
msl: null
|
|
211
|
+
height: null
|
|
331
212
|
}];
|
|
332
213
|
const lookAtPosition = _cameraUniformBlock.getLookAtVector();
|
|
333
214
|
const cameraPosition = _cameraUniformBlock.getNormalizedCameraVector();
|
|
@@ -336,16 +217,8 @@ export class CircleOnTerrainPlugin {
|
|
|
336
217
|
vec3.normalize(cameraPosition, cameraPosition);
|
|
337
218
|
const currentLOD = globe.api_GetCurrentLODWithDecimal();
|
|
338
219
|
const circlePointsLongLat = new Float64Array((CIRCLE_POINTS_COUNT) * 2);
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
keys = Array.from(this.circleMap.keys());
|
|
342
|
-
// bufferOrchestrator.resetWithCapacity(bufferManagersMap, circleMap.size);
|
|
343
|
-
}
|
|
344
|
-
else {
|
|
345
|
-
keys = subSetIDs;
|
|
346
|
-
}
|
|
347
|
-
for (const key of keys) {
|
|
348
|
-
const [{ radius, center, height = null, msl = null }, circleForAzimuthCalc] = this.circleMap.get(key);
|
|
220
|
+
for (const [key, circle] of this.circleMap.entries()) {
|
|
221
|
+
const [{ radius, center, height = null }, circleForAzimuthCalc] = circle;
|
|
349
222
|
const closestAzimuthAngle = CircleMethods.closestAzimuthAngle(circleForAzimuthCalc, cameraPosition);
|
|
350
223
|
const stregthLevel = defineStregthLevel(currentLOD, radius);
|
|
351
224
|
if (stregthLevel < 0) {
|
|
@@ -357,61 +230,69 @@ export class CircleOnTerrainPlugin {
|
|
|
357
230
|
data[0].key = key;
|
|
358
231
|
data[0].longLatArr = circlePointsLongLat;
|
|
359
232
|
data[0].height = height;
|
|
360
|
-
data[0].msl = msl;
|
|
361
233
|
// Add to buffer orchestrator
|
|
362
|
-
this.bufferOrchestrator.insertBulk(data,
|
|
363
|
-
this.globe?.api_GetCurrentGeometry() === 0 ? "position3d" : "position2d",
|
|
364
|
-
]);
|
|
234
|
+
this.bufferOrchestrator.insertBulk(data, bufferManagerMap, ["position3d", "position2d"]);
|
|
365
235
|
}
|
|
366
236
|
}
|
|
367
237
|
// this will be used to build static circles, which are not affected by camera position or LOD.
|
|
368
238
|
// LOD < 8 or something
|
|
369
239
|
__buildStaticCircles(subSetIDs = null) {
|
|
370
|
-
const { globe, gl, _cameraUniformBlock, lineProgram, bufferOrchestrator,
|
|
240
|
+
const { globe, gl, _cameraUniformBlock, lineProgram, bufferOrchestrator, bufferManagerMap, circleMap } = this;
|
|
371
241
|
if (!globe || !gl || !_cameraUniformBlock || !lineProgram ||
|
|
372
|
-
!bufferOrchestrator || !
|
|
242
|
+
!bufferOrchestrator || !bufferManagerMap || !circleMap)
|
|
373
243
|
throw new Error("Plugin not initialized properly");
|
|
374
|
-
const
|
|
244
|
+
const data = [{
|
|
245
|
+
key: "",
|
|
246
|
+
longLatArr: [],
|
|
247
|
+
height: null,
|
|
248
|
+
color: [1, 1, 1, 1]
|
|
249
|
+
}];
|
|
375
250
|
// ensure buffer orchestrotrator have enough capacity
|
|
376
251
|
// all circles are build with even sampling, AttractionLevel = 0
|
|
377
252
|
const templateAngles = AnglesStash[0];
|
|
378
253
|
const zeroRotation = 0;
|
|
379
|
-
let keys;
|
|
380
254
|
if (!subSetIDs || subSetIDs.length === 0) {
|
|
381
|
-
|
|
382
|
-
|
|
255
|
+
const circlePointsLongLat = new Float64Array((CIRCLE_POINTS_COUNT) * 2);
|
|
256
|
+
bufferOrchestrator.resetWithCapacity(bufferManagerMap, circleMap.size);
|
|
257
|
+
for (const [key, circle] of this.circleMap.entries()) {
|
|
258
|
+
const [{ radius, center, height = null, color = null }, _] = circle;
|
|
259
|
+
CircleCDF.globeFindPointByPolarHalfCircle(circlePointsLongLat, globe, center[0], center[1], radius, zeroRotation, templateAngles);
|
|
260
|
+
data[0].key = key;
|
|
261
|
+
data[0].longLatArr = circlePointsLongLat;
|
|
262
|
+
data[0].height = height;
|
|
263
|
+
data[0].color = color || this._styleOptions.defaultColor;
|
|
264
|
+
this.bufferOrchestrator.insertBulk(data, bufferManagerMap);
|
|
265
|
+
}
|
|
383
266
|
}
|
|
384
267
|
else {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
268
|
+
// This does check the size beforehand.
|
|
269
|
+
// subset is probably is used to insert a single item or,
|
|
270
|
+
// rebuild of existing items which passed from rbushTree or similar indexed search.
|
|
271
|
+
// therefore, it is not necessary to check for new items and extend capacity
|
|
272
|
+
for (let key of subSetIDs) {
|
|
273
|
+
if (!this.circleMap.has(key)) {
|
|
274
|
+
console.warn(`CircleOnTerrainPlugin: Circle ${key} not found in circleMap.`);
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
const [{ radius, center, height = null, color = null }, _] = this.circleMap.get(key);
|
|
278
|
+
const circlePointsLongLat = new Float64Array((CIRCLE_POINTS_COUNT) * 2);
|
|
279
|
+
CircleCDF.globeFindPointByPolarHalfCircle(circlePointsLongLat, globe, center[0], center[1], radius, zeroRotation, templateAngles);
|
|
280
|
+
data[0].key = key;
|
|
281
|
+
data[0].longLatArr = circlePointsLongLat;
|
|
282
|
+
data[0].height = height;
|
|
283
|
+
data[0].color = color || this._styleOptions.defaultColor;
|
|
284
|
+
this.bufferOrchestrator.insertBulk(data, bufferManagerMap);
|
|
391
285
|
}
|
|
392
|
-
const [{ radius, center, height = null, color = null, msl = undefined }, _] = this.circleMap.get(key);
|
|
393
|
-
const circlePointsLongLat = new Float64Array((CIRCLE_POINTS_COUNT) * 2);
|
|
394
|
-
CircleCDF.globeFindPointByPolarHalfCircle(circlePointsLongLat, globe, center[0], center[1], radius, zeroRotation, templateAngles);
|
|
395
|
-
datas.push({
|
|
396
|
-
key,
|
|
397
|
-
longLatArr: circlePointsLongLat,
|
|
398
|
-
height,
|
|
399
|
-
color: color || this._options.defaultColor,
|
|
400
|
-
msl
|
|
401
|
-
});
|
|
402
286
|
}
|
|
403
|
-
this.bufferOrchestrator.insertBulk(datas, bufferManagersMap, [this.globe?.api_GetCurrentGeometry() === 0 ? "position3d" : "position2d"]);
|
|
404
287
|
}
|
|
405
288
|
// GLOBE API INTERFACE
|
|
406
289
|
draw3D() {
|
|
407
|
-
const {
|
|
408
|
-
if (
|
|
409
|
-
!
|
|
290
|
+
const { _isFree, globe, gl, lineProgram, bufferOrchestrator, bufferManagerMap, _vao, _circleUBOHandler } = this;
|
|
291
|
+
if (_isFree || !globe || !gl || !lineProgram || !bufferOrchestrator ||
|
|
292
|
+
!bufferManagerMap || !_vao || !_circleUBOHandler) {
|
|
410
293
|
return;
|
|
411
294
|
}
|
|
412
|
-
|
|
413
|
-
this._frameCounterTrigger?.trigger();
|
|
414
|
-
// this._buildCircles();
|
|
295
|
+
this._buildCircles();
|
|
415
296
|
const drawOptions = {
|
|
416
297
|
drawRange: {
|
|
417
298
|
first: 0,
|
|
@@ -423,18 +304,18 @@ export class CircleOnTerrainPlugin {
|
|
|
423
304
|
gl.enable(gl.DEPTH_TEST);
|
|
424
305
|
}
|
|
425
306
|
free() {
|
|
426
|
-
if (this.
|
|
307
|
+
if (this._isFree)
|
|
427
308
|
return;
|
|
428
|
-
this.
|
|
309
|
+
this._isFree = true;
|
|
429
310
|
if (this.lineProgram) {
|
|
430
311
|
LineStripProgramCache.release(this.lineProgram);
|
|
431
312
|
this.lineProgram = null;
|
|
432
313
|
}
|
|
433
314
|
this.circleMap.clear();
|
|
434
|
-
this.
|
|
315
|
+
this.bufferManagerMap.forEach(({ bufferManager }) => {
|
|
435
316
|
bufferManager.free();
|
|
436
317
|
});
|
|
437
|
-
this.
|
|
318
|
+
this.bufferManagerMap.clear();
|
|
438
319
|
CameraUniformBlockTotemCache.release(this.globe);
|
|
439
320
|
}
|
|
440
321
|
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { ArcOnTerrainPlugin } from "../arc-plugin";
|
|
2
|
+
const EDGE_COUNT = 5;
|
|
3
|
+
const paddingKeys = (padding) => {
|
|
4
|
+
const stepCount = padding.coverAngle / padding.stepAngle;
|
|
5
|
+
const keys = new Array(Math.ceil(stepCount));
|
|
6
|
+
for (let i = 0; i < stepCount; i++) {
|
|
7
|
+
keys[i] = padding.key + i;
|
|
8
|
+
}
|
|
9
|
+
if (keys.length > stepCount) {
|
|
10
|
+
keys[keys.length - 1] = padding.key + stepCount;
|
|
11
|
+
}
|
|
12
|
+
return keys;
|
|
13
|
+
};
|
|
14
|
+
const adapterPadding2Arc = (globe, padding) => {
|
|
15
|
+
const stepCount = padding.coverAngle / padding.stepAngle;
|
|
16
|
+
const result = new Array(Math.ceil(stepCount));
|
|
17
|
+
const fill = (i, angle) => {
|
|
18
|
+
const startPoint = globe.Math.FindPointByPolar(padding.center[0], padding.center[1], padding.outerRadius, angle);
|
|
19
|
+
const endPoint = globe.Math.FindPointByPolar(padding.center[0], padding.center[1], padding.innerRadius, angle);
|
|
20
|
+
result[i] = {
|
|
21
|
+
key: padding.key + i,
|
|
22
|
+
start: [startPoint.long, startPoint.lat],
|
|
23
|
+
end: [endPoint.long, endPoint.lat],
|
|
24
|
+
color: padding.color,
|
|
25
|
+
height: padding.height,
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
for (let i = 0; i < stepCount; i++) {
|
|
29
|
+
const angle = padding.startAngle + i * padding.stepAngle;
|
|
30
|
+
fill(i, angle);
|
|
31
|
+
}
|
|
32
|
+
if (result.length > stepCount) {
|
|
33
|
+
const i = result.length - 1;
|
|
34
|
+
const angle = padding.startAngle + padding.coverAngle;
|
|
35
|
+
fill(i, angle);
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
export const chargerAdaptor = (chargerInput, plugin, padding) => {
|
|
40
|
+
};
|
|
41
|
+
export class PaddingPlugin {
|
|
42
|
+
id;
|
|
43
|
+
arcPlugin;
|
|
44
|
+
globe = null;
|
|
45
|
+
_memory = new Map();
|
|
46
|
+
isFreed = false;
|
|
47
|
+
constructor(id, { variativeColorsOn = true, defaultColor = [1, 1, 1, 1], defaultHeightFromGroundIn3D = 30.0, vertexCount = EDGE_COUNT } = {}) {
|
|
48
|
+
this.id = id;
|
|
49
|
+
this.arcPlugin = new ArcOnTerrainPlugin(id, {
|
|
50
|
+
cameraAttractionIsOn: false,
|
|
51
|
+
vertexCount: vertexCount,
|
|
52
|
+
variativeColorsOn: variativeColorsOn,
|
|
53
|
+
defaultColor: defaultColor,
|
|
54
|
+
defaultHeightFromGroundIn3D: defaultHeightFromGroundIn3D,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
insertBulk(items) {
|
|
58
|
+
for (const padding of items) {
|
|
59
|
+
this.__delete(padding.key);
|
|
60
|
+
this._memory.set(padding.key, padding);
|
|
61
|
+
}
|
|
62
|
+
const arcInputs = items.flatMap(padding => adapterPadding2Arc(this.globe, padding));
|
|
63
|
+
this.arcPlugin.insertBulk(arcInputs);
|
|
64
|
+
}
|
|
65
|
+
deleteBulk(keys) {
|
|
66
|
+
const arcKeys = keys.flatMap(key => paddingKeys({ key, center: [0, 0], outerRadius: 0, innerRadius: 0, startAngle: 0, coverAngle: 0, stepAngle: 0, color: [0, 0, 0, 1] }));
|
|
67
|
+
this.arcPlugin.deleteBulk(arcKeys);
|
|
68
|
+
}
|
|
69
|
+
updateColor(key, color) {
|
|
70
|
+
// TODO: get all padding keys and update all of them
|
|
71
|
+
if (!this._memory.has(key)) {
|
|
72
|
+
console.warn(`Padding with key ${key} does not exist.`);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const keys = paddingKeys(this._memory.get(key));
|
|
76
|
+
for (let i = 0; i < keys.length; i++) {
|
|
77
|
+
this.arcPlugin.updateColor(keys[i], color);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
__delete(key) {
|
|
81
|
+
const padding = this._memory.get(key);
|
|
82
|
+
if (padding) {
|
|
83
|
+
const keys = paddingKeys(padding);
|
|
84
|
+
this.arcPlugin.deleteBulk(keys);
|
|
85
|
+
this._memory.delete(key);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
init(globe, gl) {
|
|
89
|
+
this.globe = globe;
|
|
90
|
+
this.arcPlugin.init(globe, gl);
|
|
91
|
+
}
|
|
92
|
+
draw3D() {
|
|
93
|
+
this.arcPlugin.draw3D();
|
|
94
|
+
}
|
|
95
|
+
free() {
|
|
96
|
+
if (this.isFreed)
|
|
97
|
+
return;
|
|
98
|
+
this.isFreed = true;
|
|
99
|
+
this.arcPlugin.free();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// // One Degree Padding
|
|
3
|
+
// /**
|
|
4
|
+
// * 2d coordinates are loaded ones
|
|
5
|
+
// * 3d coordinates are calculated on the fly.
|
|
6
|
+
// *
|
|
7
|
+
// * 2d paddings are fixed size
|
|
8
|
+
// * 3d paddings gets shortened as lod increases
|
|
9
|
+
// *
|
|
10
|
+
// * color buffer is shared and does not change on unless insert or delete
|
|
11
|
+
// * changing color can be done by re inserting
|
|
12
|
+
// *
|
|
13
|
+
// *
|
|
14
|
+
// *
|
|
15
|
+
// */
|
|
16
|
+
// import { Globe, LongLat, Meter, Color } from '../../types';
|
|
17
|
+
// import { BufferManagersMap } from '../../util/account/single-attribute-buffer-management/types';
|
|
18
|
+
// import { BufferManager } from '../../util/account/single-attribute-buffer-management/buffer-manager';
|
|
19
|
+
// import { BufferOrchestrator } from '../../util/acconut/single-attribute-buffer-management/buffer-orchestrator';
|
|
20
|
+
// import { LineStripProgramCache, LineProgram } from '../../programs/line-on-globe/linestrip/linestrip';
|
|
21
|
+
// import { ProgramInterface } from '../../types';
|
|
22
|
+
// export type OneDegreePaddingInput = {
|
|
23
|
+
// key: string;
|
|
24
|
+
// center: LongLat;
|
|
25
|
+
// outerRadius: Meter;
|
|
26
|
+
// color: Color;
|
|
27
|
+
// };
|
|
28
|
+
// const _float32Array = new Float32Array(360 * 3 * 2).fill(NaN);
|
|
29
|
+
// export class Paddings1Degree implements ProgramInterface {
|
|
30
|
+
// id: string;
|
|
31
|
+
// private globe: Globe | null = null;
|
|
32
|
+
// private bufferOrchestrator: BufferOrchestrator;
|
|
33
|
+
// private bufferManagersMap: BufferManagersMap;
|
|
34
|
+
// private lineProgram: LineProgram | null = null;
|
|
35
|
+
// private _LODCoeffecientForPaddingScale: number = 1;
|
|
36
|
+
// private _PaddingSizeRatio = 0.1; // 0.1 means 10% of the padding size is used for 3d padding
|
|
37
|
+
// private _finalPaddingSizeRatio = 0.1; // this._LODCoefficientForPaddingScale * this._PaddingSizeRatio; // final padding size ratio is the product of LOD coefficient and padding size ratio
|
|
38
|
+
// constructor(id: string, { capacity = 1000 } = {}) {
|
|
39
|
+
// this.id = id;
|
|
40
|
+
// this.bufferOrchestrator = new BufferOrchestrator({ capacity });
|
|
41
|
+
// this.bufferManagersMap = new Map();
|
|
42
|
+
// this.lineProgram = null;
|
|
43
|
+
// }
|
|
44
|
+
// init(globe: Globe): void {
|
|
45
|
+
// this.globe = globe;
|
|
46
|
+
// this.lineProgram = LineStripProgramCache.get(globe);
|
|
47
|
+
// }
|
|
48
|
+
// __updateLODCoefficientForPaddingScale(): void {
|
|
49
|
+
// // TODO: call this ones when lod changes or each frame // maybe only on 3d geometry
|
|
50
|
+
// }
|
|
51
|
+
// __fillBufferManagersMap() {
|
|
52
|
+
// const globe = this.globe as Globe;
|
|
53
|
+
// const gl = globe.gl as WebGL2RenderingContext;
|
|
54
|
+
// this.bufferManagersMap.set("position2d", {
|
|
55
|
+
// bufferManager: new BufferManager(gl,
|
|
56
|
+
// 360 * (2 + 1), // plus 1 to cut
|
|
57
|
+
// { bufferType: "STATIC_DRAW", initialCapacity: 10 }),
|
|
58
|
+
// adaptor: (PaddingInput: OneDegreePaddingInput) => {
|
|
59
|
+
// for (let i = 0; i < 360; i++) {
|
|
60
|
+
// let { long, lat } = globe.Math.FindPointByPolar(
|
|
61
|
+
// PaddingInput.center[0], // center long
|
|
62
|
+
// PaddingInput.center[1], // center lat
|
|
63
|
+
// PaddingInput.outerRadius, // outer radius
|
|
64
|
+
// i, // angle
|
|
65
|
+
// )
|
|
66
|
+
// let corrds = globe.api_GetMercator2DPoint(long, lat);
|
|
67
|
+
// // fill the second coordinate with 0
|
|
68
|
+
// _float32Array[i * 3] = corrds[0];
|
|
69
|
+
// _float32Array[i * 3 + 1] = corrds[1];
|
|
70
|
+
// ({ long, lat } = globe.Math.FindPointByPolar(
|
|
71
|
+
// PaddingInput.center[0], // center long
|
|
72
|
+
// PaddingInput.center[1], // center lat
|
|
73
|
+
// PaddingInput.outerRadius * this._finalPaddingSizeRatio, // inner radius
|
|
74
|
+
// i, // angle
|
|
75
|
+
// ));
|
|
76
|
+
// let innerCorrds = globe.api_GetMercator2DPoint(long, lat);
|
|
77
|
+
// // fill the second coordinate with 0
|
|
78
|
+
// _float32Array[i * 3 + 2] = innerCorrds[0];
|
|
79
|
+
// _float32Array[i * 3 + 3] = innerCorrds[1];
|
|
80
|
+
// }
|
|
81
|
+
// return _float32Array;
|
|
82
|
+
// }
|
|
83
|
+
// });
|
|
84
|
+
// // Other methods like draw, insertBulk, deleteBulk, etc. would go here
|
|
85
|
+
// }
|
|
@@ -60,16 +60,6 @@ export class BufferManager {
|
|
|
60
60
|
}
|
|
61
61
|
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
62
62
|
}
|
|
63
|
-
insertBlock(items, offset, adapter, Constructor = Float32Array) {
|
|
64
|
-
const { gl, buffer, itemSize } = this;
|
|
65
|
-
const cpuBuffer = new Constructor(itemSize * items.length);
|
|
66
|
-
for (let i = 0; i < items.length; i++) {
|
|
67
|
-
cpuBuffer.set(adapter(items[i]), i * itemSize);
|
|
68
|
-
}
|
|
69
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
70
|
-
gl.bufferSubData(gl.ARRAY_BUFFER, offset * itemSize * 4, cpuBuffer);
|
|
71
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
72
|
-
}
|
|
73
63
|
// TODO: this is broken
|
|
74
64
|
defrag(offsetValues, occupiedCapacity, newCapacity) {
|
|
75
65
|
const { gl, buffer, bufferType, itemSize } = this;
|