@pirireis/webglobeplugins 0.11.1-alpha → 0.12.0-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.
@@ -0,0 +1,252 @@
1
+ import { LineStripProgramCache } from "../../programs/line-on-globe/linestrip";
2
+ import { BufferManager, BufferOrchestrator } from "../../util/account/single-attribute-buffer-management/index";
3
+ import { CameraUniformBlockTotemCache } from "../../programs/totems/camerauniformblock";
4
+ import { createBufferAndReadInfo } from '../../util/gl-util/buffer/attribute-loader';
5
+ import * as CircleMethods from "../../Math/circle";
6
+ import * as CircleCDF from "../../Math/circle-cdf-points";
7
+ import * as vec3 from "../../Math/vec3";
8
+ import { globe3Dcoordinates, globe2Dcoordinates } from "../../Math/methods";
9
+ import { StaticDynamicStrategy, StaticDynamicState } from "../../util/build-strategy/static-dynamic";
10
+ import { WORLD_RADIUS_3D, WORLD_RADIUS_MERCATOR } from "../../Math/constants";
11
+ const CIRCLE_POINTS_COUNT_HALF = 65; // Half of the points plus one for the reflection
12
+ const CIRCLE_POINTS_COUNT = CIRCLE_POINTS_COUNT_HALF * 2 - 1; // Number of points to approximate the circle
13
+ const DENSE_PART_SAMPLE_RATIO = 0.80; // Ratio of the dense part of the circle
14
+ const STRENGTH_FACTOR = 2; // Strength factor for the circle sampling
15
+ // --- TUNABLE PARAMETERS ---
16
+ const ATTRACTION_LEVELS = 7;
17
+ // Radius below which the most even sampling (level 0) is always used.
18
+ const MIN_RADIUS_KM = 5000;
19
+ // The radius (km) at the center of the transition for the reference LOD.
20
+ // DECREASE this to make mid-sized circles use uneven samples EARLIER.
21
+ const MID_TRANSITION_RADIUS_KM = WORLD_RADIUS_MERCATOR * 0.85;
22
+ const RADIUS_INFLUENCE = 0.55; // How much the radius influences the transition.
23
+ // The reference LOD for the transition.
24
+ const MID_TRANSITION_LOD = 10;
25
+ // How much LOD shifts the curve. Higher means LOD has more influence.
26
+ const LOD_INFLUENCE = 0.385;
27
+ // Steepness of the transition. Higher value = more abrupt switch.
28
+ // DECREASE this to make large circles transition to higher tiers SLOWER.
29
+ const TRANSITION_STEEPNESS = 0.77;
30
+ /**
31
+ * @param lod The current zoom level.
32
+ * @param radiusMeters The circle's radius in meters.
33
+ * @returns An integer level from 0 to ATTRACTION_LEVELS - 1.
34
+ */
35
+ const defineStregthLevel = (lod, radiusMeters) => {
36
+ const radiusKm = radiusMeters;
37
+ // return ATTRACTION_LEVELS - 1;
38
+ // 1. Enforce a minimum radius for even sampling.
39
+ if (radiusKm < MIN_RADIUS_KM) {
40
+ return 0;
41
+ }
42
+ // 2. Combine radius and LOD into a single variable.
43
+ const log_r_mid = Math.log(MID_TRANSITION_RADIUS_KM);
44
+ const log_r = Math.log(radiusKm);
45
+ const combined_input = RADIUS_INFLUENCE * (log_r - log_r_mid) + LOD_INFLUENCE * (lod - MID_TRANSITION_LOD);
46
+ // 3. Apply the logistic (sigmoid) function to get a strength value [0, 1].
47
+ const strength_factor = 1.0 / (1.0 + Math.pow(2.4, -TRANSITION_STEEPNESS * combined_input));
48
+ // 4. Scale the result to the available attraction levels and clamp.
49
+ const level = Math.floor(strength_factor * ATTRACTION_LEVELS);
50
+ return Math.min(level, ATTRACTION_LEVELS - 1);
51
+ };
52
+ const AnglesStash = CircleCDF.createCummulativeTemplateStash(ATTRACTION_LEVELS, CIRCLE_POINTS_COUNT_HALF, DENSE_PART_SAMPLE_RATIO, STRENGTH_FACTOR);
53
+ export class CircleOnTerrainPlugin {
54
+ id;
55
+ globe = null;
56
+ gl = null;
57
+ lineProgram = null;
58
+ bufferManagerMap = new Map();
59
+ bufferOrchestrator = new BufferOrchestrator();
60
+ circleMap = new Map();
61
+ _cameraUniformBlock = null;
62
+ _isFree = false;
63
+ _circleUBOHandler = null;
64
+ _opacity = 1;
65
+ _vao = null;
66
+ _dobuild = true; // This is used to trigger the build of circles when the camera position changes.
67
+ _staticDynamicStrategy = null;
68
+ constructor(id) {
69
+ this.id = id;
70
+ }
71
+ _buildCircles() {
72
+ //
73
+ // @ts-ignore
74
+ this.__buildCircles();
75
+ return;
76
+ this._staticDynamicStrategy?.updateState();
77
+ const state = this._staticDynamicStrategy?.getState();
78
+ if (state === StaticDynamicState.TO_STATIC)
79
+ console.log("state", state);
80
+ if (state === StaticDynamicState.TO_STATIC) {
81
+ this.__buildStaticCircles();
82
+ }
83
+ else if (state === StaticDynamicState.DYNAMIC) {
84
+ this.__buildCircles();
85
+ }
86
+ }
87
+ __buildCircles() {
88
+ const { globe, gl, _cameraUniformBlock, lineProgram, bufferOrchestrator, bufferManagerMap, circleMap } = this;
89
+ if (!globe || !gl || !_cameraUniformBlock || !lineProgram ||
90
+ !bufferOrchestrator || !bufferManagerMap || !circleMap)
91
+ throw new Error("Plugin not initialized properly");
92
+ // unoptimized.. resets all circles.
93
+ bufferOrchestrator.resetWithCapacity(bufferManagerMap, circleMap.size);
94
+ // Prepare the data for the buffers
95
+ const data = [{
96
+ key: "",
97
+ longLatArr: []
98
+ }];
99
+ const lookAtPosition = _cameraUniformBlock.getLookAtVector();
100
+ const cameraPosition = _cameraUniformBlock.getNormalizedCameraVector();
101
+ vec3.divideScalar(cameraPosition, cameraPosition, WORLD_RADIUS_3D);
102
+ vec3.add(cameraPosition, cameraPosition, lookAtPosition);
103
+ vec3.normalize(cameraPosition, cameraPosition);
104
+ const currentLOD = globe.api_GetCurrentLODWithDecimal();
105
+ // const currentGeom = globe.api_GetCurrentGeometry();
106
+ const circlePointsLongLat = new Float64Array((CIRCLE_POINTS_COUNT) * 2);
107
+ for (const [key, circle] of this.circleMap.entries()) {
108
+ const [{ radius, center }, circleForAzimuthCalc] = circle;
109
+ const closestAzimuthAngle = CircleMethods.closestAzimuthAngle(circleForAzimuthCalc, cameraPosition);
110
+ const stregthLevel = defineStregthLevel(currentLOD, radius);
111
+ // console.log('DrawStregthLevel', stregthLevel, currentLOD, radius);
112
+ if (stregthLevel < 0) {
113
+ console.warn(`CircleOnTerrainPlugin: Circle ${key} has too small radius for current LOD ${currentLOD}. Skipping., radius: ${radius}, stregthLevel: ${stregthLevel}`);
114
+ continue;
115
+ }
116
+ const templateAngles = AnglesStash[stregthLevel];
117
+ CircleCDF.globeFindPointByPolarHalfCircle(circlePointsLongLat, globe, center[0], center[1], radius, closestAzimuthAngle, templateAngles);
118
+ data[0].key = key;
119
+ data[0].longLatArr = circlePointsLongLat;
120
+ // Add to buffer orchestrator
121
+ this.bufferOrchestrator.insertBulk(data, bufferManagerMap);
122
+ }
123
+ }
124
+ // this will be used to build static circles, which are not affected by camera position or LOD.
125
+ // LOD < 8 or something
126
+ __buildStaticCircles(subSetIDs = null) {
127
+ const { globe, gl, _cameraUniformBlock, lineProgram, bufferOrchestrator, bufferManagerMap, circleMap } = this;
128
+ if (!globe || !gl || !_cameraUniformBlock || !lineProgram ||
129
+ !bufferOrchestrator || !bufferManagerMap || !circleMap)
130
+ throw new Error("Plugin not initialized properly");
131
+ const data = [{
132
+ key: "",
133
+ longLatArr: []
134
+ }];
135
+ // ensure buffer orchestrotrator have enough capacity
136
+ // all circles are build with even sampling, AttractionLevel = 0
137
+ const templateAngles = AnglesStash[0];
138
+ const zeroRotation = 0;
139
+ if (!subSetIDs || subSetIDs.length === 0) {
140
+ const circlePointsLongLat = new Float64Array((CIRCLE_POINTS_COUNT) * 2);
141
+ bufferOrchestrator.resetWithCapacity(bufferManagerMap, circleMap.size);
142
+ for (const [key, circle] of this.circleMap.entries()) {
143
+ const [{ radius, center }, _] = circle;
144
+ CircleCDF.globeFindPointByPolarHalfCircle(circlePointsLongLat, globe, center[0], center[1], radius, zeroRotation, templateAngles);
145
+ data[0].key = key;
146
+ data[0].longLatArr = circlePointsLongLat;
147
+ this.bufferOrchestrator.insertBulk(data, bufferManagerMap);
148
+ }
149
+ }
150
+ else {
151
+ // This does check the size beforehand.
152
+ // subset is probably is used to insert a single item or,
153
+ // rebuild of existing items which passed from rbushTree or similar indexed search.
154
+ // therefore, it is not necessary to check for new items and extend capacity
155
+ for (let key of subSetIDs) {
156
+ if (!this.circleMap.has(key)) {
157
+ console.warn(`CircleOnTerrainPlugin: Circle ${key} not found in circleMap.`);
158
+ continue;
159
+ }
160
+ const [{ radius, center }, _] = this.circleMap.get(key);
161
+ const circlePointsLongLat = new Float64Array((CIRCLE_POINTS_COUNT) * 2);
162
+ CircleCDF.globeFindPointByPolarHalfCircle(circlePointsLongLat, globe, center[0], center[1], radius, zeroRotation, templateAngles);
163
+ data[0].key = key;
164
+ data[0].longLatArr = circlePointsLongLat;
165
+ this.bufferOrchestrator.insertBulk(data, bufferManagerMap);
166
+ }
167
+ }
168
+ }
169
+ init(globe, gl) {
170
+ this.globe = globe;
171
+ this.gl = gl;
172
+ // Initialize the program cache for line strip rendering.
173
+ this._staticDynamicStrategy = new StaticDynamicStrategy(globe, 8);
174
+ this.lineProgram = LineStripProgramCache.get(globe);
175
+ const g3D = globe3Dcoordinates(globe, 30);
176
+ const g2D = globe2Dcoordinates(globe);
177
+ this.bufferManagerMap.set("position3d", {
178
+ bufferManager: new BufferManager(gl, (CIRCLE_POINTS_COUNT + 1) * 3), // plus 1 is for butting linestrips
179
+ adaptor: (item) => {
180
+ const { longLatArr } = item;
181
+ const result = g3D(longLatArr, { paddingCount: 1, paddingValue: NaN });
182
+ return result;
183
+ }
184
+ });
185
+ this.bufferManagerMap.set("position2d", {
186
+ bufferManager: new BufferManager(gl, (CIRCLE_POINTS_COUNT + 1) * 2),
187
+ adaptor: (item) => {
188
+ const { longLatArr } = item;
189
+ const result = g2D(longLatArr, { paddingCount: 1, paddingValue: NaN });
190
+ return result;
191
+ }
192
+ });
193
+ this._vao = this.lineProgram.createVAO(createBufferAndReadInfo(this.bufferManagerMap.get("position3d")?.bufferManager.buffer), createBufferAndReadInfo(this.bufferManagerMap.get("position2d")?.bufferManager.buffer), null, null, null);
194
+ this._circleUBOHandler = this.lineProgram.createUBO();
195
+ this._cameraUniformBlock = CameraUniformBlockTotemCache.get(globe);
196
+ }
197
+ insertCircle(key, longitude, latitude, radius) {
198
+ const circle = {
199
+ center: [longitude, latitude],
200
+ radius: radius
201
+ };
202
+ const circleForAzimuthCalc = CircleMethods.createCircleClosestAzimuthAngleProperties(circle);
203
+ this.circleMap.set(key, [circle, circleForAzimuthCalc]);
204
+ // @ts-ignore
205
+ if (this._staticDynamicStrategy.getState() === StaticDynamicState.STATIC) {
206
+ this.__buildStaticCircles([key]);
207
+ }
208
+ this.globe?.DrawRender();
209
+ }
210
+ deleteCircle(keys) {
211
+ for (const key of keys) {
212
+ if (this.circleMap.has(key)) {
213
+ this.circleMap.delete(key);
214
+ this.globe?.DrawRender();
215
+ }
216
+ }
217
+ this._dobuild = true;
218
+ this.globe?.DrawRender();
219
+ }
220
+ draw3D() {
221
+ const { _isFree, globe, gl, lineProgram, bufferOrchestrator, bufferManagerMap, _vao, _circleUBOHandler } = this;
222
+ if (_isFree || !globe || !gl || !lineProgram || !bufferOrchestrator ||
223
+ !bufferManagerMap || !_vao || !_circleUBOHandler) {
224
+ return;
225
+ }
226
+ this._buildCircles();
227
+ const drawOptions = {
228
+ drawRange: {
229
+ first: 0,
230
+ count: bufferOrchestrator.length * (CIRCLE_POINTS_COUNT + 1), // plus 1 is for cutting linestrips
231
+ },
232
+ };
233
+ gl.disable(gl.DEPTH_TEST);
234
+ lineProgram.draw(_vao, drawOptions, this._opacity, _circleUBOHandler);
235
+ gl.enable(gl.DEPTH_TEST);
236
+ }
237
+ free() {
238
+ if (this._isFree)
239
+ return;
240
+ this._isFree = true;
241
+ if (this.lineProgram) {
242
+ LineStripProgramCache.release(this.lineProgram);
243
+ this.lineProgram = null;
244
+ }
245
+ this.circleMap.clear();
246
+ this.bufferManagerMap.forEach(({ bufferManager }) => {
247
+ bufferManager.free();
248
+ });
249
+ this.bufferManagerMap.clear();
250
+ CameraUniformBlockTotemCache.release(this.globe);
251
+ }
252
+ }
@@ -20,7 +20,7 @@ export class BufferOrchestrator {
20
20
  this._length = 0;
21
21
  }
