@pirireis/webglobeplugins 0.17.1 → 1.0.3

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.
Files changed (67) hide show
  1. package/Math/haversine.js +22 -0
  2. package/Math/methods.js +15 -2
  3. package/Math/tessellation/methods.js +4 -1
  4. package/Math/tessellation/nearest-value-padding.js +112 -0
  5. package/Math/tessellation/spherical-triangle-area.js +99 -0
  6. package/Math/tessellation/tile-merger.js +346 -215
  7. package/Math/tessellation/triangle-tessellation.js +381 -9
  8. package/Math/vec3.js +4 -0
  9. package/Math/xyz-tile.js +18 -0
  10. package/altitude-locator/plugin.js +1 -2
  11. package/investigation-tools/draw/tiles/adapters.js +2 -2
  12. package/investigation-tools/draw/tiles/tiles.js +2 -2
  13. package/package.json +1 -1
  14. package/programs/helpers/fadeaway.js +6 -1
  15. package/programs/point-on-globe/square-pixel-point.js +1 -0
  16. package/programs/polygon-on-globe/texture-dem-triangles.js +94 -116
  17. package/programs/totems/camera-totem-attactment-interface.js +1 -0
  18. package/programs/totems/camerauniformblock.js +33 -22
  19. package/programs/totems/dem-textures-manager.js +265 -0
  20. package/programs/vectorfields/logics/drawrectangleparticles.js +51 -18
  21. package/programs/vectorfields/logics/{ubo-new.js → particle-ubo.js} +5 -14
  22. package/programs/vectorfields/logics/pixelbased.js +42 -36
  23. package/programs/vectorfields/pingpongbuffermanager.js +34 -8
  24. package/semiplugins/shape-on-terrain/terrain-polygon/adapters.js +55 -0
  25. package/semiplugins/shape-on-terrain/terrain-polygon/data/cache.js +102 -0
  26. package/semiplugins/shape-on-terrain/terrain-polygon/data/index-polygon-map.js +45 -0
  27. package/semiplugins/shape-on-terrain/terrain-polygon/data/manager.js +4 -0
  28. package/semiplugins/shape-on-terrain/terrain-polygon/data/master-worker.js +177 -0
  29. package/semiplugins/shape-on-terrain/terrain-polygon/data/polygon-to-triangles.js +100 -0
  30. package/semiplugins/shape-on-terrain/terrain-polygon/data/random.js +121 -0
  31. package/semiplugins/shape-on-terrain/terrain-polygon/data/types.js +1 -0
  32. package/semiplugins/shape-on-terrain/terrain-polygon/data/worker-contact.js +63 -0
  33. package/semiplugins/shape-on-terrain/terrain-polygon/data/worker.js +125 -0
  34. package/semiplugins/shape-on-terrain/terrain-polygon/terrain-polygon.js +219 -0
  35. package/semiplugins/shape-on-terrain/terrain-polygon/types.js +8 -0
  36. package/semiplugins/shell/bbox-renderer/logic.js +18 -58
  37. package/semiplugins/shell/bbox-renderer/object.js +19 -9
  38. package/tracks/point-heat-map/point-to-heat-map-flow.js +1 -1
  39. package/tracks/point-tracks/plugin.js +13 -6
  40. package/tracks/timetracks/program-line-strip.js +1 -1
  41. package/util/account/single-attribute-buffer-management/buffer-manager.js +5 -3
  42. package/util/account/single-attribute-buffer-management/buffer-orchestrator.js +2 -2
  43. package/util/gl-util/uniform-block/manager.js +20 -10
  44. package/util/helper-methods.js +8 -0
  45. package/util/picking/fence.js +4 -2
  46. package/util/picking/picker-displayer.js +51 -9
  47. package/util/programs/draw-texture-on-canvas.js +18 -15
  48. package/util/shaderfunctions/geometrytransformations.js +67 -1
  49. package/vectorfield/waveparticles/plugin.js +241 -116
  50. package/vectorfield/wind/adapters/image-to-fields.js +61 -0
  51. package/vectorfield/wind/adapters/types.js +1 -0
  52. package/vectorfield/wind/imagetovectorfieldandmagnitude.js +6 -9
  53. package/vectorfield/wind/plugin-persistant copy.js +364 -0
  54. package/vectorfield/wind/plugin-persistant.js +375 -0
  55. package/vectorfield/wind/plugin.js +1 -1
  56. package/Math/tessellation/earcut/adapters.js +0 -37
  57. package/Math/tessellation/hybrid-triangle-tessellation-meta.js +0 -123
  58. package/Math/tessellation/shred-input.js +0 -18
  59. package/Math/tessellation/tiler.js +0 -50
  60. package/Math/tessellation/triangle-tessellation-meta.js +0 -523
  61. package/programs/polygon-on-globe/texture-dem-triangle-test-plugin-triangle.js +0 -328
  62. package/programs/vectorfields/logics/drawrectangleparticles1.js +0 -112
  63. package/semiplugins/shape-on-terrain/terrain-cover/texture-dem-cover.js +0 -1
  64. package/util/gl-util/uniform-block/types.js +0 -1
  65. package/util/webglobe/index.js +0 -2
  66. /package/Math/tessellation/{zoom-catch.js → constants.js} +0 -0
  67. /package/util/{webglobe/gldefaultstates.js → globe-default-gl-states.js} +0 -0
