@pirireis/webglobeplugins 0.15.35 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,184 @@
1
+ import { createProgram } from "../../util";
2
+ import { CameraUniformBlockTotemCache, CameraUniformBlockString } from "../totems";
3
+ import { mercatorXYToGLPosition, cartesian3DToGLPosition, R_3D, R } from "../../util/shaderfunctions/geometrytransformations";
4
+ import { noRegisterGlobeProgramCache } from "../programcache";
5
+ import { drawArrays, DrawRangeIndexParams } from "../../util/gl-util/draw-options/methods";
6
+ import { attributeLoader } from "../../util/gl-util/buffer/attribute-loader";
7
+ import { UniformBlockManager } from "../../util/gl-util/uniform-block/manager";
8
+ const uniformBindingPoints = {
9
+ camera: 0,
10
+ flexible: 1
11
+ };
12
+ const uniformBlockManager = new UniformBlockManager("FlexibleBlock", [
13
+ { name: "u_rgba", type: "vec4", value: new Float32Array([1, 1, 1, 1]) },
14
+ { name: "u_opacity", type: "float", value: new Float32Array([1.0]) },
15
+ { name: "u_size_multiplier", type: "float", value: new Float32Array([1.0]) },
16
+ { name: "u_size", type: "float", value: new Float32Array([1.0]) },
17
+ { name: "u_minimum_size", type: "float", value: new Float32Array([1.0]) },
18
+ { name: "u_draw_mode", type: "int", value: new Int32Array([0]) }, // 0.0 for point, 1.0 for line
19
+ { name: "u_is_circle", type: "bool", value: new Float32Array([1.0]) },
20
+ { name: "u_dash_count", type: "float", value: new Float32Array([1.0]) },
21
+ { name: "u_dash_opacity_multiplier", type: "float", value: new Float32Array([1.0]) },
22
+ { name: "u_dash_phase", type: "float", value: new Float32Array([0.0]) },
23
+ ], uniformBindingPoints.flexible);
24
+ const vs = `#version 300 es
25
+ ${R}
26
+ ${R_3D}
27
+ ${CameraUniformBlockString}
28
+ ${mercatorXYToGLPosition}
29
+ ${cartesian3DToGLPosition}
30
+
31
+ ${uniformBlockManager.glslCode()}
32
+
33
+ precision highp float;
34
+ precision highp int;
35
+
36
+ in vec3 pos3D;
37
+ in vec2 pos2D;
38
+ in vec4 rgba;
39
+ in float size;
40
+
41
+
42
+ flat out highp int vVertexID;
43
+
44
+ out vec4 v_rgba;
45
+
46
+ out float v_length;
47
+
48
+ void main() {
49
+
50
+ v_rgba = (rgba.r == -1.0) ? u_rgba : rgba;
51
+ v_rgba.a *= u_opacity;
52
+ gl_PointSize = max(((size == -1.0) ? u_size : size) * u_size_multiplier, u_minimum_size);
53
+
54
+ float size_fixer;
55
+ if(is3D){
56
+ gl_Position = cartesian3DToGLPosition(pos3D);
57
+ size_fixer = smoothstep(0.15, 1.0, 0.5 * R_3D / gl_Position.w) ;
58
+ } else {
59
+ gl_Position = mercatorXYToGLPosition(pos2D);
60
+ size_fixer = smoothstep(2.0, 5.2, z_level);
61
+ }
62
+ gl_PointSize *= size_fixer;
63
+ switch (u_draw_mode) {
64
+ case 0:
65
+ vVertexID = gl_VertexID;
66
+ break;
67
+ case 1:
68
+ v_length = float(gl_VertexID % 2);
69
+ vVertexID = (gl_VertexID - gl_VertexID % 2) / 2; // a line takes two points
70
+ break;
71
+ default:
72
+ break;
73
+ }
74
+ }`;
75
+ const fs = `#version 300 es
76
+ precision highp float;
77
+ precision highp int;
78
+
79
+ ${uniformBlockManager.glslCode()}
80
+
81
+ flat in highp int vVertexID;
82
+
83
+ in vec4 v_rgba;
84
+ in float v_length;
85
+
86
+ layout(location = 0) out vec4 fragColor;
87
+ layout(location = 1) out int vertexID;
88
+
89
+ void main() {
90
+ vertexID = vVertexID;
91
+ fragColor = v_rgba;
92
+
93
+ switch (u_draw_mode) {
94
+ case 0:
95
+ float d = distance(gl_PointCoord, vec2(0.5, 0.5));
96
+ if (u_is_circle) {
97
+ if (d > 0.5) discard;
98
+ fragColor.a *= smoothstep(0.5, 0.45, d);
99
+ }
100
+ if (u_dash_opacity_multiplier < 1.0) {
101
+ float dash = sin(d * 3.14159 * 2.0 * u_dash_count + u_dash_phase) * (1.0 - u_dash_opacity_multiplier) + u_dash_opacity_multiplier;
102
+ fragColor.a *= dash;
103
+ }
104
+ break;
105
+ case 1:
106
+ if (u_dash_opacity_multiplier < 1.0 && fract((v_length + u_dash_phase) * u_dash_count) < 0.5) {
107
+ fragColor.a *= u_dash_opacity_multiplier;
108
+ }
109
+ break;
110
+ }
111
+ }`;
112
+ class PointOnGlobeProgram {
113
+ constructor(globe) {
114
+ this.globe = globe;
115
+ this.gl = globe.gl;
116
+ this._isFreed = false;
117
+ this.program = createProgram(this.gl, vs, fs);
118
+ const { gl, program } = this;
119
+ // assign opacity
120
+ // assign attribute locations
121
+ gl.bindAttribLocation(program, 0, "pos3D");
122
+ gl.bindAttribLocation(program, 1, "pos2D");
123
+ gl.bindAttribLocation(program, 2, "rgba");
124
+ gl.bindAttribLocation(program, 3, "size");
125
+ // arrange camera uniform block
126
+ this.cameraBlockTotem = CameraUniformBlockTotemCache.get(globe);
127
+ this.cameraBlockTotem.assignBindingPoint(program, uniformBindingPoints.camera);
128
+ uniformBlockManager.assignBindingPoint(this.gl, this.program);
129
+ this._defaultUBO = uniformBlockManager.createUBO(this.gl);
130
+ this._defaultUBO.update(new Map([
131
+ ["u_rgba", [1, 1, 1, 1]],
132
+ ["u_opacity", [1.0]],
133
+ ["u_size_multiplier", [1.0]],
134
+ ["u_size", [1.0]],
135
+ ["u_is_circle", [1.0]],
136
+ ]));
137
+ }
138
+ createUBO() {
139
+ const ubo = uniformBlockManager.createUBO(this.gl);
140
+ return ubo;
141
+ }
142
+ createVAO(pos3DBufferObj, pos2DBufferObj, rgbaBufferObj, sizeBufferObj) {
143
+ const { gl } = this;
144
+ const vao = gl.createVertexArray();
145
+ gl.bindVertexArray(vao);
146
+ attributeLoader(gl, pos3DBufferObj, 0, 3);
147
+ attributeLoader(gl, pos2DBufferObj, 1, 2);
148
+ attributeLoader(gl, rgbaBufferObj, 2, 4, { escapeValues: [-1, -1, -1, -1] });
149
+ attributeLoader(gl, sizeBufferObj, 3, 1, { escapeValues: [-1] });
150
+ gl.bindVertexArray(null);
151
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
152
+ return vao;
153
+ }
154
+ /**
155
+ *
156
+ * @param {vertexArrayObject} vao
157
+ * @param {DrawRangeIndexParams} drawOptions
158
+ */
159
+ draw(vao, drawOptions, ubo = null) {
160
+ const { gl, program } = this;
161
+ gl.useProgram(program);
162
+ gl.bindVertexArray(vao);
163
+ this.cameraBlockTotem.bind(uniformBindingPoints.camera);
164
+ ubo = ubo || this._defaultUBO;
165
+ ubo.bind();
166
+ drawArrays(gl, gl.POINTS, drawOptions);
167
+ ubo.unbind();
168
+ this.cameraBlockTotem.unbind(uniformBindingPoints.camera);
169
+ gl.bindVertexArray(null);
170
+ }
171
+ free() {
172
+ if (this._isFreed)
173
+ return;
174
+ const { gl, globe } = this;
175
+ CameraUniformBlockTotemCache.release(globe);
176
+ gl.deleteProgram(this.program);
177
+ this._isFreed = true;
178
+ }
179
+ }
180
+ const PickableRendererProgramCache = Object.freeze({
181
+ get: (globe) => noRegisterGlobeProgramCache.getProgram(globe, PointOnGlobeProgram),
182
+ release: (globe) => noRegisterGlobeProgramCache.releaseProgram(globe, PointOnGlobeProgram)
183
+ });
184
+ export { PickableRendererProgramCache };
@@ -0,0 +1,97 @@
1
+ import { TextureDemTriangles } from "./texture-dem-triangles";
2
+ /**
3
+ * Loads a plugin with test data for TextureDemTriangles
4
+ */
5
+ const TEST_ITEM_COUNT = 1000000;
6
+ function createTestLongLatArray() {
7
+ const arr = new Float32Array(TEST_ITEM_COUNT * 2);
8
+ for (let i = 0; i < TEST_ITEM_COUNT; i++) {
9
+ arr[i * 2 + 0] = Math.random() * 360 - 180; // longitude
10
+ arr[i * 2 + 1] = Math.random() * 180 - 90; // latitude
11
+ }
12
+ return arr;
13
+ }
14
+ function createTestPos3dArray(longLatArray) {
15
+ const arr = new Float32Array(TEST_ITEM_COUNT * 3);
16
+ for (let i = 0; i < TEST_ITEM_COUNT; i++) {
17
+ const long = longLatArray[i * 2 + 0] / 180 * Math.PI;
18
+ const lat = longLatArray[i * 2 + 1] / 180 * Math.PI;
19
+ // Convert long/lat to 3D position (simplified)
20
+ arr[i * 3 + 0] = Math.cos(lat) * Math.cos(long);
21
+ arr[i * 3 + 1] = Math.cos(lat) * Math.sin(long);
22
+ arr[i * 3 + 2] = Math.sin(lat);
23
+ }
24
+ return arr;
25
+ }
26
+ const createTestBBOXES = () => {
27
+ const bboxes = [];
28
+ for (let i = 0; i < 6; i++) {
29
+ const north = Math.random() * 90; // random latitude
30
+ const west = Math.random() * -180; // random longitude
31
+ const south = north - 30; // random latitude
32
+ const east = west + 30; // random longitude
33
+ const nw = [west, north]; // random northWest
34
+ const se = [east, south]; // random southEast
35
+ bboxes.push({ northWest: nw, southEast: se });
36
+ }
37
+ return bboxes;
38
+ };
39
+ const createTestDemTextures = () => {
40
+ const textures = [];
41
+ for (let i = 0; i < 6; i++) {
42
+ const texture = [];
43
+ for (let j = 0; j < 5 * 5; j++) {
44
+ const value = 1000 * Math.random(); // random elevation value
45
+ texture.push(value);
46
+ }
47
+ textures.push(texture);
48
+ }
49
+ return textures;
50
+ };
51
+ export class TextureDemTrianglesTestPlugin {
52
+ globe = null;
53
+ textureDemTriangles = null;
54
+ vao = null;
55
+ drawOptions = null;
56
+ bufferInfo = null;
57
+ id;
58
+ constructor(id) {
59
+ this.id = id;
60
+ }
61
+ init(globe) {
62
+ this.globe = globe;
63
+ this.textureDemTriangles = new TextureDemTriangles(globe);
64
+ // set bboxes and dem textures
65
+ const demTextures = createTestDemTextures();
66
+ const demTextureBBOX = createTestBBOXES();
67
+ this.textureDemTriangles.setDemTextures(demTextures, demTextureBBOX);
68
+ //
69
+ const bufferInfo = {
70
+ pos3dBufferInfo: {
71
+ buffer: globe.gl.createBuffer(),
72
+ stride: 0,
73
+ offset: 0,
74
+ },
75
+ longLatBufferInfo: {
76
+ buffer: globe.gl.createBuffer(),
77
+ stride: 0,
78
+ offset: 0,
79
+ },
80
+ drawOptions: { drawRange: { count: TEST_ITEM_COUNT, first: 0 } }
81
+ };
82
+ this.vao = this.textureDemTriangles.createVAO(bufferInfo.pos3dBufferInfo, bufferInfo.longLatBufferInfo);
83
+ const gl = globe.gl;
84
+ const longLatArray = createTestLongLatArray();
85
+ const pos3dArray = createTestPos3dArray(longLatArray);
86
+ gl.bindBuffer(gl.ARRAY_BUFFER, bufferInfo.pos3dBufferInfo.buffer);
87
+ gl.bufferData(gl.ARRAY_BUFFER, pos3dArray, gl.STATIC_DRAW);
88
+ gl.bindBuffer(gl.ARRAY_BUFFER, bufferInfo.longLatBufferInfo.buffer);
89
+ gl.bufferData(gl.ARRAY_BUFFER, longLatArray, gl.STATIC_DRAW);
90
+ this.bufferInfo = bufferInfo;
91
+ }
92
+ draw3D() {
93
+ if (!this.globe || !this.textureDemTriangles || !this.vao || !this.bufferInfo)
94
+ return;
95
+ this.textureDemTriangles.draw(this.vao, this.bufferInfo.drawOptions);
96
+ }
97
+ }
@@ -0,0 +1,167 @@
1
+ import { createProgram } from "../../util/webglobjectbuilders";
2
+ import { CameraUniformBlockTotemCache, CameraUniformBlockString } from "../totems/camerauniformblock";
3
+ import { cartesian3DToGLPosition } from "../../util/shaderfunctions/geometrytransformations";
4
+ import { drawArrays } from "../../util/gl-util/draw-options/methods";
5
+ import { attributeLoader } from "../../util/gl-util/buffer/attribute-loader";
6
+ import { WORLD_RADIUS_3D } from "../../Math/constants";
7
+ const uniformBindingPoints = {
8
+ camera: 0,
9
+ };
10
+ const vertexShaderSource = `#version 300 es
11
+ #pragma vscode_glsllint_stage : vert
12
+
13
+ precision highp float;
14
+ precision highp sampler2DArray;
15
+
16
+ ${CameraUniformBlockString}
17
+
18
+ ${cartesian3DToGLPosition}
19
+ in vec3 a_position;
20
+ in vec2 a_longLat;
21
+ uniform sampler2DArray u_demTexture; // <-- changed from array to single
22
+ uniform vec4 u_demTextureBBOX[6];
23
+
24
+
25
+
26
+ // TODO: light directioni
27
+ // out vec3 v_position;
28
+ // out vec3 v_normal;
29
+ // out vec2 v_textureCoord;
30
+
31
+ out vec4 v_color;
32
+
33
+ bool isPointInBBox(vec2 point, vec4 bbox) {
34
+ return point.x >= bbox.x && point.x <= bbox.z && point.y >= bbox.y && point.y <= bbox.w;
35
+ }
36
+
37
+ void main() {
38
+
39
+ float elevation = ${WORLD_RADIUS_3D}; // default elevation at sea level
40
+ v_color = vec4(1.0, 1.0, 1.0, 1.0); // default color white
41
+ for (int i = 0; i < 6; i++) {
42
+ if (isPointInBBox(a_longLat, u_demTextureBBOX[i])) {
43
+ vec2 uv = (a_longLat - u_demTextureBBOX[i].xy) / (u_demTextureBBOX[i].zw - u_demTextureBBOX[i].xy);
44
+ float altitude = texture(u_demTexture, vec3(uv, float(i))).r;
45
+ elevation += altitude;
46
+ v_color = mix(vec4(0.0, 0.0, 1.0, 1.0), vec4(1.0, 0.0, 0.0, 1.0), altitude / 1000.0); // color from blue to red based on altitude
47
+ // elevation += 1000.0 * float(i); // temporary for testing
48
+ break;
49
+ }
50
+ }
51
+
52
+
53
+ vec3 position = a_position * elevation;
54
+ gl_Position = cartesian3DToGLPosition(position);
55
+ gl_PointSize = 1.0; // for POINTS rendering
56
+ }
57
+ `;
58
+ const fragmentShaderSource = `#version 300 es
59
+ #pragma vscode_glsllint_stage : frag
60
+
61
+ precision highp float;
62
+ in vec4 v_color;
63
+ out vec4 outColor;
64
+ void main() {
65
+ outColor = v_color; // use the varying color from the vertex shader
66
+ }
67
+ `;
68
+ export class TextureDemTriangles {
69
+ globe;
70
+ gl;
71
+ program;
72
+ // Later an injection will handle demTextures and demTextureBBOX
73
+ texture;
74
+ // demTextures: WebGLTexture[] = [];
75
+ // demTextureBBOX: Float32Array = new Float32Array(6 * 4); // 6 bounding boxes
76
+ cameraUniformBlock;
77
+ locations = {
78
+ attributes: {
79
+ a_position: -1,
80
+ a_longLat: -1,
81
+ },
82
+ uniforms: {
83
+ u_demTexture: -1,
84
+ u_demTextureBBOX: -1,
85
+ }
86
+ };
87
+ constructor(globe) {
88
+ this.globe = globe;
89
+ this.gl = globe.gl;
90
+ this.program = createProgram(this.gl, vertexShaderSource, fragmentShaderSource);
91
+ this.cameraUniformBlock = CameraUniformBlockTotemCache.get(this.globe);
92
+ this.cameraUniformBlock.assignBindingPoint(this.program, uniformBindingPoints.camera);
93
+ // get attribute locations
94
+ this.locations.attributes.a_position = this.gl.getAttribLocation(this.program, 'a_position');
95
+ this.locations.attributes.a_longLat = this.gl.getAttribLocation(this.program, 'a_longLat');
96
+ // get uniform locations
97
+ this.locations.uniforms.u_demTexture = this.gl.getUniformLocation(this.program, 'u_demTexture');
98
+ this.locations.uniforms.u_demTextureBBOX = this.gl.getUniformLocation(this.program, 'u_demTextureBBOX');
99
+ // create 3d texture
100
+ const texture = this.gl.createTexture();
101
+ this.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY, texture);
102
+ // this.gl.texImage3D(this.gl.TEXTURE_2D_ARRAY, 0, this.gl.R32F, 25, 25, 6, 0, this.gl.RED, this.gl.FLOAT, null);
103
+ this.gl.texStorage3D(this.gl.TEXTURE_2D_ARRAY, 1, this.gl.R32F, 5, 5, 6);
104
+ // set texture parameters
105
+ const ext = this.gl.getExtension('OES_texture_float_linear');
106
+ this.gl.texParameteri(this.gl.TEXTURE_2D_ARRAY, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
107
+ this.gl.texParameteri(this.gl.TEXTURE_2D_ARRAY, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);
108
+ this.gl.texParameteri(this.gl.TEXTURE_2D_ARRAY, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
109
+ this.gl.texParameteri(this.gl.TEXTURE_2D_ARRAY, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
110
+ this.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY, null);
111
+ this.texture = texture;
112
+ }
113
+ createVAO(pos3dBufferInfo, longLatBufferInfo) {
114
+ const vao = this.gl.createVertexArray();
115
+ this.gl.bindVertexArray(vao);
116
+ attributeLoader(this.gl, pos3dBufferInfo, this.locations.attributes.a_position, 3);
117
+ attributeLoader(this.gl, longLatBufferInfo, this.locations.attributes.a_longLat, 2);
118
+ this.gl.bindVertexArray(null);
119
+ return vao;
120
+ }
121
+ setDemTextures(demTexturesData, demTextureBBOX) {
122
+ // bind textures to texture units
123
+ const gl = this.gl;
124
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, this.texture);
125
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
126
+ // turn off premultiply alpha
127
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
128
+ // bind and upload each texture to the 3D texture array
129
+ for (let i = 0; i < demTexturesData.length; i++) {
130
+ const data = demTexturesData[i];
131
+ if (data.length === 5 * 5) { // <-- FIXED
132
+ gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, i, 5, 5, 1, gl.RED, gl.FLOAT, new Float32Array(data));
133
+ }
134
+ }
135
+ // set uniform for texture units
136
+ const bboxVec4Array = new Float32Array(6 * 4);
137
+ for (let i = 0; i < demTextureBBOX.length; i++) {
138
+ const bbox = demTextureBBOX[i];
139
+ bboxVec4Array[i * 4 + 0] = bbox.northWest[0];
140
+ bboxVec4Array[i * 4 + 1] = bbox.southEast[1];
141
+ bboxVec4Array[i * 4 + 2] = bbox.southEast[0];
142
+ bboxVec4Array[i * 4 + 3] = bbox.northWest[1];
143
+ }
144
+ const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
145
+ gl.useProgram(this.program);
146
+ gl.uniform4fv(this.locations.uniforms.u_demTextureBBOX, bboxVec4Array);
147
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, null);
148
+ gl.useProgram(currentProgram);
149
+ }
150
+ draw(vao, drawOptions, ubo = null) {
151
+ const gl = this.gl;
152
+ console.log('Drawing TextureDemTriangles drawOptions:', drawOptions);
153
+ gl.useProgram(this.program);
154
+ this.cameraUniformBlock.bind(uniformBindingPoints.camera);
155
+ // TURN OFF flip y for texture
156
+ gl.activeTexture(gl.TEXTURE0);
157
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, this.texture);
158
+ gl.uniform1i(this.locations.uniforms.u_demTexture, 0); // texture unit 0
159
+ // bind VAO and draw
160
+ gl.bindVertexArray(vao);
161
+ drawArrays(gl, gl.POINTS, drawOptions);
162
+ gl.bindVertexArray(null);
163
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, null);
164
+ gl.useProgram(null);
165
+ this.cameraUniformBlock.unbind(uniformBindingPoints.camera);
166
+ }
167
+ }
@@ -2,6 +2,7 @@ import { globeProgramCache } from "../programcache";
2
2
  import { fromLongLatToUnitVector } from "../../Math/vec3";