22
22
  insertBulk(items, bufferManagersMap) {
23
- this.autoExtendBuffers(items.length, bufferManagersMap);
23
+ this.ensureSpace(items.length, bufferManagersMap);
24
24
  const { offsetMap } = this;
25
25
  const offsets = [];
26
26
  for (const item of items) {
@@ -88,7 +88,7 @@ export class BufferOrchestrator {
88
88
  }
89
89
  return false;
90
90
  }
91
- autoExtendBuffers(itemsLength, bufferManagersMap) {
91
+ ensureSpace(itemsLength, bufferManagersMap) {
92
92
  if (itemsLength <= this.emptySpace)
93
93
  return;
94
94
  const newCapacity = this.length + itemsLength;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * # Considerations ---
3
+ * - RABIT LOD change should trigger build immediately
4
+ * - CRUD operations should trigger build immediately
5
+ * - CameraAngle Change should trigger build immediately for Plugins employ DENSITY variation mechanism
6
+ *
7
+ */
8
+ var State;
9
+ (function (State) {
10
+ State["STATIC"] = "STATIC";
11
+ State["DYNAMIC"] = "DYNAMIC";
12
+ State["TRANSIENT"] = "TRANSIENT";
13
+ })(State || (State = {}));
14
+ class GeneralStrategy {
15
+ globe;
16
+ _state = State.DYNAMIC;
17
+ _transitionLevel = 8; // Default transition level
18
+ _lastLOD = 1000; // an extreme value to trigger initial build
19
+ _lastCameraPosition = [0, 0, 0]; // Initial camera position
20
+ _lastLookInfo = {
21
+ CenterLong: 0,
22
+ CenterLat: 0,
23
+ Distance: 0,
24
+ Tilt: 0,
25
+ NorthAng: 0
26
+ };
27
+ _currentLOD = 1000; // an extreme value to trigger initial build
28
+ _currentCameraPosition = [0, 0, 0]; // Initial camera position
29
+ _currentLookInfo = {
30
+ CenterLong: 0,
31
+ CenterLat: 0,
32
+ Distance: 0,
33
+ Tilt: 0,
34
+ NorthAng: 0
35
+ };
36
+ // private _staticBuildThreshold: number = 8; // Default static build threshold
37
+ // private _triggerStaticBuild: boolean = false;
38
+ // private _isMovedParams: boolean = false
39
+ // private _isCameraChangedParams: boolean = false
40
+ // private _elevationChangedParams: boolean = false
41
+ constructor(globe, transitionLevel = 8) {
42
+ // Initialization logic if needed
43
+ this.globe = globe;
44
+ this._transitionLevel = transitionLevel;
45
+ }
46
+ calculateState() {
47
+ }
48
+ getState() {
49
+ return this._state;
50
+ }
51
+ // Additional methods and properties can be added here as needed
52
+ // @ts-ignore
53
+ _isMoved() {
54
+ }
55
+ // @ts-ignore
56
+ _isCameraChanged() {
57
+ }
58
+ // @ts-ignore
59
+ _elevationChanged() {
60
+ }
61
+ }
62
+ export {};
@@ -0,0 +1,31 @@
1
+ export var StaticDynamicState;
2
+ (function (StaticDynamicState) {
3
+ StaticDynamicState["STATIC"] = "STATIC";
4
+ StaticDynamicState["DYNAMIC"] = "DYNAMIC";
5
+ StaticDynamicState["TO_STATIC"] = "TO_STATIC"; // TODO: Change this not bidirectional, go to static
6
+ })(StaticDynamicState || (StaticDynamicState = {}));
7
+ export class StaticDynamicStrategy {
8
+ globe;
9
+ _staticDynamicState = StaticDynamicState.DYNAMIC;
10
+ _transitionLevel = 8; // Default transition level
11
+ _lastStaticDynamicState = StaticDynamicState.STATIC;
12
+ constructor(globe, transitionLevel = 8) {
13
+ this.globe = globe;
14
+ this._transitionLevel = transitionLevel;
15
+ this.updateState();
16
+ }
17
+ updateState() {
18
+ const currentLOD = this.globe.api_GetCurrentLODWithDecimal();
19
+ const state = currentLOD < this._transitionLevel ? StaticDynamicState.STATIC : StaticDynamicState.DYNAMIC;
20
+ if (this._lastStaticDynamicState === StaticDynamicState.STATIC && state === StaticDynamicState.DYNAMIC) {
21
+ this._staticDynamicState = StaticDynamicState.TO_STATIC;
22
+ }
23
+ else {
24
+ this._staticDynamicState = state;
25
+ }
26
+ this._lastStaticDynamicState = this._staticDynamicState;
27
+ }
28
+ getState() {
29
+ return this._staticDynamicState;
30
+ }
31
+ }
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * @typedef DrawRange
4
3
  * @type {Object}
@@ -13,3 +12,4 @@
13
12
  * @property {null|int} drawMode
14
13
  *
15
14
  */
15
+ export {};
package/globe-types.js DELETED
@@ -1 +0,0 @@
1
- "use strict";
@@ -1 +0,0 @@
1
- "use strict";
@@ -1,171 +0,0 @@
1
- import { globeProgramCache } from "../programcache";
2
- // import { getFrustumPlanes } from "../../Math/frustum/from-projection-matrix";
3
- // import { getFrustum } from "../../Math/frustum/from-globeinfo"
4
- // import { Plane } from "../../Math/";
5
- export const CameraUniformBlockString = `
6
- layout(std140) uniform CameraUniformBlock {
7
- mat4 view; // 64 bytes 0
8
- mat4 projection; // 64 bytes 64
9
- vec3 translate; // 12 bytes 128
10
- bool is3D; // 4 bytes 140
11
- vec2 mapWH; // 8 bytes 144
12
- vec2 screenWH; // 8 bytes 152
13
- float z_level; // 4 bytes 160 | 164
14
- float world_distance; // 4 bytes 164
15
- float world_tilt; // 4 bytes 168
16
- float world_north_angle; // 4 bytes 172
17
- vec2 world_center_radian; // 8 bytes 176 | 184
18
- }; // 14 lines
19
- `;
20
- const Radian = Math.PI / 180.0;
21
- export default class CameraUniformBlockTotem {
22
- constructor() {
23
- this.id = "CameraUniformBlockTotem";
24
- this.description = `Sets a uniform block and provides buffer for it. The following is the glsl uniform block:` + CameraUniformBlockString;
25
- this.gl = null;
26
- this.globe = null;
27
- this.ubo = null;
28
- // this._frustumPlanes = {
29
- // left: new Plane(),
30
- // right: new Plane(),
31
- // top: new Plane(),
32
- // bottom: new Plane(),
33
- // near: new Plane(),
34
- // far: new Plane()
35
- // }
36
- this._isMovedParams = {
37
- lastLod: null,
38
- isMoved: false,
39
- };
40
- }
41
- init(globe, gl) {
42
- this.gl = gl;
43
- this.globe = globe;
44
- this.ubo = this._createUBO();
45
- this.traslateFloat32 = new Float32Array(3);
46
- this.mapWHFloat32 = new Float32Array(2);
47
- this.setGeometry();
48
- this.resize();
49
- }
50
- _createUBO() {
51
- const { gl } = this;
52
- const ubo = gl.createBuffer();
53
- gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
54
- // 184 bytes in reality. Overflow on linux for some reason. So, 200 bytes.
55
- gl.bufferData(gl.UNIFORM_BUFFER, 200, gl.STREAM_DRAW);
56
- gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, ubo);
57
- gl.bindBuffer(gl.UNIFORM_BUFFER, null);
58
- return ubo;
59
- }
60
- resize() {
61
- const { gl, globe, ubo } = this;
62
- gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
63
- gl.bufferSubData(gl.UNIFORM_BUFFER, 152, new Float32Array([globe.api_ScrW(), globe.api_ScrH()]));
64
- gl.bindBuffer(gl.UNIFORM_BUFFER, null);
65
- }
66
- setGeometry() {
67
- const { gl, globe, ubo } = this;
68
- const is3D = globe.api_GetCurrentGeometry() === 0;
69
- gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
70
- gl.bufferSubData(gl.UNIFORM_BUFFER, 140, new Float32Array([is3D]));
71
- }
72
- draw3D(projection, modelView, translate) {
73
- const { gl, traslateFloat32, ubo, mapWHFloat32, globe } = this;
74
- gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
75
- { // view, projection, translat
76
- gl.bufferSubData(gl.UNIFORM_BUFFER, 0, modelView);
77
- gl.bufferSubData(gl.UNIFORM_BUFFER, 64, projection);
78
- traslateFloat32.set([translate.x, translate.y, translate.z], 0);
79
- gl.bufferSubData(gl.UNIFORM_BUFFER, 128, traslateFloat32);
80
- }
81
- {
82
- // zoom level
83
- gl.bufferSubData(gl.UNIFORM_BUFFER, 160, new Float32Array([globe.api_GetCurrentLODWithDecimal()]));
84
- }
85
- { // mapWH
86
- if (globe.api_GetCurrentGeometry() === 1) {
87
- const { width, height } = globe.api_GetCurrentWorldWH();
88
- mapWHFloat32.set([width, height]);
89
- gl.bufferSubData(gl.UNIFORM_BUFFER, 144, mapWHFloat32);
90
- }
91
- }
92
- {
93
- // float world_distance; // 4 bytes 164
94
- // float world_tilt; // 4 bytes 168
95
- // float world_north_angle; // 4 bytes 172
96
- // vec2 world_center_radian; // 8 bytes 180
97
- const { CenterLong, CenterLat, Distance, Tilt, NorthAng } = globe.api_GetCurrentLookInfo();
98
- gl.bufferSubData(gl.UNIFORM_BUFFER, 164, new Float32Array([
99
- Distance, Radian * Tilt, Radian * NorthAng, Radian * CenterLong, Radian * CenterLat
100
- ]));
101
- }
102
- // this._frustumPlanes = getFrustumPlanes(projection, translate);
103
- gl.bindBuffer(gl.UNIFORM_BUFFER, null);
104
- { // isMoved
105
- const currentLOD = globe.api_GetCurrentLODWithDecimal();
106
- this._isMovedParams.isMoved = this._isMovedParams.lastLod !== currentLOD || globe.api_IsScreenMoving();
107
- this._isMovedParams.lastLod = currentLOD;
108
- }
109
- // getFrustum(globe, 50, this._frustumPlanes);
110
- this._normalizedCameraVector = (() => {
111
- const { Fp, FUPos } = globe;
112
- const cameraVector = [Fp.x, Fp.y, Fp.z];
113
- const length = Math.sqrt(cameraVector.reduce((sum, val) => sum + val * val, 0));
114
- return normalizedCameraVector.map(val => val / length);
115
- })();
116
- }
117
- assignBindingPoint(program, bindingPoint) {
118
- const { gl } = this;
119
- const cameraBlockIndex = gl.getUniformBlockIndex(program, "CameraUniformBlock");
120
- gl.uniformBlockBinding(program, cameraBlockIndex, bindingPoint);
121
- }
122
- getUBO() {
123
- return this.ubo;
124
- }
125
- getFrustumPlanes() {
126
- return this._frustumPlanes;
127
- }
128
- bind(bindingPoint) {
129
- const { gl, ubo } = this;
130
- gl.bindBufferBase(gl.UNIFORM_BUFFER, bindingPoint, ubo);
131
- }
132
- unbind(bindingPoint) {
133
- const { gl } = this;
134
- gl.bindBufferBase(gl.UNIFORM_BUFFER, bindingPoint, null);
135
- }
136
- isMoved() {
137
- return this._isMovedParams.isMoved;
138
- }
139
- getCameraVector() {
140
- return [this.globe.Fp.x, this.globe.Fp.y, this.globe.Fp.z];
141
- }
142
- getNormalizedCameraVector() {
143
- return this._normalizedCameraVector;
144
- }
145
- getCameraUpPosition() {
146
- return [this.globe.FUPos.x, this.globe.FUPos.y, this.globe.FUPos.z];
147
- }
148
- free() {
149
- const { gl, ubo } = this;
150
- gl.deleteBuffer(ubo);
151
- }
152
- readBuffer() {
153
- const result = new Float32Array(41);
154
- this.gl.bindBuffer(this.gl.UNIFORM_BUFFER, this.ubo);
155
- this.gl.getBufferSubData(this.gl.UNIFORM_BUFFER, 0, result);
156
- this.gl.bindBuffer(this.gl.UNIFORM_BUFFER, null);
157
- return {
158
- view: result.slice(0, 16),
159
- projection: result.slice(16, 32),
160
- translate: result.slice(32, 35),
161
- is3D: result[35],
162
- mapWH: result.slice(36, 38),
163
- screenWH: result.slice(38, 40),
164
- z_level: result[40]
165
- };
166
- }
167
- }
168
- export const CameraUniformBlockTotemCache = Object.freeze({
169
- get: (globe) => { return globeProgramCache.getProgram(globe, CameraUniformBlockTotem); },
170
- release: (globe) => { return globeProgramCache.releaseProgram(globe, CameraUniformBlockTotem); }
171
- });