@@ -10,7 +10,9 @@ const typeSizes = {
10
10
  'ivec2': 8,
11
11
  'ivec3': 16,
12
12
  'ivec4': 16,
13
- 'bool': 4
13
+ 'uvec4': 16,
14
+ 'uint': 4,
15
+ 'bool': 4,
14
16
  };
15
17
  const typeAlignments = {
16
18
  'float': 4,
@@ -24,7 +26,9 @@ const typeAlignments = {
24
26
  'ivec2': 8,
25
27
  'ivec3': 16,
26
28
  'ivec4': 16,
27
- 'bool': 4
29
+ 'uvec4': 16,
30
+ 'uint': 4,
31
+ 'bool': 4,
28
32
  };
29
33
  const typeArrayConstructors = {
30
34
  'float': Float32Array,
@@ -38,8 +42,16 @@ const typeArrayConstructors = {
38
42
  'ivec2': Int32Array,
39
43
  'ivec3': Int32Array,
40
44
  'ivec4': Int32Array,
41
- 'bool': Float32Array
45
+ 'bool': Float32Array,
46
+ 'uint': Uint32Array,
47
+ 'uvec2': Uint32Array,
48
+ 'uvec3': Uint32Array,
49
+ 'uvec4': Uint32Array,
42
50
  };
51
+ // TODO: the input types should be all same for a single block.
52
+ // no need to ask for typed array constructor in the constructor
53
+ // eacher remove it and raise error when different types are used in the same block
54
+ // or implicitly manage multiple blocks with different types
43
55
  export class UniformBlockManager {
44
56
  /**
45
57
  *
@@ -104,20 +116,19 @@ export class UniformBlockManager {
104
116
  if (offset === undefined) {
105
117
  throw new Error(`Uniform block member ${key} not found in offset map.\nPossible members: ${Array.from(this.offsetMap.keys()).join(", ")}`);
106
118
  }
107
- // @ts-ignore
108
- const type = this.blockMembers.find(member => member.name === key).type;
119
+ const memberType = this.blockMembers.find(member => member.name === key).type;
109
120
  let data;
110
121
  if (Array.isArray(value)) {
111
- data = new typeArrayConstructors[type](value);
122
+ data = new typeArrayConstructors[memberType](value);
112
123
  }
113
124
  else if (typeof value === 'number') {
114
- data = new typeArrayConstructors[type]([value]);
125
+ data = new typeArrayConstructors[memberType]([value]);
115
126
  }
116
127
  else if (value instanceof ArrayBuffer) {
117
- data = new typeArrayConstructors[type](value);
128
+ data = new typeArrayConstructors[memberType](value);
118
129
  }
119
130
  else if (ArrayBuffer.isView(value) && !(value instanceof DataView)) {
120
- data = (typeof value === 'number') ? new typeArrayConstructors[type]([value]) : new typeArrayConstructors[type](value);
131
+ data = (typeof value === 'number') ? new typeArrayConstructors[memberType]([value]) : new typeArrayConstructors[memberType](value);
121
132
  }
122
133
  else {
123
134
  throw new Error(`Unsupported value type for ${key}: ${typeof value}.\n Supported types are: number, Array, ArrayBuffer, TypedArray.`);
@@ -132,7 +143,6 @@ export class UniformBlockManager {
132
143
  if (offset === undefined) {
133
144
  throw new Error(`Uniform block member ${name} not found in offset map.\nPossible members: ${Array.from(this.offsetMap.keys()).join(", ")}`);
134
145
  }
135
- // @ts-ignore
136
146
  const type = this.blockMembers.find(member => member.name === name).type;
137
147
  let data;
138
148
  if (Array.isArray(value)) {
@@ -0,0 +1,8 @@
1
+ export function hashColorTo4IntArray(pickedColor) {
2
+ const pickedHex = pickedColor.replace('#', '');
3
+ const pickedR = parseInt(pickedHex.substring(0, 2), 16) / 255;
4
+ const pickedG = parseInt(pickedHex.substring(2, 4), 16) / 255;
5
+ const pickedB = parseInt(pickedHex.substring(4, 6), 16) / 255;
6
+ const pickedA = parseInt(pickedHex.substring(6, 8) || 'FF', 16) / 255;
7
+ return [pickedR, pickedG, pickedB, pickedA];
8
+ }
@@ -4,6 +4,10 @@ const fence = (gl) => new Promise((resolve, reject) => {
4
4
  // This means JS can continue to work on other tasks while the read instruction
5
5
  // completes.
6
6
  const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
7
+ if (!sync) {
8
+ reject(new Error('Failed to create fence sync object.'));
9
+ return;
10
+ }
7
11
  gl.flush();
8
12
  // There are TWO possible ways to check on the status of a WebGLSync object.
9
13
  // 1. This will check it using clientWaitSync()
@@ -26,8 +30,6 @@ const fence = (gl) => new Promise((resolve, reject) => {
26
30
  // 2. This will check with getSyncParameter(s, gl.SYNC_STATUS)
27
31
  const checkStatus_v2 = () => {
28
32
  const status = gl.getSyncParameter(sync, gl.SYNC_STATUS);
29
- // There are only two possible values for status: SIGNALED and UNSIGNALED
30
- // Note that there is no `error` signal, so there is no reason to use `reject()` here
31
33
  if (status === gl.SIGNALED) {
32
34
  gl.deleteSync(sync);
33
35
  resolve();
@@ -6,15 +6,40 @@ import { textureOnCanvasProgramCache } from "../programs/draw-texture-on-canvas"
6
6
  import { fence } from "./fence";
7
7
  const ESCAPE_VALUE = -1;
8
8
  class PickerDisplayer {
9
- constructor(globe) {
9
+ globe;
10
+ gl;
11
+ colorTexture;
12
+ indexTexture;
13
+ fbo;
14
+ _pbo;
15
+ _pboSize;
16
+ displayer;
17
+ _inProgress;
18
+ _indexType; // R32I for Integer, R32F for Float
19
+ _typedArrayConstructor;
20
+ constructor(globe, indexType = "R32I") {
10
21
  this.globe = globe;
11
22
  this.gl = globe.gl;
12
23
  const gl = this.gl;
13
24
  this.colorTexture = gl.createTexture(); // bind to color attachment 0
14
25
  this.indexTexture = gl.createTexture(); // bind to color attachment 1
15
26
  this.fbo = gl.createFramebuffer();
27
+ if (indexType === "R32F" && this.gl.getExtension("EXT_color_buffer_float") === null) {
28
+ throw new Error("EXT_color_buffer_float extension is required for R32F index type.");
29
+ }
30
+ this._indexType = indexType;
31
+ if (indexType === "R32I") {
32
+ this._typedArrayConstructor = Int32Array;
33
+ }
34
+ else if (indexType === "R32F") {
35
+ this._typedArrayConstructor = Float32Array;
36
+ }
37
+ else {
38
+ throw new Error("Invalid index type. Must be 'R32I' or 'R32F'.");
39
+ }
16
40
  this._pbo = undefined;
17
41
  this._pboSize = 0;
42
+ this._inProgress = false;
18
43
  this.resize();
19
44
  this.displayer = textureOnCanvasProgramCache.get(this.gl);
20
45
  }
@@ -27,12 +52,13 @@ class PickerDisplayer {
27
52
  gl.deleteTexture(colorTexture);
28
53
  gl.deleteTexture(indexTexture);
29
54
  const colorTextureNew = gl.createTexture();
55
+ gl.activeTexture(gl.TEXTURE0);
30
56
  gl.bindTexture(gl.TEXTURE_2D, colorTextureNew);
31
57
  gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, width, height);
32
58
  const indexTextureNew = gl.createTexture();
59
+ gl.activeTexture(gl.TEXTURE1);
33
60
  gl.bindTexture(gl.TEXTURE_2D, indexTextureNew);
34
- // gl.texStorage2D(gl.TEXTURE_2D, 1, gl.R16I, width, height);
35
- gl.texStorage2D(gl.TEXTURE_2D, 1, gl.R32I, width, height);
61
+ gl.texStorage2D(gl.TEXTURE_2D, 1, gl[this._indexType], width, height); // gl.R32I or gl.R32F
36
62
  gl.bindTexture(gl.TEXTURE_2D, null);
37
63
  this.colorTexture = colorTextureNew;
38
64
  this.indexTexture = indexTextureNew;
@@ -41,7 +67,12 @@ class PickerDisplayer {
41
67
  const { gl, colorTexture, indexTexture } = this;
42
68
  gl.activeTexture(gl.TEXTURE1);
43
69
  gl.bindTexture(gl.TEXTURE_2D, indexTexture);
44
- gl.clearBufferiv(gl.COLOR, 1, new Int32Array([-1, -1, -1, -1]));
70
+ if (this._indexType === "R32I") {
71
+ gl.clearBufferiv(gl.COLOR, 1, new Int32Array([-1, -1, -1, -1]));
72
+ }
73
+ else {
74
+ gl.clearBufferfv(gl.COLOR, 1, new Float32Array([-1, -1, -1, -1]));
75
+ }
45
76
  gl.activeTexture(gl.TEXTURE0);
46
77
  gl.bindTexture(gl.TEXTURE_2D, colorTexture);
47
78
  gl.clearBufferfv(gl.COLOR, 0, new Float32Array([0, 0, 0, 0]));
@@ -57,20 +88,26 @@ class PickerDisplayer {
57
88
  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.colorTexture, 0);
58
89
  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, this.indexTexture, 0);
59
90
  gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1]);
91
+ const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
92
+ if (status !== gl.FRAMEBUFFER_COMPLETE) {
93
+ throw new Error(`Framebuffer is not complete: ${status.toString(16)}`);
94
+ }
60
95
  }
61
96
  // call after drawing the scene with gl picker shader
62
97
  drawColorTexture() {
63
98
  const { gl, colorTexture } = this;
64
99
  gl.bindFramebuffer(gl.FRAMEBUFFER, null);
100
+ gl.disable(gl.DEPTH_TEST);
65
101
  this.displayer.draw(colorTexture);
102
+ gl.enable(gl.DEPTH_TEST);
66
103
  }
67
104
  pickXY(x, y, selectionPointFilling = 1, callback = () => { }) {
68
105
  const size = Math.pow(1 + 2 * selectionPointFilling, 2);
69
- this._pick(size, x - selectionPointFilling, y - selectionPointFilling, 1 + 2 * selectionPointFilling, 1 + 2 * selectionPointFilling, callback);
106
+ return this._pick(size, x - selectionPointFilling, y - selectionPointFilling, 1 + 2 * selectionPointFilling, 1 + 2 * selectionPointFilling, callback);
70
107
  }
71
108
  pickBbox(left, top, right, bottom, callback) {
72
- const size = (right - left) * (bottom - top) * 4;
73
- this._pick(size, left, top, right - left, bottom - top, callback);
109
+ const size = (right - left) * (bottom - top);
110
+ return this._pick(size, left, top, right - left, bottom - top, callback);
74
111
  }
75
112
  _pick(size, startX, startY, lengthX, lengthY, callback) {
76
113
  if (this._inProgress)
@@ -81,14 +118,16 @@ class PickerDisplayer {
81
118
  gl.bindBuffer(gl.PIXEL_PACK_BUFFER, _pbo);
82
119
  this.bindFBO();
83
120
  gl.readBuffer(gl.COLOR_ATTACHMENT1); // This is the attachment we want to read
121
+ const format = this._indexType === "R32I" ? gl.RED_INTEGER : gl.RED;
122
+ const type = this._indexType === "R32I" ? gl.INT : gl.FLOAT;
84
123
  gl.readPixels(// This will read the pixels to the buffer asynchronously
85
- startX, startY, lengthX, lengthY, gl.RED_INTEGER, gl.INT, 0);
124
+ startX, startY, lengthX, lengthY, format, type, 0);
86
125
  gl.bindFramebuffer(gl.FRAMEBUFFER, null);
87
126
  gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
88
127
  fence(this.gl).then(() => {
89
128
  gl.bindBuffer(gl.PIXEL_PACK_BUFFER, _pbo);
90
129
  // const data = new Int16Array(size);
91
- const data = new Int32Array(size);
130
+ const data = new this._typedArrayConstructor(size); // Int32Array or Float32Array
92
131
  gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, data);
93
132
  gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
94
133
  const result = this._pickFromBuffer(data, size);
@@ -128,6 +167,9 @@ class PickerDisplayer {
128
167
  gl.deleteTexture(colorTexture);
129
168
  gl.deleteTexture(indexTexture);
130
169
  gl.deleteFramebuffer(fbo);
170
+ if (this._pbo) {
171
+ gl.deleteBuffer(this._pbo);
172
+ }
131
173
  textureOnCanvasProgramCache.release(this.gl);
132
174
  }
133
175
  }
@@ -15,7 +15,7 @@ const fs = `#version 300 es
15
15
  precision highp float;
16
16
 
17
17
  uniform sampler2D u_texture;
18
- uniform float u_opacity;
18
+ uniform float u_opacity;
19
19
  in vec2 v_texcoord;
20
20
  out vec4 fragColor;
21
21
 
@@ -24,6 +24,13 @@ void main() {
24
24
  fragColor.a *= u_opacity;
25
25
  }`;
26
26
  class TextureOnCanvasProgram {
27
+ gl;
28
+ vao;
29
+ buffer;
30
+ program;
31
+ uniforms;
32
+ _lastOpacity;
33
+ _isFreed = false;
27
34
  constructor(gl) {
28
35
  this.gl = gl;
29
36
  this.vao = this.gl.createVertexArray();
@@ -41,20 +48,16 @@ class TextureOnCanvasProgram {
41
48
  this.gl.bindVertexArray(null);
42
49
  this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);
43
50
  this.program = createProgram(this.gl, vs, fs);
44
- {
45
- const { gl, program } = this;
46
- this.uniforms = {
47
- texture: gl.getUniformLocation(program, "u_texture"),
48
- opacity: gl.getUniformLocation(program, "u_opacity"),
49
- };
50
- }
51
- {
52
- this._lastOpacity = 1.0;
53
- const currentProgram = this.gl.getParameter(this.gl.CURRENT_PROGRAM);
54
- this.gl.useProgram(this.program);
55
- this.gl.uniform1f(this.uniforms.opacity, this._lastOpacity);
56
- this.gl.useProgram(currentProgram);
57
- }
51
+ const { program } = this;
52
+ this.uniforms = {
53
+ texture: gl.getUniformLocation(program, "u_texture"),
54
+ opacity: gl.getUniformLocation(program, "u_opacity"),
55
+ };
56
+ this._lastOpacity = 1.0;
57
+ const currentProgram = this.gl.getParameter(this.gl.CURRENT_PROGRAM);
58
+ this.gl.useProgram(this.program);
59
+ this.gl.uniform1f(this.uniforms.opacity, this._lastOpacity);
60
+ this.gl.useProgram(currentProgram);
58
61
  }
59
62
  draw(texture, { opacity = 1.0 } = {}) {
60
63
  const { gl, program, uniforms, vao } = this;
@@ -189,6 +189,34 @@ float circleCircumferenceInterPolationOf2PointsRadian(vec2 center, vec2 target,
189
189
  return angle;
190
190
  }
191
191
  `;
192
+ export const slopeFromTexture = R + PI + `
193
+ float slopeFromTexture(highp sampler2DArray heightMap, vec3 uv, vec2 texelSize) {
194
+ float hL = texture(heightMap, uv - vec3(texelSize.x, 0.0, 0.0)).r;
195
+ float hR = texture(heightMap, uv + vec3(texelSize.x, 0.0, 0.0)).r;
196
+ float hD = texture(heightMap, uv - vec3(0.0, texelSize.y, 0.0)).r;
197
+ float hU = texture(heightMap, uv + vec3(0.0, texelSize.y, 0.0)).r;
198
+ float dX = (hR - hL) / (2.0 * texelSize.x);
199
+ float dY = (hU - hD) / (2.0 * texelSize.y);
200
+ float slope = sqrt(dX * dX + dY * dY);
201
+ return slope;
202
+ }
203
+ `;
204
+ export const normalFromTexture = `
205
+ vec3 normalFromTexture(highp sampler2DArray heightMap, vec3 uv, vec2 texelSize, float strength) {
206
+ float hL = texture(heightMap, uv - vec3(texelSize.x, 0.0, 0.0)).r;
207
+ float hR = texture(heightMap, uv + vec3(texelSize.x, 0.0, 0.0)).r;
208
+ float hD = texture(heightMap, uv - vec3(0.0, texelSize.y, 0.0)).r;
209
+ float hU = texture(heightMap, uv + vec3(0.0, texelSize.y, 0.0)).r;
210
+
211
+ // Calculate gradient
212
+ // Strength factor controls how "bumpy" the terrain looks
213
+ float dX = (hR - hL) * strength;
214
+ float dY = (hU - hD) * strength;
215
+
216
+ // Return normalized surface normal (-dX, -dY, 1.0)
217
+ return normalize(vec3(-dX, -dY, 1.0));
218
+ }
219
+ `;
192
220
  export const realDistanceOnSphereR1 = `
193
221
  float realDistanceOnSphereR1(vec2 longLat1, vec2 longLat2) {
194
222
  float dLat = longLat2.y - longLat1.y;
@@ -200,7 +228,45 @@ float realDistanceOnSphereR1(vec2 longLat1, vec2 longLat2) {
200
228
  `;
201
229
  export const isPointInBBox = `
202
230
  bool isPointInBBox(vec2 point, vec4 bbox) {
203
- return point.x >= bbox.x && point.x <= bbox.z && point.y >= bbox.y && point.y <= bbox.w;
231
+ return point.x + ${EPSILON} >= bbox.x && point.x <= bbox.z + ${EPSILON}&& point.y + ${EPSILON} >= bbox.y && point.y <= bbox.w + ${EPSILON};
232
+ }
233
+ `;
234
+ export const relativeBBoxPositionRadian = `
235
+ ${PI}
236
+ ${isPointInBBox}
237
+ vec2 relativeBBoxPositionRadian(vec2 point, vec4 bbox) {
238
+ if ( bbox.z > bbox.x) {
239
+ if ( isPointInBBox(point, bbox) ) {
240
+ float x_ratio = (point.x - bbox.x) / (bbox.z - bbox.x);
241
+ float y_ratio = (point.y - bbox.y) / (bbox.w - bbox.y);
242
+ return vec2(x_ratio, y_ratio);
243
+ }
244
+ return vec2(-1.0, -1.0);
245
+ }
246
+ else {
247
+ // BBox crosses the antimeridian
248
+ if ( isPointInBBox(point, vec4(bbox.x, bbox.y, PI , bbox.w) ) ) {
249
+ float x_ratio = (point.x - bbox.x) / (PI - bbox.x);
250
+ float y_ratio = (point.y - bbox.y) / (bbox.w - bbox.y);
251
+ return vec2(x_ratio, y_ratio);
252
+ }
253
+ else if ( isPointInBBox(point, vec4(-PI, bbox.y, bbox.z, bbox.w) ) ) {
254
+ float x_ratio = (point.x + PI) / (bbox.z + PI);
255
+ float y_ratio = (point.y - bbox.y) / (bbox.w - bbox.y);
256
+ return vec2(x_ratio, y_ratio);
257
+ }
258
+ }
259
+ return vec2(-1.0, -1.0);
260
+ }
261
+ `;
262
+ export const isPointInBBox2 = `
263
+ bool isPointInBBox(vec2 point, vec4 bbox) {
264
+ float horizontal_epsilon = (bbox.z - bbox.x) * 0.05;
265
+ float vertical_epsilon = (bbox.w - bbox.y) * 0.05;
266
+ return point.x + horizontal_epsilon >= bbox.x &&
267
+ point.x <= bbox.z + horizontal_epsilon &&
268
+ point.y + vertical_epsilon >= bbox.y &&
269
+ point.y <= bbox.w + vertical_epsilon;
204
270
  }
205
271
  `;
206
272
  const pointsOnSphereBetween = `