3
3
  import { RADIANS } from "../../Math/methods";
4
4
  import { GlobeChangeObserver } from "./globe-changes";
5
+ // import { approximatedZoomLevel } from "../../util/geometry/index";
5
6
  export const CameraUniformBlockString = `
6
7
  layout(std140) uniform CameraUniformBlock {
7
8
  mat4 view; // 64 bytes 0
@@ -30,6 +31,7 @@ export class CameraUniformBlockTotem {
30
31
  _isMovedParams;
31
32
  _normalizedCameraVector = [0, 0, 0]; // Normalized camera vector
32
33
  // _frustumPlanes: any; // Uncomment and type if used
34
+ _aproximatedLOD = -1;
33
35
  _globeChangeObserver = null;
34
36
  constructor() {
35
37
  this.id = "CameraUniformBlockTotem";
@@ -135,6 +137,7 @@ export class CameraUniformBlockTotem {
135
137
  this._isMovedParams.lastLod = currentLOD;
136
138
  }
137
139
  this.__setCameraVectors();
140
+ // this._calculateAproximatedLOD();
138
141
  }
139
142
  __setCameraVectors() {
140
143
  if (!this.globe) {
@@ -167,9 +170,6 @@ export class CameraUniformBlockTotem {
167
170
  getUBO() {
168
171
  return this.ubo;
169
172
  }
170
- // getFrustumPlanes() {
171
- // return this._frustumPlanes;
172
- // }
173
173
  bind(bindingPoint) {
174
174
  const gl = this.gl;
175
175
  const ubo = this.ubo;
@@ -203,6 +203,13 @@ export class CameraUniformBlockTotem {
203
203
  getGlobeChanges() {
204
204
  return this._globeChangeObserver?.getChanges();
205
205
  }
206
+ // getApproximatedLOD(): number {
207
+ // return this._aproximatedLOD;
208
+ // }
209
+ // _calculateAproximatedLOD(){
210
+ // const globe = this.globe!;
211
+ // this._aproximatedLOD = approximatedZoomLevel(globe)
212
+ // }
206
213
  free() {
207
214
  const gl = this.gl;
208
215
  const ubo = this.ubo;
@@ -1,3 +1,4 @@
1
+ import { GLOBE_DEFAULT_MIN_LOD, GLOBE_DEFAULT_MAX_LOD, POLE2 } from "../../constants";
1
2
  function latLongToPixelXY(latitude, longitude) {
2
3
  return {
3
4
  x: (longitude + 180) / 360,
@@ -44,4 +45,77 @@ function normalize(array, newLength = 1) {
44
45
  function sphereCoord(long, lat, globe, height = 0) {
45
46
  return normalize(globe.api_GetCartesian3DPoint(long, lat, 0, false), 6378.137 + height);
46
47
  }
47
- export { createBBoxMatrix, latLongToPixelXY, latLongBboxtoPixelXYBbox, sphereCoord, normalize };
48
+ function clamp(value, min, max) {
49
+ return Math.min(Math.max(value, min), max);
50
+ }
51
+ function _flatZoomLevel(globe) {
52
+ const { width, height } = globe.api_GetCurrentWorldWH();
53
+ const curLod = Math.log(POLE2 / Math.min(width, height)) / Math.LN2 + GLOBE_DEFAULT_MIN_LOD;
54
+ return curLod;
55
+ }
56
+ function _sphereZoomLevel(globe) {
57
+ // Sorted array of [lod, altitude]
58
+ const altitudesAsMeterByLod = [
59
+ [25, 39.97],
60
+ [24, 39.97],
61
+ [23, 39.97],
62
+ [22, 39.97],
63
+ [21, 84.84],
64
+ [20, 169.95],
65
+ [19, 335.87],
66
+ [18, 672.80],
67
+ [17, 1352.01],
68
+ [16, 2688.90],
69
+ [15, 5386.31],
70
+ [14, 10611.02],
71
+ [13, 21526.80],
72
+ [12, 43121.77],
73
+ [11, 86927.14],
74
+ [10, 171201.96],
75
+ [9, 336039.90],
76
+ [8, 678769.05],
77
+ [7, 1379009.96],
78
+ [6, 2770920.56],
79
+ [5, 5837640.93],
80
+ [4, 12408290.88],
81
+ [3, 25512546.06],
82
+ [2, 25512546.06],
83
+ [1, 25512546.06],
84
+ [0, 25512546.06]
85
+ ];
86
+ const { Distance: altitude } = globe.api_GetCurrentLookInfo();
87
+ const defMinLod = GLOBE_DEFAULT_MIN_LOD;
88
+ const defMaxLod = GLOBE_DEFAULT_MAX_LOD;
89
+ // Binary search for correct LOD
90
+ let left = 0, right = altitudesAsMeterByLod.length - 1;
91
+ if (altitude > altitudesAsMeterByLod[right][1]) {
92
+ return clamp(0, defMinLod, defMaxLod);
93
+ }
94
+ if (altitude < altitudesAsMeterByLod[0][1]) {
95
+ return clamp(25, defMinLod, defMaxLod);
96
+ }
97
+ while (left < right) {
98
+ let mid = Math.floor((left + right) / 2);
99
+ let currAlt = altitudesAsMeterByLod[mid][1];
100
+ let nextAlt = altitudesAsMeterByLod[mid + 1][1];
101
+ if (altitude >= currAlt && altitude <= nextAlt) {
102
+ let lod = altitudesAsMeterByLod[mid][0];
103
+ if (currAlt === nextAlt) {
104
+ return clamp(lod, defMinLod, defMaxLod);
105
+ }
106
+ return clamp(lod + (-currAlt + altitude) / (-currAlt + nextAlt), defMinLod, defMaxLod);
107
+ }
108
+ if (altitude > nextAlt) {
109
+ left = mid + 1;
110
+ }
111
+ else {
112
+ right = mid;
113
+ }
114
+ }
115
+ return GLOBE_DEFAULT_MIN_LOD;
116
+ }
117
+ function approximatedZoomLevel(globe) {
118
+ const is3D = globe.api_GetCurrentGeometry() === 0;
119
+ return is3D ? _sphereZoomLevel(globe) : _flatZoomLevel(globe);
120
+ }
121
+ export { createBBoxMatrix, latLongToPixelXY, latLongBboxtoPixelXYBbox, sphereCoord, normalize, approximatedZoomLevel };