@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.
- package/Math/mesh/mapbox-delaunay.js +544 -0
- package/constants.js +3 -0
- package/package.json +5 -4
- package/programs/picking/pickable-polygon-renderer.js +184 -0
- package/programs/polygon-on-globe/texture-dem-triangle-test-plugin.js +97 -0
- package/programs/polygon-on-globe/texture-dem-triangles.js +167 -0
- package/programs/totems/camerauniformblock.js +10 -3
- package/semiplugins/shape-on-terrain/terrain-cover/texture-dem-cover.js +1 -0
- package/util/geometry/index.js +75 -1
- package/write-text/context-text-bulk.js +198 -0
- package/Math/frustum/camera.js +0 -24
- package/Math/frustum/from-globeinfo.js +0 -48
- package/Math/frustum/types.js +0 -1
|
@@ -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;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
package/util/geometry/index.js
CHANGED
|
@@ -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
|
-
|
|
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 };
|