@deck.gl/extensions 9.4.0-alpha.2 → 9.4.0-beta.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.
- package/dist/clip/clip-extension.d.ts +3 -0
- package/dist/clip/clip-extension.d.ts.map +1 -1
- package/dist/clip/clip-extension.js +7 -0
- package/dist/clip/clip-extension.js.map +1 -1
- package/dist/dist.dev.js +2195 -142
- package/dist/fill-style/fill-style-extension.d.ts +38 -6
- package/dist/fill-style/fill-style-extension.d.ts.map +1 -1
- package/dist/fill-style/fill-style-extension.js +88 -10
- package/dist/fill-style/fill-style-extension.js.map +1 -1
- package/dist/fill-style/procedural-pattern.d.ts +65 -0
- package/dist/fill-style/procedural-pattern.d.ts.map +1 -0
- package/dist/fill-style/procedural-pattern.js +135 -0
- package/dist/fill-style/procedural-pattern.js.map +1 -0
- package/dist/fill-style/shader-module.d.ts +13 -4
- package/dist/fill-style/shader-module.d.ts.map +1 -1
- package/dist/fill-style/shader-module.js +212 -21
- package/dist/fill-style/shader-module.js.map +1 -1
- package/dist/index.cjs +3484 -215
- package/dist/index.cjs.map +3 -4
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/mask/shader-module.d.ts +1 -0
- package/dist/mask/shader-module.d.ts.map +1 -1
- package/dist/path-style/path-style-extension.d.ts +49 -6
- package/dist/path-style/path-style-extension.d.ts.map +1 -1
- package/dist/path-style/path-style-extension.js +237 -37
- package/dist/path-style/path-style-extension.js.map +1 -1
- package/dist/path-style/shaders.glsl.d.ts +30 -1
- package/dist/path-style/shaders.glsl.d.ts.map +1 -1
- package/dist/path-style/shaders.glsl.js +136 -21
- package/dist/path-style/shaders.glsl.js.map +1 -1
- package/dist/terrain/shader-module.d.ts +17 -2
- package/dist/terrain/shader-module.d.ts.map +1 -1
- package/dist/utils/debug.d.ts.map +1 -1
- package/dist.min.js +1251 -96
- package/package.json +6 -6
- package/src/clip/clip-extension.ts +15 -1
- package/src/fill-style/fill-style-extension.ts +135 -13
- package/src/fill-style/procedural-pattern.ts +203 -0
- package/src/fill-style/shader-module.ts +233 -23
- package/src/index.ts +10 -1
- package/src/path-style/path-style-extension.ts +350 -44
- package/src/path-style/shaders.glsl.ts +268 -27
package/dist/index.cjs
CHANGED
|
@@ -15,11 +15,11 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
15
|
}
|
|
16
16
|
return to;
|
|
17
17
|
};
|
|
18
|
-
var __toCommonJS = (
|
|
18
|
+
var __toCommonJS = (mod2) => __copyProps(__defProp({}, "__esModule", { value: true }), mod2);
|
|
19
19
|
|
|
20
20
|
// dist/index.js
|
|
21
|
-
var
|
|
22
|
-
__export(
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
23
|
BrushingExtension: () => brushing_extension_default,
|
|
24
24
|
ClipExtension: () => clip_extension_default,
|
|
25
25
|
CollisionFilterExtension: () => collision_filter_extension_default,
|
|
@@ -31,13 +31,2642 @@ __export(dist_exports, {
|
|
|
31
31
|
_TerrainExtension: () => terrain_extension_default,
|
|
32
32
|
project64: () => project64_default
|
|
33
33
|
});
|
|
34
|
-
module.exports = __toCommonJS(
|
|
34
|
+
module.exports = __toCommonJS(index_exports);
|
|
35
35
|
|
|
36
|
-
//
|
|
37
|
-
var
|
|
36
|
+
// ../core/src/utils/log.ts
|
|
37
|
+
var import_log = require("@probe.gl/log");
|
|
38
|
+
var defaultLogger = new import_log.Log({ id: "deck" });
|
|
39
|
+
var log_default = defaultLogger;
|
|
40
|
+
|
|
41
|
+
// ../core/src/shaderlib/index.ts
|
|
42
|
+
var import_shadertools2 = require("@luma.gl/shadertools");
|
|
43
|
+
|
|
44
|
+
// ../core/src/shaderlib/misc/geometry.ts
|
|
45
|
+
var source = (
|
|
46
|
+
/* wgsl */
|
|
47
|
+
`const SMOOTH_EDGE_RADIUS: f32 = 0.5;
|
|
48
|
+
|
|
49
|
+
struct VertexGeometry {
|
|
50
|
+
position: vec4<f32>,
|
|
51
|
+
worldPosition: vec3<f32>,
|
|
52
|
+
worldPositionAlt: vec3<f32>,
|
|
53
|
+
normal: vec3<f32>,
|
|
54
|
+
uv: vec2<f32>,
|
|
55
|
+
pickingColor: vec3<f32>,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
var<private> geometry_: VertexGeometry = VertexGeometry(
|
|
59
|
+
vec4<f32>(0.0, 0.0, 1.0, 0.0),
|
|
60
|
+
vec3<f32>(0.0, 0.0, 0.0),
|
|
61
|
+
vec3<f32>(0.0, 0.0, 0.0),
|
|
62
|
+
vec3<f32>(0.0, 0.0, 0.0),
|
|
63
|
+
vec2<f32>(0.0, 0.0),
|
|
64
|
+
vec3<f32>(0.0, 0.0, 0.0)
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
struct FragmentGeometry {
|
|
68
|
+
uv: vec2<f32>,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
var<private> fragmentGeometry: FragmentGeometry;
|
|
72
|
+
|
|
73
|
+
fn smoothedge(edge: f32, x: f32) -> f32 {
|
|
74
|
+
return smoothstep(edge - SMOOTH_EDGE_RADIUS, edge + SMOOTH_EDGE_RADIUS, x);
|
|
75
|
+
}
|
|
76
|
+
`
|
|
77
|
+
);
|
|
78
|
+
var defines = "#define SMOOTH_EDGE_RADIUS 0.5";
|
|
79
|
+
var vs = (
|
|
80
|
+
/* glsl */
|
|
81
|
+
`${defines}
|
|
82
|
+
|
|
83
|
+
struct VertexGeometry {
|
|
84
|
+
vec4 position;
|
|
85
|
+
vec3 worldPosition;
|
|
86
|
+
vec3 worldPositionAlt;
|
|
87
|
+
vec3 normal;
|
|
88
|
+
vec2 uv;
|
|
89
|
+
vec3 pickingColor;
|
|
90
|
+
} geometry = VertexGeometry(
|
|
91
|
+
vec4(0.0, 0.0, 1.0, 0.0),
|
|
92
|
+
vec3(0.0),
|
|
93
|
+
vec3(0.0),
|
|
94
|
+
vec3(0.0),
|
|
95
|
+
vec2(0.0),
|
|
96
|
+
vec3(0.0)
|
|
97
|
+
);
|
|
98
|
+
`
|
|
99
|
+
);
|
|
100
|
+
var fs = (
|
|
101
|
+
/* glsl */
|
|
102
|
+
`${defines}
|
|
103
|
+
|
|
104
|
+
struct FragmentGeometry {
|
|
105
|
+
vec2 uv;
|
|
106
|
+
};
|
|
107
|
+
FragmentGeometry geometry;
|
|
108
|
+
|
|
109
|
+
float smoothedge(float edge, float x) {
|
|
110
|
+
return smoothstep(edge - SMOOTH_EDGE_RADIUS, edge + SMOOTH_EDGE_RADIUS, x);
|
|
111
|
+
}
|
|
112
|
+
`
|
|
113
|
+
);
|
|
114
|
+
var geometry_default = {
|
|
115
|
+
name: "geometry",
|
|
116
|
+
source,
|
|
117
|
+
vs,
|
|
118
|
+
fs
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// ../core/src/shaderlib/project/project.ts
|
|
122
|
+
var import_shadertools = require("@luma.gl/shadertools");
|
|
123
|
+
|
|
124
|
+
// ../core/src/shaderlib/project/viewport-uniforms.ts
|
|
125
|
+
var import_core = require("@math.gl/core");
|
|
126
|
+
|
|
127
|
+
// ../core/src/lib/constants.ts
|
|
128
|
+
var import_mjolnir = require("mjolnir.js");
|
|
129
|
+
var COORDINATE_SYSTEM = {
|
|
130
|
+
/**
|
|
131
|
+
* `LNGLAT` if rendering into a geospatial viewport, `CARTESIAN` otherwise
|
|
132
|
+
*/
|
|
133
|
+
DEFAULT: "default",
|
|
134
|
+
/**
|
|
135
|
+
* Positions are interpreted as [longitude, latitude, elevation]
|
|
136
|
+
* longitude/latitude are in degrees, elevation is in meters.
|
|
137
|
+
* Dimensions are in meters.
|
|
138
|
+
*/
|
|
139
|
+
LNGLAT: "lnglat",
|
|
140
|
+
/**
|
|
141
|
+
* Positions are interpreted as [x, y, z] in meter offsets from the coordinate origin.
|
|
142
|
+
* Dimensions are in meters.
|
|
143
|
+
*/
|
|
144
|
+
METER_OFFSETS: "meter-offsets",
|
|
145
|
+
/**
|
|
146
|
+
* Positions are interpreted as [deltaLng, deltaLat, elevation] from the coordinate origin.
|
|
147
|
+
* deltaLng/deltaLat are in degrees, elevation is in meters.
|
|
148
|
+
* Dimensions are in meters.
|
|
149
|
+
*/
|
|
150
|
+
LNGLAT_OFFSETS: "lnglat-offsets",
|
|
151
|
+
/**
|
|
152
|
+
* Positions and dimensions are in the common units of the viewport.
|
|
153
|
+
*/
|
|
154
|
+
CARTESIAN: "cartesian"
|
|
155
|
+
};
|
|
156
|
+
Object.defineProperty(COORDINATE_SYSTEM, "IDENTITY", {
|
|
157
|
+
get: () => {
|
|
158
|
+
log_default.deprecated("COORDINATE_SYSTEM.IDENTITY", "COORDINATE_SYSTEM.CARTESIAN")();
|
|
159
|
+
return COORDINATE_SYSTEM.CARTESIAN;
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
var PROJECTION_MODE = {
|
|
163
|
+
/**
|
|
164
|
+
* Render geospatial data in Web Mercator projection
|
|
165
|
+
*/
|
|
166
|
+
WEB_MERCATOR: 1,
|
|
167
|
+
/**
|
|
168
|
+
* Render geospatial data as a 3D globe
|
|
169
|
+
*/
|
|
170
|
+
GLOBE: 2,
|
|
171
|
+
/**
|
|
172
|
+
* (Internal use only) Web Mercator projection at high zoom
|
|
173
|
+
*/
|
|
174
|
+
WEB_MERCATOR_AUTO_OFFSET: 4,
|
|
175
|
+
/**
|
|
176
|
+
* No transformation
|
|
177
|
+
*/
|
|
178
|
+
IDENTITY: 0
|
|
179
|
+
};
|
|
180
|
+
var UNIT = {
|
|
181
|
+
common: 0,
|
|
182
|
+
meters: 1,
|
|
183
|
+
pixels: 2
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// ../core/src/utils/memoize.ts
|
|
187
|
+
function isEqual(a, b) {
|
|
188
|
+
if (a === b) {
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
if (Array.isArray(a)) {
|
|
192
|
+
const len = a.length;
|
|
193
|
+
if (!b || b.length !== len) {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
for (let i = 0; i < len; i++) {
|
|
197
|
+
if (a[i] !== b[i]) {
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
function memoize(compute) {
|
|
206
|
+
let cachedArgs = {};
|
|
207
|
+
let cachedResult;
|
|
208
|
+
return (args) => {
|
|
209
|
+
for (const key in args) {
|
|
210
|
+
if (!isEqual(args[key], cachedArgs[key])) {
|
|
211
|
+
cachedResult = compute(args);
|
|
212
|
+
cachedArgs = args;
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return cachedResult;
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// ../core/src/shaderlib/project/viewport-uniforms.ts
|
|
221
|
+
var ZERO_VECTOR = [0, 0, 0, 0];
|
|
222
|
+
var VECTOR_TO_POINT_MATRIX = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0];
|
|
223
|
+
var IDENTITY_MATRIX = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
|
|
224
|
+
var DEFAULT_PIXELS_PER_UNIT2 = [0, 0, 0];
|
|
225
|
+
var DEFAULT_COORDINATE_ORIGIN = [0, 0, 0];
|
|
226
|
+
var COORDINATE_SYSTEM_NUMBERS = {
|
|
227
|
+
default: -1,
|
|
228
|
+
cartesian: 0,
|
|
229
|
+
lnglat: 1,
|
|
230
|
+
"meter-offsets": 2,
|
|
231
|
+
"lnglat-offsets": 3
|
|
232
|
+
};
|
|
233
|
+
function getShaderCoordinateSystem(coordinateSystem) {
|
|
234
|
+
const shaderCoordinateSystem = COORDINATE_SYSTEM_NUMBERS[coordinateSystem];
|
|
235
|
+
if (shaderCoordinateSystem === void 0) {
|
|
236
|
+
throw new Error(`Invalid coordinateSystem: ${coordinateSystem}`);
|
|
237
|
+
}
|
|
238
|
+
return shaderCoordinateSystem;
|
|
239
|
+
}
|
|
240
|
+
var getMemoizedViewportUniforms = memoize(calculateViewportUniforms);
|
|
241
|
+
function getOffsetOrigin(viewport, coordinateSystem, coordinateOrigin = DEFAULT_COORDINATE_ORIGIN) {
|
|
242
|
+
if (coordinateOrigin.length < 3) {
|
|
243
|
+
coordinateOrigin = [coordinateOrigin[0], coordinateOrigin[1], 0];
|
|
244
|
+
}
|
|
245
|
+
let shaderCoordinateOrigin = coordinateOrigin;
|
|
246
|
+
let geospatialOrigin;
|
|
247
|
+
let offsetMode = true;
|
|
248
|
+
if (coordinateSystem === "lnglat-offsets" || coordinateSystem === "meter-offsets") {
|
|
249
|
+
geospatialOrigin = coordinateOrigin;
|
|
250
|
+
} else {
|
|
251
|
+
geospatialOrigin = viewport.isGeospatial ? (
|
|
252
|
+
// @ts-expect-error longitude and latitude are not defined on the base Viewport, but is expected on geospatial viewports
|
|
253
|
+
[Math.fround(viewport.longitude), Math.fround(viewport.latitude), 0]
|
|
254
|
+
) : null;
|
|
255
|
+
}
|
|
256
|
+
switch (viewport.projectionMode) {
|
|
257
|
+
case PROJECTION_MODE.WEB_MERCATOR:
|
|
258
|
+
if (coordinateSystem === "lnglat" || coordinateSystem === "cartesian") {
|
|
259
|
+
geospatialOrigin = [0, 0, 0];
|
|
260
|
+
offsetMode = false;
|
|
261
|
+
}
|
|
262
|
+
break;
|
|
263
|
+
case PROJECTION_MODE.WEB_MERCATOR_AUTO_OFFSET:
|
|
264
|
+
if (coordinateSystem === "lnglat") {
|
|
265
|
+
shaderCoordinateOrigin = geospatialOrigin;
|
|
266
|
+
} else if (coordinateSystem === "cartesian") {
|
|
267
|
+
shaderCoordinateOrigin = [
|
|
268
|
+
Math.fround(viewport.center[0]),
|
|
269
|
+
Math.fround(viewport.center[1]),
|
|
270
|
+
0
|
|
271
|
+
];
|
|
272
|
+
geospatialOrigin = viewport.unprojectPosition(shaderCoordinateOrigin);
|
|
273
|
+
shaderCoordinateOrigin[0] -= coordinateOrigin[0];
|
|
274
|
+
shaderCoordinateOrigin[1] -= coordinateOrigin[1];
|
|
275
|
+
shaderCoordinateOrigin[2] -= coordinateOrigin[2];
|
|
276
|
+
}
|
|
277
|
+
break;
|
|
278
|
+
case PROJECTION_MODE.IDENTITY:
|
|
279
|
+
shaderCoordinateOrigin = viewport.position.map(Math.fround);
|
|
280
|
+
shaderCoordinateOrigin[2] = shaderCoordinateOrigin[2] || 0;
|
|
281
|
+
break;
|
|
282
|
+
case PROJECTION_MODE.GLOBE:
|
|
283
|
+
offsetMode = false;
|
|
284
|
+
geospatialOrigin = null;
|
|
285
|
+
break;
|
|
286
|
+
default:
|
|
287
|
+
offsetMode = false;
|
|
288
|
+
}
|
|
289
|
+
return { geospatialOrigin, shaderCoordinateOrigin, offsetMode };
|
|
290
|
+
}
|
|
291
|
+
function calculateMatrixAndOffset(viewport, coordinateSystem, coordinateOrigin) {
|
|
292
|
+
const { viewMatrixUncentered, projectionMatrix } = viewport;
|
|
293
|
+
let { viewMatrix: viewMatrix2, viewProjectionMatrix } = viewport;
|
|
294
|
+
let projectionCenter = ZERO_VECTOR;
|
|
295
|
+
let originCommon = ZERO_VECTOR;
|
|
296
|
+
let cameraPosCommon = viewport.cameraPosition;
|
|
297
|
+
const { geospatialOrigin, shaderCoordinateOrigin, offsetMode } = getOffsetOrigin(
|
|
298
|
+
viewport,
|
|
299
|
+
coordinateSystem,
|
|
300
|
+
coordinateOrigin
|
|
301
|
+
);
|
|
302
|
+
if (offsetMode) {
|
|
303
|
+
originCommon = viewport.projectPosition(geospatialOrigin || shaderCoordinateOrigin);
|
|
304
|
+
cameraPosCommon = [
|
|
305
|
+
cameraPosCommon[0] - originCommon[0],
|
|
306
|
+
cameraPosCommon[1] - originCommon[1],
|
|
307
|
+
cameraPosCommon[2] - originCommon[2]
|
|
308
|
+
];
|
|
309
|
+
originCommon[3] = 1;
|
|
310
|
+
projectionCenter = import_core.vec4.transformMat4([], originCommon, viewProjectionMatrix);
|
|
311
|
+
viewMatrix2 = viewMatrixUncentered || viewMatrix2;
|
|
312
|
+
viewProjectionMatrix = import_core.mat4.multiply([], projectionMatrix, viewMatrix2);
|
|
313
|
+
viewProjectionMatrix = import_core.mat4.multiply([], viewProjectionMatrix, VECTOR_TO_POINT_MATRIX);
|
|
314
|
+
}
|
|
315
|
+
return {
|
|
316
|
+
viewMatrix: viewMatrix2,
|
|
317
|
+
viewProjectionMatrix,
|
|
318
|
+
projectionCenter,
|
|
319
|
+
originCommon,
|
|
320
|
+
cameraPosCommon,
|
|
321
|
+
shaderCoordinateOrigin,
|
|
322
|
+
geospatialOrigin
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
function getUniformsFromViewport({
|
|
326
|
+
viewport,
|
|
327
|
+
devicePixelRatio = 1,
|
|
328
|
+
modelMatrix = null,
|
|
329
|
+
// Match Layer.defaultProps
|
|
330
|
+
coordinateSystem = "default",
|
|
331
|
+
coordinateOrigin = DEFAULT_COORDINATE_ORIGIN,
|
|
332
|
+
autoWrapLongitude = false
|
|
333
|
+
}) {
|
|
334
|
+
if (coordinateSystem === "default") {
|
|
335
|
+
coordinateSystem = viewport.isGeospatial ? "lnglat" : "cartesian";
|
|
336
|
+
}
|
|
337
|
+
const uniforms = getMemoizedViewportUniforms({
|
|
338
|
+
viewport,
|
|
339
|
+
devicePixelRatio,
|
|
340
|
+
coordinateSystem,
|
|
341
|
+
coordinateOrigin
|
|
342
|
+
});
|
|
343
|
+
uniforms.wrapLongitude = autoWrapLongitude;
|
|
344
|
+
uniforms.modelMatrix = modelMatrix || IDENTITY_MATRIX;
|
|
345
|
+
return uniforms;
|
|
346
|
+
}
|
|
347
|
+
function calculateViewportUniforms({
|
|
348
|
+
viewport,
|
|
349
|
+
devicePixelRatio,
|
|
350
|
+
coordinateSystem,
|
|
351
|
+
coordinateOrigin
|
|
352
|
+
}) {
|
|
353
|
+
const {
|
|
354
|
+
projectionCenter,
|
|
355
|
+
viewProjectionMatrix,
|
|
356
|
+
originCommon,
|
|
357
|
+
cameraPosCommon,
|
|
358
|
+
shaderCoordinateOrigin,
|
|
359
|
+
geospatialOrigin
|
|
360
|
+
} = calculateMatrixAndOffset(viewport, coordinateSystem, coordinateOrigin);
|
|
361
|
+
const distanceScales = viewport.getDistanceScales();
|
|
362
|
+
const viewportSize = [
|
|
363
|
+
viewport.width * devicePixelRatio,
|
|
364
|
+
viewport.height * devicePixelRatio
|
|
365
|
+
];
|
|
366
|
+
const focalDistance = import_core.vec4.transformMat4([], [0, 0, -viewport.focalDistance, 1], viewport.projectionMatrix)[3] || 1;
|
|
367
|
+
const uniforms = {
|
|
368
|
+
// Projection mode values
|
|
369
|
+
coordinateSystem: getShaderCoordinateSystem(coordinateSystem),
|
|
370
|
+
projectionMode: viewport.projectionMode,
|
|
371
|
+
coordinateOrigin: shaderCoordinateOrigin,
|
|
372
|
+
commonOrigin: originCommon.slice(0, 3),
|
|
373
|
+
center: projectionCenter,
|
|
374
|
+
// Backward compatibility
|
|
375
|
+
// TODO: remove in v9
|
|
376
|
+
// @ts-expect-error _pseudoMeters is only defined on WebMercator viewport
|
|
377
|
+
pseudoMeters: Boolean(viewport._pseudoMeters),
|
|
378
|
+
// Screen size
|
|
379
|
+
viewportSize,
|
|
380
|
+
devicePixelRatio,
|
|
381
|
+
focalDistance,
|
|
382
|
+
commonUnitsPerMeter: distanceScales.unitsPerMeter,
|
|
383
|
+
commonUnitsPerWorldUnit: distanceScales.unitsPerMeter,
|
|
384
|
+
commonUnitsPerWorldUnit2: DEFAULT_PIXELS_PER_UNIT2,
|
|
385
|
+
scale: viewport.scale,
|
|
386
|
+
// This is the mercator scale (2 ** zoom)
|
|
387
|
+
wrapLongitude: false,
|
|
388
|
+
viewProjectionMatrix,
|
|
389
|
+
modelMatrix: IDENTITY_MATRIX,
|
|
390
|
+
// This is for lighting calculations
|
|
391
|
+
cameraPosition: cameraPosCommon
|
|
392
|
+
};
|
|
393
|
+
if (geospatialOrigin) {
|
|
394
|
+
const distanceScalesAtOrigin = viewport.getDistanceScales(geospatialOrigin);
|
|
395
|
+
switch (coordinateSystem) {
|
|
396
|
+
case "meter-offsets":
|
|
397
|
+
uniforms.commonUnitsPerWorldUnit = distanceScalesAtOrigin.unitsPerMeter;
|
|
398
|
+
uniforms.commonUnitsPerWorldUnit2 = distanceScalesAtOrigin.unitsPerMeter2;
|
|
399
|
+
break;
|
|
400
|
+
case "lnglat":
|
|
401
|
+
case "lnglat-offsets":
|
|
402
|
+
if (!viewport._pseudoMeters) {
|
|
403
|
+
uniforms.commonUnitsPerMeter = distanceScalesAtOrigin.unitsPerMeter;
|
|
404
|
+
}
|
|
405
|
+
uniforms.commonUnitsPerWorldUnit = distanceScalesAtOrigin.unitsPerDegree;
|
|
406
|
+
uniforms.commonUnitsPerWorldUnit2 = distanceScalesAtOrigin.unitsPerDegree2;
|
|
407
|
+
break;
|
|
408
|
+
// a.k.a "preprojected" positions
|
|
409
|
+
case "cartesian":
|
|
410
|
+
uniforms.commonUnitsPerWorldUnit = [1, 1, distanceScalesAtOrigin.unitsPerMeter[2]];
|
|
411
|
+
uniforms.commonUnitsPerWorldUnit2 = [0, 0, distanceScalesAtOrigin.unitsPerMeter2[2]];
|
|
412
|
+
break;
|
|
413
|
+
default:
|
|
414
|
+
break;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
if (viewport.projectionMode === PROJECTION_MODE.GLOBE && coordinateSystem === "meter-offsets") {
|
|
418
|
+
const EARTH_RADIUS2 = 6370972;
|
|
419
|
+
const GLOBE_RADIUS2 = 256;
|
|
420
|
+
const lambda = coordinateOrigin[0] * Math.PI / 180;
|
|
421
|
+
const phi = coordinateOrigin[1] * Math.PI / 180;
|
|
422
|
+
const cosPhi = Math.cos(phi);
|
|
423
|
+
const D = ((coordinateOrigin[2] || 0) / EARTH_RADIUS2 + 1) * GLOBE_RADIUS2;
|
|
424
|
+
uniforms.commonOrigin = [
|
|
425
|
+
Math.sin(lambda) * cosPhi * D,
|
|
426
|
+
-Math.cos(lambda) * cosPhi * D,
|
|
427
|
+
Math.sin(phi) * D
|
|
428
|
+
];
|
|
429
|
+
}
|
|
430
|
+
return uniforms;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// ../core/src/shaderlib/project/project.wgsl.ts
|
|
434
|
+
var SHADER_COORDINATE_SYSTEMS = [
|
|
435
|
+
"default",
|
|
436
|
+
"lnglat",
|
|
437
|
+
"meter-offsets",
|
|
438
|
+
"lnglat-offsets",
|
|
439
|
+
"cartesian"
|
|
440
|
+
];
|
|
441
|
+
var COORDINATE_SYSTEM_WGSL_CONSTANTS = SHADER_COORDINATE_SYSTEMS.map(
|
|
442
|
+
(coordinateSystem) => `const COORDINATE_SYSTEM_${coordinateSystem.toUpperCase().replaceAll("-", "_")}: i32 = ${getShaderCoordinateSystem(coordinateSystem)};`
|
|
443
|
+
).join("");
|
|
444
|
+
var PROJECTION_MODE_WGSL_CONSTANTS = Object.keys(PROJECTION_MODE).map((key) => `const PROJECTION_MODE_${key}: i32 = ${PROJECTION_MODE[key]};`).join("");
|
|
445
|
+
var UNIT_WGSL_CONSTANTS = Object.keys(UNIT).map((key) => `const UNIT_${key.toUpperCase()}: i32 = ${UNIT[key]};`).join("");
|
|
446
|
+
var projectWGSLHeader = (
|
|
447
|
+
/* wgsl */
|
|
448
|
+
`${COORDINATE_SYSTEM_WGSL_CONSTANTS}
|
|
449
|
+
${PROJECTION_MODE_WGSL_CONSTANTS}
|
|
450
|
+
${UNIT_WGSL_CONSTANTS}
|
|
451
|
+
|
|
452
|
+
const TILE_SIZE: f32 = 512.0;
|
|
453
|
+
const PI: f32 = 3.1415926536;
|
|
454
|
+
const WORLD_SCALE: f32 = TILE_SIZE / (PI * 2.0);
|
|
455
|
+
const ZERO_64_LOW: vec3<f32> = vec3<f32>(0.0, 0.0, 0.0);
|
|
456
|
+
const EARTH_RADIUS: f32 = 6370972.0; // meters
|
|
457
|
+
const GLOBE_RADIUS: f32 = 256.0;
|
|
458
|
+
|
|
459
|
+
// -----------------------------------------------------------------------------
|
|
460
|
+
// Uniform block (converted from GLSL uniform block)
|
|
461
|
+
// -----------------------------------------------------------------------------
|
|
462
|
+
struct ProjectUniforms {
|
|
463
|
+
wrapLongitude: i32,
|
|
464
|
+
coordinateSystem: i32,
|
|
465
|
+
commonUnitsPerMeter: vec3<f32>,
|
|
466
|
+
projectionMode: i32,
|
|
467
|
+
scale: f32,
|
|
468
|
+
commonUnitsPerWorldUnit: vec3<f32>,
|
|
469
|
+
commonUnitsPerWorldUnit2: vec3<f32>,
|
|
470
|
+
center: vec4<f32>,
|
|
471
|
+
modelMatrix: mat4x4<f32>,
|
|
472
|
+
viewProjectionMatrix: mat4x4<f32>,
|
|
473
|
+
viewportSize: vec2<f32>,
|
|
474
|
+
devicePixelRatio: f32,
|
|
475
|
+
focalDistance: f32,
|
|
476
|
+
cameraPosition: vec3<f32>,
|
|
477
|
+
coordinateOrigin: vec3<f32>,
|
|
478
|
+
commonOrigin: vec3<f32>,
|
|
479
|
+
pseudoMeters: i32,
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
@group(0) @binding(auto)
|
|
483
|
+
var<uniform> project: ProjectUniforms;
|
|
484
|
+
|
|
485
|
+
// -----------------------------------------------------------------------------
|
|
486
|
+
// Geometry data shared across the project helpers.
|
|
487
|
+
// The active layer shader is responsible for populating this private module
|
|
488
|
+
// state before calling the project functions below.
|
|
489
|
+
// -----------------------------------------------------------------------------
|
|
490
|
+
|
|
491
|
+
// Structure to carry additional geometry data used by deck.gl filters.
|
|
492
|
+
struct Geometry {
|
|
493
|
+
worldPosition: vec3<f32>,
|
|
494
|
+
worldPositionAlt: vec3<f32>,
|
|
495
|
+
position: vec4<f32>,
|
|
496
|
+
normal: vec3<f32>,
|
|
497
|
+
uv: vec2<f32>,
|
|
498
|
+
pickingColor: vec3<f32>,
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
var<private> geometry: Geometry;
|
|
502
|
+
`
|
|
503
|
+
);
|
|
504
|
+
var projectWGSL = (
|
|
505
|
+
/* wgsl */
|
|
506
|
+
`${projectWGSLHeader}
|
|
507
|
+
|
|
508
|
+
// -----------------------------------------------------------------------------
|
|
509
|
+
// Functions
|
|
510
|
+
// -----------------------------------------------------------------------------
|
|
511
|
+
|
|
512
|
+
// Returns an adjustment factor for commonUnitsPerMeter
|
|
513
|
+
fn _project_size_at_latitude(lat: f32) -> f32 {
|
|
514
|
+
let y = clamp(lat, -89.9, 89.9);
|
|
515
|
+
return 1.0 / cos(radians(y));
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// Overloaded version: scales a value in meters at a given latitude.
|
|
519
|
+
fn _project_size_at_latitude_m(meters: f32, lat: f32) -> f32 {
|
|
520
|
+
return meters * project.commonUnitsPerMeter.z * _project_size_at_latitude(lat);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// Computes a non-linear scale factor based on geometry.
|
|
524
|
+
// (Note: This function relies on "geometry" being provided.)
|
|
525
|
+
fn project_size() -> f32 {
|
|
526
|
+
if (project.projectionMode == PROJECTION_MODE_WEB_MERCATOR &&
|
|
527
|
+
project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT &&
|
|
528
|
+
project.pseudoMeters == 0) {
|
|
529
|
+
if (geometry.position.w == 0.0) {
|
|
530
|
+
return _project_size_at_latitude(geometry.worldPosition.y);
|
|
531
|
+
}
|
|
532
|
+
let y: f32 = geometry.position.y / TILE_SIZE * 2.0 - 1.0;
|
|
533
|
+
let y2 = y * y;
|
|
534
|
+
let y4 = y2 * y2;
|
|
535
|
+
let y6 = y4 * y2;
|
|
536
|
+
return 1.0 + 4.9348 * y2 + 4.0587 * y4 + 1.5642 * y6;
|
|
537
|
+
}
|
|
538
|
+
return 1.0;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// Overloads to scale offsets (meters to world units)
|
|
542
|
+
fn project_size_float(meters: f32) -> f32 {
|
|
543
|
+
return meters * project.commonUnitsPerMeter.z * project_size();
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
fn project_size_vec2(meters: vec2<f32>) -> vec2<f32> {
|
|
547
|
+
return meters * project.commonUnitsPerMeter.xy * project_size();
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
fn project_size_vec3(meters: vec3<f32>) -> vec3<f32> {
|
|
551
|
+
return meters * project.commonUnitsPerMeter * project_size();
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
fn project_size_vec4(meters: vec4<f32>) -> vec4<f32> {
|
|
555
|
+
return vec4<f32>(meters.xyz * project.commonUnitsPerMeter, meters.w);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// Returns a rotation matrix aligning the z\u2011axis with the given up vector.
|
|
559
|
+
fn project_get_orientation_matrix(up: vec3<f32>) -> mat3x3<f32> {
|
|
560
|
+
let uz = normalize(up);
|
|
561
|
+
let ux = select(
|
|
562
|
+
vec3<f32>(1.0, 0.0, 0.0),
|
|
563
|
+
normalize(vec3<f32>(uz.y, -uz.x, 0.0)),
|
|
564
|
+
abs(uz.z) == 1.0
|
|
565
|
+
);
|
|
566
|
+
let uy = cross(uz, ux);
|
|
567
|
+
return mat3x3<f32>(ux, uy, uz);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// Since WGSL does not support "out" parameters, we return a struct.
|
|
571
|
+
struct RotationResult {
|
|
572
|
+
needsRotation: bool,
|
|
573
|
+
transform: mat3x3<f32>,
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
fn project_needs_rotation(commonPosition: vec3<f32>) -> RotationResult {
|
|
577
|
+
if (project.projectionMode == PROJECTION_MODE_GLOBE) {
|
|
578
|
+
return RotationResult(true, project_get_orientation_matrix(commonPosition));
|
|
579
|
+
} else {
|
|
580
|
+
return RotationResult(false, mat3x3<f32>()); // identity alternative if needed
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// Projects a normal vector from the current coordinate system to world space.
|
|
585
|
+
fn project_normal(vector: vec3<f32>) -> vec3<f32> {
|
|
586
|
+
let normal_modelspace = project.modelMatrix * vec4<f32>(vector, 0.0);
|
|
587
|
+
var n = normalize(normal_modelspace.xyz * project.commonUnitsPerMeter);
|
|
588
|
+
let rotResult = project_needs_rotation(geometry.position.xyz);
|
|
589
|
+
if (rotResult.needsRotation) {
|
|
590
|
+
n = rotResult.transform * n;
|
|
591
|
+
}
|
|
592
|
+
return n;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// Applies a scale offset based on y-offset (dy)
|
|
596
|
+
fn project_offset_(offset: vec4<f32>) -> vec4<f32> {
|
|
597
|
+
let dy: f32 = offset.y;
|
|
598
|
+
let commonUnitsPerWorldUnit = project.commonUnitsPerWorldUnit + project.commonUnitsPerWorldUnit2 * dy;
|
|
599
|
+
return vec4<f32>(offset.xyz * commonUnitsPerWorldUnit, offset.w);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// Projects lng/lat coordinates to a unit tile [0,1]
|
|
603
|
+
fn project_mercator_(lnglat: vec2<f32>) -> vec2<f32> {
|
|
604
|
+
var x = lnglat.x;
|
|
605
|
+
if (project.wrapLongitude != 0) {
|
|
606
|
+
x = ((x + 180.0) % 360.0) - 180.0;
|
|
607
|
+
}
|
|
608
|
+
let y = clamp(lnglat.y, -89.9, 89.9);
|
|
609
|
+
return vec2<f32>(
|
|
610
|
+
radians(x) + PI,
|
|
611
|
+
PI + log(tan_fp32(PI * 0.25 + radians(y) * 0.5))
|
|
612
|
+
) * WORLD_SCALE;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// Projects lng/lat/z coordinates for a globe projection.
|
|
616
|
+
fn project_globe_(lnglatz: vec3<f32>) -> vec3<f32> {
|
|
617
|
+
let lambda = radians(lnglatz.x);
|
|
618
|
+
let phi = radians(lnglatz.y);
|
|
619
|
+
let cosPhi = cos(phi);
|
|
620
|
+
let D = (lnglatz.z / EARTH_RADIUS + 1.0) * GLOBE_RADIUS;
|
|
621
|
+
return vec3<f32>(
|
|
622
|
+
sin(lambda) * cosPhi,
|
|
623
|
+
-cos(lambda) * cosPhi,
|
|
624
|
+
sin(phi)
|
|
625
|
+
) * D;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// Projects positions (with an optional 64-bit low part) from the input
|
|
629
|
+
// coordinate system to the common space.
|
|
630
|
+
fn project_position_vec4_f64(position: vec4<f32>, position64Low: vec3<f32>) -> vec4<f32> {
|
|
631
|
+
var position_world = project.modelMatrix * position;
|
|
632
|
+
|
|
633
|
+
// Work around for a Mac+NVIDIA bug:
|
|
634
|
+
if (project.projectionMode == PROJECTION_MODE_WEB_MERCATOR) {
|
|
635
|
+
if (project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT) {
|
|
636
|
+
return vec4<f32>(
|
|
637
|
+
project_mercator_(position_world.xy),
|
|
638
|
+
_project_size_at_latitude_m(position_world.z, position_world.y),
|
|
639
|
+
position_world.w
|
|
640
|
+
);
|
|
641
|
+
}
|
|
642
|
+
if (project.coordinateSystem == COORDINATE_SYSTEM_CARTESIAN) {
|
|
643
|
+
position_world = vec4f(position_world.xyz + project.coordinateOrigin, position_world.w);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
if (project.projectionMode == PROJECTION_MODE_GLOBE) {
|
|
647
|
+
if (project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT) {
|
|
648
|
+
return vec4<f32>(
|
|
649
|
+
project_globe_(position_world.xyz),
|
|
650
|
+
position_world.w
|
|
651
|
+
);
|
|
652
|
+
}
|
|
653
|
+
if (project.coordinateSystem == COORDINATE_SYSTEM_METER_OFFSETS) {
|
|
654
|
+
let enuMatrix = project_get_orientation_matrix(project.commonOrigin);
|
|
655
|
+
let metersToCommon = GLOBE_RADIUS / EARTH_RADIUS;
|
|
656
|
+
let offsetCommon = (enuMatrix * vec3<f32>(-position_world.x, -position_world.y, position_world.z)) * metersToCommon;
|
|
657
|
+
return vec4<f32>(project.commonOrigin + offsetCommon, position_world.w);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
if (project.projectionMode == PROJECTION_MODE_WEB_MERCATOR_AUTO_OFFSET) {
|
|
661
|
+
if (project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT) {
|
|
662
|
+
if (abs(position_world.y - project.coordinateOrigin.y) > 0.25) {
|
|
663
|
+
return vec4<f32>(
|
|
664
|
+
project_mercator_(position_world.xy) - project.commonOrigin.xy,
|
|
665
|
+
project_size_float(position_world.z),
|
|
666
|
+
position_world.w
|
|
667
|
+
);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
if (project.projectionMode == PROJECTION_MODE_IDENTITY ||
|
|
672
|
+
(project.projectionMode == PROJECTION_MODE_WEB_MERCATOR_AUTO_OFFSET &&
|
|
673
|
+
(project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT ||
|
|
674
|
+
project.coordinateSystem == COORDINATE_SYSTEM_CARTESIAN))) {
|
|
675
|
+
position_world = vec4f(position_world.xyz - project.coordinateOrigin, position_world.w);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
return project_offset_(position_world) +
|
|
679
|
+
project_offset_(project.modelMatrix * vec4<f32>(position64Low, 0.0));
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// Overloaded versions for different input types.
|
|
683
|
+
fn project_position_vec4_f32(position: vec4<f32>) -> vec4<f32> {
|
|
684
|
+
return project_position_vec4_f64(position, ZERO_64_LOW);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
fn project_position_vec3_f64(position: vec3<f32>, position64Low: vec3<f32>) -> vec3<f32> {
|
|
688
|
+
let projected_position = project_position_vec4_f64(vec4<f32>(position, 1.0), position64Low);
|
|
689
|
+
return projected_position.xyz;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
fn project_position_vec3_f32(position: vec3<f32>) -> vec3<f32> {
|
|
693
|
+
let projected_position = project_position_vec4_f64(vec4<f32>(position, 1.0), ZERO_64_LOW);
|
|
694
|
+
return projected_position.xyz;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
fn project_position_vec2_f32(position: vec2<f32>) -> vec2<f32> {
|
|
698
|
+
let projected_position = project_position_vec4_f64(vec4<f32>(position, 0.0, 1.0), ZERO_64_LOW);
|
|
699
|
+
return projected_position.xy;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// Transforms a common space position to clip space.
|
|
703
|
+
fn project_common_position_to_clipspace_with_projection(position: vec4<f32>, viewProjectionMatrix: mat4x4<f32>, center: vec4<f32>) -> vec4<f32> {
|
|
704
|
+
var clipPosition = viewProjectionMatrix * position + center;
|
|
705
|
+
// deck.gl projection matrices use WebGL's [-w, w] depth range; WebGPU clips z to [0, w].
|
|
706
|
+
clipPosition.z = (clipPosition.z + clipPosition.w) * 0.5;
|
|
707
|
+
return clipPosition;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// Uses the project viewProjectionMatrix and center.
|
|
711
|
+
fn project_common_position_to_clipspace(position: vec4<f32>) -> vec4<f32> {
|
|
712
|
+
return project_common_position_to_clipspace_with_projection(position, project.viewProjectionMatrix, project.center);
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
// Returns a clip space offset corresponding to a given number of screen pixels.
|
|
716
|
+
fn project_pixel_size_to_clipspace(pixels: vec2<f32>) -> vec2<f32> {
|
|
717
|
+
let offset = pixels / project.viewportSize * project.devicePixelRatio * 2.0;
|
|
718
|
+
return offset * project.focalDistance;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
fn project_meter_size_to_pixel(meters: f32) -> f32 {
|
|
722
|
+
return project_size_float(meters) * project.scale;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
fn project_unit_size_to_pixel(size: f32, unit: i32) -> f32 {
|
|
726
|
+
if (unit == UNIT_METERS) {
|
|
727
|
+
return project_meter_size_to_pixel(size);
|
|
728
|
+
} else if (unit == UNIT_COMMON) {
|
|
729
|
+
return size * project.scale;
|
|
730
|
+
}
|
|
731
|
+
// UNIT_PIXELS: no scaling applied.
|
|
732
|
+
return size;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
fn project_pixel_size_float(pixels: f32) -> f32 {
|
|
736
|
+
return pixels / project.scale;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
fn project_pixel_size_vec2(pixels: vec2<f32>) -> vec2<f32> {
|
|
740
|
+
return pixels / project.scale;
|
|
741
|
+
}
|
|
742
|
+
`
|
|
743
|
+
);
|
|
744
|
+
|
|
745
|
+
// ../core/src/shaderlib/project/project.glsl.ts
|
|
746
|
+
var SHADER_COORDINATE_SYSTEMS2 = [
|
|
747
|
+
"default",
|
|
748
|
+
"lnglat",
|
|
749
|
+
"meter-offsets",
|
|
750
|
+
"lnglat-offsets",
|
|
751
|
+
"cartesian"
|
|
752
|
+
];
|
|
753
|
+
var COORDINATE_SYSTEM_GLSL_CONSTANTS = SHADER_COORDINATE_SYSTEMS2.map(
|
|
754
|
+
(coordinateSystem) => `const int COORDINATE_SYSTEM_${coordinateSystem.toUpperCase().replaceAll("-", "_")} = ${getShaderCoordinateSystem(coordinateSystem)};`
|
|
755
|
+
).join("");
|
|
756
|
+
var PROJECTION_MODE_GLSL_CONSTANTS = Object.keys(PROJECTION_MODE).map((key) => `const int PROJECTION_MODE_${key} = ${PROJECTION_MODE[key]};`).join("");
|
|
757
|
+
var UNIT_GLSL_CONSTANTS = Object.keys(UNIT).map((key) => `const int UNIT_${key.toUpperCase()} = ${UNIT[key]};`).join("");
|
|
758
|
+
var projectGLSL = (
|
|
759
|
+
/* glsl */
|
|
760
|
+
`${COORDINATE_SYSTEM_GLSL_CONSTANTS}
|
|
761
|
+
${PROJECTION_MODE_GLSL_CONSTANTS}
|
|
762
|
+
${UNIT_GLSL_CONSTANTS}
|
|
763
|
+
|
|
764
|
+
layout(std140) uniform projectUniforms {
|
|
765
|
+
bool wrapLongitude;
|
|
766
|
+
int coordinateSystem;
|
|
767
|
+
vec3 commonUnitsPerMeter;
|
|
768
|
+
int projectionMode;
|
|
769
|
+
float scale;
|
|
770
|
+
vec3 commonUnitsPerWorldUnit;
|
|
771
|
+
vec3 commonUnitsPerWorldUnit2;
|
|
772
|
+
vec4 center;
|
|
773
|
+
mat4 modelMatrix;
|
|
774
|
+
mat4 viewProjectionMatrix;
|
|
775
|
+
vec2 viewportSize;
|
|
776
|
+
float devicePixelRatio;
|
|
777
|
+
float focalDistance;
|
|
778
|
+
vec3 cameraPosition;
|
|
779
|
+
vec3 coordinateOrigin;
|
|
780
|
+
vec3 commonOrigin;
|
|
781
|
+
bool pseudoMeters;
|
|
782
|
+
} project;
|
|
783
|
+
|
|
784
|
+
|
|
785
|
+
const float TILE_SIZE = 512.0;
|
|
786
|
+
const float PI = 3.1415926536;
|
|
787
|
+
const float WORLD_SCALE = TILE_SIZE / (PI * 2.0);
|
|
788
|
+
const vec3 ZERO_64_LOW = vec3(0.0);
|
|
789
|
+
const float EARTH_RADIUS = 6370972.0; // meters
|
|
790
|
+
const float GLOBE_RADIUS = 256.0;
|
|
791
|
+
|
|
792
|
+
// returns an adjustment factor for uCommonUnitsPerMeter
|
|
793
|
+
float project_size_at_latitude(float lat) {
|
|
794
|
+
float y = clamp(lat, -89.9, 89.9);
|
|
795
|
+
return 1.0 / cos(radians(y));
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
float project_size() {
|
|
799
|
+
if (project.projectionMode == PROJECTION_MODE_WEB_MERCATOR &&
|
|
800
|
+
project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT &&
|
|
801
|
+
project.pseudoMeters == false) {
|
|
802
|
+
|
|
803
|
+
// uCommonUnitsPerMeter in low-zoom Web Mercator is non-linear
|
|
804
|
+
// Adjust by 1 / cos(latitude)
|
|
805
|
+
// If geometry.position (vertex in common space) is populated, use it
|
|
806
|
+
// Otherwise use geometry.worldPosition (anchor in world space)
|
|
807
|
+
|
|
808
|
+
if (geometry.position.w == 0.0) {
|
|
809
|
+
return project_size_at_latitude(geometry.worldPosition.y);
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
// latitude from common y: 2.0 * (atan(exp(y / TILE_SIZE * 2.0 * PI - PI)) - PI / 4.0)
|
|
813
|
+
// Taylor series of 1 / cos(latitude)
|
|
814
|
+
// Max error < 0.003
|
|
815
|
+
|
|
816
|
+
float y = geometry.position.y / TILE_SIZE * 2.0 - 1.0;
|
|
817
|
+
float y2 = y * y;
|
|
818
|
+
float y4 = y2 * y2;
|
|
819
|
+
float y6 = y4 * y2;
|
|
820
|
+
return 1.0 + 4.9348 * y2 + 4.0587 * y4 + 1.5642 * y6;
|
|
821
|
+
}
|
|
822
|
+
return 1.0;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
float project_size_at_latitude(float meters, float lat) {
|
|
826
|
+
return meters * project.commonUnitsPerMeter.z * project_size_at_latitude(lat);
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
//
|
|
830
|
+
// Scaling offsets - scales meters to "world distance"
|
|
831
|
+
// Note the scalar version of project_size is for scaling the z component only
|
|
832
|
+
//
|
|
833
|
+
float project_size(float meters) {
|
|
834
|
+
// For scatter relevant
|
|
835
|
+
return meters * project.commonUnitsPerMeter.z * project_size();
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
vec2 project_size(vec2 meters) {
|
|
839
|
+
return meters * project.commonUnitsPerMeter.xy * project_size();
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
vec3 project_size(vec3 meters) {
|
|
843
|
+
return meters * project.commonUnitsPerMeter * project_size();
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
vec4 project_size(vec4 meters) {
|
|
847
|
+
return vec4(meters.xyz * project.commonUnitsPerMeter, meters.w);
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
// Get rotation matrix that aligns the z axis with the given up vector
|
|
851
|
+
// Find 3 unit vectors ux, uy, uz that are perpendicular to each other and uz == up
|
|
852
|
+
mat3 project_get_orientation_matrix(vec3 up) {
|
|
853
|
+
vec3 uz = normalize(up);
|
|
854
|
+
// Tangent on XY plane
|
|
855
|
+
vec3 ux = abs(uz.z) == 1.0 ? vec3(1.0, 0.0, 0.0) : normalize(vec3(uz.y, -uz.x, 0));
|
|
856
|
+
vec3 uy = cross(uz, ux);
|
|
857
|
+
return mat3(ux, uy, uz);
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
bool project_needs_rotation(vec3 commonPosition, out mat3 transform) {
|
|
861
|
+
if (project.projectionMode == PROJECTION_MODE_GLOBE) {
|
|
862
|
+
transform = project_get_orientation_matrix(commonPosition);
|
|
863
|
+
return true;
|
|
864
|
+
}
|
|
865
|
+
return false;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
//
|
|
869
|
+
// Projecting normal - transform deltas from current coordinate system to
|
|
870
|
+
// normals in the worldspace
|
|
871
|
+
//
|
|
872
|
+
vec3 project_normal(vec3 vector) {
|
|
873
|
+
// Apply model matrix
|
|
874
|
+
vec4 normal_modelspace = project.modelMatrix * vec4(vector, 0.0);
|
|
875
|
+
vec3 n = normalize(normal_modelspace.xyz * project.commonUnitsPerMeter);
|
|
876
|
+
mat3 rotation;
|
|
877
|
+
if (project_needs_rotation(geometry.position.xyz, rotation)) {
|
|
878
|
+
n = rotation * n;
|
|
879
|
+
}
|
|
880
|
+
return n;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
vec4 project_offset_(vec4 offset) {
|
|
884
|
+
float dy = offset.y;
|
|
885
|
+
vec3 commonUnitsPerWorldUnit = project.commonUnitsPerWorldUnit + project.commonUnitsPerWorldUnit2 * dy;
|
|
886
|
+
return vec4(offset.xyz * commonUnitsPerWorldUnit, offset.w);
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
//
|
|
890
|
+
// Projecting positions - non-linear projection: lnglats => unit tile [0-1, 0-1]
|
|
891
|
+
//
|
|
892
|
+
vec2 project_mercator_(vec2 lnglat) {
|
|
893
|
+
float x = lnglat.x;
|
|
894
|
+
if (project.wrapLongitude) {
|
|
895
|
+
x = mod(x + 180., 360.0) - 180.;
|
|
896
|
+
}
|
|
897
|
+
float y = clamp(lnglat.y, -89.9, 89.9);
|
|
898
|
+
return vec2(
|
|
899
|
+
radians(x) + PI,
|
|
900
|
+
PI + log(tan_fp32(PI * 0.25 + radians(y) * 0.5))
|
|
901
|
+
) * WORLD_SCALE;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
vec3 project_globe_(vec3 lnglatz) {
|
|
905
|
+
float lambda = radians(lnglatz.x);
|
|
906
|
+
float phi = radians(lnglatz.y);
|
|
907
|
+
float cosPhi = cos(phi);
|
|
908
|
+
float D = (lnglatz.z / EARTH_RADIUS + 1.0) * GLOBE_RADIUS;
|
|
909
|
+
|
|
910
|
+
return vec3(
|
|
911
|
+
sin(lambda) * cosPhi,
|
|
912
|
+
-cos(lambda) * cosPhi,
|
|
913
|
+
sin(phi)
|
|
914
|
+
) * D;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
//
|
|
918
|
+
// Projects positions (defined by project.coordinateSystem) to common space (defined by project.projectionMode)
|
|
919
|
+
//
|
|
920
|
+
vec4 project_position(vec4 position, vec3 position64Low) {
|
|
921
|
+
vec4 position_world = project.modelMatrix * position;
|
|
922
|
+
|
|
923
|
+
// Work around for a Mac+NVIDIA bug https://github.com/visgl/deck.gl/issues/4145
|
|
924
|
+
if (project.projectionMode == PROJECTION_MODE_WEB_MERCATOR) {
|
|
925
|
+
if (project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT) {
|
|
926
|
+
return vec4(
|
|
927
|
+
project_mercator_(position_world.xy),
|
|
928
|
+
project_size_at_latitude(position_world.z, position_world.y),
|
|
929
|
+
position_world.w
|
|
930
|
+
);
|
|
931
|
+
}
|
|
932
|
+
if (project.coordinateSystem == COORDINATE_SYSTEM_CARTESIAN) {
|
|
933
|
+
position_world.xyz += project.coordinateOrigin;
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
if (project.projectionMode == PROJECTION_MODE_GLOBE) {
|
|
937
|
+
if (project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT) {
|
|
938
|
+
return vec4(
|
|
939
|
+
project_globe_(position_world.xyz),
|
|
940
|
+
position_world.w
|
|
941
|
+
);
|
|
942
|
+
}
|
|
943
|
+
if (project.coordinateSystem == COORDINATE_SYSTEM_METER_OFFSETS) {
|
|
944
|
+
mat3 enuMatrix = project_get_orientation_matrix(project.commonOrigin);
|
|
945
|
+
float metersToCommon = GLOBE_RADIUS / EARTH_RADIUS;
|
|
946
|
+
vec3 offsetCommon = (enuMatrix * vec3(-position_world.xy, position_world.z)) * metersToCommon;
|
|
947
|
+
return vec4(project.commonOrigin + offsetCommon, position_world.w);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
if (project.projectionMode == PROJECTION_MODE_WEB_MERCATOR_AUTO_OFFSET) {
|
|
951
|
+
if (project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT) {
|
|
952
|
+
if (abs(position_world.y - project.coordinateOrigin.y) > 0.25) {
|
|
953
|
+
// Too far from the projection center for offset mode to be accurate
|
|
954
|
+
// Only use high parts
|
|
955
|
+
return vec4(
|
|
956
|
+
project_mercator_(position_world.xy) - project.commonOrigin.xy,
|
|
957
|
+
project_size(position_world.z),
|
|
958
|
+
position_world.w
|
|
959
|
+
);
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
if (project.projectionMode == PROJECTION_MODE_IDENTITY ||
|
|
964
|
+
(project.projectionMode == PROJECTION_MODE_WEB_MERCATOR_AUTO_OFFSET &&
|
|
965
|
+
(project.coordinateSystem == COORDINATE_SYSTEM_LNGLAT ||
|
|
966
|
+
project.coordinateSystem == COORDINATE_SYSTEM_CARTESIAN))) {
|
|
967
|
+
// Subtract high part of 64 bit value. Convert remainder to float32, preserving precision.
|
|
968
|
+
position_world.xyz -= project.coordinateOrigin;
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
// Translation is already added to the high parts
|
|
972
|
+
return project_offset_(position_world) + project_offset_(project.modelMatrix * vec4(position64Low, 0.0));
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
vec4 project_position(vec4 position) {
|
|
976
|
+
return project_position(position, ZERO_64_LOW);
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
vec3 project_position(vec3 position, vec3 position64Low) {
|
|
980
|
+
vec4 projected_position = project_position(vec4(position, 1.0), position64Low);
|
|
981
|
+
return projected_position.xyz;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
vec3 project_position(vec3 position) {
|
|
985
|
+
vec4 projected_position = project_position(vec4(position, 1.0), ZERO_64_LOW);
|
|
986
|
+
return projected_position.xyz;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
vec2 project_position(vec2 position) {
|
|
990
|
+
vec4 projected_position = project_position(vec4(position, 0.0, 1.0), ZERO_64_LOW);
|
|
991
|
+
return projected_position.xy;
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
vec4 project_common_position_to_clipspace(vec4 position, mat4 viewProjectionMatrix, vec4 center) {
|
|
995
|
+
return viewProjectionMatrix * position + center;
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
//
|
|
999
|
+
// Projects from common space coordinates to clip space.
|
|
1000
|
+
// Uses project.viewProjectionMatrix
|
|
1001
|
+
//
|
|
1002
|
+
vec4 project_common_position_to_clipspace(vec4 position) {
|
|
1003
|
+
return project_common_position_to_clipspace(position, project.viewProjectionMatrix, project.center);
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
// Returns a clip space offset that corresponds to a given number of screen pixels
|
|
1007
|
+
vec2 project_pixel_size_to_clipspace(vec2 pixels) {
|
|
1008
|
+
vec2 offset = pixels / project.viewportSize * project.devicePixelRatio * 2.0;
|
|
1009
|
+
return offset * project.focalDistance;
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
float project_size_to_pixel(float meters) {
|
|
1013
|
+
return project_size(meters) * project.scale;
|
|
1014
|
+
}
|
|
1015
|
+
vec2 project_size_to_pixel(vec2 meters) {
|
|
1016
|
+
return project_size(meters) * project.scale;
|
|
1017
|
+
}
|
|
1018
|
+
float project_size_to_pixel(float size, int unit) {
|
|
1019
|
+
if (unit == UNIT_METERS) return project_size_to_pixel(size);
|
|
1020
|
+
if (unit == UNIT_COMMON) return size * project.scale;
|
|
1021
|
+
// UNIT_PIXELS
|
|
1022
|
+
return size;
|
|
1023
|
+
}
|
|
1024
|
+
float project_pixel_size(float pixels) {
|
|
1025
|
+
return pixels / project.scale;
|
|
1026
|
+
}
|
|
1027
|
+
vec2 project_pixel_size(vec2 pixels) {
|
|
1028
|
+
return pixels / project.scale;
|
|
1029
|
+
}
|
|
1030
|
+
`
|
|
1031
|
+
);
|
|
1032
|
+
|
|
1033
|
+
// ../core/src/shaderlib/project/project.ts
|
|
1034
|
+
var INITIAL_MODULE_OPTIONS = {};
|
|
1035
|
+
function getUniforms(opts = INITIAL_MODULE_OPTIONS) {
|
|
1036
|
+
if ("viewport" in opts) {
|
|
1037
|
+
return getUniformsFromViewport(opts);
|
|
1038
|
+
}
|
|
1039
|
+
return {};
|
|
1040
|
+
}
|
|
1041
|
+
var project_default = {
|
|
1042
|
+
name: "project",
|
|
1043
|
+
dependencies: [import_shadertools.fp32, geometry_default],
|
|
1044
|
+
source: projectWGSL,
|
|
1045
|
+
vs: projectGLSL,
|
|
1046
|
+
getUniforms,
|
|
1047
|
+
uniformTypes: {
|
|
1048
|
+
wrapLongitude: "f32",
|
|
1049
|
+
coordinateSystem: "i32",
|
|
1050
|
+
commonUnitsPerMeter: "vec3<f32>",
|
|
1051
|
+
projectionMode: "i32",
|
|
1052
|
+
scale: "f32",
|
|
1053
|
+
commonUnitsPerWorldUnit: "vec3<f32>",
|
|
1054
|
+
commonUnitsPerWorldUnit2: "vec3<f32>",
|
|
1055
|
+
center: "vec4<f32>",
|
|
1056
|
+
modelMatrix: "mat4x4<f32>",
|
|
1057
|
+
viewProjectionMatrix: "mat4x4<f32>",
|
|
1058
|
+
viewportSize: "vec2<f32>",
|
|
1059
|
+
devicePixelRatio: "f32",
|
|
1060
|
+
focalDistance: "f32",
|
|
1061
|
+
cameraPosition: "vec3<f32>",
|
|
1062
|
+
coordinateOrigin: "vec3<f32>",
|
|
1063
|
+
commonOrigin: "vec3<f32>",
|
|
1064
|
+
pseudoMeters: "f32"
|
|
1065
|
+
}
|
|
1066
|
+
// @ts-ignore TODO v9.1
|
|
1067
|
+
};
|
|
1068
|
+
|
|
1069
|
+
// ../core/src/passes/pass.ts
|
|
1070
|
+
var Pass = class {
|
|
1071
|
+
/** Create a new Pass instance */
|
|
1072
|
+
constructor(device, props = { id: "pass" }) {
|
|
1073
|
+
const { id } = props;
|
|
1074
|
+
this.id = id;
|
|
1075
|
+
this.device = device;
|
|
1076
|
+
this.props = { ...props };
|
|
1077
|
+
}
|
|
1078
|
+
setProps(props) {
|
|
1079
|
+
Object.assign(this.props, props);
|
|
1080
|
+
}
|
|
1081
|
+
render(params) {
|
|
1082
|
+
}
|
|
1083
|
+
// eslint-disable-line @typescript-eslint/no-empty-function
|
|
1084
|
+
cleanup() {
|
|
1085
|
+
}
|
|
1086
|
+
// eslint-disable-line @typescript-eslint/no-empty-function
|
|
1087
|
+
};
|
|
1088
|
+
|
|
1089
|
+
// ../core/src/passes/layers-pass.ts
|
|
1090
|
+
var WEBGPU_DEFAULT_DRAW_PARAMETERS = {
|
|
1091
|
+
depthWriteEnabled: true,
|
|
1092
|
+
depthCompare: "less-equal",
|
|
1093
|
+
blendColorOperation: "add",
|
|
1094
|
+
blendColorSrcFactor: "one",
|
|
1095
|
+
blendColorDstFactor: "one-minus-src-alpha",
|
|
1096
|
+
blendAlphaOperation: "add",
|
|
1097
|
+
blendAlphaSrcFactor: "one",
|
|
1098
|
+
blendAlphaDstFactor: "one-minus-src-alpha"
|
|
1099
|
+
};
|
|
1100
|
+
var LayersPass = class extends Pass {
|
|
1101
|
+
constructor() {
|
|
1102
|
+
super(...arguments);
|
|
1103
|
+
this._lastRenderIndex = -1;
|
|
1104
|
+
}
|
|
1105
|
+
render(options) {
|
|
1106
|
+
this._render(options);
|
|
1107
|
+
}
|
|
1108
|
+
_render(options) {
|
|
1109
|
+
const { canvasContext = this.device.canvasContext } = options;
|
|
1110
|
+
const framebuffer = options.target ?? canvasContext.getCurrentFramebuffer();
|
|
1111
|
+
const [width, height] = canvasContext.getDrawingBufferSize();
|
|
1112
|
+
const clearCanvas = options.clearCanvas ?? true;
|
|
1113
|
+
let clearColor = options.clearColor ?? (clearCanvas ? [0, 0, 0, 0] : false);
|
|
1114
|
+
let clearDepth = clearCanvas ? 1 : false;
|
|
1115
|
+
let clearStencil = clearCanvas ? 0 : false;
|
|
1116
|
+
const colorMask = options.colorMask ?? 15;
|
|
1117
|
+
const parameters2 = { viewport: [0, 0, width, height] };
|
|
1118
|
+
if (options.colorMask) {
|
|
1119
|
+
parameters2.colorMask = colorMask;
|
|
1120
|
+
}
|
|
1121
|
+
if (options.scissorRect) {
|
|
1122
|
+
parameters2.scissorRect = options.scissorRect;
|
|
1123
|
+
}
|
|
1124
|
+
const { shaderModuleProps, viewports, views, onViewportActive, clearStack = true } = options;
|
|
1125
|
+
const pass = options.pass || "unknown";
|
|
1126
|
+
const submitEachRenderPass = this.device.type === "webgpu";
|
|
1127
|
+
if (clearStack) {
|
|
1128
|
+
this._lastRenderIndex = -1;
|
|
1129
|
+
}
|
|
1130
|
+
const renderStats = [];
|
|
1131
|
+
if (!viewports.length) {
|
|
1132
|
+
const renderPass = this.device.beginRenderPass({
|
|
1133
|
+
framebuffer,
|
|
1134
|
+
parameters: parameters2,
|
|
1135
|
+
clearColor,
|
|
1136
|
+
clearDepth,
|
|
1137
|
+
clearStencil
|
|
1138
|
+
});
|
|
1139
|
+
renderPass.end();
|
|
1140
|
+
this.device.submit();
|
|
1141
|
+
return renderStats;
|
|
1142
|
+
}
|
|
1143
|
+
try {
|
|
1144
|
+
for (const viewport of viewports) {
|
|
1145
|
+
onViewportActive == null ? void 0 : onViewportActive(viewport);
|
|
1146
|
+
const drawLayerParams = this._getDrawLayerParams(viewport, options);
|
|
1147
|
+
const view = views && views[viewport.id];
|
|
1148
|
+
const subViewports = viewport.subViewports || [viewport];
|
|
1149
|
+
const renderGroups = submitEachRenderPass ? subViewports.map((subViewport) => [subViewport]) : [subViewports];
|
|
1150
|
+
for (const renderGroup of renderGroups) {
|
|
1151
|
+
const renderPass = this.device.beginRenderPass({
|
|
1152
|
+
framebuffer,
|
|
1153
|
+
parameters: parameters2,
|
|
1154
|
+
clearColor,
|
|
1155
|
+
clearDepth,
|
|
1156
|
+
clearStencil
|
|
1157
|
+
});
|
|
1158
|
+
try {
|
|
1159
|
+
for (const subViewport of renderGroup) {
|
|
1160
|
+
const stats = this._drawLayersInViewport(
|
|
1161
|
+
renderPass,
|
|
1162
|
+
{
|
|
1163
|
+
target: framebuffer,
|
|
1164
|
+
canvasContext,
|
|
1165
|
+
shaderModuleProps,
|
|
1166
|
+
viewport: subViewport,
|
|
1167
|
+
view,
|
|
1168
|
+
pass,
|
|
1169
|
+
layers: options.layers,
|
|
1170
|
+
isPicking: options.isPicking
|
|
1171
|
+
},
|
|
1172
|
+
drawLayerParams
|
|
1173
|
+
);
|
|
1174
|
+
renderStats.push(stats);
|
|
1175
|
+
}
|
|
1176
|
+
} finally {
|
|
1177
|
+
renderPass.end();
|
|
1178
|
+
if (submitEachRenderPass) {
|
|
1179
|
+
this.device.submit();
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
clearColor = false;
|
|
1183
|
+
clearDepth = false;
|
|
1184
|
+
clearStencil = false;
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
return renderStats;
|
|
1188
|
+
} finally {
|
|
1189
|
+
if (!submitEachRenderPass) {
|
|
1190
|
+
this.device.submit();
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
// When a viewport contains multiple subviewports (e.g. repeated web mercator map),
|
|
1195
|
+
// this is only done once for the parent viewport
|
|
1196
|
+
/* Resolve the parameters needed to draw each layer */
|
|
1197
|
+
_getDrawLayerParams(viewport, {
|
|
1198
|
+
layers,
|
|
1199
|
+
pass,
|
|
1200
|
+
isPicking = false,
|
|
1201
|
+
layerFilter,
|
|
1202
|
+
cullRect,
|
|
1203
|
+
views,
|
|
1204
|
+
effects,
|
|
1205
|
+
canvasContext = this.device.canvasContext,
|
|
1206
|
+
shaderModuleProps
|
|
1207
|
+
}, evaluateShouldDrawOnly = false) {
|
|
1208
|
+
var _a, _b;
|
|
1209
|
+
const drawLayerParams = [];
|
|
1210
|
+
const indexResolver = layerIndexResolver(this._lastRenderIndex + 1);
|
|
1211
|
+
const drawContext = {
|
|
1212
|
+
layer: layers[0],
|
|
1213
|
+
viewport,
|
|
1214
|
+
isPicking,
|
|
1215
|
+
renderPass: pass,
|
|
1216
|
+
cullRect
|
|
1217
|
+
};
|
|
1218
|
+
const layerFilterCache = {};
|
|
1219
|
+
for (let layerIndex = 0; layerIndex < layers.length; layerIndex++) {
|
|
1220
|
+
const layer = layers[layerIndex];
|
|
1221
|
+
const shouldDrawLayer = this._shouldDrawLayer(
|
|
1222
|
+
layer,
|
|
1223
|
+
drawContext,
|
|
1224
|
+
layerFilter,
|
|
1225
|
+
layerFilterCache
|
|
1226
|
+
);
|
|
1227
|
+
const layerParam = { shouldDrawLayer };
|
|
1228
|
+
if (shouldDrawLayer && !evaluateShouldDrawOnly) {
|
|
1229
|
+
layerParam.shouldDrawLayer = true;
|
|
1230
|
+
layerParam.layerRenderIndex = indexResolver(layer, shouldDrawLayer);
|
|
1231
|
+
layerParam.shaderModuleProps = this._getShaderModuleProps(
|
|
1232
|
+
layer,
|
|
1233
|
+
effects,
|
|
1234
|
+
pass,
|
|
1235
|
+
canvasContext,
|
|
1236
|
+
shaderModuleProps
|
|
1237
|
+
);
|
|
1238
|
+
const defaultParams = layer.context.device.type === "webgpu" ? WEBGPU_DEFAULT_DRAW_PARAMETERS : null;
|
|
1239
|
+
layerParam.layerParameters = {
|
|
1240
|
+
...defaultParams,
|
|
1241
|
+
...(_a = layer.context.deck) == null ? void 0 : _a.props.parameters,
|
|
1242
|
+
...(_b = views == null ? void 0 : views[viewport.id]) == null ? void 0 : _b.props.parameters,
|
|
1243
|
+
...this.getLayerParameters(layer, layerIndex, viewport)
|
|
1244
|
+
};
|
|
1245
|
+
}
|
|
1246
|
+
drawLayerParams[layerIndex] = layerParam;
|
|
1247
|
+
}
|
|
1248
|
+
return drawLayerParams;
|
|
1249
|
+
}
|
|
1250
|
+
// Draws a list of layers in one viewport
|
|
1251
|
+
// TODO - when picking we could completely skip rendering viewports that dont
|
|
1252
|
+
// intersect with the picking rect
|
|
1253
|
+
/* eslint-disable max-depth, max-statements, complexity */
|
|
1254
|
+
_drawLayersInViewport(renderPass, {
|
|
1255
|
+
layers,
|
|
1256
|
+
shaderModuleProps: globalModuleParameters,
|
|
1257
|
+
pass,
|
|
1258
|
+
target,
|
|
1259
|
+
canvasContext,
|
|
1260
|
+
viewport,
|
|
1261
|
+
view,
|
|
1262
|
+
isPicking
|
|
1263
|
+
}, drawLayerParams) {
|
|
1264
|
+
const glViewport = getGLViewport(this.device, {
|
|
1265
|
+
canvasContext,
|
|
1266
|
+
shaderModuleProps: globalModuleParameters,
|
|
1267
|
+
target,
|
|
1268
|
+
viewport
|
|
1269
|
+
});
|
|
1270
|
+
if (view) {
|
|
1271
|
+
const { clear, clearColor, clearDepth, clearStencil } = view.props;
|
|
1272
|
+
if (clear) {
|
|
1273
|
+
let colorToUse = [0, 0, 0, 0];
|
|
1274
|
+
let depthToUse = 1;
|
|
1275
|
+
let stencilToUse = 0;
|
|
1276
|
+
if (Array.isArray(clearColor) && !isPicking) {
|
|
1277
|
+
colorToUse = [...clearColor.slice(0, 3), clearColor[3] || 255].map(
|
|
1278
|
+
(c) => c / 255
|
|
1279
|
+
);
|
|
1280
|
+
} else if (clearColor === false) {
|
|
1281
|
+
colorToUse = false;
|
|
1282
|
+
}
|
|
1283
|
+
if (clearDepth !== void 0) {
|
|
1284
|
+
depthToUse = clearDepth;
|
|
1285
|
+
}
|
|
1286
|
+
if (clearStencil !== void 0) {
|
|
1287
|
+
stencilToUse = clearStencil;
|
|
1288
|
+
}
|
|
1289
|
+
const clearRenderPass = this.device.beginRenderPass({
|
|
1290
|
+
framebuffer: target,
|
|
1291
|
+
parameters: {
|
|
1292
|
+
viewport: glViewport,
|
|
1293
|
+
scissorRect: glViewport
|
|
1294
|
+
},
|
|
1295
|
+
clearColor: colorToUse,
|
|
1296
|
+
clearDepth: depthToUse,
|
|
1297
|
+
clearStencil: stencilToUse
|
|
1298
|
+
});
|
|
1299
|
+
clearRenderPass.end();
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
const renderStatus = {
|
|
1303
|
+
totalCount: layers.length,
|
|
1304
|
+
visibleCount: 0,
|
|
1305
|
+
compositeCount: 0,
|
|
1306
|
+
pickableCount: 0
|
|
1307
|
+
};
|
|
1308
|
+
renderPass.setParameters({ viewport: glViewport });
|
|
1309
|
+
for (let layerIndex = 0; layerIndex < layers.length; layerIndex++) {
|
|
1310
|
+
const layer = layers[layerIndex];
|
|
1311
|
+
const drawLayerParameters = drawLayerParams[layerIndex];
|
|
1312
|
+
const { shouldDrawLayer } = drawLayerParameters;
|
|
1313
|
+
if (shouldDrawLayer && layer.props.pickable) {
|
|
1314
|
+
renderStatus.pickableCount++;
|
|
1315
|
+
}
|
|
1316
|
+
if (layer.isComposite) {
|
|
1317
|
+
renderStatus.compositeCount++;
|
|
1318
|
+
}
|
|
1319
|
+
if (layer.isDrawable && drawLayerParameters.shouldDrawLayer) {
|
|
1320
|
+
const { layerRenderIndex, shaderModuleProps, layerParameters } = drawLayerParameters;
|
|
1321
|
+
renderStatus.visibleCount++;
|
|
1322
|
+
this._lastRenderIndex = Math.max(this._lastRenderIndex, layerRenderIndex);
|
|
1323
|
+
if (shaderModuleProps.project) {
|
|
1324
|
+
shaderModuleProps.project.viewport = viewport;
|
|
1325
|
+
}
|
|
1326
|
+
layer.context.renderPass = renderPass;
|
|
1327
|
+
try {
|
|
1328
|
+
layer._drawLayer({
|
|
1329
|
+
renderPass,
|
|
1330
|
+
shaderModuleProps,
|
|
1331
|
+
uniforms: { layerIndex: layerRenderIndex },
|
|
1332
|
+
parameters: layerParameters
|
|
1333
|
+
});
|
|
1334
|
+
} catch (err) {
|
|
1335
|
+
layer.raiseError(err, `drawing ${layer} to ${pass}`);
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
return renderStatus;
|
|
1340
|
+
}
|
|
1341
|
+
/* eslint-enable max-depth, max-statements */
|
|
1342
|
+
/* Methods for subclass overrides */
|
|
1343
|
+
shouldDrawLayer(layer) {
|
|
1344
|
+
return true;
|
|
1345
|
+
}
|
|
1346
|
+
getShaderModuleProps(layer, effects, otherShaderModuleProps) {
|
|
1347
|
+
return null;
|
|
1348
|
+
}
|
|
1349
|
+
getLayerParameters(layer, layerIndex, viewport) {
|
|
1350
|
+
return layer.props.parameters;
|
|
1351
|
+
}
|
|
1352
|
+
/* Private */
|
|
1353
|
+
_shouldDrawLayer(layer, drawContext, layerFilter, layerFilterCache) {
|
|
1354
|
+
const shouldDrawLayer = layer.props.visible && this.shouldDrawLayer(layer);
|
|
1355
|
+
if (!shouldDrawLayer) {
|
|
1356
|
+
return false;
|
|
1357
|
+
}
|
|
1358
|
+
drawContext.layer = layer;
|
|
1359
|
+
let parent = layer.parent;
|
|
1360
|
+
while (parent) {
|
|
1361
|
+
if (!parent.props.visible || !parent.filterSubLayer(drawContext)) {
|
|
1362
|
+
return false;
|
|
1363
|
+
}
|
|
1364
|
+
drawContext.layer = parent;
|
|
1365
|
+
parent = parent.parent;
|
|
1366
|
+
}
|
|
1367
|
+
if (layerFilter) {
|
|
1368
|
+
const rootLayerId = drawContext.layer.id;
|
|
1369
|
+
if (!(rootLayerId in layerFilterCache)) {
|
|
1370
|
+
layerFilterCache[rootLayerId] = layerFilter(drawContext);
|
|
1371
|
+
}
|
|
1372
|
+
if (!layerFilterCache[rootLayerId]) {
|
|
1373
|
+
return false;
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
layer.activateViewport(drawContext.viewport);
|
|
1377
|
+
return true;
|
|
1378
|
+
}
|
|
1379
|
+
_getShaderModuleProps(layer, effects, pass, canvasContext, overrides) {
|
|
1380
|
+
var _a, _b;
|
|
1381
|
+
const devicePixelRatio = canvasContext.cssToDeviceRatio();
|
|
1382
|
+
const layerProps = ((_a = layer.internalState) == null ? void 0 : _a.propsInTransition) || layer.props;
|
|
1383
|
+
const shaderModuleProps = {
|
|
1384
|
+
layer: layerProps,
|
|
1385
|
+
picking: {
|
|
1386
|
+
isActive: false
|
|
1387
|
+
},
|
|
1388
|
+
project: {
|
|
1389
|
+
viewport: layer.context.viewport,
|
|
1390
|
+
devicePixelRatio,
|
|
1391
|
+
modelMatrix: layerProps.modelMatrix,
|
|
1392
|
+
coordinateSystem: layerProps.coordinateSystem,
|
|
1393
|
+
coordinateOrigin: layerProps.coordinateOrigin,
|
|
1394
|
+
autoWrapLongitude: layer.wrapLongitude
|
|
1395
|
+
}
|
|
1396
|
+
};
|
|
1397
|
+
if (effects) {
|
|
1398
|
+
for (const effect of effects) {
|
|
1399
|
+
mergeModuleParameters(
|
|
1400
|
+
shaderModuleProps,
|
|
1401
|
+
(_b = effect.getShaderModuleProps) == null ? void 0 : _b.call(effect, layer, shaderModuleProps)
|
|
1402
|
+
);
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
for (const module2 of layer.context.defaultShaderModules) {
|
|
1406
|
+
if (!(module2.name in shaderModuleProps)) {
|
|
1407
|
+
shaderModuleProps[module2.name] = {};
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
return mergeModuleParameters(
|
|
1411
|
+
shaderModuleProps,
|
|
1412
|
+
this.getShaderModuleProps(layer, effects, shaderModuleProps),
|
|
1413
|
+
overrides
|
|
1414
|
+
);
|
|
1415
|
+
}
|
|
1416
|
+
};
|
|
1417
|
+
function layerIndexResolver(startIndex = 0, layerIndices = {}) {
|
|
1418
|
+
const resolvers = {};
|
|
1419
|
+
const resolveLayerIndex = (layer, isDrawn) => {
|
|
1420
|
+
const indexOverride = layer.props._offset;
|
|
1421
|
+
const layerId = layer.id;
|
|
1422
|
+
const parentId = layer.parent && layer.parent.id;
|
|
1423
|
+
let index;
|
|
1424
|
+
if (parentId && !(parentId in layerIndices)) {
|
|
1425
|
+
resolveLayerIndex(layer.parent, false);
|
|
1426
|
+
}
|
|
1427
|
+
if (parentId in resolvers) {
|
|
1428
|
+
const resolver = resolvers[parentId] = resolvers[parentId] || layerIndexResolver(layerIndices[parentId], layerIndices);
|
|
1429
|
+
index = resolver(layer, isDrawn);
|
|
1430
|
+
resolvers[layerId] = resolver;
|
|
1431
|
+
} else if (Number.isFinite(indexOverride)) {
|
|
1432
|
+
index = indexOverride + (layerIndices[parentId] || 0);
|
|
1433
|
+
resolvers[layerId] = null;
|
|
1434
|
+
} else {
|
|
1435
|
+
index = startIndex;
|
|
1436
|
+
}
|
|
1437
|
+
if (isDrawn && index >= startIndex) {
|
|
1438
|
+
startIndex = index + 1;
|
|
1439
|
+
}
|
|
1440
|
+
layerIndices[layerId] = index;
|
|
1441
|
+
return index;
|
|
1442
|
+
};
|
|
1443
|
+
return resolveLayerIndex;
|
|
1444
|
+
}
|
|
1445
|
+
function getGLViewport(device, {
|
|
1446
|
+
canvasContext = device.canvasContext,
|
|
1447
|
+
shaderModuleProps,
|
|
1448
|
+
target,
|
|
1449
|
+
viewport
|
|
1450
|
+
}) {
|
|
1451
|
+
var _a;
|
|
1452
|
+
const pixelRatio = ((_a = shaderModuleProps == null ? void 0 : shaderModuleProps.project) == null ? void 0 : _a.devicePixelRatio) ?? canvasContext.cssToDeviceRatio();
|
|
1453
|
+
const [, drawingBufferHeight] = canvasContext.getDrawingBufferSize();
|
|
1454
|
+
const height = target ? target.height : drawingBufferHeight;
|
|
1455
|
+
const dimensions = viewport;
|
|
1456
|
+
return [
|
|
1457
|
+
dimensions.x * pixelRatio,
|
|
1458
|
+
height - (dimensions.y + dimensions.height) * pixelRatio,
|
|
1459
|
+
dimensions.width * pixelRatio,
|
|
1460
|
+
dimensions.height * pixelRatio
|
|
1461
|
+
];
|
|
1462
|
+
}
|
|
1463
|
+
function mergeModuleParameters(target, ...sources) {
|
|
1464
|
+
for (const source2 of sources) {
|
|
1465
|
+
if (source2) {
|
|
1466
|
+
for (const key in source2) {
|
|
1467
|
+
if (target[key]) {
|
|
1468
|
+
Object.assign(target[key], source2[key]);
|
|
1469
|
+
} else {
|
|
1470
|
+
target[key] = source2[key];
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
return target;
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
// ../core/src/utils/math-utils.ts
|
|
1479
|
+
var import_core2 = require("@math.gl/core");
|
|
1480
|
+
function createMat4() {
|
|
1481
|
+
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
|
|
1482
|
+
}
|
|
1483
|
+
function mod(value, divisor) {
|
|
1484
|
+
const modulus = value % divisor;
|
|
1485
|
+
return modulus < 0 ? divisor + modulus : modulus;
|
|
1486
|
+
}
|
|
1487
|
+
function getCameraPosition(viewMatrixInverse) {
|
|
1488
|
+
return [viewMatrixInverse[12], viewMatrixInverse[13], viewMatrixInverse[14]];
|
|
1489
|
+
}
|
|
1490
|
+
function getFrustumPlanes(viewProjectionMatrix) {
|
|
1491
|
+
return {
|
|
1492
|
+
left: getFrustumPlane(
|
|
1493
|
+
viewProjectionMatrix[3] + viewProjectionMatrix[0],
|
|
1494
|
+
viewProjectionMatrix[7] + viewProjectionMatrix[4],
|
|
1495
|
+
viewProjectionMatrix[11] + viewProjectionMatrix[8],
|
|
1496
|
+
viewProjectionMatrix[15] + viewProjectionMatrix[12]
|
|
1497
|
+
),
|
|
1498
|
+
right: getFrustumPlane(
|
|
1499
|
+
viewProjectionMatrix[3] - viewProjectionMatrix[0],
|
|
1500
|
+
viewProjectionMatrix[7] - viewProjectionMatrix[4],
|
|
1501
|
+
viewProjectionMatrix[11] - viewProjectionMatrix[8],
|
|
1502
|
+
viewProjectionMatrix[15] - viewProjectionMatrix[12]
|
|
1503
|
+
),
|
|
1504
|
+
bottom: getFrustumPlane(
|
|
1505
|
+
viewProjectionMatrix[3] + viewProjectionMatrix[1],
|
|
1506
|
+
viewProjectionMatrix[7] + viewProjectionMatrix[5],
|
|
1507
|
+
viewProjectionMatrix[11] + viewProjectionMatrix[9],
|
|
1508
|
+
viewProjectionMatrix[15] + viewProjectionMatrix[13]
|
|
1509
|
+
),
|
|
1510
|
+
top: getFrustumPlane(
|
|
1511
|
+
viewProjectionMatrix[3] - viewProjectionMatrix[1],
|
|
1512
|
+
viewProjectionMatrix[7] - viewProjectionMatrix[5],
|
|
1513
|
+
viewProjectionMatrix[11] - viewProjectionMatrix[9],
|
|
1514
|
+
viewProjectionMatrix[15] - viewProjectionMatrix[13]
|
|
1515
|
+
),
|
|
1516
|
+
near: getFrustumPlane(
|
|
1517
|
+
viewProjectionMatrix[3] + viewProjectionMatrix[2],
|
|
1518
|
+
viewProjectionMatrix[7] + viewProjectionMatrix[6],
|
|
1519
|
+
viewProjectionMatrix[11] + viewProjectionMatrix[10],
|
|
1520
|
+
viewProjectionMatrix[15] + viewProjectionMatrix[14]
|
|
1521
|
+
),
|
|
1522
|
+
far: getFrustumPlane(
|
|
1523
|
+
viewProjectionMatrix[3] - viewProjectionMatrix[2],
|
|
1524
|
+
viewProjectionMatrix[7] - viewProjectionMatrix[6],
|
|
1525
|
+
viewProjectionMatrix[11] - viewProjectionMatrix[10],
|
|
1526
|
+
viewProjectionMatrix[15] - viewProjectionMatrix[14]
|
|
1527
|
+
)
|
|
1528
|
+
};
|
|
1529
|
+
}
|
|
1530
|
+
var scratchVector = new import_core2.Vector3();
|
|
1531
|
+
function getFrustumPlane(a, b, c, d) {
|
|
1532
|
+
scratchVector.set(a, b, c);
|
|
1533
|
+
const L = scratchVector.len();
|
|
1534
|
+
return { distance: d / L, normal: new import_core2.Vector3(-a / L, -b / L, -c / L) };
|
|
1535
|
+
}
|
|
1536
|
+
function fp64LowPart(x) {
|
|
1537
|
+
return x - Math.fround(x);
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
// ../core/src/viewports/viewport.ts
|
|
1541
|
+
var import_core3 = require("@math.gl/core");
|
|
1542
|
+
var import_web_mercator = require("@math.gl/web-mercator");
|
|
1543
|
+
var DEGREES_TO_RADIANS = Math.PI / 180;
|
|
1544
|
+
var IDENTITY = createMat4();
|
|
1545
|
+
var ZERO_VECTOR2 = [0, 0, 0];
|
|
1546
|
+
var DEFAULT_DISTANCE_SCALES = {
|
|
1547
|
+
unitsPerMeter: [1, 1, 1],
|
|
1548
|
+
metersPerUnit: [1, 1, 1]
|
|
1549
|
+
};
|
|
1550
|
+
function createProjectionMatrix({
|
|
1551
|
+
width,
|
|
1552
|
+
height,
|
|
1553
|
+
orthographic,
|
|
1554
|
+
fovyRadians,
|
|
1555
|
+
focalDistance,
|
|
1556
|
+
padding,
|
|
1557
|
+
near,
|
|
1558
|
+
far
|
|
1559
|
+
}) {
|
|
1560
|
+
const aspect = width / height;
|
|
1561
|
+
const matrix = orthographic ? new import_core3.Matrix4().orthographic({ fovy: fovyRadians, aspect, focalDistance, near, far }) : new import_core3.Matrix4().perspective({ fovy: fovyRadians, aspect, near, far });
|
|
1562
|
+
if (padding) {
|
|
1563
|
+
const { left = 0, right = 0, top = 0, bottom = 0 } = padding;
|
|
1564
|
+
const offsetX = (0, import_core3.clamp)((left + width - right) / 2, 0, width) - width / 2;
|
|
1565
|
+
const offsetY = (0, import_core3.clamp)((top + height - bottom) / 2, 0, height) - height / 2;
|
|
1566
|
+
matrix[8] -= offsetX * 2 / width;
|
|
1567
|
+
matrix[9] += offsetY * 2 / height;
|
|
1568
|
+
}
|
|
1569
|
+
return matrix;
|
|
1570
|
+
}
|
|
1571
|
+
var _Viewport = class _Viewport {
|
|
1572
|
+
// eslint-disable-next-line complexity
|
|
1573
|
+
constructor(opts = {}) {
|
|
1574
|
+
this._frustumPlanes = {};
|
|
1575
|
+
this.id = opts.id || this.constructor.displayName || "viewport";
|
|
1576
|
+
this.x = opts.x || 0;
|
|
1577
|
+
this.y = opts.y || 0;
|
|
1578
|
+
this.width = opts.width || 1;
|
|
1579
|
+
this.height = opts.height || 1;
|
|
1580
|
+
this.zoom = opts.zoom || 0;
|
|
1581
|
+
this.padding = opts.padding;
|
|
1582
|
+
this.distanceScales = opts.distanceScales || DEFAULT_DISTANCE_SCALES;
|
|
1583
|
+
this.focalDistance = opts.focalDistance || 1;
|
|
1584
|
+
this.position = opts.position || ZERO_VECTOR2;
|
|
1585
|
+
this.modelMatrix = opts.modelMatrix || null;
|
|
1586
|
+
const { longitude, latitude } = opts;
|
|
1587
|
+
this.isGeospatial = Number.isFinite(latitude) && Number.isFinite(longitude);
|
|
1588
|
+
this._initProps(opts);
|
|
1589
|
+
this._initMatrices(opts);
|
|
1590
|
+
this.equals = this.equals.bind(this);
|
|
1591
|
+
this.project = this.project.bind(this);
|
|
1592
|
+
this.unproject = this.unproject.bind(this);
|
|
1593
|
+
this.projectPosition = this.projectPosition.bind(this);
|
|
1594
|
+
this.unprojectPosition = this.unprojectPosition.bind(this);
|
|
1595
|
+
this.projectFlat = this.projectFlat.bind(this);
|
|
1596
|
+
this.unprojectFlat = this.unprojectFlat.bind(this);
|
|
1597
|
+
}
|
|
1598
|
+
get subViewports() {
|
|
1599
|
+
return null;
|
|
1600
|
+
}
|
|
1601
|
+
get metersPerPixel() {
|
|
1602
|
+
return this.distanceScales.metersPerUnit[2] / this.scale;
|
|
1603
|
+
}
|
|
1604
|
+
get projectionMode() {
|
|
1605
|
+
if (this.isGeospatial) {
|
|
1606
|
+
return this.zoom < 12 ? PROJECTION_MODE.WEB_MERCATOR : PROJECTION_MODE.WEB_MERCATOR_AUTO_OFFSET;
|
|
1607
|
+
}
|
|
1608
|
+
return PROJECTION_MODE.IDENTITY;
|
|
1609
|
+
}
|
|
1610
|
+
// Two viewports are equal if their dimensions, common-space scale, and
|
|
1611
|
+
// view and projection matrices are (approximately) equal.
|
|
1612
|
+
equals(viewport) {
|
|
1613
|
+
if (!(viewport instanceof _Viewport)) {
|
|
1614
|
+
return false;
|
|
1615
|
+
}
|
|
1616
|
+
if (this === viewport) {
|
|
1617
|
+
return true;
|
|
1618
|
+
}
|
|
1619
|
+
return viewport.width === this.width && viewport.height === this.height && viewport.scale === this.scale && viewport.projectionMode === this.projectionMode && viewport.resolution === this.resolution && (0, import_core3.equals)(viewport.distanceScales.unitsPerMeter, this.distanceScales.unitsPerMeter) && (0, import_core3.equals)(viewport.projectionMatrix, this.projectionMatrix) && (0, import_core3.equals)(viewport.viewMatrix, this.viewMatrix);
|
|
1620
|
+
}
|
|
1621
|
+
/**
|
|
1622
|
+
* Projects xyz (possibly latitude and longitude) to pixel coordinates in window
|
|
1623
|
+
* using viewport projection parameters
|
|
1624
|
+
* - [longitude, latitude] to [x, y]
|
|
1625
|
+
* - [longitude, latitude, Z] => [x, y, z]
|
|
1626
|
+
* Note: By default, returns top-left coordinates for canvas/SVG type render
|
|
1627
|
+
*
|
|
1628
|
+
* @param {Array} lngLatZ - [lng, lat] or [lng, lat, Z]
|
|
1629
|
+
* @param {Object} opts - options
|
|
1630
|
+
* @param {Object} opts.topLeft=true - Whether projected coords are top left
|
|
1631
|
+
* @return {Array} - [x, y] or [x, y, z] in top left coords
|
|
1632
|
+
*/
|
|
1633
|
+
project(xyz, { topLeft = true } = {}) {
|
|
1634
|
+
const worldPosition = this.projectPosition(xyz);
|
|
1635
|
+
const coord = (0, import_web_mercator.worldToPixels)(worldPosition, this.pixelProjectionMatrix);
|
|
1636
|
+
const [x, y] = coord;
|
|
1637
|
+
const y2 = topLeft ? y : this.height - y;
|
|
1638
|
+
return xyz.length === 2 ? [x, y2] : [x, y2, coord[2]];
|
|
1639
|
+
}
|
|
1640
|
+
/**
|
|
1641
|
+
* Unproject pixel coordinates on screen onto world coordinates,
|
|
1642
|
+
* (possibly [lon, lat]) on map.
|
|
1643
|
+
* - [x, y] => [lng, lat]
|
|
1644
|
+
* - [x, y, z] => [lng, lat, Z]
|
|
1645
|
+
* @param {Array} xyz -
|
|
1646
|
+
* @param {Object} opts - options
|
|
1647
|
+
* @param {Object} opts.topLeft=true - Whether origin is top left
|
|
1648
|
+
* @return {Array|null} - [lng, lat, Z] or [X, Y, Z]
|
|
1649
|
+
*/
|
|
1650
|
+
unproject(xyz, { topLeft = true, targetZ } = {}) {
|
|
1651
|
+
const [x, y, z] = xyz;
|
|
1652
|
+
const y2 = topLeft ? y : this.height - y;
|
|
1653
|
+
const targetZWorld = targetZ && targetZ * this.distanceScales.unitsPerMeter[2];
|
|
1654
|
+
const coord = (0, import_web_mercator.pixelsToWorld)([x, y2, z], this.pixelUnprojectionMatrix, targetZWorld);
|
|
1655
|
+
const [X, Y, Z] = this.unprojectPosition(coord);
|
|
1656
|
+
if (Number.isFinite(z)) {
|
|
1657
|
+
return [X, Y, Z];
|
|
1658
|
+
}
|
|
1659
|
+
return Number.isFinite(targetZ) ? [X, Y, targetZ] : [X, Y];
|
|
1660
|
+
}
|
|
1661
|
+
// NON_LINEAR PROJECTION HOOKS
|
|
1662
|
+
// Used for web meractor projection
|
|
1663
|
+
projectPosition(xyz) {
|
|
1664
|
+
const [X, Y] = this.projectFlat(xyz);
|
|
1665
|
+
const Z = (xyz[2] || 0) * this.distanceScales.unitsPerMeter[2];
|
|
1666
|
+
return [X, Y, Z];
|
|
1667
|
+
}
|
|
1668
|
+
unprojectPosition(xyz) {
|
|
1669
|
+
const [X, Y] = this.unprojectFlat(xyz);
|
|
1670
|
+
const Z = (xyz[2] || 0) * this.distanceScales.metersPerUnit[2];
|
|
1671
|
+
return [X, Y, Z];
|
|
1672
|
+
}
|
|
1673
|
+
/**
|
|
1674
|
+
* Project [lng,lat] on sphere onto [x,y] on 512*512 Mercator Zoom 0 tile.
|
|
1675
|
+
* Performs the nonlinear part of the web mercator projection.
|
|
1676
|
+
* Remaining projection is done with 4x4 matrices which also handles
|
|
1677
|
+
* perspective.
|
|
1678
|
+
* @param {Array} lngLat - [lng, lat] coordinates
|
|
1679
|
+
* Specifies a point on the sphere to project onto the map.
|
|
1680
|
+
* @return {Array} [x,y] coordinates.
|
|
1681
|
+
*/
|
|
1682
|
+
projectFlat(xyz) {
|
|
1683
|
+
if (this.isGeospatial) {
|
|
1684
|
+
const result = (0, import_web_mercator.lngLatToWorld)(xyz);
|
|
1685
|
+
result[1] = (0, import_core3.clamp)(result[1], -318, 830);
|
|
1686
|
+
return result;
|
|
1687
|
+
}
|
|
1688
|
+
return xyz;
|
|
1689
|
+
}
|
|
1690
|
+
/**
|
|
1691
|
+
* Unproject world point [x,y] on map onto {lat, lon} on sphere
|
|
1692
|
+
* @param {object|Vector} xy - object with {x,y} members
|
|
1693
|
+
* representing point on projected map plane
|
|
1694
|
+
* @return {GeoCoordinates} - object with {lat,lon} of point on sphere.
|
|
1695
|
+
* Has toArray method if you need a GeoJSON Array.
|
|
1696
|
+
* Per cartographic tradition, lat and lon are specified as degrees.
|
|
1697
|
+
*/
|
|
1698
|
+
unprojectFlat(xyz) {
|
|
1699
|
+
if (this.isGeospatial) {
|
|
1700
|
+
return (0, import_web_mercator.worldToLngLat)(xyz);
|
|
1701
|
+
}
|
|
1702
|
+
return xyz;
|
|
1703
|
+
}
|
|
1704
|
+
/**
|
|
1705
|
+
* Get bounds of the current viewport
|
|
1706
|
+
* @return {Array} - [minX, minY, maxX, maxY]
|
|
1707
|
+
*/
|
|
1708
|
+
getBounds(options = {}) {
|
|
1709
|
+
const unprojectOption = { targetZ: options.z || 0 };
|
|
1710
|
+
const topLeft = this.unproject([0, 0], unprojectOption);
|
|
1711
|
+
const topRight = this.unproject([this.width, 0], unprojectOption);
|
|
1712
|
+
const bottomLeft = this.unproject([0, this.height], unprojectOption);
|
|
1713
|
+
const bottomRight = this.unproject([this.width, this.height], unprojectOption);
|
|
1714
|
+
return [
|
|
1715
|
+
Math.min(topLeft[0], topRight[0], bottomLeft[0], bottomRight[0]),
|
|
1716
|
+
Math.min(topLeft[1], topRight[1], bottomLeft[1], bottomRight[1]),
|
|
1717
|
+
Math.max(topLeft[0], topRight[0], bottomLeft[0], bottomRight[0]),
|
|
1718
|
+
Math.max(topLeft[1], topRight[1], bottomLeft[1], bottomRight[1])
|
|
1719
|
+
];
|
|
1720
|
+
}
|
|
1721
|
+
getDistanceScales(coordinateOrigin) {
|
|
1722
|
+
if (coordinateOrigin && this.isGeospatial) {
|
|
1723
|
+
return (0, import_web_mercator.getDistanceScales)({
|
|
1724
|
+
longitude: coordinateOrigin[0],
|
|
1725
|
+
latitude: coordinateOrigin[1],
|
|
1726
|
+
highPrecision: true
|
|
1727
|
+
});
|
|
1728
|
+
}
|
|
1729
|
+
return this.distanceScales;
|
|
1730
|
+
}
|
|
1731
|
+
containsPixel({
|
|
1732
|
+
x,
|
|
1733
|
+
y,
|
|
1734
|
+
width = 1,
|
|
1735
|
+
height = 1
|
|
1736
|
+
}) {
|
|
1737
|
+
return x < this.x + this.width && this.x < x + width && y < this.y + this.height && this.y < y + height;
|
|
1738
|
+
}
|
|
1739
|
+
// Extract frustum planes in common space
|
|
1740
|
+
getFrustumPlanes() {
|
|
1741
|
+
if (this._frustumPlanes.near) {
|
|
1742
|
+
return this._frustumPlanes;
|
|
1743
|
+
}
|
|
1744
|
+
Object.assign(this._frustumPlanes, getFrustumPlanes(this.viewProjectionMatrix));
|
|
1745
|
+
return this._frustumPlanes;
|
|
1746
|
+
}
|
|
1747
|
+
// EXPERIMENTAL METHODS
|
|
1748
|
+
/**
|
|
1749
|
+
* Needed by panning and linear transition
|
|
1750
|
+
* Pan the viewport to place a given world coordinate at screen point [x, y]
|
|
1751
|
+
*
|
|
1752
|
+
* @param {Array} coords - world coordinates
|
|
1753
|
+
* @param {Array} pixel - [x,y] coordinates on screen
|
|
1754
|
+
* @param {Array} startPixel - [x,y] screen position where pan started (optional, for delta-based panning)
|
|
1755
|
+
* @return {Object} props of the new viewport
|
|
1756
|
+
*/
|
|
1757
|
+
panByPosition(coords, pixel, startPixel) {
|
|
1758
|
+
return null;
|
|
1759
|
+
}
|
|
1760
|
+
// INTERNAL METHODS
|
|
1761
|
+
/* eslint-disable complexity, max-statements */
|
|
1762
|
+
_initProps(opts) {
|
|
1763
|
+
const longitude = opts.longitude;
|
|
1764
|
+
const latitude = opts.latitude;
|
|
1765
|
+
if (this.isGeospatial) {
|
|
1766
|
+
if (!Number.isFinite(opts.zoom)) {
|
|
1767
|
+
this.zoom = (0, import_web_mercator.getMeterZoom)({ latitude }) + Math.log2(this.focalDistance);
|
|
1768
|
+
}
|
|
1769
|
+
this.distanceScales = opts.distanceScales || (0, import_web_mercator.getDistanceScales)({ latitude, longitude });
|
|
1770
|
+
}
|
|
1771
|
+
const scale = Math.pow(2, this.zoom);
|
|
1772
|
+
this.scale = scale;
|
|
1773
|
+
const { position, modelMatrix } = opts;
|
|
1774
|
+
let meterOffset = ZERO_VECTOR2;
|
|
1775
|
+
if (position) {
|
|
1776
|
+
meterOffset = modelMatrix ? new import_core3.Matrix4(modelMatrix).transformAsVector(position, []) : position;
|
|
1777
|
+
}
|
|
1778
|
+
if (this.isGeospatial) {
|
|
1779
|
+
const center = this.projectPosition([longitude, latitude, 0]);
|
|
1780
|
+
this.center = new import_core3.Vector3(meterOffset).scale(this.distanceScales.unitsPerMeter).add(center);
|
|
1781
|
+
} else {
|
|
1782
|
+
this.center = this.projectPosition(meterOffset);
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
/* eslint-enable complexity, max-statements */
|
|
1786
|
+
_initMatrices(opts) {
|
|
1787
|
+
const {
|
|
1788
|
+
// View matrix
|
|
1789
|
+
viewMatrix: viewMatrix2 = IDENTITY,
|
|
1790
|
+
// Projection matrix
|
|
1791
|
+
projectionMatrix = null,
|
|
1792
|
+
// Projection matrix parameters, used if projectionMatrix not supplied
|
|
1793
|
+
orthographic = false,
|
|
1794
|
+
fovyRadians,
|
|
1795
|
+
fovy = 75,
|
|
1796
|
+
near = 0.1,
|
|
1797
|
+
// Distance of near clipping plane
|
|
1798
|
+
far = 1e3,
|
|
1799
|
+
// Distance of far clipping plane
|
|
1800
|
+
padding = null,
|
|
1801
|
+
// Center offset in pixels
|
|
1802
|
+
focalDistance = 1
|
|
1803
|
+
} = opts;
|
|
1804
|
+
this.viewMatrixUncentered = viewMatrix2;
|
|
1805
|
+
this.viewMatrix = new import_core3.Matrix4().multiplyRight(viewMatrix2).translate(new import_core3.Vector3(this.center).negate());
|
|
1806
|
+
this.projectionMatrix = projectionMatrix || createProjectionMatrix({
|
|
1807
|
+
width: this.width,
|
|
1808
|
+
height: this.height,
|
|
1809
|
+
orthographic,
|
|
1810
|
+
fovyRadians: fovyRadians || fovy * DEGREES_TO_RADIANS,
|
|
1811
|
+
focalDistance,
|
|
1812
|
+
padding,
|
|
1813
|
+
near,
|
|
1814
|
+
far
|
|
1815
|
+
});
|
|
1816
|
+
const vpm = createMat4();
|
|
1817
|
+
import_core3.mat4.multiply(vpm, vpm, this.projectionMatrix);
|
|
1818
|
+
import_core3.mat4.multiply(vpm, vpm, this.viewMatrix);
|
|
1819
|
+
this.viewProjectionMatrix = vpm;
|
|
1820
|
+
this.viewMatrixInverse = import_core3.mat4.invert([], this.viewMatrix) || this.viewMatrix;
|
|
1821
|
+
this.cameraPosition = getCameraPosition(this.viewMatrixInverse);
|
|
1822
|
+
const viewportMatrix = createMat4();
|
|
1823
|
+
const pixelProjectionMatrix = createMat4();
|
|
1824
|
+
import_core3.mat4.scale(viewportMatrix, viewportMatrix, [this.width / 2, -this.height / 2, 1]);
|
|
1825
|
+
import_core3.mat4.translate(viewportMatrix, viewportMatrix, [1, -1, 0]);
|
|
1826
|
+
import_core3.mat4.multiply(pixelProjectionMatrix, viewportMatrix, this.viewProjectionMatrix);
|
|
1827
|
+
this.pixelProjectionMatrix = pixelProjectionMatrix;
|
|
1828
|
+
this.pixelUnprojectionMatrix = import_core3.mat4.invert(createMat4(), this.pixelProjectionMatrix);
|
|
1829
|
+
if (!this.pixelUnprojectionMatrix) {
|
|
1830
|
+
log_default.warn("Pixel project matrix not invertible")();
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
};
|
|
1834
|
+
_Viewport.displayName = "Viewport";
|
|
1835
|
+
var Viewport = _Viewport;
|
|
1836
|
+
|
|
1837
|
+
// ../core/src/viewports/web-mercator-viewport.ts
|
|
1838
|
+
var import_web_mercator2 = require("@math.gl/web-mercator");
|
|
1839
|
+
var import_core4 = require("@math.gl/core");
|
|
1840
|
+
var _WebMercatorViewport = class _WebMercatorViewport extends Viewport {
|
|
1841
|
+
/* eslint-disable complexity, max-statements */
|
|
1842
|
+
constructor(opts = {}) {
|
|
1843
|
+
const {
|
|
1844
|
+
latitude = 0,
|
|
1845
|
+
longitude = 0,
|
|
1846
|
+
zoom = 0,
|
|
1847
|
+
pitch = 0,
|
|
1848
|
+
bearing = 0,
|
|
1849
|
+
nearZMultiplier = 0.1,
|
|
1850
|
+
farZMultiplier = 1.01,
|
|
1851
|
+
nearZ,
|
|
1852
|
+
farZ,
|
|
1853
|
+
orthographic = false,
|
|
1854
|
+
projectionMatrix,
|
|
1855
|
+
repeat = false,
|
|
1856
|
+
worldOffset = 0,
|
|
1857
|
+
position,
|
|
1858
|
+
padding,
|
|
1859
|
+
// backward compatibility
|
|
1860
|
+
// TODO: remove in v9
|
|
1861
|
+
legacyMeterSizes = false
|
|
1862
|
+
} = opts;
|
|
1863
|
+
let { width, height, altitude = 1.5 } = opts;
|
|
1864
|
+
const scale = Math.pow(2, zoom);
|
|
1865
|
+
width = width || 1;
|
|
1866
|
+
height = height || 1;
|
|
1867
|
+
let fovy;
|
|
1868
|
+
let projectionParameters = null;
|
|
1869
|
+
if (projectionMatrix) {
|
|
1870
|
+
altitude = projectionMatrix[5] / 2;
|
|
1871
|
+
fovy = (0, import_web_mercator2.altitudeToFovy)(altitude);
|
|
1872
|
+
} else {
|
|
1873
|
+
if (opts.fovy) {
|
|
1874
|
+
fovy = opts.fovy;
|
|
1875
|
+
altitude = (0, import_web_mercator2.fovyToAltitude)(fovy);
|
|
1876
|
+
} else {
|
|
1877
|
+
fovy = (0, import_web_mercator2.altitudeToFovy)(altitude);
|
|
1878
|
+
}
|
|
1879
|
+
let offset;
|
|
1880
|
+
if (padding) {
|
|
1881
|
+
const { top = 0, bottom = 0 } = padding;
|
|
1882
|
+
offset = [0, (0, import_core4.clamp)((top + height - bottom) / 2, 0, height) - height / 2];
|
|
1883
|
+
}
|
|
1884
|
+
projectionParameters = (0, import_web_mercator2.getProjectionParameters)({
|
|
1885
|
+
width,
|
|
1886
|
+
height,
|
|
1887
|
+
scale,
|
|
1888
|
+
center: position && [0, 0, position[2] * (0, import_web_mercator2.unitsPerMeter)(latitude)],
|
|
1889
|
+
offset,
|
|
1890
|
+
pitch,
|
|
1891
|
+
fovy,
|
|
1892
|
+
nearZMultiplier,
|
|
1893
|
+
farZMultiplier
|
|
1894
|
+
});
|
|
1895
|
+
if (Number.isFinite(nearZ)) {
|
|
1896
|
+
projectionParameters.near = nearZ;
|
|
1897
|
+
}
|
|
1898
|
+
if (Number.isFinite(farZ)) {
|
|
1899
|
+
projectionParameters.far = farZ;
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
let viewMatrixUncentered = (0, import_web_mercator2.getViewMatrix)({
|
|
1903
|
+
height,
|
|
1904
|
+
pitch,
|
|
1905
|
+
bearing,
|
|
1906
|
+
scale,
|
|
1907
|
+
altitude
|
|
1908
|
+
});
|
|
1909
|
+
if (worldOffset) {
|
|
1910
|
+
const viewOffset = new import_core4.Matrix4().translate([512 * worldOffset, 0, 0]);
|
|
1911
|
+
viewMatrixUncentered = viewOffset.multiplyLeft(viewMatrixUncentered);
|
|
1912
|
+
}
|
|
1913
|
+
super({
|
|
1914
|
+
...opts,
|
|
1915
|
+
// x, y,
|
|
1916
|
+
width,
|
|
1917
|
+
height,
|
|
1918
|
+
// view matrix
|
|
1919
|
+
viewMatrix: viewMatrixUncentered,
|
|
1920
|
+
longitude,
|
|
1921
|
+
latitude,
|
|
1922
|
+
zoom,
|
|
1923
|
+
// projection matrix parameters
|
|
1924
|
+
...projectionParameters,
|
|
1925
|
+
fovy,
|
|
1926
|
+
focalDistance: altitude
|
|
1927
|
+
});
|
|
1928
|
+
this.latitude = latitude;
|
|
1929
|
+
this.longitude = longitude;
|
|
1930
|
+
this.zoom = zoom;
|
|
1931
|
+
this.pitch = pitch;
|
|
1932
|
+
this.bearing = bearing;
|
|
1933
|
+
this.altitude = altitude;
|
|
1934
|
+
this.fovy = fovy;
|
|
1935
|
+
this.orthographic = orthographic;
|
|
1936
|
+
this._subViewports = repeat ? [] : null;
|
|
1937
|
+
this._pseudoMeters = legacyMeterSizes;
|
|
1938
|
+
Object.freeze(this);
|
|
1939
|
+
}
|
|
1940
|
+
/* eslint-enable complexity, max-statements */
|
|
1941
|
+
get subViewports() {
|
|
1942
|
+
if (this._subViewports && !this._subViewports.length) {
|
|
1943
|
+
const bounds = this.getBounds();
|
|
1944
|
+
const minOffset = Math.floor((bounds[0] + 180) / 360);
|
|
1945
|
+
const maxOffset = Math.ceil((bounds[2] - 180) / 360);
|
|
1946
|
+
for (let x = minOffset; x <= maxOffset; x++) {
|
|
1947
|
+
const offsetViewport = x ? new _WebMercatorViewport({
|
|
1948
|
+
...this,
|
|
1949
|
+
worldOffset: x
|
|
1950
|
+
}) : this;
|
|
1951
|
+
this._subViewports.push(offsetViewport);
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
return this._subViewports;
|
|
1955
|
+
}
|
|
1956
|
+
/** Returns whether two Web Mercator viewports use the same projection settings. */
|
|
1957
|
+
equals(viewport) {
|
|
1958
|
+
return viewport instanceof _WebMercatorViewport && viewport._pseudoMeters === this._pseudoMeters && super.equals(viewport);
|
|
1959
|
+
}
|
|
1960
|
+
projectPosition(xyz) {
|
|
1961
|
+
if (this._pseudoMeters) {
|
|
1962
|
+
return super.projectPosition(xyz);
|
|
1963
|
+
}
|
|
1964
|
+
const [X, Y] = this.projectFlat(xyz);
|
|
1965
|
+
const Z = (xyz[2] || 0) * (0, import_web_mercator2.unitsPerMeter)(xyz[1]);
|
|
1966
|
+
return [X, Y, Z];
|
|
1967
|
+
}
|
|
1968
|
+
unprojectPosition(xyz) {
|
|
1969
|
+
if (this._pseudoMeters) {
|
|
1970
|
+
return super.unprojectPosition(xyz);
|
|
1971
|
+
}
|
|
1972
|
+
const [X, Y] = this.unprojectFlat(xyz);
|
|
1973
|
+
const Z = (xyz[2] || 0) / (0, import_web_mercator2.unitsPerMeter)(Y);
|
|
1974
|
+
return [X, Y, Z];
|
|
1975
|
+
}
|
|
1976
|
+
/**
|
|
1977
|
+
* Add a meter delta to a base lnglat coordinate, returning a new lnglat array
|
|
1978
|
+
*
|
|
1979
|
+
* Note: Uses simple linear approximation around the viewport center
|
|
1980
|
+
* Error increases with size of offset (roughly 1% per 100km)
|
|
1981
|
+
*
|
|
1982
|
+
* @param {[Number,Number]|[Number,Number,Number]) lngLatZ - base coordinate
|
|
1983
|
+
* @param {[Number,Number]|[Number,Number,Number]) xyz - array of meter deltas
|
|
1984
|
+
* @return {[Number,Number]|[Number,Number,Number]) array of [lng,lat,z] deltas
|
|
1985
|
+
*/
|
|
1986
|
+
addMetersToLngLat(lngLatZ, xyz) {
|
|
1987
|
+
return (0, import_web_mercator2.addMetersToLngLat)(lngLatZ, xyz);
|
|
1988
|
+
}
|
|
1989
|
+
panByPosition(coords, pixel, startPixel) {
|
|
1990
|
+
const fromLocation = (0, import_web_mercator2.pixelsToWorld)(pixel, this.pixelUnprojectionMatrix);
|
|
1991
|
+
const toLocation = this.projectFlat(coords);
|
|
1992
|
+
const translate = import_core4.vec2.add([], toLocation, import_core4.vec2.negate([], fromLocation));
|
|
1993
|
+
const newCenter = import_core4.vec2.add([], this.center, translate);
|
|
1994
|
+
const [longitude, latitude] = this.unprojectFlat(newCenter);
|
|
1995
|
+
return { longitude, latitude };
|
|
1996
|
+
}
|
|
1997
|
+
/**
|
|
1998
|
+
* Returns a new longitude and latitude that keeps a 3D world coordinate at a given screen pixel
|
|
1999
|
+
* This version handles the z-component (altitude) properly for cameras positioned above ground
|
|
2000
|
+
*/
|
|
2001
|
+
panByPosition3D(coords, pixel) {
|
|
2002
|
+
const targetZ = coords[2] || 0;
|
|
2003
|
+
const deltaLngLat = import_core4.vec2.sub([], coords, this.unproject(pixel, { targetZ }));
|
|
2004
|
+
return { longitude: this.longitude + deltaLngLat[0], latitude: this.latitude + deltaLngLat[1] };
|
|
2005
|
+
}
|
|
2006
|
+
getBounds(options = {}) {
|
|
2007
|
+
const corners = (0, import_web_mercator2.getBounds)(this, options.z || 0);
|
|
2008
|
+
return [
|
|
2009
|
+
Math.min(corners[0][0], corners[1][0], corners[2][0], corners[3][0]),
|
|
2010
|
+
Math.min(corners[0][1], corners[1][1], corners[2][1], corners[3][1]),
|
|
2011
|
+
Math.max(corners[0][0], corners[1][0], corners[2][0], corners[3][0]),
|
|
2012
|
+
Math.max(corners[0][1], corners[1][1], corners[2][1], corners[3][1])
|
|
2013
|
+
];
|
|
2014
|
+
}
|
|
2015
|
+
/**
|
|
2016
|
+
* Returns a new viewport that fit around the given rectangle.
|
|
2017
|
+
* Only supports non-perspective mode.
|
|
2018
|
+
*/
|
|
2019
|
+
fitBounds(bounds, options = {}) {
|
|
2020
|
+
const { width, height } = this;
|
|
2021
|
+
const { longitude, latitude, zoom } = (0, import_web_mercator2.fitBounds)({ width, height, bounds, ...options });
|
|
2022
|
+
return new _WebMercatorViewport({ width, height, longitude, latitude, zoom });
|
|
2023
|
+
}
|
|
2024
|
+
};
|
|
2025
|
+
_WebMercatorViewport.displayName = "WebMercatorViewport";
|
|
2026
|
+
var WebMercatorViewport = _WebMercatorViewport;
|
|
2027
|
+
|
|
2028
|
+
// ../core/src/passes/pick-layers-pass.ts
|
|
2029
|
+
var PICKING_BLENDING = {
|
|
2030
|
+
blendColorOperation: "add",
|
|
2031
|
+
blendColorSrcFactor: "one",
|
|
2032
|
+
blendColorDstFactor: "zero",
|
|
2033
|
+
blendAlphaOperation: "add",
|
|
2034
|
+
blendAlphaSrcFactor: "constant",
|
|
2035
|
+
blendAlphaDstFactor: "zero"
|
|
2036
|
+
};
|
|
2037
|
+
var PickLayersPass = class extends LayersPass {
|
|
2038
|
+
constructor() {
|
|
2039
|
+
super(...arguments);
|
|
2040
|
+
this._colorEncoderState = null;
|
|
2041
|
+
}
|
|
2042
|
+
render(props) {
|
|
2043
|
+
if ("pickingFBO" in props) {
|
|
2044
|
+
return this._drawPickingBuffer(props);
|
|
2045
|
+
}
|
|
2046
|
+
const stats = super._render(props);
|
|
2047
|
+
return { decodePickingColor: null, stats };
|
|
2048
|
+
}
|
|
2049
|
+
// Private
|
|
2050
|
+
// Draws list of layers and viewports into the picking buffer
|
|
2051
|
+
// Note: does not sample the buffer, that has to be done by the caller
|
|
2052
|
+
_drawPickingBuffer({
|
|
2053
|
+
layers,
|
|
2054
|
+
layerFilter,
|
|
2055
|
+
views,
|
|
2056
|
+
viewports,
|
|
2057
|
+
onViewportActive,
|
|
2058
|
+
pickingFBO,
|
|
2059
|
+
deviceRect: { x, y, width, height },
|
|
2060
|
+
cullRect,
|
|
2061
|
+
effects,
|
|
2062
|
+
pass = "picking",
|
|
2063
|
+
pickZ,
|
|
2064
|
+
canvasContext,
|
|
2065
|
+
shaderModuleProps,
|
|
2066
|
+
clearColor
|
|
2067
|
+
}) {
|
|
2068
|
+
this.pickZ = pickZ;
|
|
2069
|
+
const colorEncoderState = this._resetColorEncoder(pickZ);
|
|
2070
|
+
const scissorRect = [x, y, width, height];
|
|
2071
|
+
const renderStatus = super._render({
|
|
2072
|
+
target: pickingFBO,
|
|
2073
|
+
layers,
|
|
2074
|
+
layerFilter,
|
|
2075
|
+
views,
|
|
2076
|
+
viewports,
|
|
2077
|
+
onViewportActive,
|
|
2078
|
+
cullRect,
|
|
2079
|
+
effects: effects == null ? void 0 : effects.filter((e) => e.useInPicking),
|
|
2080
|
+
pass,
|
|
2081
|
+
canvasContext,
|
|
2082
|
+
isPicking: true,
|
|
2083
|
+
shaderModuleProps,
|
|
2084
|
+
clearColor: clearColor ?? [0, 0, 0, 0],
|
|
2085
|
+
colorMask: 15,
|
|
2086
|
+
scissorRect
|
|
2087
|
+
});
|
|
2088
|
+
this._colorEncoderState = null;
|
|
2089
|
+
const decodePickingColor = colorEncoderState && decodeColor.bind(null, colorEncoderState);
|
|
2090
|
+
return { decodePickingColor, stats: renderStatus };
|
|
2091
|
+
}
|
|
2092
|
+
shouldDrawLayer(layer) {
|
|
2093
|
+
const { pickable, operation } = layer.props;
|
|
2094
|
+
return pickable && operation.includes("draw") || operation.includes("terrain") || operation.includes("mask");
|
|
2095
|
+
}
|
|
2096
|
+
getShaderModuleProps(layer, effects, otherShaderModuleProps) {
|
|
2097
|
+
var _a;
|
|
2098
|
+
return {
|
|
2099
|
+
picking: {
|
|
2100
|
+
isActive: 1,
|
|
2101
|
+
isAttribute: this.pickZ,
|
|
2102
|
+
disabledPickingIndices: (_a = layer.internalState) == null ? void 0 : _a.disabledPickingIndices
|
|
2103
|
+
},
|
|
2104
|
+
lighting: { enabled: false }
|
|
2105
|
+
};
|
|
2106
|
+
}
|
|
2107
|
+
getLayerParameters(layer, layerIndex, viewport) {
|
|
2108
|
+
var _a;
|
|
2109
|
+
const pickParameters = {
|
|
2110
|
+
...layer.props.parameters
|
|
2111
|
+
};
|
|
2112
|
+
const { pickable, operation } = layer.props;
|
|
2113
|
+
if (!this._colorEncoderState) {
|
|
2114
|
+
pickParameters.blend = false;
|
|
2115
|
+
} else if (pickable && operation.includes("draw")) {
|
|
2116
|
+
Object.assign(pickParameters, PICKING_BLENDING);
|
|
2117
|
+
pickParameters.blend = true;
|
|
2118
|
+
if (this.device.type === "webgpu") {
|
|
2119
|
+
pickParameters.blendConstant = encodeColor(this._colorEncoderState, layer, viewport);
|
|
2120
|
+
} else {
|
|
2121
|
+
pickParameters.blendColor = encodeColor(this._colorEncoderState, layer, viewport);
|
|
2122
|
+
}
|
|
2123
|
+
if (operation.includes("terrain") && ((_a = layer.state) == null ? void 0 : _a._hasPickingCover)) {
|
|
2124
|
+
pickParameters.blendAlphaSrcFactor = "one";
|
|
2125
|
+
}
|
|
2126
|
+
} else if (operation.includes("terrain")) {
|
|
2127
|
+
pickParameters.blend = false;
|
|
2128
|
+
}
|
|
2129
|
+
return pickParameters;
|
|
2130
|
+
}
|
|
2131
|
+
_resetColorEncoder(pickZ) {
|
|
2132
|
+
this._colorEncoderState = pickZ ? null : {
|
|
2133
|
+
byLayer: /* @__PURE__ */ new Map(),
|
|
2134
|
+
byAlpha: []
|
|
2135
|
+
};
|
|
2136
|
+
return this._colorEncoderState;
|
|
2137
|
+
}
|
|
2138
|
+
};
|
|
2139
|
+
function encodeColor(encoded, layer, viewport) {
|
|
2140
|
+
const { byLayer, byAlpha } = encoded;
|
|
2141
|
+
let a;
|
|
2142
|
+
let entry = byLayer.get(layer);
|
|
2143
|
+
if (entry) {
|
|
2144
|
+
entry.viewports.push(viewport);
|
|
2145
|
+
a = entry.a;
|
|
2146
|
+
} else {
|
|
2147
|
+
a = byLayer.size + 1;
|
|
2148
|
+
if (a <= 255) {
|
|
2149
|
+
entry = { a, layer, viewports: [viewport] };
|
|
2150
|
+
byLayer.set(layer, entry);
|
|
2151
|
+
byAlpha[a] = entry;
|
|
2152
|
+
} else {
|
|
2153
|
+
log_default.warn("Too many pickable layers, only picking the first 255")();
|
|
2154
|
+
a = 0;
|
|
2155
|
+
}
|
|
2156
|
+
}
|
|
2157
|
+
return [0, 0, 0, a / 255];
|
|
2158
|
+
}
|
|
2159
|
+
function decodeColor(encoded, pickedColor) {
|
|
2160
|
+
const entry = encoded.byAlpha[pickedColor[3]];
|
|
2161
|
+
return entry && {
|
|
2162
|
+
pickedLayer: entry.layer,
|
|
2163
|
+
pickedViewports: entry.viewports,
|
|
2164
|
+
pickedObjectIndex: entry.layer.decodePickingColor(pickedColor)
|
|
2165
|
+
};
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
// ../core/src/utils/deep-equal.ts
|
|
2169
|
+
function deepEqual(a, b, depth) {
|
|
2170
|
+
if (a === b) {
|
|
2171
|
+
return true;
|
|
2172
|
+
}
|
|
2173
|
+
if (!depth || !a || !b) {
|
|
2174
|
+
return false;
|
|
2175
|
+
}
|
|
2176
|
+
if (Array.isArray(a)) {
|
|
2177
|
+
if (!Array.isArray(b) || a.length !== b.length) {
|
|
2178
|
+
return false;
|
|
2179
|
+
}
|
|
2180
|
+
for (let i = 0; i < a.length; i++) {
|
|
2181
|
+
if (!deepEqual(a[i], b[i], depth - 1)) {
|
|
2182
|
+
return false;
|
|
2183
|
+
}
|
|
2184
|
+
}
|
|
2185
|
+
return true;
|
|
2186
|
+
}
|
|
2187
|
+
if (Array.isArray(b)) {
|
|
2188
|
+
return false;
|
|
2189
|
+
}
|
|
2190
|
+
if (typeof a === "object" && typeof b === "object") {
|
|
2191
|
+
const aKeys = Object.keys(a);
|
|
2192
|
+
const bKeys = Object.keys(b);
|
|
2193
|
+
if (aKeys.length !== bKeys.length) {
|
|
2194
|
+
return false;
|
|
2195
|
+
}
|
|
2196
|
+
for (const key of aKeys) {
|
|
2197
|
+
if (!b.hasOwnProperty(key)) {
|
|
2198
|
+
return false;
|
|
2199
|
+
}
|
|
2200
|
+
if (!deepEqual(a[key], b[key], depth - 1)) {
|
|
2201
|
+
return false;
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
return true;
|
|
2205
|
+
}
|
|
2206
|
+
return false;
|
|
2207
|
+
}
|
|
2208
|
+
|
|
2209
|
+
// ../core/src/utils/shader.ts
|
|
2210
|
+
function mergeShaders(target, source2) {
|
|
2211
|
+
if (!source2) {
|
|
2212
|
+
return target;
|
|
2213
|
+
}
|
|
2214
|
+
const result = { ...target, ...source2 };
|
|
2215
|
+
if ("defines" in source2) {
|
|
2216
|
+
result.defines = { ...target.defines, ...source2.defines };
|
|
2217
|
+
}
|
|
2218
|
+
if ("modules" in source2) {
|
|
2219
|
+
result.modules = (target.modules || []).concat(source2.modules);
|
|
2220
|
+
if (source2.modules.some((module2) => module2.name === "project64")) {
|
|
2221
|
+
const index = result.modules.findIndex((module2) => module2.name === "project32");
|
|
2222
|
+
if (index >= 0) {
|
|
2223
|
+
result.modules.splice(index, 1);
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
if ("inject" in source2) {
|
|
2228
|
+
if (!target.inject) {
|
|
2229
|
+
result.inject = source2.inject;
|
|
2230
|
+
} else {
|
|
2231
|
+
const mergedInjection = { ...target.inject };
|
|
2232
|
+
for (const key in source2.inject) {
|
|
2233
|
+
mergedInjection[key] = (mergedInjection[key] || "") + source2.inject[key];
|
|
2234
|
+
}
|
|
2235
|
+
result.inject = mergedInjection;
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
return result;
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
// ../core/src/viewports/globe-viewport.ts
|
|
2242
|
+
var import_core5 = require("@math.gl/core");
|
|
2243
|
+
var import_web_mercator3 = require("@math.gl/web-mercator");
|
|
2244
|
+
var DEGREES_TO_RADIANS2 = Math.PI / 180;
|
|
2245
|
+
var RADIANS_TO_DEGREES = 180 / Math.PI;
|
|
2246
|
+
var NORTH_UP_BEARING_THRESHOLD = 1;
|
|
2247
|
+
var EARTH_RADIUS = 6370972;
|
|
2248
|
+
var GLOBE_RADIUS = 256;
|
|
2249
|
+
var GLOBE_ZOOM_ANCHOR_DAMPING_START_RATIO = 0.75;
|
|
2250
|
+
var GLOBE_ZOOM_ANCHOR_MAX_DISTANCE_RATIO = 1.15;
|
|
2251
|
+
function isGlobeNorthUp(bearing) {
|
|
2252
|
+
const normalizedBearing = mod(bearing + 180, 360) - 180;
|
|
2253
|
+
return Math.abs(normalizedBearing) < NORTH_UP_BEARING_THRESHOLD;
|
|
2254
|
+
}
|
|
2255
|
+
function getDistanceScales2() {
|
|
2256
|
+
const unitsPerMeter2 = GLOBE_RADIUS / EARTH_RADIUS;
|
|
2257
|
+
const unitsPerDegree = Math.PI / 180 * GLOBE_RADIUS;
|
|
2258
|
+
return {
|
|
2259
|
+
unitsPerMeter: [unitsPerMeter2, unitsPerMeter2, unitsPerMeter2],
|
|
2260
|
+
unitsPerMeter2: [0, 0, 0],
|
|
2261
|
+
metersPerUnit: [1 / unitsPerMeter2, 1 / unitsPerMeter2, 1 / unitsPerMeter2],
|
|
2262
|
+
unitsPerDegree: [unitsPerDegree, unitsPerDegree, unitsPerMeter2],
|
|
2263
|
+
unitsPerDegree2: [0, 0, 0],
|
|
2264
|
+
degreesPerUnit: [1 / unitsPerDegree, 1 / unitsPerDegree, 1 / unitsPerMeter2]
|
|
2265
|
+
};
|
|
2266
|
+
}
|
|
2267
|
+
var GlobeViewport = class extends Viewport {
|
|
2268
|
+
constructor(opts = {}) {
|
|
2269
|
+
const {
|
|
2270
|
+
longitude = 0,
|
|
2271
|
+
bearing = 0,
|
|
2272
|
+
pitch = 0,
|
|
2273
|
+
zoom = 0,
|
|
2274
|
+
// Matches Maplibre defaults
|
|
2275
|
+
// https://github.com/maplibre/maplibre-gl-js/blob/f8ab4b48d59ab8fe7b068b102538793bbdd4c848/src/geo/projection/globe_transform.ts#L632-L633
|
|
2276
|
+
nearZMultiplier = 0.5,
|
|
2277
|
+
farZMultiplier = 1,
|
|
2278
|
+
resolution = 10
|
|
2279
|
+
} = opts;
|
|
2280
|
+
let { latitude = 0, height, altitude = 1.5, fovy } = opts;
|
|
2281
|
+
latitude = Math.max(Math.min(latitude, 90), -90);
|
|
2282
|
+
height = height || 1;
|
|
2283
|
+
if (fovy) {
|
|
2284
|
+
altitude = (0, import_web_mercator3.fovyToAltitude)(fovy);
|
|
2285
|
+
} else {
|
|
2286
|
+
fovy = (0, import_web_mercator3.altitudeToFovy)(altitude);
|
|
2287
|
+
}
|
|
2288
|
+
const scaleLatitude = Math.max(Math.min(latitude, import_web_mercator3.MAX_LATITUDE), -import_web_mercator3.MAX_LATITUDE);
|
|
2289
|
+
const scale = Math.pow(2, zoom - zoomAdjust(scaleLatitude));
|
|
2290
|
+
const pitchRadians = pitch * DEGREES_TO_RADIANS2;
|
|
2291
|
+
const nearZ = opts.nearZ ?? nearZMultiplier;
|
|
2292
|
+
const farZ = opts.farZ ?? (altitude + GLOBE_RADIUS * 2 * scale / height / Math.max(Math.cos(pitchRadians), 0.1)) * farZMultiplier;
|
|
2293
|
+
const viewMatrix2 = new import_core5.Matrix4().lookAt({ eye: [0, -altitude, 0], up: [0, 0, 1] }).rotateX(-pitchRadians).rotateY(-bearing * DEGREES_TO_RADIANS2).rotateX(latitude * DEGREES_TO_RADIANS2).rotateZ(-longitude * DEGREES_TO_RADIANS2).scale(scale / height);
|
|
2294
|
+
super({
|
|
2295
|
+
...opts,
|
|
2296
|
+
// x, y, width,
|
|
2297
|
+
height,
|
|
2298
|
+
// view matrix
|
|
2299
|
+
viewMatrix: viewMatrix2,
|
|
2300
|
+
longitude,
|
|
2301
|
+
latitude,
|
|
2302
|
+
zoom,
|
|
2303
|
+
// projection matrix parameters
|
|
2304
|
+
distanceScales: getDistanceScales2(),
|
|
2305
|
+
fovy,
|
|
2306
|
+
focalDistance: altitude,
|
|
2307
|
+
near: nearZ,
|
|
2308
|
+
far: farZ
|
|
2309
|
+
});
|
|
2310
|
+
this.scale = scale;
|
|
2311
|
+
this.latitude = latitude;
|
|
2312
|
+
this.longitude = longitude;
|
|
2313
|
+
this.bearing = bearing;
|
|
2314
|
+
this.pitch = pitch;
|
|
2315
|
+
this.fovy = fovy;
|
|
2316
|
+
this.resolution = resolution;
|
|
2317
|
+
}
|
|
2318
|
+
get projectionMode() {
|
|
2319
|
+
return PROJECTION_MODE.GLOBE;
|
|
2320
|
+
}
|
|
2321
|
+
getDistanceScales() {
|
|
2322
|
+
return this.distanceScales;
|
|
2323
|
+
}
|
|
2324
|
+
getBounds(options = {}) {
|
|
2325
|
+
const unprojectOption = { targetZ: options.z || 0 };
|
|
2326
|
+
const left = this.unproject([0, this.height / 2], unprojectOption);
|
|
2327
|
+
const top = this.unproject([this.width / 2, 0], unprojectOption);
|
|
2328
|
+
const right = this.unproject([this.width, this.height / 2], unprojectOption);
|
|
2329
|
+
const bottom = this.unproject([this.width / 2, this.height], unprojectOption);
|
|
2330
|
+
if (right[0] < this.longitude) right[0] += 360;
|
|
2331
|
+
if (left[0] > this.longitude) left[0] -= 360;
|
|
2332
|
+
return [
|
|
2333
|
+
Math.min(left[0], right[0], top[0], bottom[0]),
|
|
2334
|
+
Math.min(left[1], right[1], top[1], bottom[1]),
|
|
2335
|
+
Math.max(left[0], right[0], top[0], bottom[0]),
|
|
2336
|
+
Math.max(left[1], right[1], top[1], bottom[1])
|
|
2337
|
+
];
|
|
2338
|
+
}
|
|
2339
|
+
/**
|
|
2340
|
+
* Builds the screen-pixel → globe-center ray and the intermediate ray/sphere
|
|
2341
|
+
* math reused by `unproject` and anchored zoom. One function so the same
|
|
2342
|
+
* pixelUnprojectionMatrix work isn't duplicated.
|
|
2343
|
+
*/
|
|
2344
|
+
_getRayToGlobe(screenPosition, { topLeft = true, targetZ } = {}) {
|
|
2345
|
+
const [screenX, screenY] = screenPosition;
|
|
2346
|
+
const adjustedScreenY = topLeft ? screenY : this.height - screenY;
|
|
2347
|
+
const { pixelUnprojectionMatrix } = this;
|
|
2348
|
+
const rayStartPosition = transformVector(pixelUnprojectionMatrix, [
|
|
2349
|
+
screenX,
|
|
2350
|
+
adjustedScreenY,
|
|
2351
|
+
-1,
|
|
2352
|
+
1
|
|
2353
|
+
]);
|
|
2354
|
+
const rayEndPosition = transformVector(pixelUnprojectionMatrix, [
|
|
2355
|
+
screenX,
|
|
2356
|
+
adjustedScreenY,
|
|
2357
|
+
1,
|
|
2358
|
+
1
|
|
2359
|
+
]);
|
|
2360
|
+
const radius = ((targetZ || 0) / EARTH_RADIUS + 1) * GLOBE_RADIUS;
|
|
2361
|
+
const rayLengthSquared = import_core5.vec3.sqrLen(import_core5.vec3.sub([], rayStartPosition, rayEndPosition));
|
|
2362
|
+
const rayStartDistanceSquared = import_core5.vec3.sqrLen(rayStartPosition);
|
|
2363
|
+
const rayEndDistanceSquared = import_core5.vec3.sqrLen(rayEndPosition);
|
|
2364
|
+
const triangleAreaSquared = (4 * rayStartDistanceSquared * rayEndDistanceSquared - (rayLengthSquared - rayStartDistanceSquared - rayEndDistanceSquared) ** 2) / 16;
|
|
2365
|
+
const distanceToCenterSquared = 4 * triangleAreaSquared / rayLengthSquared;
|
|
2366
|
+
return {
|
|
2367
|
+
rayStartPosition,
|
|
2368
|
+
rayEndPosition,
|
|
2369
|
+
radius,
|
|
2370
|
+
rayLengthSquared,
|
|
2371
|
+
rayStartDistanceSquared,
|
|
2372
|
+
distanceToCenterSquared
|
|
2373
|
+
};
|
|
2374
|
+
}
|
|
2375
|
+
_getRayDistanceToGlobeCenterRatio(screenPosition, options) {
|
|
2376
|
+
const { distanceToCenterSquared, radius } = this._getRayToGlobe(screenPosition, options);
|
|
2377
|
+
return Math.sqrt(Math.max(0, distanceToCenterSquared)) / radius;
|
|
2378
|
+
}
|
|
2379
|
+
/**
|
|
2380
|
+
* Returns how strongly a screen position should anchor zoom on the visible globe.
|
|
2381
|
+
* A value of `0` means that the controller should fall back to center zoom.
|
|
2382
|
+
* @param screenPosition - Screen position to evaluate.
|
|
2383
|
+
* @returns Anchor strength from `0` to `1`.
|
|
2384
|
+
*/
|
|
2385
|
+
getZoomAnchorStrength(screenPosition) {
|
|
2386
|
+
const distanceRatio = this._getRayDistanceToGlobeCenterRatio(screenPosition);
|
|
2387
|
+
if (distanceRatio >= GLOBE_ZOOM_ANCHOR_MAX_DISTANCE_RATIO) {
|
|
2388
|
+
return 0;
|
|
2389
|
+
}
|
|
2390
|
+
const edgeProgress = Math.max(
|
|
2391
|
+
0,
|
|
2392
|
+
Math.min(
|
|
2393
|
+
1,
|
|
2394
|
+
(distanceRatio - GLOBE_ZOOM_ANCHOR_DAMPING_START_RATIO) / (GLOBE_ZOOM_ANCHOR_MAX_DISTANCE_RATIO - GLOBE_ZOOM_ANCHOR_DAMPING_START_RATIO)
|
|
2395
|
+
)
|
|
2396
|
+
);
|
|
2397
|
+
const smoothProgress = edgeProgress * edgeProgress * (3 - 2 * edgeProgress);
|
|
2398
|
+
return 1 - smoothProgress;
|
|
2399
|
+
}
|
|
2400
|
+
unproject(xyz, { topLeft = true, targetZ } = {}) {
|
|
2401
|
+
const [x, y, z] = xyz;
|
|
2402
|
+
const y2 = topLeft ? y : this.height - y;
|
|
2403
|
+
const { pixelUnprojectionMatrix } = this;
|
|
2404
|
+
let coord;
|
|
2405
|
+
if (Number.isFinite(z)) {
|
|
2406
|
+
coord = transformVector(pixelUnprojectionMatrix, [x, y2, z, 1]);
|
|
2407
|
+
} else {
|
|
2408
|
+
const {
|
|
2409
|
+
rayStartPosition,
|
|
2410
|
+
rayEndPosition,
|
|
2411
|
+
radius,
|
|
2412
|
+
rayLengthSquared,
|
|
2413
|
+
rayStartDistanceSquared,
|
|
2414
|
+
distanceToCenterSquared
|
|
2415
|
+
} = this._getRayToGlobe(xyz, { topLeft, targetZ });
|
|
2416
|
+
const rayStartToClosestApproach = Math.sqrt(
|
|
2417
|
+
rayStartDistanceSquared - distanceToCenterSquared
|
|
2418
|
+
);
|
|
2419
|
+
const closestApproachToIntersection = Math.sqrt(
|
|
2420
|
+
Math.max(0, radius * radius - distanceToCenterSquared)
|
|
2421
|
+
);
|
|
2422
|
+
const intersectionRatio = (rayStartToClosestApproach - closestApproachToIntersection) / Math.sqrt(rayLengthSquared);
|
|
2423
|
+
coord = import_core5.vec3.lerp([], rayStartPosition, rayEndPosition, intersectionRatio);
|
|
2424
|
+
}
|
|
2425
|
+
const [X, Y, Z] = this.unprojectPosition(coord);
|
|
2426
|
+
if (Number.isFinite(z)) {
|
|
2427
|
+
return [X, Y, Z];
|
|
2428
|
+
}
|
|
2429
|
+
return Number.isFinite(targetZ) ? [X, Y, targetZ] : [X, Y];
|
|
2430
|
+
}
|
|
2431
|
+
projectPosition(xyz) {
|
|
2432
|
+
const [lng, lat, Z = 0] = xyz;
|
|
2433
|
+
const lambda = lng * DEGREES_TO_RADIANS2;
|
|
2434
|
+
const phi = lat * DEGREES_TO_RADIANS2;
|
|
2435
|
+
const cosPhi = Math.cos(phi);
|
|
2436
|
+
const D = (Z / EARTH_RADIUS + 1) * GLOBE_RADIUS;
|
|
2437
|
+
return [Math.sin(lambda) * cosPhi * D, -Math.cos(lambda) * cosPhi * D, Math.sin(phi) * D];
|
|
2438
|
+
}
|
|
2439
|
+
unprojectPosition(xyz) {
|
|
2440
|
+
const [x, y, z] = xyz;
|
|
2441
|
+
const D = import_core5.vec3.len(xyz);
|
|
2442
|
+
const phi = Math.asin(z / D);
|
|
2443
|
+
const lambda = Math.atan2(x, -y);
|
|
2444
|
+
const lng = lambda * RADIANS_TO_DEGREES;
|
|
2445
|
+
const lat = phi * RADIANS_TO_DEGREES;
|
|
2446
|
+
const Z = (D / GLOBE_RADIUS - 1) * EARTH_RADIUS;
|
|
2447
|
+
return [lng, lat, Z];
|
|
2448
|
+
}
|
|
2449
|
+
projectFlat(xyz) {
|
|
2450
|
+
return xyz;
|
|
2451
|
+
}
|
|
2452
|
+
unprojectFlat(xyz) {
|
|
2453
|
+
return xyz;
|
|
2454
|
+
}
|
|
2455
|
+
/**
|
|
2456
|
+
* Pan the globe to place geographic coordinates at a screen pixel.
|
|
2457
|
+
* When `dragStartPosition` is supplied, applies the delta-based movement used by globe dragging.
|
|
2458
|
+
* @param coordinates - Geographic anchor, or the starting longitude, latitude and zoom.
|
|
2459
|
+
* @param screenPosition - Current screen position.
|
|
2460
|
+
* @param dragStartPosition - Screen position where a drag started.
|
|
2461
|
+
* @returns Updated viewport options.
|
|
2462
|
+
*/
|
|
2463
|
+
panByPosition(coordinates, screenPosition, dragStartPosition) {
|
|
2464
|
+
if (!dragStartPosition) {
|
|
2465
|
+
let anchorStrength = this.getZoomAnchorStrength(screenPosition);
|
|
2466
|
+
if (anchorStrength === 0) {
|
|
2467
|
+
return { longitude: this.longitude, latitude: this.latitude };
|
|
2468
|
+
}
|
|
2469
|
+
const currentCoordinates = this.unproject(screenPosition);
|
|
2470
|
+
const longitudeDelta = mod(coordinates[0] - currentCoordinates[0] + 180, 360) - 180;
|
|
2471
|
+
const latitudeDelta = coordinates[1] - currentCoordinates[1];
|
|
2472
|
+
const crossesPole = Math.abs(currentCoordinates[1]) > import_web_mercator3.MAX_LATITUDE || Math.abs(longitudeDelta) > 90;
|
|
2473
|
+
if (isGlobeNorthUp(this.bearing) && crossesPole) {
|
|
2474
|
+
return { longitude: this.longitude, latitude: this.latitude };
|
|
2475
|
+
}
|
|
2476
|
+
if (isGlobeNorthUp(this.bearing) && latitudeDelta !== 0) {
|
|
2477
|
+
const latitudeLimit = latitudeDelta > 0 ? import_web_mercator3.MAX_LATITUDE : -import_web_mercator3.MAX_LATITUDE;
|
|
2478
|
+
const latitudeConstraintStrength = (latitudeLimit - this.latitude) / latitudeDelta;
|
|
2479
|
+
anchorStrength = Math.min(anchorStrength, Math.max(0, latitudeConstraintStrength));
|
|
2480
|
+
}
|
|
2481
|
+
const longitude2 = this.longitude + longitudeDelta * anchorStrength;
|
|
2482
|
+
const latitude2 = Math.max(Math.min(this.latitude + latitudeDelta * anchorStrength, 90), -90);
|
|
2483
|
+
return { longitude: longitude2, latitude: latitude2 };
|
|
2484
|
+
}
|
|
2485
|
+
const [startLongitude, startLatitude, startZoom] = coordinates;
|
|
2486
|
+
const scale = Math.pow(2, this.zoom - zoomAdjust(this.latitude));
|
|
2487
|
+
const rotationSpeed = 0.25 / scale;
|
|
2488
|
+
const longitude = startLongitude + rotationSpeed * (dragStartPosition[0] - screenPosition[0]);
|
|
2489
|
+
let latitude = startLatitude - rotationSpeed * (dragStartPosition[1] - screenPosition[1]);
|
|
2490
|
+
latitude = Math.max(Math.min(latitude, 90), -90);
|
|
2491
|
+
const nextViewState = { longitude, latitude, zoom: startZoom - zoomAdjust(startLatitude) };
|
|
2492
|
+
nextViewState.zoom += zoomAdjust(nextViewState.latitude);
|
|
2493
|
+
return nextViewState;
|
|
2494
|
+
}
|
|
2495
|
+
};
|
|
2496
|
+
GlobeViewport.displayName = "GlobeViewport";
|
|
2497
|
+
function zoomAdjust(latitude, clampToPoles) {
|
|
2498
|
+
if (clampToPoles) {
|
|
2499
|
+
latitude = Math.max(Math.min(latitude, import_web_mercator3.MAX_LATITUDE), -import_web_mercator3.MAX_LATITUDE);
|
|
2500
|
+
}
|
|
2501
|
+
const scaleAdjust = Math.PI * Math.cos(latitude * Math.PI / 180);
|
|
2502
|
+
return Math.log2(scaleAdjust);
|
|
2503
|
+
}
|
|
2504
|
+
function transformVector(matrix, vector) {
|
|
2505
|
+
const result = import_core5.vec4.transformMat4([], vector, matrix);
|
|
2506
|
+
import_core5.vec4.scale(result, result, 1 / result[3]);
|
|
2507
|
+
return result;
|
|
2508
|
+
}
|
|
2509
|
+
|
|
2510
|
+
// ../core/src/viewports/orthographic-viewport.ts
|
|
2511
|
+
var import_core6 = require("@math.gl/core");
|
|
2512
|
+
var import_web_mercator4 = require("@math.gl/web-mercator");
|
|
2513
|
+
var viewMatrix = new import_core6.Matrix4().lookAt({ eye: [0, 0, 1] });
|
|
2514
|
+
function getProjectionMatrix({
|
|
2515
|
+
width,
|
|
2516
|
+
height,
|
|
2517
|
+
near,
|
|
2518
|
+
far,
|
|
2519
|
+
padding
|
|
2520
|
+
}) {
|
|
2521
|
+
let left = -width / 2;
|
|
2522
|
+
let right = width / 2;
|
|
2523
|
+
let bottom = -height / 2;
|
|
2524
|
+
let top = height / 2;
|
|
2525
|
+
if (padding) {
|
|
2526
|
+
const { left: l = 0, right: r = 0, top: t = 0, bottom: b = 0 } = padding;
|
|
2527
|
+
const offsetX = (0, import_core6.clamp)((l + width - r) / 2, 0, width) - width / 2;
|
|
2528
|
+
const offsetY = (0, import_core6.clamp)((t + height - b) / 2, 0, height) - height / 2;
|
|
2529
|
+
left -= offsetX;
|
|
2530
|
+
right -= offsetX;
|
|
2531
|
+
bottom += offsetY;
|
|
2532
|
+
top += offsetY;
|
|
2533
|
+
}
|
|
2534
|
+
return new import_core6.Matrix4().ortho({
|
|
2535
|
+
left,
|
|
2536
|
+
right,
|
|
2537
|
+
bottom,
|
|
2538
|
+
top,
|
|
2539
|
+
near,
|
|
2540
|
+
far
|
|
2541
|
+
});
|
|
2542
|
+
}
|
|
2543
|
+
var OrthographicViewport = class extends Viewport {
|
|
2544
|
+
constructor(props) {
|
|
2545
|
+
const {
|
|
2546
|
+
width,
|
|
2547
|
+
height,
|
|
2548
|
+
near = 0.1,
|
|
2549
|
+
far = 1e3,
|
|
2550
|
+
zoom = 0,
|
|
2551
|
+
target = [0, 0, 0],
|
|
2552
|
+
padding = null,
|
|
2553
|
+
flipY = true
|
|
2554
|
+
} = props;
|
|
2555
|
+
const zoomX = props.zoomX ?? (Array.isArray(zoom) ? zoom[0] : zoom);
|
|
2556
|
+
const zoomY = props.zoomY ?? (Array.isArray(zoom) ? zoom[1] : zoom);
|
|
2557
|
+
const zoom_ = Number.isFinite(props.zoom) ? props.zoom : Math.min(zoomX, zoomY);
|
|
2558
|
+
const scale = Math.pow(2, zoom_);
|
|
2559
|
+
let distanceScales;
|
|
2560
|
+
if (zoomX !== zoom_ || zoomY !== zoom_) {
|
|
2561
|
+
const scaleX = Math.pow(2, zoomX);
|
|
2562
|
+
const scaleY = Math.pow(2, zoomY);
|
|
2563
|
+
distanceScales = {
|
|
2564
|
+
unitsPerMeter: [scaleX / scale, scaleY / scale, 1],
|
|
2565
|
+
metersPerUnit: [scale / scaleX, scale / scaleY, 1]
|
|
2566
|
+
};
|
|
2567
|
+
}
|
|
2568
|
+
super({
|
|
2569
|
+
...props,
|
|
2570
|
+
// in case viewState contains longitude/latitude values,
|
|
2571
|
+
// make sure that the base Viewport class does not treat this as a geospatial viewport
|
|
2572
|
+
longitude: void 0,
|
|
2573
|
+
position: target,
|
|
2574
|
+
viewMatrix: viewMatrix.clone().scale([scale, scale * (flipY ? -1 : 1), scale]),
|
|
2575
|
+
projectionMatrix: getProjectionMatrix({
|
|
2576
|
+
width: width || 1,
|
|
2577
|
+
height: height || 1,
|
|
2578
|
+
padding,
|
|
2579
|
+
near,
|
|
2580
|
+
far
|
|
2581
|
+
}),
|
|
2582
|
+
zoom: zoom_,
|
|
2583
|
+
distanceScales
|
|
2584
|
+
});
|
|
2585
|
+
this.target = target;
|
|
2586
|
+
this.zoomX = zoomX;
|
|
2587
|
+
this.zoomY = zoomY;
|
|
2588
|
+
this.flipY = flipY;
|
|
2589
|
+
}
|
|
2590
|
+
projectFlat([X, Y]) {
|
|
2591
|
+
const { unitsPerMeter: unitsPerMeter2 } = this.distanceScales;
|
|
2592
|
+
return [X * unitsPerMeter2[0], Y * unitsPerMeter2[1]];
|
|
2593
|
+
}
|
|
2594
|
+
unprojectFlat([x, y]) {
|
|
2595
|
+
const { metersPerUnit } = this.distanceScales;
|
|
2596
|
+
return [x * metersPerUnit[0], y * metersPerUnit[1]];
|
|
2597
|
+
}
|
|
2598
|
+
/* Needed by LinearInterpolator */
|
|
2599
|
+
panByPosition(coords, pixel, startPixel) {
|
|
2600
|
+
const fromLocation = (0, import_web_mercator4.pixelsToWorld)(pixel, this.pixelUnprojectionMatrix);
|
|
2601
|
+
const toLocation = this.projectFlat(coords);
|
|
2602
|
+
const translate = import_core6.vec2.add([], toLocation, import_core6.vec2.negate([], fromLocation));
|
|
2603
|
+
const newCenter = import_core6.vec2.add([], this.center, translate);
|
|
2604
|
+
return { target: this.unprojectFlat(newCenter) };
|
|
2605
|
+
}
|
|
2606
|
+
};
|
|
2607
|
+
OrthographicViewport.displayName = "OrthographicViewport";
|
|
2608
|
+
|
|
2609
|
+
// ../core/src/lib/layer-extension.ts
|
|
2610
|
+
var LayerExtension = class {
|
|
2611
|
+
static get componentName() {
|
|
2612
|
+
return Object.prototype.hasOwnProperty.call(this, "extensionName") ? this.extensionName : "";
|
|
2613
|
+
}
|
|
2614
|
+
constructor(opts) {
|
|
2615
|
+
if (opts) {
|
|
2616
|
+
this.opts = opts;
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
/** Returns true if two extensions are equivalent */
|
|
2620
|
+
equals(extension) {
|
|
2621
|
+
if (this === extension) {
|
|
2622
|
+
return true;
|
|
2623
|
+
}
|
|
2624
|
+
return this.constructor === extension.constructor && deepEqual(this.opts, extension.opts, 1);
|
|
2625
|
+
}
|
|
2626
|
+
/** Only called if attached to a primitive layer */
|
|
2627
|
+
getShaders(extension) {
|
|
2628
|
+
return null;
|
|
2629
|
+
}
|
|
2630
|
+
/** Only called if attached to a CompositeLayer */
|
|
2631
|
+
getSubLayerProps(extension) {
|
|
2632
|
+
const { defaultProps: defaultProps9 } = extension.constructor;
|
|
2633
|
+
const newProps = {
|
|
2634
|
+
updateTriggers: {}
|
|
2635
|
+
};
|
|
2636
|
+
for (const key in defaultProps9) {
|
|
2637
|
+
if (key in this.props) {
|
|
2638
|
+
const propDef = defaultProps9[key];
|
|
2639
|
+
const propValue = this.props[key];
|
|
2640
|
+
newProps[key] = propValue;
|
|
2641
|
+
if (propDef && propDef.type === "accessor") {
|
|
2642
|
+
newProps.updateTriggers[key] = this.props.updateTriggers[key];
|
|
2643
|
+
if (typeof propValue === "function") {
|
|
2644
|
+
newProps[key] = this.getSubLayerAccessor(propValue);
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
return newProps;
|
|
2650
|
+
}
|
|
2651
|
+
/* eslint-disable @typescript-eslint/no-empty-function */
|
|
2652
|
+
initializeState(context, extension) {
|
|
2653
|
+
}
|
|
2654
|
+
updateState(params, extension) {
|
|
2655
|
+
}
|
|
2656
|
+
onNeedsRedraw(extension) {
|
|
2657
|
+
}
|
|
2658
|
+
getNeedsPickingBuffer(extension) {
|
|
2659
|
+
return false;
|
|
2660
|
+
}
|
|
2661
|
+
draw(params, extension) {
|
|
2662
|
+
}
|
|
2663
|
+
finalizeState(context, extension) {
|
|
2664
|
+
}
|
|
2665
|
+
};
|
|
2666
|
+
LayerExtension.defaultProps = {};
|
|
2667
|
+
LayerExtension.extensionName = "LayerExtension";
|
|
38
2668
|
|
|
39
2669
|
// dist/brushing/shader-module.js
|
|
40
|
-
var import_core = require("@deck.gl/core");
|
|
41
2670
|
var uniformBlock = (
|
|
42
2671
|
/* glsl */
|
|
43
2672
|
`layout(std140) uniform brushingUniforms {
|
|
@@ -75,7 +2704,7 @@ var vertex = (
|
|
|
75
2704
|
}
|
|
76
2705
|
`
|
|
77
2706
|
);
|
|
78
|
-
var
|
|
2707
|
+
var vs2 = `
|
|
79
2708
|
${uniformBlock}
|
|
80
2709
|
${vertex}
|
|
81
2710
|
`;
|
|
@@ -85,7 +2714,7 @@ var fragment = (
|
|
|
85
2714
|
in float brushing_isVisible;
|
|
86
2715
|
`
|
|
87
2716
|
);
|
|
88
|
-
var
|
|
2717
|
+
var fs2 = `
|
|
89
2718
|
${uniformBlock}
|
|
90
2719
|
${fragment}
|
|
91
2720
|
`;
|
|
@@ -128,9 +2757,9 @@ var inject = {
|
|
|
128
2757
|
};
|
|
129
2758
|
var shader_module_default = {
|
|
130
2759
|
name: "brushing",
|
|
131
|
-
dependencies: [
|
|
132
|
-
vs,
|
|
133
|
-
fs,
|
|
2760
|
+
dependencies: [project_default],
|
|
2761
|
+
vs: vs2,
|
|
2762
|
+
fs: fs2,
|
|
134
2763
|
inject,
|
|
135
2764
|
getUniforms: (opts) => {
|
|
136
2765
|
if (!opts || !("viewport" in opts)) {
|
|
@@ -159,7 +2788,7 @@ var defaultProps = {
|
|
|
159
2788
|
brushingEnabled: true,
|
|
160
2789
|
brushingRadius: 1e4
|
|
161
2790
|
};
|
|
162
|
-
var BrushingExtension = class extends
|
|
2791
|
+
var BrushingExtension = class extends LayerExtension {
|
|
163
2792
|
getShaders() {
|
|
164
2793
|
return {
|
|
165
2794
|
modules: [shader_module_default]
|
|
@@ -214,9 +2843,6 @@ BrushingExtension.defaultProps = defaultProps;
|
|
|
214
2843
|
BrushingExtension.extensionName = "BrushingExtension";
|
|
215
2844
|
var brushing_extension_default = BrushingExtension;
|
|
216
2845
|
|
|
217
|
-
// dist/data-filter/data-filter-extension.js
|
|
218
|
-
var import_core3 = require("@deck.gl/core");
|
|
219
|
-
|
|
220
2846
|
// dist/data-filter/shader-module.js
|
|
221
2847
|
var uniformBlock2 = (
|
|
222
2848
|
/* glsl */
|
|
@@ -400,7 +3026,7 @@ float dataFilter_reduceValue(vec4 value) {
|
|
|
400
3026
|
#endif
|
|
401
3027
|
`
|
|
402
3028
|
);
|
|
403
|
-
var
|
|
3029
|
+
var vs3 = `
|
|
404
3030
|
${uniformBlock2}
|
|
405
3031
|
${vertex2}
|
|
406
3032
|
`;
|
|
@@ -410,11 +3036,11 @@ var fragment2 = (
|
|
|
410
3036
|
in float dataFilter_value;
|
|
411
3037
|
`
|
|
412
3038
|
);
|
|
413
|
-
var
|
|
3039
|
+
var fs3 = `
|
|
414
3040
|
${uniformBlock2}
|
|
415
3041
|
${fragment2}
|
|
416
3042
|
`;
|
|
417
|
-
function
|
|
3043
|
+
function getUniforms2(opts) {
|
|
418
3044
|
if (!opts || !("extensions" in opts)) {
|
|
419
3045
|
return {};
|
|
420
3046
|
}
|
|
@@ -449,7 +3075,7 @@ function getUniforms64(opts) {
|
|
|
449
3075
|
if (!opts || !("extensions" in opts)) {
|
|
450
3076
|
return {};
|
|
451
3077
|
}
|
|
452
|
-
const uniforms =
|
|
3078
|
+
const uniforms = getUniforms2(opts);
|
|
453
3079
|
const min64High = uniforms.min.map(Math.fround);
|
|
454
3080
|
uniforms.min = uniforms.min.map((x, i) => x - min64High[i]);
|
|
455
3081
|
uniforms.softMin = uniforms.softMin.map((x, i) => x - min64High[i]);
|
|
@@ -527,16 +3153,16 @@ function uniformTypesFromOptions(opts) {
|
|
|
527
3153
|
}
|
|
528
3154
|
var dataFilter = {
|
|
529
3155
|
name: "dataFilter",
|
|
530
|
-
vs:
|
|
531
|
-
fs:
|
|
3156
|
+
vs: vs3,
|
|
3157
|
+
fs: fs3,
|
|
532
3158
|
inject: inject2,
|
|
533
|
-
getUniforms,
|
|
3159
|
+
getUniforms: getUniforms2,
|
|
534
3160
|
uniformTypesFromOptions
|
|
535
3161
|
};
|
|
536
3162
|
var dataFilter64 = {
|
|
537
3163
|
name: "dataFilter",
|
|
538
|
-
vs:
|
|
539
|
-
fs:
|
|
3164
|
+
vs: vs3,
|
|
3165
|
+
fs: fs3,
|
|
540
3166
|
inject: inject2,
|
|
541
3167
|
getUniforms: getUniforms64,
|
|
542
3168
|
uniformTypesFromOptions
|
|
@@ -681,24 +3307,24 @@ var DATA_TYPE_FROM_SIZE = {
|
|
|
681
3307
|
3: "vec3",
|
|
682
3308
|
4: "vec4"
|
|
683
3309
|
};
|
|
684
|
-
var DataFilterExtension = class extends
|
|
3310
|
+
var DataFilterExtension = class extends LayerExtension {
|
|
685
3311
|
constructor(opts = {}) {
|
|
686
3312
|
super({ ...defaultOptions, ...opts });
|
|
687
3313
|
}
|
|
688
3314
|
getShaders(extension) {
|
|
689
3315
|
const { categorySize, filterSize, fp64: fp642 } = extension.opts;
|
|
690
|
-
const
|
|
3316
|
+
const defines2 = {};
|
|
691
3317
|
if (categorySize) {
|
|
692
|
-
|
|
693
|
-
|
|
3318
|
+
defines2.DATACATEGORY_TYPE = CATEGORY_TYPE_FROM_SIZE[categorySize];
|
|
3319
|
+
defines2.DATACATEGORY_CHANNELS = categorySize;
|
|
694
3320
|
}
|
|
695
3321
|
if (filterSize) {
|
|
696
|
-
|
|
697
|
-
|
|
3322
|
+
defines2.DATAFILTER_TYPE = DATA_TYPE_FROM_SIZE[filterSize];
|
|
3323
|
+
defines2.DATAFILTER_DOUBLE = Boolean(fp642);
|
|
698
3324
|
}
|
|
699
3325
|
const module2 = fp642 ? dataFilter64 : dataFilter;
|
|
700
3326
|
module2.uniformTypes = module2.uniformTypesFromOptions(extension.opts);
|
|
701
|
-
return { modules: [module2], defines };
|
|
3327
|
+
return { modules: [module2], defines: defines2 };
|
|
702
3328
|
}
|
|
703
3329
|
initializeState(context, extension) {
|
|
704
3330
|
const attributeManager = this.getAttributeManager();
|
|
@@ -768,7 +3394,7 @@ var DataFilterExtension = class extends import_core3.LayerExtension {
|
|
|
768
3394
|
}
|
|
769
3395
|
}
|
|
770
3396
|
if (attributeManager == null ? void 0 : attributeManager.attributes.filterCategoryValues) {
|
|
771
|
-
const categoryBitMaskNeedsUpdate = attributeManager.attributes.filterCategoryValues.needsUpdate() || !(
|
|
3397
|
+
const categoryBitMaskNeedsUpdate = attributeManager.attributes.filterCategoryValues.needsUpdate() || !deepEqual(props.filterCategories, oldProps.filterCategories, 2);
|
|
772
3398
|
if (categoryBitMaskNeedsUpdate) {
|
|
773
3399
|
this.setState({ categoryBitMask: null });
|
|
774
3400
|
}
|
|
@@ -862,7 +3488,7 @@ var DataFilterExtension = class extends import_core3.LayerExtension {
|
|
|
862
3488
|
const channel = c * (maxCategories / 32) + Math.floor(key / 32);
|
|
863
3489
|
categoryBitMask[channel] += Math.pow(2, key % 32);
|
|
864
3490
|
} else {
|
|
865
|
-
|
|
3491
|
+
log_default.warn(`Exceeded maximum number of categories (${maxCategories})`)();
|
|
866
3492
|
}
|
|
867
3493
|
}
|
|
868
3494
|
}
|
|
@@ -884,12 +3510,8 @@ DataFilterExtension.defaultProps = defaultProps2;
|
|
|
884
3510
|
DataFilterExtension.extensionName = "DataFilterExtension";
|
|
885
3511
|
var data_filter_extension_default = DataFilterExtension;
|
|
886
3512
|
|
|
887
|
-
// dist/fp64/fp64-extension.js
|
|
888
|
-
var import_core5 = require("@deck.gl/core");
|
|
889
|
-
|
|
890
3513
|
// dist/fp64/project64.js
|
|
891
|
-
var
|
|
892
|
-
var import_core4 = require("@deck.gl/core");
|
|
3514
|
+
var import_shadertools3 = require("@luma.gl/shadertools");
|
|
893
3515
|
|
|
894
3516
|
// dist/fp64/project64.glsl.js
|
|
895
3517
|
var project64_glsl_default = `const vec2 WORLD_SCALE_FP64 = vec2(81.4873275756836, 0.0000032873668232014097);
|
|
@@ -968,12 +3590,12 @@ position, position64xyLow, offset, commonPosition
|
|
|
968
3590
|
`;
|
|
969
3591
|
|
|
970
3592
|
// dist/fp64/project64.js
|
|
971
|
-
var { fp64ify, fp64ifyMatrix4 } =
|
|
3593
|
+
var { fp64ify, fp64ifyMatrix4 } = import_shadertools3.fp64;
|
|
972
3594
|
var project64_default = {
|
|
973
3595
|
name: "project64",
|
|
974
|
-
dependencies: [
|
|
3596
|
+
dependencies: [project_default, import_shadertools3.fp64],
|
|
975
3597
|
vs: project64_glsl_default,
|
|
976
|
-
getUniforms:
|
|
3598
|
+
getUniforms: getUniforms3,
|
|
977
3599
|
uniformTypes: {
|
|
978
3600
|
scale: "vec2<f32>",
|
|
979
3601
|
// Cannot pass as vec2[16], so instead split into 2 mat4x4
|
|
@@ -981,8 +3603,8 @@ var project64_default = {
|
|
|
981
3603
|
viewProjectionMatrix64Low: "mat4x4<f32>"
|
|
982
3604
|
}
|
|
983
3605
|
};
|
|
984
|
-
var getMemoizedUniforms = (
|
|
985
|
-
function
|
|
3606
|
+
var getMemoizedUniforms = memoize(calculateUniforms);
|
|
3607
|
+
function getUniforms3(opts) {
|
|
986
3608
|
if (opts && "viewport" in opts) {
|
|
987
3609
|
const { viewProjectionMatrix, scale } = opts.viewport;
|
|
988
3610
|
return getMemoizedUniforms({ viewProjectionMatrix, scale });
|
|
@@ -1009,7 +3631,7 @@ function calculateUniforms({ viewProjectionMatrix, scale }) {
|
|
|
1009
3631
|
}
|
|
1010
3632
|
|
|
1011
3633
|
// dist/fp64/fp64-extension.js
|
|
1012
|
-
var Fp64Extension = class extends
|
|
3634
|
+
var Fp64Extension = class extends LayerExtension {
|
|
1013
3635
|
getShaders() {
|
|
1014
3636
|
const { coordinateSystem } = this.props;
|
|
1015
3637
|
if (coordinateSystem !== "lnglat" && coordinateSystem !== "default") {
|
|
@@ -1028,8 +3650,7 @@ Fp64Extension.extensionName = "Fp64Extension";
|
|
|
1028
3650
|
var fp64_extension_default = Fp64Extension;
|
|
1029
3651
|
|
|
1030
3652
|
// dist/path-style/path-style-extension.js
|
|
1031
|
-
var
|
|
1032
|
-
var import_core7 = require("@math.gl/core");
|
|
3653
|
+
var import_core13 = require("@math.gl/core");
|
|
1033
3654
|
|
|
1034
3655
|
// dist/path-style/shaders.glsl.js
|
|
1035
3656
|
var dashShaders = {
|
|
@@ -1037,26 +3658,68 @@ var dashShaders = {
|
|
|
1037
3658
|
"vs:#decl": `
|
|
1038
3659
|
in vec2 instanceDashArrays;
|
|
1039
3660
|
#ifdef HIGH_PRECISION_DASH
|
|
1040
|
-
in
|
|
3661
|
+
in vec2 instanceDashOffsets;
|
|
1041
3662
|
#endif
|
|
1042
3663
|
out vec2 vDashArray;
|
|
1043
3664
|
out float vDashOffset;
|
|
3665
|
+
out float vDashPathLength;
|
|
3666
|
+
layout(std140) uniform pathStyleUniforms {
|
|
3667
|
+
float dashAlignMode;
|
|
3668
|
+
bool dashGapPickable;
|
|
3669
|
+
highp int dashUnits;
|
|
3670
|
+
} pathStyle;
|
|
1044
3671
|
`,
|
|
1045
3672
|
"vs:#main-end": `
|
|
1046
|
-
|
|
3673
|
+
float dashWidthPixels = path.billboard
|
|
3674
|
+
? width.x * project.focalDistance
|
|
3675
|
+
: width.x * project.scale;
|
|
3676
|
+
float strokeHalfWidthPixels = path.billboard ? width.x : width.x * project.scale;
|
|
3677
|
+
float dashUnitPixels = strokeHalfWidthPixels;
|
|
3678
|
+
if (pathStyle.dashUnits == 1) {
|
|
3679
|
+
dashUnitPixels = 1.0;
|
|
3680
|
+
} else if (pathStyle.dashUnits == 2) {
|
|
3681
|
+
dashUnitPixels = project_size_to_pixel(1.0);
|
|
3682
|
+
} else if (pathStyle.dashUnits == 3) {
|
|
3683
|
+
dashUnitPixels = project.scale;
|
|
3684
|
+
}
|
|
3685
|
+
vDashArray = instanceDashArrays * (dashUnitPixels / dashWidthPixels);
|
|
1047
3686
|
#ifdef HIGH_PRECISION_DASH
|
|
1048
|
-
|
|
3687
|
+
vec2 dashOffsetAndLength = (instanceDashOffsets * project.scale) / dashWidthPixels;
|
|
3688
|
+
vDashPathLength = dashOffsetAndLength.y;
|
|
3689
|
+
float dashUnitLength = vDashArray.x + vDashArray.y;
|
|
3690
|
+
float dashPeriod = pathStyle.dashAlignMode == 0.0
|
|
3691
|
+
? dashUnitLength
|
|
3692
|
+
: vDashPathLength / max(round(vDashPathLength / max(dashUnitLength, 0.0001)), 1.0);
|
|
3693
|
+
vDashOffset = dashPeriod > 0.0 ? mod(dashOffsetAndLength.x, dashPeriod) : 0.0;
|
|
1049
3694
|
#else
|
|
1050
3695
|
vDashOffset = 0.0;
|
|
3696
|
+
vDashPathLength = 0.0;
|
|
1051
3697
|
#endif
|
|
1052
3698
|
`,
|
|
1053
3699
|
"fs:#decl": `
|
|
1054
3700
|
layout(std140) uniform pathStyleUniforms {
|
|
1055
3701
|
float dashAlignMode;
|
|
1056
3702
|
bool dashGapPickable;
|
|
3703
|
+
highp int dashUnits;
|
|
1057
3704
|
} pathStyle;
|
|
1058
3705
|
in vec2 vDashArray;
|
|
1059
3706
|
in float vDashOffset;
|
|
3707
|
+
in float vDashPathLength;
|
|
3708
|
+
float dashPatternIntegral(float position, float solidLength, float unitLength) {
|
|
3709
|
+
return floor(position / unitLength) * solidLength +
|
|
3710
|
+
min(mod(position, unitLength), solidLength);
|
|
3711
|
+
}
|
|
3712
|
+
float dashPatternCoverage(
|
|
3713
|
+
float position,
|
|
3714
|
+
float solidLength,
|
|
3715
|
+
float unitLength,
|
|
3716
|
+
float filterWidth
|
|
3717
|
+
) {
|
|
3718
|
+
float halfFilter = 0.5 * filterWidth;
|
|
3719
|
+
float reducedPosition = mod(position, unitLength);
|
|
3720
|
+
return (dashPatternIntegral(reducedPosition + halfFilter, solidLength, unitLength) -
|
|
3721
|
+
dashPatternIntegral(reducedPosition - halfFilter, solidLength, unitLength)) / filterWidth;
|
|
3722
|
+
}
|
|
1060
3723
|
`,
|
|
1061
3724
|
// if given position is in the gap part of the dashed line
|
|
1062
3725
|
// dashArray.x: solid stroke length, relative to width
|
|
@@ -1067,36 +3730,90 @@ in float vDashOffset;
|
|
|
1067
3730
|
// 1 - stretch to fit, draw half dash at each end for nicer joints
|
|
1068
3731
|
// o-- ---- ---- ---- --o-- --o-- ---- --o
|
|
1069
3732
|
"fs:#main-start": `
|
|
3733
|
+
float dashCoverage = 1.0;
|
|
3734
|
+
bool shouldDiscardDash = false;
|
|
3735
|
+
bool inRoundedDashGap = false;
|
|
3736
|
+
float roundedDashResolvedCoverage = 1.0;
|
|
3737
|
+
float roundedDashSubPixelBlend = 0.0;
|
|
3738
|
+
float roundedDashDutyCycle = 1.0;
|
|
1070
3739
|
float solidLength = vDashArray.x;
|
|
1071
3740
|
float gapLength = vDashArray.y;
|
|
1072
3741
|
float unitLength = solidLength + gapLength;
|
|
3742
|
+
if (unitLength > 0.0 && gapLength > 0.0) {
|
|
1073
3743
|
float offset;
|
|
1074
|
-
if (unitLength > 0.0) {
|
|
1075
3744
|
if (pathStyle.dashAlignMode == 0.0) {
|
|
1076
3745
|
offset = vDashOffset;
|
|
1077
3746
|
} else {
|
|
1078
|
-
|
|
3747
|
+
#ifdef HIGH_PRECISION_DASH
|
|
3748
|
+
unitLength = vDashPathLength / max(round(vDashPathLength / unitLength), 1.0);
|
|
3749
|
+
#else
|
|
3750
|
+
unitLength = vPathLength / max(round(vPathLength / unitLength), 1.0);
|
|
3751
|
+
#endif
|
|
3752
|
+
solidLength = min(solidLength, unitLength);
|
|
1079
3753
|
offset = solidLength / 2.0;
|
|
3754
|
+
#ifdef HIGH_PRECISION_DASH
|
|
3755
|
+
offset += vDashOffset;
|
|
3756
|
+
#endif
|
|
1080
3757
|
}
|
|
1081
|
-
float
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
if (
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
float distToEnd = length(vec2(
|
|
3758
|
+
float alongPath = vPathPosition.y + offset;
|
|
3759
|
+
float unitOffset = mod(alongPath, unitLength);
|
|
3760
|
+
float filterWidth = max(fwidth(alongPath), 0.0001);
|
|
3761
|
+
if (bool(picking.isActive)) {
|
|
3762
|
+
bool inGap = unitOffset > solidLength;
|
|
3763
|
+
if (inGap && path.capType > 0.5) {
|
|
3764
|
+
inGap = length(vec2(
|
|
1089
3765
|
min(unitOffset - solidLength, unitLength - unitOffset),
|
|
1090
3766
|
vPathPosition.x
|
|
1091
|
-
));
|
|
1092
|
-
|
|
1093
|
-
if (!
|
|
1094
|
-
|
|
3767
|
+
)) > 1.0;
|
|
3768
|
+
}
|
|
3769
|
+
if (inGap && !pathStyle.dashGapPickable) {
|
|
3770
|
+
shouldDiscardDash = true;
|
|
3771
|
+
}
|
|
3772
|
+
} else if (path.capType <= 0.5) {
|
|
3773
|
+
dashCoverage = dashPatternCoverage(alongPath, solidLength, unitLength, filterWidth);
|
|
3774
|
+
} else {
|
|
3775
|
+
float distanceAlongGap = min(unitOffset - solidLength, unitLength - unitOffset);
|
|
3776
|
+
float distanceToEnd = length(vec2(max(distanceAlongGap, 0.0), vPathPosition.x));
|
|
3777
|
+
float capEdgePixels = (1.0 - distanceToEnd) / max(fwidth(distanceToEnd), 1e-6);
|
|
3778
|
+
if (distanceAlongGap > 0.0) {
|
|
3779
|
+
inRoundedDashGap = true;
|
|
3780
|
+
roundedDashResolvedCoverage = smoothedge(0.0, capEdgePixels);
|
|
3781
|
+
dashCoverage = roundedDashResolvedCoverage;
|
|
1095
3782
|
}
|
|
3783
|
+
float subPixelBlend = smoothstep(unitLength, 2.0 * unitLength, filterWidth);
|
|
3784
|
+
roundedDashSubPixelBlend = subPixelBlend;
|
|
3785
|
+
float boundedSolidLength = min(solidLength, unitLength);
|
|
3786
|
+
float effectiveGap = max(unitLength - boundedSolidLength, 0.0);
|
|
3787
|
+
float capSpan = 2.0 * sqrt(max(1.0 - vPathPosition.x * vPathPosition.x, 0.0));
|
|
3788
|
+
float roundedDutyCycle = clamp(
|
|
3789
|
+
(boundedSolidLength + min(effectiveGap, capSpan)) / unitLength,
|
|
3790
|
+
0.0,
|
|
3791
|
+
1.0
|
|
3792
|
+
);
|
|
3793
|
+
roundedDashDutyCycle = roundedDutyCycle;
|
|
3794
|
+
dashCoverage = mix(dashCoverage, roundedDutyCycle, subPixelBlend);
|
|
1096
3795
|
}
|
|
3796
|
+
dashCoverage = clamp(dashCoverage, 0.0, 1.0);
|
|
3797
|
+
shouldDiscardDash = shouldDiscardDash || dashCoverage <= 0.0;
|
|
1097
3798
|
}
|
|
3799
|
+
`,
|
|
3800
|
+
"fs:#main-end": `
|
|
3801
|
+
#ifdef ANTIALIASING
|
|
3802
|
+
if (inRoundedDashGap) {
|
|
3803
|
+
float pathCoverage = smoothedge(0.0, edgePixels);
|
|
3804
|
+
float resolvedCapMultiplier =
|
|
3805
|
+
min(pathCoverage, roundedDashResolvedCoverage) / max(pathCoverage, 1e-6);
|
|
3806
|
+
dashCoverage = mix(
|
|
3807
|
+
resolvedCapMultiplier,
|
|
3808
|
+
roundedDashDutyCycle,
|
|
3809
|
+
roundedDashSubPixelBlend
|
|
3810
|
+
);
|
|
1098
3811
|
}
|
|
3812
|
+
#endif
|
|
3813
|
+
if (shouldDiscardDash) {
|
|
3814
|
+
discard;
|
|
1099
3815
|
}
|
|
3816
|
+
fragColor.a *= dashCoverage;
|
|
1100
3817
|
`
|
|
1101
3818
|
}
|
|
1102
3819
|
};
|
|
@@ -1297,13 +4014,32 @@ float offsetDir = sign(instanceOffsets);
|
|
|
1297
4014
|
vPathPosition.x = (vPathPosition.x + offsetDir) * offsetWidth - offsetDir;
|
|
1298
4015
|
vPathPosition.y *= offsetWidth;
|
|
1299
4016
|
vPathLength *= offsetWidth;
|
|
4017
|
+
#ifdef DASH_ENABLED
|
|
4018
|
+
if (pathStyle.dashUnits != 0) {
|
|
4019
|
+
vDashArray *= offsetWidth;
|
|
4020
|
+
}
|
|
4021
|
+
vPathBounds *= offsetWidth;
|
|
4022
|
+
#ifdef HIGH_PRECISION_DASH
|
|
4023
|
+
vDashPathLength *= offsetWidth;
|
|
4024
|
+
float restoredDashUnitLength = vDashArray.x + vDashArray.y;
|
|
4025
|
+
float restoredDashPeriod = pathStyle.dashAlignMode == 0.0
|
|
4026
|
+
? restoredDashUnitLength
|
|
4027
|
+
: vDashPathLength /
|
|
4028
|
+
max(round(vDashPathLength / max(restoredDashUnitLength, 0.0001)), 1.0);
|
|
4029
|
+
vDashOffset = restoredDashPeriod > 0.0
|
|
4030
|
+
? mod(dashOffsetAndLength.x * offsetWidth, restoredDashPeriod)
|
|
4031
|
+
: 0.0;
|
|
4032
|
+
#else
|
|
4033
|
+
vDashOffset *= offsetWidth;
|
|
4034
|
+
#endif
|
|
4035
|
+
#endif
|
|
1300
4036
|
`,
|
|
1301
|
-
"fs:#main-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
if (isInside == 0.0) {
|
|
4037
|
+
"fs:#main-end": `
|
|
4038
|
+
#ifndef ANTIALIASING
|
|
4039
|
+
if (abs(vPathPosition.x) > 1.0) {
|
|
1305
4040
|
discard;
|
|
1306
4041
|
}
|
|
4042
|
+
#endif
|
|
1307
4043
|
`
|
|
1308
4044
|
}
|
|
1309
4045
|
};
|
|
@@ -1313,11 +4049,56 @@ var defaultProps3 = {
|
|
|
1313
4049
|
getDashArray: { type: "accessor", value: [0, 0] },
|
|
1314
4050
|
getOffset: { type: "accessor", value: 0 },
|
|
1315
4051
|
dashJustified: false,
|
|
1316
|
-
dashGapPickable: false
|
|
4052
|
+
dashGapPickable: false,
|
|
4053
|
+
dashUnits: "widths"
|
|
1317
4054
|
};
|
|
1318
|
-
var
|
|
1319
|
-
|
|
1320
|
-
|
|
4055
|
+
var DASH_UNITS = {
|
|
4056
|
+
widths: 0,
|
|
4057
|
+
pixels: 1,
|
|
4058
|
+
meters: 2,
|
|
4059
|
+
common: 3
|
|
4060
|
+
};
|
|
4061
|
+
var PATH_STYLE_ATTRIBUTES = ["instanceDashArrays", "instanceDashOffsets", "instanceOffsets"];
|
|
4062
|
+
function dashMetricsProjectionPropsChanged({ props, oldProps }) {
|
|
4063
|
+
return !deepEqual(props.modelMatrix, oldProps.modelMatrix, 2) || props.coordinateSystem !== oldProps.coordinateSystem || !deepEqual(props.coordinateOrigin, oldProps.coordinateOrigin, 1);
|
|
4064
|
+
}
|
|
4065
|
+
function projectRenderedPathPosition(layer, position, projectUniforms) {
|
|
4066
|
+
const viewport = layer.context.viewport;
|
|
4067
|
+
if (!(viewport instanceof WebMercatorViewport) || viewport.zoom < 12) {
|
|
4068
|
+
return layer.projectPosition(position, { autoOffset: false });
|
|
4069
|
+
}
|
|
4070
|
+
const positionWorld = import_core13.vec4.transformMat4([], [position[0], position[1], position[2] || 0, 1], projectUniforms.modelMatrix);
|
|
4071
|
+
const coordinateSystem = layer.props.coordinateSystem === "default" ? "lnglat" : layer.props.coordinateSystem;
|
|
4072
|
+
if (coordinateSystem === "lnglat") {
|
|
4073
|
+
if (Math.abs(positionWorld[1] - projectUniforms.coordinateOrigin[1]) > 0.25) {
|
|
4074
|
+
let longitude = positionWorld[0];
|
|
4075
|
+
if (projectUniforms.wrapLongitude) {
|
|
4076
|
+
longitude = ((longitude + 180) % 360 + 360) % 360 - 180;
|
|
4077
|
+
}
|
|
4078
|
+
const commonPosition = viewport.projectPosition([longitude, positionWorld[1], 0]);
|
|
4079
|
+
return [
|
|
4080
|
+
commonPosition[0] - projectUniforms.commonOrigin[0],
|
|
4081
|
+
commonPosition[1] - projectUniforms.commonOrigin[1],
|
|
4082
|
+
positionWorld[2] * projectUniforms.commonUnitsPerMeter[2]
|
|
4083
|
+
];
|
|
4084
|
+
}
|
|
4085
|
+
import_core13.vec3.sub(positionWorld, positionWorld, projectUniforms.coordinateOrigin);
|
|
4086
|
+
} else if (coordinateSystem === "cartesian") {
|
|
4087
|
+
import_core13.vec3.sub(positionWorld, positionWorld, projectUniforms.coordinateOrigin);
|
|
4088
|
+
}
|
|
4089
|
+
const deltaLatitude = positionWorld[1];
|
|
4090
|
+
const scale = import_core13.vec3.scaleAndAdd([], projectUniforms.commonUnitsPerWorldUnit, projectUniforms.commonUnitsPerWorldUnit2, deltaLatitude);
|
|
4091
|
+
return import_core13.vec3.multiply([], positionWorld, scale);
|
|
4092
|
+
}
|
|
4093
|
+
var PathStyleExtension = class extends LayerExtension {
|
|
4094
|
+
constructor({ dash = false, offset = false, dashMode, highPrecisionDash = false } = {}) {
|
|
4095
|
+
const resolvedDashMode = dashMode ?? (highPrecisionDash ? "path" : "segment");
|
|
4096
|
+
super({
|
|
4097
|
+
dash: dash || highPrecisionDash || dashMode !== void 0,
|
|
4098
|
+
offset,
|
|
4099
|
+
dashMode: resolvedDashMode,
|
|
4100
|
+
highPrecisionDash: resolvedDashMode === "path"
|
|
4101
|
+
});
|
|
1321
4102
|
}
|
|
1322
4103
|
getLayerType(layer) {
|
|
1323
4104
|
if ("pathTesselator" in layer.state) {
|
|
@@ -1332,6 +4113,59 @@ var PathStyleExtension = class extends import_core6.LayerExtension {
|
|
|
1332
4113
|
}
|
|
1333
4114
|
return null;
|
|
1334
4115
|
}
|
|
4116
|
+
synchronizeAttributes(layer) {
|
|
4117
|
+
const attributeManager = layer.getAttributeManager();
|
|
4118
|
+
const layerType = this.getLayerType(layer);
|
|
4119
|
+
if (!attributeManager || !layerType) {
|
|
4120
|
+
return false;
|
|
4121
|
+
}
|
|
4122
|
+
const attributes = attributeManager.getAttributes();
|
|
4123
|
+
const desiredAttributes = /* @__PURE__ */ new Set();
|
|
4124
|
+
if (this.opts.dash) {
|
|
4125
|
+
desiredAttributes.add("instanceDashArrays");
|
|
4126
|
+
}
|
|
4127
|
+
if (layerType === "path" && this.opts.dash && this.opts.dashMode === "path") {
|
|
4128
|
+
desiredAttributes.add("instanceDashOffsets");
|
|
4129
|
+
}
|
|
4130
|
+
if (layerType === "path" && this.opts.offset) {
|
|
4131
|
+
desiredAttributes.add("instanceOffsets");
|
|
4132
|
+
}
|
|
4133
|
+
let topologyChanged = false;
|
|
4134
|
+
for (const attributeName of PATH_STYLE_ATTRIBUTES) {
|
|
4135
|
+
if (attributes[attributeName] && !desiredAttributes.has(attributeName)) {
|
|
4136
|
+
attributeManager.remove([attributeName]);
|
|
4137
|
+
topologyChanged = true;
|
|
4138
|
+
}
|
|
4139
|
+
}
|
|
4140
|
+
if (desiredAttributes.has("instanceDashArrays") && !attributes.instanceDashArrays) {
|
|
4141
|
+
attributeManager.addInstanced({
|
|
4142
|
+
instanceDashArrays: { size: 2, accessor: "getDashArray" }
|
|
4143
|
+
});
|
|
4144
|
+
topologyChanged = true;
|
|
4145
|
+
}
|
|
4146
|
+
if (desiredAttributes.has("instanceDashOffsets") && !attributes.instanceDashOffsets) {
|
|
4147
|
+
attributeManager.addInstanced({
|
|
4148
|
+
instanceDashOffsets: {
|
|
4149
|
+
// [distance from the start of the path, total length of the path]
|
|
4150
|
+
size: 2,
|
|
4151
|
+
// Recalculate from rendered geometry when getPath changes. A binary getPath buffer
|
|
4152
|
+
// contains positions, not dash metrics, so keep it as an update trigger rather than
|
|
4153
|
+
// binding it directly to this attribute.
|
|
4154
|
+
accessor: ["getPath"],
|
|
4155
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
4156
|
+
update: this.calculateDashMetrics
|
|
4157
|
+
}
|
|
4158
|
+
});
|
|
4159
|
+
topologyChanged = true;
|
|
4160
|
+
}
|
|
4161
|
+
if (desiredAttributes.has("instanceOffsets") && !attributes.instanceOffsets) {
|
|
4162
|
+
attributeManager.addInstanced({
|
|
4163
|
+
instanceOffsets: { size: 1, accessor: "getOffset" }
|
|
4164
|
+
});
|
|
4165
|
+
topologyChanged = true;
|
|
4166
|
+
}
|
|
4167
|
+
return topologyChanged;
|
|
4168
|
+
}
|
|
1335
4169
|
isEnabled(layer) {
|
|
1336
4170
|
return this.getLayerType(layer) !== null;
|
|
1337
4171
|
}
|
|
@@ -1355,60 +4189,58 @@ var PathStyleExtension = class extends import_core6.LayerExtension {
|
|
|
1355
4189
|
return { modules: [pathStyle2] };
|
|
1356
4190
|
}
|
|
1357
4191
|
let result = {};
|
|
1358
|
-
const
|
|
4192
|
+
const defines2 = {};
|
|
1359
4193
|
if (extension.opts.dash) {
|
|
1360
|
-
result = (
|
|
1361
|
-
|
|
1362
|
-
|
|
4194
|
+
result = mergeShaders(result, dashShaders);
|
|
4195
|
+
defines2.DASH_ENABLED = true;
|
|
4196
|
+
if (extension.opts.dashMode === "path") {
|
|
4197
|
+
defines2.HIGH_PRECISION_DASH = true;
|
|
1363
4198
|
}
|
|
1364
4199
|
}
|
|
1365
4200
|
if (extension.opts.offset) {
|
|
1366
|
-
result = (
|
|
4201
|
+
result = mergeShaders(result, offsetShaders);
|
|
4202
|
+
defines2.PATH_STYLE_OFFSET = true;
|
|
1367
4203
|
}
|
|
1368
4204
|
const { inject: inject6 } = result;
|
|
1369
4205
|
const pathStyle = {
|
|
1370
4206
|
name: "pathStyle",
|
|
1371
|
-
inject: inject6
|
|
1372
|
-
uniformTypes: {
|
|
1373
|
-
dashAlignMode: "f32",
|
|
1374
|
-
dashGapPickable: "i32"
|
|
1375
|
-
}
|
|
4207
|
+
inject: inject6
|
|
1376
4208
|
};
|
|
4209
|
+
if (extension.opts.dash) {
|
|
4210
|
+
pathStyle.uniformTypes = {
|
|
4211
|
+
dashAlignMode: "f32",
|
|
4212
|
+
dashGapPickable: "i32",
|
|
4213
|
+
dashUnits: "i32"
|
|
4214
|
+
};
|
|
4215
|
+
}
|
|
1377
4216
|
return {
|
|
1378
4217
|
modules: [pathStyle],
|
|
1379
|
-
defines
|
|
4218
|
+
defines: defines2
|
|
1380
4219
|
};
|
|
1381
4220
|
}
|
|
1382
4221
|
initializeState(context, extension) {
|
|
1383
|
-
|
|
1384
|
-
const layerType = extension.getLayerType(this);
|
|
1385
|
-
if (!attributeManager || !layerType) {
|
|
1386
|
-
return;
|
|
1387
|
-
}
|
|
1388
|
-
if (extension.opts.dash) {
|
|
1389
|
-
attributeManager.addInstanced({
|
|
1390
|
-
instanceDashArrays: { size: 2, accessor: "getDashArray" },
|
|
1391
|
-
...layerType === "path" && extension.opts.highPrecisionDash ? {
|
|
1392
|
-
instanceDashOffsets: {
|
|
1393
|
-
size: 1,
|
|
1394
|
-
accessor: "getPath",
|
|
1395
|
-
transform: extension.getDashOffsets.bind(this)
|
|
1396
|
-
}
|
|
1397
|
-
} : {}
|
|
1398
|
-
});
|
|
1399
|
-
}
|
|
1400
|
-
if (layerType === "path" && extension.opts.offset) {
|
|
1401
|
-
attributeManager.addInstanced({
|
|
1402
|
-
instanceOffsets: { size: 1, accessor: "getOffset" }
|
|
1403
|
-
});
|
|
1404
|
-
}
|
|
4222
|
+
extension.synchronizeAttributes(this);
|
|
1405
4223
|
}
|
|
1406
4224
|
updateState(params, extension) {
|
|
4225
|
+
var _a;
|
|
1407
4226
|
if (!extension.isEnabled(this)) {
|
|
1408
4227
|
return;
|
|
1409
4228
|
}
|
|
4229
|
+
if (params.changeFlags.extensionsChanged) {
|
|
4230
|
+
const topologyChanged = extension.synchronizeAttributes(this);
|
|
4231
|
+
const attributeManager = this.getAttributeManager();
|
|
4232
|
+
if (attributeManager && topologyChanged) {
|
|
4233
|
+
attributeManager.invalidateAll();
|
|
4234
|
+
for (const model of this.getModels()) {
|
|
4235
|
+
model.setBufferLayout(attributeManager.getBufferLayouts(model));
|
|
4236
|
+
}
|
|
4237
|
+
}
|
|
4238
|
+
}
|
|
1410
4239
|
if (extension.opts.dash) {
|
|
1411
4240
|
const layerType = extension.getLayerType(this);
|
|
4241
|
+
if (layerType === "path" && extension.opts.dashMode === "path" && dashMetricsProjectionPropsChanged(params)) {
|
|
4242
|
+
(_a = this.getAttributeManager()) == null ? void 0 : _a.invalidate("instanceDashOffsets");
|
|
4243
|
+
}
|
|
1412
4244
|
if (layerType === "scatterplot" || layerType === "textBackground") {
|
|
1413
4245
|
const pathStyleProps = {
|
|
1414
4246
|
dashGapPickable: Boolean(this.props.dashGapPickable)
|
|
@@ -1417,12 +4249,96 @@ var PathStyleExtension = class extends import_core6.LayerExtension {
|
|
|
1417
4249
|
} else {
|
|
1418
4250
|
const pathStyleProps = {
|
|
1419
4251
|
dashAlignMode: this.props.dashJustified ? 1 : 0,
|
|
1420
|
-
dashGapPickable: Boolean(this.props.dashGapPickable)
|
|
4252
|
+
dashGapPickable: Boolean(this.props.dashGapPickable),
|
|
4253
|
+
dashUnits: DASH_UNITS[this.props.dashUnits ?? "widths"]
|
|
1421
4254
|
};
|
|
1422
4255
|
this.setShaderModuleProps({ pathStyle: pathStyleProps });
|
|
1423
4256
|
}
|
|
1424
4257
|
}
|
|
1425
4258
|
}
|
|
4259
|
+
calculateDashMetrics(attribute, { startRow, endRow }) {
|
|
4260
|
+
var _a, _b, _c;
|
|
4261
|
+
const pathTesselator = this.state.pathTesselator;
|
|
4262
|
+
const vertexStarts = pathTesselator == null ? void 0 : pathTesselator.vertexStarts;
|
|
4263
|
+
const instanceCount = pathTesselator == null ? void 0 : pathTesselator.instanceCount;
|
|
4264
|
+
const packedPositions = pathTesselator == null ? void 0 : pathTesselator.get("positions");
|
|
4265
|
+
if (!vertexStarts || instanceCount === void 0 || typeof (pathTesselator == null ? void 0 : pathTesselator.getPathSegmentIndices) !== "function") {
|
|
4266
|
+
throw new Error("PathStyleExtension requires PathLayer tessellation data for path dashes.");
|
|
4267
|
+
}
|
|
4268
|
+
const binaryPath = (_b = (_a = this.props.data) == null ? void 0 : _a.attributes) == null ? void 0 : _b.getPath;
|
|
4269
|
+
const binaryValue = ArrayBuffer.isView(binaryPath) ? binaryPath : binaryPath == null ? void 0 : binaryPath.value;
|
|
4270
|
+
const hasReadableBinaryPath = ArrayBuffer.isView(binaryValue);
|
|
4271
|
+
const usePackedPositions = packedPositions && (!binaryPath || pathTesselator.normalize || ((_c = pathTesselator.opts) == null ? void 0 : _c.isWebGPU));
|
|
4272
|
+
if (binaryPath && !hasReadableBinaryPath || !usePackedPositions && !hasReadableBinaryPath) {
|
|
4273
|
+
throw new Error("PathStyleExtension cannot calculate whole-path dash metrics from GPU-only getPath data; supply data.attributes.instanceDashOffsets.");
|
|
4274
|
+
}
|
|
4275
|
+
const output = attribute.value;
|
|
4276
|
+
const metricSize = attribute.size;
|
|
4277
|
+
const firstRow = Math.max(0, startRow);
|
|
4278
|
+
const lastRow = Math.min(endRow, vertexStarts.length - 1);
|
|
4279
|
+
let binarySize = 3;
|
|
4280
|
+
let binaryStride = 3;
|
|
4281
|
+
let binaryOffset = 0;
|
|
4282
|
+
if (!usePackedPositions) {
|
|
4283
|
+
const bytesPerElement = binaryValue.BYTES_PER_ELEMENT;
|
|
4284
|
+
binarySize = (binaryPath == null ? void 0 : binaryPath.size) || (this.props.positionFormat === "XY" ? 2 : 3);
|
|
4285
|
+
binaryStride = (binaryPath == null ? void 0 : binaryPath.stride) ? binaryPath.stride / bytesPerElement : binarySize;
|
|
4286
|
+
binaryOffset = (binaryPath == null ? void 0 : binaryPath.offset) ? binaryPath.offset / bytesPerElement : 0;
|
|
4287
|
+
}
|
|
4288
|
+
const sourcePosition = new Array(3);
|
|
4289
|
+
const projectUniforms = project_default.getUniforms({
|
|
4290
|
+
viewport: this.context.viewport,
|
|
4291
|
+
modelMatrix: this.props.modelMatrix,
|
|
4292
|
+
coordinateSystem: this.props.coordinateSystem,
|
|
4293
|
+
coordinateOrigin: this.props.coordinateOrigin,
|
|
4294
|
+
// PathLayer normalizes/cuts wrapped paths on the CPU; its shader never wraps again.
|
|
4295
|
+
autoWrapLongitude: this.wrapLongitude
|
|
4296
|
+
});
|
|
4297
|
+
const readPosition = (vertexIndex) => {
|
|
4298
|
+
if (usePackedPositions) {
|
|
4299
|
+
sourcePosition[0] = packedPositions[vertexIndex * 3];
|
|
4300
|
+
sourcePosition[1] = packedPositions[vertexIndex * 3 + 1];
|
|
4301
|
+
sourcePosition[2] = packedPositions[vertexIndex * 3 + 2];
|
|
4302
|
+
} else {
|
|
4303
|
+
const sourceIndex = binaryOffset + vertexIndex * binaryStride;
|
|
4304
|
+
sourcePosition[0] = binaryValue[sourceIndex];
|
|
4305
|
+
sourcePosition[1] = binaryValue[sourceIndex + 1];
|
|
4306
|
+
sourcePosition[2] = binarySize === 3 ? binaryValue[sourceIndex + 2] : 0;
|
|
4307
|
+
}
|
|
4308
|
+
return sourcePosition;
|
|
4309
|
+
};
|
|
4310
|
+
attribute.startIndices = vertexStarts;
|
|
4311
|
+
for (let row = firstRow; row < lastRow; row++) {
|
|
4312
|
+
const rowStart = vertexStarts[row];
|
|
4313
|
+
const rowEnd = Math.min(vertexStarts[row + 1] ?? instanceCount, instanceCount);
|
|
4314
|
+
output.fill(0, rowStart * metricSize, rowEnd * metricSize);
|
|
4315
|
+
const validSegments = pathTesselator.getPathSegmentIndices(row);
|
|
4316
|
+
let phase = 0;
|
|
4317
|
+
let previousSegment = -2;
|
|
4318
|
+
let previousEnd = null;
|
|
4319
|
+
for (const segmentIndex of validSegments) {
|
|
4320
|
+
const outputIndex = segmentIndex * metricSize;
|
|
4321
|
+
output[outputIndex] = phase;
|
|
4322
|
+
const start = segmentIndex === previousSegment + 1 && previousEnd ? previousEnd : projectRenderedPathPosition(this, readPosition(segmentIndex), projectUniforms);
|
|
4323
|
+
const end = projectRenderedPathPosition(this, readPosition(segmentIndex + 1), projectUniforms);
|
|
4324
|
+
phase += import_core13.vec3.dist(start, end);
|
|
4325
|
+
previousSegment = segmentIndex;
|
|
4326
|
+
previousEnd = end;
|
|
4327
|
+
}
|
|
4328
|
+
if (metricSize > 1) {
|
|
4329
|
+
for (let vertexIndex = rowStart; vertexIndex < rowEnd; vertexIndex++) {
|
|
4330
|
+
output[vertexIndex * metricSize + 1] = phase;
|
|
4331
|
+
}
|
|
4332
|
+
}
|
|
4333
|
+
}
|
|
4334
|
+
}
|
|
4335
|
+
/**
|
|
4336
|
+
* Calculates the distance from the start of a path to each rendered segment.
|
|
4337
|
+
*
|
|
4338
|
+
* The final entry is zero because PathLayer reserves the final vertex as invalid padding.
|
|
4339
|
+
* This scalar return shape is retained for compatibility; path-mode rendering uses an
|
|
4340
|
+
* internal attribute containing both each segment offset and the total path length.
|
|
4341
|
+
*/
|
|
1426
4342
|
getDashOffsets(path) {
|
|
1427
4343
|
const result = [0];
|
|
1428
4344
|
const positionSize = this.props.positionFormat === "XY" ? 2 : 3;
|
|
@@ -1432,9 +4348,9 @@ var PathStyleExtension = class extends import_core6.LayerExtension {
|
|
|
1432
4348
|
let prevP;
|
|
1433
4349
|
for (let i = 0; i < geometrySize - 1; i++) {
|
|
1434
4350
|
p = isNested ? path[i] : path.slice(i * positionSize, i * positionSize + positionSize);
|
|
1435
|
-
p = this.projectPosition(p);
|
|
4351
|
+
p = this.projectPosition(p, { autoOffset: false });
|
|
1436
4352
|
if (i > 0) {
|
|
1437
|
-
result[i] = result[i - 1] +
|
|
4353
|
+
result[i] = result[i - 1] + import_core13.vec3.dist(prevP, p);
|
|
1438
4354
|
}
|
|
1439
4355
|
prevP = p;
|
|
1440
4356
|
}
|
|
@@ -1446,17 +4362,27 @@ PathStyleExtension.defaultProps = defaultProps3;
|
|
|
1446
4362
|
PathStyleExtension.extensionName = "PathStyleExtension";
|
|
1447
4363
|
var path_style_extension_default = PathStyleExtension;
|
|
1448
4364
|
|
|
1449
|
-
// dist/fill-style/fill-style-extension.js
|
|
1450
|
-
var import_core9 = require("@deck.gl/core");
|
|
1451
|
-
|
|
1452
4365
|
// dist/fill-style/shader-module.js
|
|
1453
|
-
var
|
|
4366
|
+
var FILL_UV_SCALE = 512 / 4e7;
|
|
4367
|
+
function getPatternUnitScale(sizeUnits, viewport) {
|
|
4368
|
+
switch (sizeUnits) {
|
|
4369
|
+
case "pixels":
|
|
4370
|
+
return 2 ** -Math.round(viewport.zoom);
|
|
4371
|
+
case "common":
|
|
4372
|
+
return 1;
|
|
4373
|
+
default:
|
|
4374
|
+
return FILL_UV_SCALE;
|
|
4375
|
+
}
|
|
4376
|
+
}
|
|
1454
4377
|
var uniformBlock3 = (
|
|
1455
4378
|
/* glsl */
|
|
1456
4379
|
`layout(std140) uniform fillUniforms {
|
|
1457
4380
|
vec2 patternTextureSize;
|
|
4381
|
+
float patternUnitScale;
|
|
1458
4382
|
bool patternEnabled;
|
|
1459
4383
|
bool patternMask;
|
|
4384
|
+
bool procedural;
|
|
4385
|
+
bool flipY;
|
|
1460
4386
|
vec2 uvCoordinateOrigin;
|
|
1461
4387
|
vec2 uvCoordinateOrigin64Low;
|
|
1462
4388
|
} fill;
|
|
@@ -1465,16 +4391,23 @@ var uniformBlock3 = (
|
|
|
1465
4391
|
var patternVs = (
|
|
1466
4392
|
/* glsl */
|
|
1467
4393
|
`
|
|
4394
|
+
uniform sampler2D fill_patternTexture;
|
|
4395
|
+
|
|
1468
4396
|
in vec4 fillPatternFrames;
|
|
1469
4397
|
in float fillPatternScales;
|
|
1470
4398
|
in vec2 fillPatternOffsets;
|
|
4399
|
+
in vec4 fillPatternBackgroundColors;
|
|
1471
4400
|
|
|
1472
4401
|
out vec2 fill_uv;
|
|
1473
4402
|
out vec4 fill_patternBounds;
|
|
1474
4403
|
out vec4 fill_patternPlacement;
|
|
4404
|
+
out vec4 fill_backgroundColor;
|
|
4405
|
+
out float fill_patternCoordinateScale;
|
|
4406
|
+
flat out vec4 fill_patternParams0;
|
|
4407
|
+
flat out vec4 fill_patternParams1;
|
|
1475
4408
|
`
|
|
1476
4409
|
);
|
|
1477
|
-
var
|
|
4410
|
+
var vs4 = `
|
|
1478
4411
|
${uniformBlock3}
|
|
1479
4412
|
${patternVs}
|
|
1480
4413
|
`;
|
|
@@ -1485,29 +4418,172 @@ uniform sampler2D fill_patternTexture;
|
|
|
1485
4418
|
|
|
1486
4419
|
in vec4 fill_patternBounds;
|
|
1487
4420
|
in vec4 fill_patternPlacement;
|
|
4421
|
+
in vec4 fill_backgroundColor;
|
|
1488
4422
|
in vec2 fill_uv;
|
|
4423
|
+
in float fill_patternCoordinateScale;
|
|
4424
|
+
flat in vec4 fill_patternParams0;
|
|
4425
|
+
flat in vec4 fill_patternParams1;
|
|
4426
|
+
|
|
4427
|
+
const float FILL_PATTERN_HATCH = 1.0;
|
|
4428
|
+
const float FILL_PATTERN_CROSS_HATCH = 2.0;
|
|
4429
|
+
const float FILL_PATTERN_DOTS = 3.0;
|
|
4430
|
+
|
|
4431
|
+
float fill_getPatternCoordinate(vec2 axis, float period, float offset) {
|
|
4432
|
+
float coordinateScale = max(abs(fill_patternCoordinateScale), 1.0e-20);
|
|
4433
|
+
vec2 coordinateOrigin = fill.uvCoordinateOrigin;
|
|
4434
|
+
vec2 coordinateOffset = fill.uvCoordinateOrigin64Low + fill_uv;
|
|
4435
|
+
float yDirection = fill.flipY ? 1.0 : -1.0;
|
|
4436
|
+
coordinateOrigin.y *= yDirection;
|
|
4437
|
+
coordinateOffset.y *= yDirection;
|
|
4438
|
+
|
|
4439
|
+
// Reduce the high part before adding the local offset to retain precision in large coordinates.
|
|
4440
|
+
float highPart = mod(dot(coordinateOrigin, axis) / coordinateScale, period);
|
|
4441
|
+
float lowPart = dot(coordinateOffset, axis) / coordinateScale;
|
|
4442
|
+
return mod(highPart + lowPart + offset * period, period);
|
|
4443
|
+
}
|
|
4444
|
+
|
|
4445
|
+
vec2 fill_getPatternCoords(
|
|
4446
|
+
vec2 axis0,
|
|
4447
|
+
vec2 axis1,
|
|
4448
|
+
vec2 period,
|
|
4449
|
+
vec2 offset
|
|
4450
|
+
) {
|
|
4451
|
+
return vec2(
|
|
4452
|
+
fill_getPatternCoordinate(axis0, period.x, offset.x),
|
|
4453
|
+
fill_getPatternCoordinate(axis1, period.y, offset.y)
|
|
4454
|
+
);
|
|
4455
|
+
}
|
|
1489
4456
|
|
|
1490
|
-
|
|
4457
|
+
float fill_getScreenSpaceAlpha(float signedDistance) {
|
|
4458
|
+
float distanceDerivative = fwidth(signedDistance);
|
|
4459
|
+
if (distanceDerivative == 0.0) {
|
|
4460
|
+
return signedDistance <= 0.0 ? 1.0 : 0.0;
|
|
4461
|
+
}
|
|
4462
|
+
// Normalize the SDF to screen pixels so the coverage ramp is independent of pattern units.
|
|
4463
|
+
float distanceInPixels = signedDistance / distanceDerivative;
|
|
4464
|
+
return 1.0 - smoothstep(-0.5, 0.5, distanceInPixels);
|
|
4465
|
+
}
|
|
4466
|
+
|
|
4467
|
+
float fill_getLineAlpha(float position, float center, float period, float strokeWidth) {
|
|
4468
|
+
float distanceToLine = abs(mod(position - center + period * 0.5, period) - period * 0.5);
|
|
4469
|
+
return fill_getScreenSpaceAlpha(distanceToLine - strokeWidth * 0.5);
|
|
4470
|
+
}
|
|
4471
|
+
|
|
4472
|
+
float fill_getHatchAlpha(float angle, float strokeWidth, vec2 gaps, bool alternating) {
|
|
4473
|
+
vec2 lineDirection = vec2(cos(angle), sin(angle));
|
|
4474
|
+
vec2 lineNormal = vec2(-lineDirection.y, lineDirection.x);
|
|
4475
|
+
float period = alternating
|
|
4476
|
+
? strokeWidth * 2.0 + gaps.x + gaps.y
|
|
4477
|
+
: strokeWidth + gaps.x;
|
|
4478
|
+
float offset = dot(fill_patternPlacement.xy, lineNormal);
|
|
4479
|
+
float position = fill_getPatternCoordinate(lineNormal, period, offset);
|
|
4480
|
+
float alpha = fill_getLineAlpha(position, 0.0, period, strokeWidth);
|
|
4481
|
+
if (alternating) {
|
|
4482
|
+
alpha = max(
|
|
4483
|
+
alpha,
|
|
4484
|
+
fill_getLineAlpha(position, strokeWidth + gaps.x, period, strokeWidth)
|
|
4485
|
+
);
|
|
4486
|
+
}
|
|
4487
|
+
return alpha;
|
|
4488
|
+
}
|
|
4489
|
+
|
|
4490
|
+
float fill_getDotAlpha(float angle, float skew, float radius, float gap) {
|
|
4491
|
+
vec2 axis0 = vec2(cos(angle), sin(angle));
|
|
4492
|
+
float axis1Angle = angle + 1.5707963267948966 - skew;
|
|
4493
|
+
vec2 axis1 = vec2(cos(axis1Angle), sin(axis1Angle));
|
|
4494
|
+
float determinant = axis0.x * axis1.y - axis0.y * axis1.x;
|
|
4495
|
+
|
|
4496
|
+
// The reciprocal basis maps common coordinates into the skewed dot lattice.
|
|
4497
|
+
vec2 reciprocal0 = vec2(axis1.y, -axis1.x) / determinant;
|
|
4498
|
+
vec2 reciprocal1 = vec2(-axis0.y, axis0.x) / determinant;
|
|
4499
|
+
float period = radius * 2.0 + gap;
|
|
4500
|
+
vec2 latticeCoords = fill_getPatternCoords(
|
|
4501
|
+
reciprocal0,
|
|
4502
|
+
reciprocal1,
|
|
4503
|
+
vec2(period),
|
|
4504
|
+
fill_patternPlacement.xy
|
|
4505
|
+
);
|
|
4506
|
+
vec2 cellOffset = mod(latticeCoords + period * 0.5, period) - period * 0.5;
|
|
4507
|
+
float distanceToDotSquared = 1.0e20;
|
|
4508
|
+
// In a skewed lattice the closest dot is not necessarily in the independently wrapped cell.
|
|
4509
|
+
// Include adjacent cells to keep the repeated distance field continuous at cell boundaries.
|
|
4510
|
+
for (int x = -1; x <= 1; x++) {
|
|
4511
|
+
for (int y = -1; y <= 1; y++) {
|
|
4512
|
+
vec2 neighborOffset = cellOffset + vec2(float(x), float(y)) * period;
|
|
4513
|
+
vec2 dotOffset = axis0 * neighborOffset.x + axis1 * neighborOffset.y;
|
|
4514
|
+
distanceToDotSquared = min(distanceToDotSquared, dot(dotOffset, dotOffset));
|
|
4515
|
+
}
|
|
4516
|
+
}
|
|
4517
|
+
float distanceToDot = sqrt(distanceToDotSquared);
|
|
4518
|
+
return fill_getScreenSpaceAlpha(distanceToDot - radius);
|
|
4519
|
+
}
|
|
4520
|
+
|
|
4521
|
+
float fill_getProceduralPatternAlpha() {
|
|
4522
|
+
float patternType = fill_patternParams0.x;
|
|
4523
|
+
float size = fill_patternParams0.y;
|
|
4524
|
+
vec2 gaps = fill_patternParams0.zw;
|
|
4525
|
+
vec2 angles = fill_patternParams1.xy;
|
|
4526
|
+
float elementCount = fill_patternParams1.z;
|
|
4527
|
+
|
|
4528
|
+
if (patternType == FILL_PATTERN_HATCH) {
|
|
4529
|
+
return fill_getHatchAlpha(angles.x, size, gaps, elementCount == 2.0);
|
|
4530
|
+
}
|
|
4531
|
+
if (patternType == FILL_PATTERN_CROSS_HATCH) {
|
|
4532
|
+
return max(
|
|
4533
|
+
fill_getHatchAlpha(angles.x, size, gaps, false),
|
|
4534
|
+
fill_getHatchAlpha(angles.y, size, gaps, false)
|
|
4535
|
+
);
|
|
4536
|
+
}
|
|
4537
|
+
if (patternType == FILL_PATTERN_DOTS) {
|
|
4538
|
+
return fill_getDotAlpha(angles.x, angles.y, size, gaps.x);
|
|
4539
|
+
}
|
|
4540
|
+
return 1.0;
|
|
4541
|
+
}
|
|
4542
|
+
|
|
4543
|
+
// Draw the pattern over the background fill (Porter-Duff source-over)
|
|
4544
|
+
vec4 fill_blendOverBackground(vec4 pattern, vec4 background) {
|
|
4545
|
+
if (background.a == 0.0 || layer.opacity == 0.0) return pattern;
|
|
4546
|
+
float patternAlpha = pattern.a / layer.opacity;
|
|
4547
|
+
float blendedAlpha = patternAlpha + background.a * (1.0 - patternAlpha);
|
|
4548
|
+
vec3 blendedRGB = mix(background.rgb, pattern.rgb, patternAlpha / blendedAlpha);
|
|
4549
|
+
return vec4(blendedRGB, blendedAlpha * layer.opacity);
|
|
4550
|
+
}
|
|
1491
4551
|
`
|
|
1492
4552
|
);
|
|
1493
|
-
var
|
|
4553
|
+
var fs4 = `
|
|
1494
4554
|
${uniformBlock3}
|
|
1495
4555
|
${patternFs}
|
|
1496
4556
|
`;
|
|
1497
4557
|
var inject3 = {
|
|
1498
4558
|
"vs:DECKGL_FILTER_GL_POSITION": (
|
|
1499
|
-
/* glsl */
|
|
1500
|
-
`
|
|
1501
|
-
fill_uv = geometry.position.xy;
|
|
1502
|
-
`
|
|
1503
|
-
),
|
|
1504
|
-
"vs:DECKGL_FILTER_COLOR": (
|
|
1505
4559
|
/* glsl */
|
|
1506
4560
|
`
|
|
1507
4561
|
if (fill.patternEnabled) {
|
|
1508
|
-
fill_patternBounds = fillPatternFrames / vec4(fill.patternTextureSize, fill.patternTextureSize);
|
|
1509
4562
|
fill_patternPlacement.xy = fillPatternOffsets;
|
|
1510
|
-
|
|
4563
|
+
fill_backgroundColor = fillPatternBackgroundColors;
|
|
4564
|
+
if (fill.procedural) {
|
|
4565
|
+
fill_uv = geometry.position.xy;
|
|
4566
|
+
fill_patternCoordinateScale = fill.patternUnitScale * fillPatternScales;
|
|
4567
|
+
int texelIndex = int(fillPatternFrames.x) * 4;
|
|
4568
|
+
fill_patternParams0 = vec4(
|
|
4569
|
+
texelFetch(fill_patternTexture, ivec2(texelIndex, 0), 0).rg,
|
|
4570
|
+
texelFetch(fill_patternTexture, ivec2(texelIndex + 1, 0), 0).rg
|
|
4571
|
+
);
|
|
4572
|
+
fill_patternParams1 = vec4(
|
|
4573
|
+
texelFetch(fill_patternTexture, ivec2(texelIndex + 2, 0), 0).rg,
|
|
4574
|
+
texelFetch(fill_patternTexture, ivec2(texelIndex + 3, 0), 0).rg
|
|
4575
|
+
);
|
|
4576
|
+
} else {
|
|
4577
|
+
fill_patternBounds = fillPatternFrames / vec4(fill.patternTextureSize, fill.patternTextureSize);
|
|
4578
|
+
vec2 patternFrameCommon = fill.patternUnitScale * fillPatternScales * fillPatternFrames.zw;
|
|
4579
|
+
// Reduce the coordinate origin to within one tile before adding the vertex position. The
|
|
4580
|
+
// origin is large in common space, and fp32 cannot carry the sum at full precision.
|
|
4581
|
+
vec2 origin = mod(fill.uvCoordinateOrigin, patternFrameCommon) + fill.uvCoordinateOrigin64Low;
|
|
4582
|
+
fill_uv = (origin + geometry.position.xy) / patternFrameCommon;
|
|
4583
|
+
// Pattern atlases use top-left coordinates, so reverse common-space Y in bottom-left views.
|
|
4584
|
+
fill_uv.y *= fill.flipY ? 1.0 : -1.0;
|
|
4585
|
+
fill_uv += fillPatternOffsets;
|
|
4586
|
+
}
|
|
1511
4587
|
}
|
|
1512
4588
|
`
|
|
1513
4589
|
),
|
|
@@ -1515,22 +4591,31 @@ var inject3 = {
|
|
|
1515
4591
|
/* glsl */
|
|
1516
4592
|
`
|
|
1517
4593
|
if (fill.patternEnabled) {
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
4594
|
+
if (fill.procedural) {
|
|
4595
|
+
color.a *= fill_getProceduralPatternAlpha();
|
|
4596
|
+
} else {
|
|
4597
|
+
vec2 patternUV = fract(fill_uv);
|
|
4598
|
+
vec2 texCoords = fill_patternBounds.xy + fill_patternBounds.zw * patternUV;
|
|
1521
4599
|
|
|
1522
|
-
|
|
4600
|
+
// Tiling is emulated by wrapping the coordinate, so texCoords jumps from the end of the
|
|
4601
|
+
// frame back to its start once per tile, leading to the wrong mip level being selected,
|
|
4602
|
+
// which leads to artifacts at pattern edges. fill_uv is continuous across the primitive,
|
|
4603
|
+
// meaning that the correct mip level is always selected
|
|
4604
|
+
vec4 grad = fill_patternBounds.zwzw * vec4(dFdx(fill_uv), dFdy(fill_uv));
|
|
4605
|
+
vec4 patternColor = textureGrad(fill_patternTexture, texCoords, grad.xy, grad.zw);
|
|
1523
4606
|
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
4607
|
+
color.a *= patternColor.a;
|
|
4608
|
+
if (!fill.patternMask) {
|
|
4609
|
+
color.rgb = patternColor.rgb;
|
|
4610
|
+
}
|
|
1528
4611
|
}
|
|
4612
|
+
color = fill_blendOverBackground(color, fill_backgroundColor);
|
|
1529
4613
|
}
|
|
1530
4614
|
`
|
|
1531
4615
|
)
|
|
1532
4616
|
};
|
|
1533
4617
|
function getPatternUniforms(opts) {
|
|
4618
|
+
var _a;
|
|
1534
4619
|
if (!opts) {
|
|
1535
4620
|
return {};
|
|
1536
4621
|
}
|
|
@@ -1541,54 +4626,200 @@ function getPatternUniforms(opts) {
|
|
|
1541
4626
|
uniforms.patternTextureSize = [fillPatternTexture.width, fillPatternTexture.height];
|
|
1542
4627
|
}
|
|
1543
4628
|
if ("project" in opts) {
|
|
1544
|
-
const { fillPatternMask = true, fillPatternEnabled = true } = opts;
|
|
1545
|
-
const projectUniforms =
|
|
4629
|
+
const { fillPatternMask = true, fillPatternEnabled = true, fillPatternSizeUnits = "meters", fillPatternCommonFrame = null, procedural = false } = opts;
|
|
4630
|
+
const projectUniforms = project_default.getUniforms(opts.project);
|
|
1546
4631
|
const { commonOrigin: coordinateOriginCommon } = projectUniforms;
|
|
1547
|
-
const
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
4632
|
+
const unitScale = getPatternUnitScale(fillPatternSizeUnits, opts.project.viewport);
|
|
4633
|
+
const origin = [coordinateOriginCommon[0], coordinateOriginCommon[1]];
|
|
4634
|
+
if (fillPatternCommonFrame) {
|
|
4635
|
+
origin[0] %= unitScale * fillPatternCommonFrame[0];
|
|
4636
|
+
origin[1] %= unitScale * fillPatternCommonFrame[1];
|
|
4637
|
+
}
|
|
4638
|
+
uniforms.uvCoordinateOrigin = origin;
|
|
4639
|
+
uniforms.uvCoordinateOrigin64Low = [fp64LowPart(origin[0]), fp64LowPart(origin[1])];
|
|
4640
|
+
uniforms.patternUnitScale = unitScale;
|
|
1553
4641
|
uniforms.patternMask = fillPatternMask;
|
|
1554
4642
|
uniforms.patternEnabled = fillPatternEnabled;
|
|
4643
|
+
uniforms.procedural = procedural;
|
|
4644
|
+
uniforms.flipY = ((_a = opts.project.viewport) == null ? void 0 : _a.flipY) ?? false;
|
|
1555
4645
|
}
|
|
1556
4646
|
return uniforms;
|
|
1557
4647
|
}
|
|
1558
4648
|
var patternShaders = {
|
|
1559
4649
|
name: "fill",
|
|
1560
|
-
vs:
|
|
1561
|
-
fs:
|
|
4650
|
+
vs: vs4,
|
|
4651
|
+
fs: fs4,
|
|
1562
4652
|
inject: inject3,
|
|
1563
|
-
dependencies: [
|
|
4653
|
+
dependencies: [project_default],
|
|
1564
4654
|
getUniforms: getPatternUniforms,
|
|
1565
4655
|
uniformTypes: {
|
|
1566
4656
|
patternTextureSize: "vec2<f32>",
|
|
4657
|
+
patternUnitScale: "f32",
|
|
1567
4658
|
patternEnabled: "i32",
|
|
1568
4659
|
patternMask: "i32",
|
|
4660
|
+
procedural: "i32",
|
|
4661
|
+
flipY: "i32",
|
|
1569
4662
|
uvCoordinateOrigin: "vec2<f32>",
|
|
1570
4663
|
uvCoordinateOrigin64Low: "vec2<f32>"
|
|
1571
4664
|
}
|
|
1572
4665
|
};
|
|
1573
4666
|
|
|
4667
|
+
// dist/fill-style/procedural-pattern.js
|
|
4668
|
+
var PROCEDURAL_PATTERN_TEXTURE_FORMAT = "rg32float";
|
|
4669
|
+
var PROCEDURAL_PATTERN_COMPONENTS_PER_TEXEL = 2;
|
|
4670
|
+
var PROCEDURAL_PATTERN_TEXELS_PER_PATTERN = 4;
|
|
4671
|
+
var PROCEDURAL_PATTERN_TYPES = {
|
|
4672
|
+
none: 0,
|
|
4673
|
+
hatch: 1,
|
|
4674
|
+
crossHatch: 2,
|
|
4675
|
+
dots: 3
|
|
4676
|
+
};
|
|
4677
|
+
var PROCEDURAL_PATTERN_OFFSETS = {
|
|
4678
|
+
type: 0,
|
|
4679
|
+
size: 1,
|
|
4680
|
+
gap0: 2,
|
|
4681
|
+
gap1: 3,
|
|
4682
|
+
angle0: 4,
|
|
4683
|
+
angle1: 5,
|
|
4684
|
+
/** Number of alternating gaps, hatch directions, or dot-grid axes, depending on type. */
|
|
4685
|
+
elementCount: 6
|
|
4686
|
+
};
|
|
4687
|
+
var COMPONENTS_PER_PATTERN = PROCEDURAL_PATTERN_COMPONENTS_PER_TEXEL * PROCEDURAL_PATTERN_TEXELS_PER_PATTERN;
|
|
4688
|
+
var DEGREES_TO_RADIANS3 = Math.PI / 180;
|
|
4689
|
+
var DEFAULT_SIZE = 1;
|
|
4690
|
+
var DEFAULT_GAP = 1;
|
|
4691
|
+
var DEFAULT_HATCH_ANGLE = 0;
|
|
4692
|
+
var DEFAULT_CROSS_HATCH_ANGLES = [45, 135];
|
|
4693
|
+
var DEFAULT_DOT_ANGLE = 0;
|
|
4694
|
+
var DEFAULT_DOT_SKEW = 0;
|
|
4695
|
+
function packProceduralPatterns(mapping) {
|
|
4696
|
+
const entries = Object.entries(mapping);
|
|
4697
|
+
const data = new Float32Array((entries.length + 1) * COMPONENTS_PER_PATTERN);
|
|
4698
|
+
const patternIndices = /* @__PURE__ */ new Map();
|
|
4699
|
+
entries.forEach(([id, config], entryIndex) => {
|
|
4700
|
+
const patternIndex = entryIndex + 1;
|
|
4701
|
+
const offset = patternIndex * COMPONENTS_PER_PATTERN;
|
|
4702
|
+
patternIndices.set(id, patternIndex);
|
|
4703
|
+
switch (config.type) {
|
|
4704
|
+
case "hatch": {
|
|
4705
|
+
const gap = config.gap === void 0 ? DEFAULT_GAP : config.gap;
|
|
4706
|
+
const strokeWidth = config.strokeWidth === void 0 ? DEFAULT_SIZE : config.strokeWidth;
|
|
4707
|
+
const angle = config.angle === void 0 ? DEFAULT_HATCH_ANGLE : config.angle;
|
|
4708
|
+
if (Array.isArray(gap) && gap.length !== 2) {
|
|
4709
|
+
throw new Error(`${id}.gap must be a number or a two-element array`);
|
|
4710
|
+
}
|
|
4711
|
+
const gaps = Array.isArray(gap) ? gap : [gap, gap];
|
|
4712
|
+
validatePositive(strokeWidth, `${id}.strokeWidth`);
|
|
4713
|
+
validateNonNegative(gaps[0], `${id}.gap[0]`);
|
|
4714
|
+
validateNonNegative(gaps[1], `${id}.gap[1]`);
|
|
4715
|
+
validateAngle(angle, `${id}.angle`);
|
|
4716
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.type] = PROCEDURAL_PATTERN_TYPES.hatch;
|
|
4717
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.size] = strokeWidth;
|
|
4718
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.gap0] = gaps[0];
|
|
4719
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.gap1] = gaps[1];
|
|
4720
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.angle0] = angle * DEGREES_TO_RADIANS3;
|
|
4721
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.elementCount] = Array.isArray(gap) ? 2 : 1;
|
|
4722
|
+
break;
|
|
4723
|
+
}
|
|
4724
|
+
case "cross-hatch": {
|
|
4725
|
+
const angles = config.angles === void 0 ? DEFAULT_CROSS_HATCH_ANGLES : config.angles;
|
|
4726
|
+
const strokeWidth = config.strokeWidth === void 0 ? DEFAULT_SIZE : config.strokeWidth;
|
|
4727
|
+
const gap = config.gap === void 0 ? DEFAULT_GAP : config.gap;
|
|
4728
|
+
if (!Array.isArray(angles) || angles.length !== 2) {
|
|
4729
|
+
throw new Error(`${id}.angles must be a two-element array`);
|
|
4730
|
+
}
|
|
4731
|
+
validatePositive(strokeWidth, `${id}.strokeWidth`);
|
|
4732
|
+
validateNonNegative(gap, `${id}.gap`);
|
|
4733
|
+
validateAngle(angles[0], `${id}.angles[0]`);
|
|
4734
|
+
validateAngle(angles[1], `${id}.angles[1]`);
|
|
4735
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.type] = PROCEDURAL_PATTERN_TYPES.crossHatch;
|
|
4736
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.size] = strokeWidth;
|
|
4737
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.gap0] = gap;
|
|
4738
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.gap1] = gap;
|
|
4739
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.angle0] = angles[0] * DEGREES_TO_RADIANS3;
|
|
4740
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.angle1] = angles[1] * DEGREES_TO_RADIANS3;
|
|
4741
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.elementCount] = 2;
|
|
4742
|
+
break;
|
|
4743
|
+
}
|
|
4744
|
+
case "dots": {
|
|
4745
|
+
const radius = config.radius === void 0 ? DEFAULT_SIZE : config.radius;
|
|
4746
|
+
const gap = config.gap === void 0 ? DEFAULT_GAP : config.gap;
|
|
4747
|
+
const angle = config.angle === void 0 ? DEFAULT_DOT_ANGLE : config.angle;
|
|
4748
|
+
const skew = config.skew === void 0 ? DEFAULT_DOT_SKEW : config.skew;
|
|
4749
|
+
validatePositive(radius, `${id}.radius`);
|
|
4750
|
+
validateNonNegative(gap, `${id}.gap`);
|
|
4751
|
+
validateAngle(angle, `${id}.angle`);
|
|
4752
|
+
validateSkew(skew, `${id}.skew`);
|
|
4753
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.type] = PROCEDURAL_PATTERN_TYPES.dots;
|
|
4754
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.size] = radius;
|
|
4755
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.gap0] = gap;
|
|
4756
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.gap1] = gap;
|
|
4757
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.angle0] = angle * DEGREES_TO_RADIANS3;
|
|
4758
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.angle1] = skew * DEGREES_TO_RADIANS3;
|
|
4759
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.elementCount] = 2;
|
|
4760
|
+
break;
|
|
4761
|
+
}
|
|
4762
|
+
default:
|
|
4763
|
+
throw new Error(`${id}.type is not a supported procedural pattern type`);
|
|
4764
|
+
}
|
|
4765
|
+
});
|
|
4766
|
+
return {
|
|
4767
|
+
data,
|
|
4768
|
+
width: data.length / PROCEDURAL_PATTERN_COMPONENTS_PER_TEXEL,
|
|
4769
|
+
height: 1,
|
|
4770
|
+
patternIndices
|
|
4771
|
+
};
|
|
4772
|
+
}
|
|
4773
|
+
function validatePositive(value, name) {
|
|
4774
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
4775
|
+
throw new Error(`${name} must be a finite number greater than 0`);
|
|
4776
|
+
}
|
|
4777
|
+
}
|
|
4778
|
+
function validateNonNegative(value, name) {
|
|
4779
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
4780
|
+
throw new Error(`${name} must be a finite number greater than or equal to 0`);
|
|
4781
|
+
}
|
|
4782
|
+
}
|
|
4783
|
+
function validateAngle(value, name) {
|
|
4784
|
+
if (!Number.isFinite(value)) {
|
|
4785
|
+
throw new Error(`${name} must be a finite number`);
|
|
4786
|
+
}
|
|
4787
|
+
}
|
|
4788
|
+
function validateSkew(value, name) {
|
|
4789
|
+
if (!Number.isFinite(value) || value <= -90 || value >= 90) {
|
|
4790
|
+
throw new Error(`${name} must be a finite number greater than -90 and less than 90`);
|
|
4791
|
+
}
|
|
4792
|
+
}
|
|
4793
|
+
|
|
1574
4794
|
// dist/fill-style/fill-style-extension.js
|
|
4795
|
+
function leastCommonMultiple(a, b) {
|
|
4796
|
+
if (!Number.isInteger(b) || b <= 0)
|
|
4797
|
+
return 0;
|
|
4798
|
+
if (a === 0)
|
|
4799
|
+
return b;
|
|
4800
|
+
let [x, y] = [a, b];
|
|
4801
|
+
while (y > 0)
|
|
4802
|
+
[x, y] = [y, x % y];
|
|
4803
|
+
return a / x * b;
|
|
4804
|
+
}
|
|
1575
4805
|
var defaultProps4 = {
|
|
1576
4806
|
fillPatternEnabled: true,
|
|
1577
4807
|
fillPatternAtlas: {
|
|
1578
4808
|
type: "image",
|
|
1579
4809
|
value: null,
|
|
1580
|
-
async: true
|
|
1581
|
-
parameters: { lodMaxClamp: 0 }
|
|
4810
|
+
async: true
|
|
1582
4811
|
},
|
|
1583
4812
|
fillPatternMapping: { type: "object", value: {}, async: true },
|
|
1584
4813
|
fillPatternMask: true,
|
|
4814
|
+
fillPatternSizeUnits: "meters",
|
|
1585
4815
|
getFillPattern: { type: "accessor", value: (d) => d.pattern },
|
|
1586
4816
|
getFillPatternScale: { type: "accessor", value: 1 },
|
|
1587
|
-
getFillPatternOffset: { type: "accessor", value: [0, 0] }
|
|
4817
|
+
getFillPatternOffset: { type: "accessor", value: [0, 0] },
|
|
4818
|
+
getFillPatternBackgroundColor: { type: "accessor", value: [0, 0, 0, 0] }
|
|
1588
4819
|
};
|
|
1589
|
-
var FillStyleExtension = class extends
|
|
1590
|
-
constructor({ pattern = false } = {}) {
|
|
1591
|
-
super({ pattern });
|
|
4820
|
+
var FillStyleExtension = class extends LayerExtension {
|
|
4821
|
+
constructor({ pattern = false, proceduralPattern = false } = {}) {
|
|
4822
|
+
super({ pattern: pattern || proceduralPattern, proceduralPattern });
|
|
1592
4823
|
}
|
|
1593
4824
|
isEnabled(layer) {
|
|
1594
4825
|
return layer.getAttributeManager() !== null && !("pathTesselator" in layer.state);
|
|
@@ -1612,7 +4843,7 @@ var FillStyleExtension = class extends import_core9.LayerExtension {
|
|
|
1612
4843
|
size: 4,
|
|
1613
4844
|
stepMode: "dynamic",
|
|
1614
4845
|
accessor: "getFillPattern",
|
|
1615
|
-
transform: extension.getPatternFrame.bind(this)
|
|
4846
|
+
transform: extension.opts.proceduralPattern ? extension.getProceduralPatternIndex.bind(this) : extension.getPatternFrame.bind(this)
|
|
1616
4847
|
},
|
|
1617
4848
|
fillPatternScales: {
|
|
1618
4849
|
size: 1,
|
|
@@ -1624,6 +4855,13 @@ var FillStyleExtension = class extends import_core9.LayerExtension {
|
|
|
1624
4855
|
size: 2,
|
|
1625
4856
|
stepMode: "dynamic",
|
|
1626
4857
|
accessor: "getFillPatternOffset"
|
|
4858
|
+
},
|
|
4859
|
+
fillPatternBackgroundColors: {
|
|
4860
|
+
size: 4,
|
|
4861
|
+
type: "unorm8",
|
|
4862
|
+
stepMode: "dynamic",
|
|
4863
|
+
accessor: "getFillPatternBackgroundColor",
|
|
4864
|
+
defaultValue: [0, 0, 0, 255]
|
|
1627
4865
|
}
|
|
1628
4866
|
});
|
|
1629
4867
|
}
|
|
@@ -1632,7 +4870,8 @@ var FillStyleExtension = class extends import_core9.LayerExtension {
|
|
|
1632
4870
|
data: new Uint8Array(4),
|
|
1633
4871
|
width: 1,
|
|
1634
4872
|
height: 1
|
|
1635
|
-
})
|
|
4873
|
+
}),
|
|
4874
|
+
...extension.opts.proceduralPattern && extension.createProceduralPatternTexture.call(this, {})
|
|
1636
4875
|
});
|
|
1637
4876
|
}
|
|
1638
4877
|
updateState({ props, oldProps }, extension) {
|
|
@@ -1640,30 +4879,81 @@ var FillStyleExtension = class extends import_core9.LayerExtension {
|
|
|
1640
4879
|
return;
|
|
1641
4880
|
}
|
|
1642
4881
|
if (props.fillPatternMapping && props.fillPatternMapping !== oldProps.fillPatternMapping) {
|
|
4882
|
+
if (extension.opts.proceduralPattern && typeof props.fillPatternMapping !== "string") {
|
|
4883
|
+
const oldTexture = this.state.proceduralPatternTexture;
|
|
4884
|
+
this.setState(extension.createProceduralPatternTexture.call(this, props.fillPatternMapping));
|
|
4885
|
+
oldTexture == null ? void 0 : oldTexture.delete();
|
|
4886
|
+
}
|
|
1643
4887
|
this.getAttributeManager().invalidate("getFillPattern");
|
|
1644
4888
|
}
|
|
4889
|
+
if (props.fillPatternMapping !== oldProps.fillPatternMapping || props.getFillPatternScale !== oldProps.getFillPatternScale) {
|
|
4890
|
+
this.setState({ commonFrame: extension.getCommonFrame(props) });
|
|
4891
|
+
}
|
|
1645
4892
|
}
|
|
1646
4893
|
draw(params, extension) {
|
|
1647
4894
|
if (!extension.isEnabled(this)) {
|
|
1648
4895
|
return;
|
|
1649
4896
|
}
|
|
1650
|
-
const { fillPatternAtlas, fillPatternEnabled, fillPatternMask } = this.props;
|
|
4897
|
+
const { fillPatternAtlas, fillPatternEnabled, fillPatternMask, fillPatternSizeUnits } = this.props;
|
|
1651
4898
|
const fillProps = {
|
|
1652
4899
|
project: params.shaderModuleProps.project,
|
|
1653
4900
|
fillPatternEnabled,
|
|
1654
4901
|
fillPatternMask,
|
|
1655
|
-
|
|
4902
|
+
fillPatternSizeUnits,
|
|
4903
|
+
procedural: extension.opts.proceduralPattern,
|
|
4904
|
+
fillPatternTexture: extension.opts.proceduralPattern ? this.state.proceduralPatternTexture || this.state.emptyTexture : fillPatternAtlas || this.state.emptyTexture,
|
|
4905
|
+
fillPatternCommonFrame: this.state.commonFrame
|
|
1656
4906
|
};
|
|
1657
4907
|
this.setShaderModuleProps({ fill: fillProps });
|
|
1658
4908
|
}
|
|
1659
4909
|
finalizeState() {
|
|
1660
4910
|
const emptyTexture = this.state.emptyTexture;
|
|
1661
4911
|
emptyTexture == null ? void 0 : emptyTexture.delete();
|
|
4912
|
+
const proceduralPatternTexture = this.state.proceduralPatternTexture;
|
|
4913
|
+
proceduralPatternTexture == null ? void 0 : proceduralPatternTexture.delete();
|
|
1662
4914
|
}
|
|
1663
4915
|
getPatternFrame(name) {
|
|
1664
4916
|
const { fillPatternMapping } = this.getCurrentLayer().props;
|
|
1665
4917
|
const def = fillPatternMapping && fillPatternMapping[name];
|
|
1666
|
-
return def ? [def.x, def.y, def.width, def.height] : [0, 0, 0, 0];
|
|
4918
|
+
return def && "x" in def ? [def.x, def.y, def.width, def.height] : [0, 0, 0, 0];
|
|
4919
|
+
}
|
|
4920
|
+
/**
|
|
4921
|
+
* Returns common frame into which all patterns fit as integer multiples
|
|
4922
|
+
*/
|
|
4923
|
+
getCommonFrame(props) {
|
|
4924
|
+
const { fillPatternMapping, getFillPatternScale: scale } = props;
|
|
4925
|
+
if (typeof scale !== "number" || !(scale > 0) || typeof fillPatternMapping !== "object") {
|
|
4926
|
+
return null;
|
|
4927
|
+
}
|
|
4928
|
+
let width = 0;
|
|
4929
|
+
let height = 0;
|
|
4930
|
+
for (const name in fillPatternMapping) {
|
|
4931
|
+
const frame = fillPatternMapping[name];
|
|
4932
|
+
if (!("width" in frame))
|
|
4933
|
+
return null;
|
|
4934
|
+
width = leastCommonMultiple(width, frame.width);
|
|
4935
|
+
height = leastCommonMultiple(height, frame.height);
|
|
4936
|
+
if (!width || !height)
|
|
4937
|
+
return null;
|
|
4938
|
+
}
|
|
4939
|
+
return width ? [scale * width, scale * height] : null;
|
|
4940
|
+
}
|
|
4941
|
+
getProceduralPatternIndex(name) {
|
|
4942
|
+
const patternIndices = this.state.proceduralPatternIndices;
|
|
4943
|
+
return [(patternIndices == null ? void 0 : patternIndices.get(name)) ?? 0, 0, 0, 0];
|
|
4944
|
+
}
|
|
4945
|
+
createProceduralPatternTexture(mapping) {
|
|
4946
|
+
const packedPatterns = packProceduralPatterns(mapping);
|
|
4947
|
+
return {
|
|
4948
|
+
proceduralPatternIndices: packedPatterns.patternIndices,
|
|
4949
|
+
proceduralPatternTexture: this.context.device.createTexture({
|
|
4950
|
+
data: packedPatterns.data,
|
|
4951
|
+
width: packedPatterns.width,
|
|
4952
|
+
height: packedPatterns.height,
|
|
4953
|
+
format: PROCEDURAL_PATTERN_TEXTURE_FORMAT,
|
|
4954
|
+
sampler: { minFilter: "nearest", magFilter: "nearest" }
|
|
4955
|
+
})
|
|
4956
|
+
};
|
|
1667
4957
|
}
|
|
1668
4958
|
};
|
|
1669
4959
|
FillStyleExtension.defaultProps = defaultProps4;
|
|
@@ -1671,7 +4961,6 @@ FillStyleExtension.extensionName = "FillStyleExtension";
|
|
|
1671
4961
|
var fill_style_extension_default = FillStyleExtension;
|
|
1672
4962
|
|
|
1673
4963
|
// dist/clip/clip-extension.js
|
|
1674
|
-
var import_core10 = require("@deck.gl/core");
|
|
1675
4964
|
var defaultProps5 = {
|
|
1676
4965
|
clipBounds: [0, 0, 1, 1],
|
|
1677
4966
|
clipByInstance: void 0
|
|
@@ -1754,13 +5043,16 @@ in vec2 clip_commonPosition;
|
|
|
1754
5043
|
`
|
|
1755
5044
|
)
|
|
1756
5045
|
};
|
|
1757
|
-
var ClipExtension = class extends
|
|
5046
|
+
var ClipExtension = class extends LayerExtension {
|
|
1758
5047
|
getShaders() {
|
|
1759
5048
|
let clipByInstance = "instancePositions" in this.getAttributeManager().attributes;
|
|
1760
5049
|
if (this.props.clipByInstance !== void 0) {
|
|
1761
5050
|
clipByInstance = Boolean(this.props.clipByInstance);
|
|
1762
5051
|
}
|
|
1763
5052
|
this.state.clipByInstance = clipByInstance;
|
|
5053
|
+
if (this.context.device.type === "webgpu") {
|
|
5054
|
+
return {};
|
|
5055
|
+
}
|
|
1764
5056
|
return clipByInstance ? {
|
|
1765
5057
|
modules: [shaderModuleVs],
|
|
1766
5058
|
inject: injectionVs
|
|
@@ -1785,6 +5077,10 @@ var ClipExtension = class extends import_core10.LayerExtension {
|
|
|
1785
5077
|
Math.max(corner0[1], corner1[1])
|
|
1786
5078
|
];
|
|
1787
5079
|
}
|
|
5080
|
+
if (this.context.device.type === "webgpu") {
|
|
5081
|
+
clipProps.enabled = true;
|
|
5082
|
+
clipProps.mode = this.state.clipByInstance ? "instance" : "geometry";
|
|
5083
|
+
}
|
|
1788
5084
|
this.setShaderModuleProps({ clip: clipProps });
|
|
1789
5085
|
}
|
|
1790
5086
|
};
|
|
@@ -1792,12 +5088,8 @@ ClipExtension.defaultProps = defaultProps5;
|
|
|
1792
5088
|
ClipExtension.extensionName = "ClipExtension";
|
|
1793
5089
|
var clip_extension_default = ClipExtension;
|
|
1794
5090
|
|
|
1795
|
-
// dist/collision-filter/collision-filter-extension.js
|
|
1796
|
-
var import_core15 = require("@deck.gl/core");
|
|
1797
|
-
|
|
1798
5091
|
// dist/collision-filter/shader-module.js
|
|
1799
|
-
var
|
|
1800
|
-
var vs4 = (
|
|
5092
|
+
var vs5 = (
|
|
1801
5093
|
/* glsl */
|
|
1802
5094
|
`
|
|
1803
5095
|
in float collisionPriorities;
|
|
@@ -1895,8 +5187,8 @@ var getCollisionUniforms = (opts) => {
|
|
|
1895
5187
|
};
|
|
1896
5188
|
var shader_module_default2 = {
|
|
1897
5189
|
name: "collision",
|
|
1898
|
-
dependencies: [
|
|
1899
|
-
vs:
|
|
5190
|
+
dependencies: [project_default],
|
|
5191
|
+
vs: vs5,
|
|
1900
5192
|
inject: inject4,
|
|
1901
5193
|
getUniforms: getCollisionUniforms,
|
|
1902
5194
|
uniformTypes: {
|
|
@@ -1906,12 +5198,10 @@ var shader_module_default2 = {
|
|
|
1906
5198
|
};
|
|
1907
5199
|
|
|
1908
5200
|
// dist/collision-filter/collision-filter-effect.js
|
|
1909
|
-
var
|
|
1910
|
-
var import_core14 = require("@deck.gl/core");
|
|
5201
|
+
var import_core19 = require("@math.gl/core");
|
|
1911
5202
|
|
|
1912
5203
|
// dist/collision-filter/collision-filter-pass.js
|
|
1913
|
-
var
|
|
1914
|
-
var CollisionFilterPass = class extends import_core12._LayersPass {
|
|
5204
|
+
var CollisionFilterPass = class extends LayersPass {
|
|
1915
5205
|
renderCollisionMap(target, options) {
|
|
1916
5206
|
const padding = 1;
|
|
1917
5207
|
const clearColor = [0, 0, 0, 0];
|
|
@@ -2002,8 +5292,8 @@ var CollisionFilterEffect = class {
|
|
|
2002
5292
|
}
|
|
2003
5293
|
const needsRender = viewportChanged || // If render info is new
|
|
2004
5294
|
renderInfo === oldRenderInfo || // If sublayers have changed
|
|
2005
|
-
!(
|
|
2006
|
-
renderInfo.layerBounds.some((b, i) => !(0,
|
|
5295
|
+
!deepEqual(oldRenderInfo.layers, renderInfo.layers, 1) || // If a sublayer's bounds have been updated
|
|
5296
|
+
renderInfo.layerBounds.some((b, i) => !(0, import_core19.equals)(b, oldRenderInfo.layerBounds[i])) || // If a sublayer's isLoaded state has been updated
|
|
2007
5297
|
renderInfo.allLayersLoaded !== oldRenderInfo.allLayersLoaded || // Some prop is in transition
|
|
2008
5298
|
renderInfo.layers.some((layer) => layer.props.transitions);
|
|
2009
5299
|
this.channels[collisionGroup] = renderInfo;
|
|
@@ -2135,7 +5425,7 @@ var defaultProps6 = {
|
|
|
2135
5425
|
collisionGroup: { type: "string", value: "default" },
|
|
2136
5426
|
collisionTestProps: {}
|
|
2137
5427
|
};
|
|
2138
|
-
var CollisionFilterExtension = class extends
|
|
5428
|
+
var CollisionFilterExtension = class extends LayerExtension {
|
|
2139
5429
|
getShaders() {
|
|
2140
5430
|
return { modules: [shader_module_default2] };
|
|
2141
5431
|
}
|
|
@@ -2169,11 +5459,7 @@ CollisionFilterExtension.defaultProps = defaultProps6;
|
|
|
2169
5459
|
CollisionFilterExtension.extensionName = "CollisionFilterExtension";
|
|
2170
5460
|
var collision_filter_extension_default = CollisionFilterExtension;
|
|
2171
5461
|
|
|
2172
|
-
// dist/mask/mask-extension.js
|
|
2173
|
-
var import_core21 = require("@deck.gl/core");
|
|
2174
|
-
|
|
2175
5462
|
// dist/mask/shader-module.js
|
|
2176
|
-
var import_core16 = require("@deck.gl/core");
|
|
2177
5463
|
var uniformBlock4 = (
|
|
2178
5464
|
/* glsl */
|
|
2179
5465
|
`layout(std140) uniform maskUniforms {
|
|
@@ -2193,7 +5479,7 @@ vec2 mask_getCoords(vec4 position) {
|
|
|
2193
5479
|
}
|
|
2194
5480
|
`
|
|
2195
5481
|
);
|
|
2196
|
-
var
|
|
5482
|
+
var vs6 = `
|
|
2197
5483
|
${uniformBlock4}
|
|
2198
5484
|
${vertex3}
|
|
2199
5485
|
`;
|
|
@@ -2226,7 +5512,7 @@ bool mask_isInBounds(vec2 texCoords) {
|
|
|
2226
5512
|
}
|
|
2227
5513
|
`
|
|
2228
5514
|
);
|
|
2229
|
-
var
|
|
5515
|
+
var fs5 = `
|
|
2230
5516
|
${uniformBlock4}
|
|
2231
5517
|
${fragment3}
|
|
2232
5518
|
`;
|
|
@@ -2280,9 +5566,9 @@ var getMaskUniforms = (opts) => {
|
|
|
2280
5566
|
};
|
|
2281
5567
|
var shader_module_default3 = {
|
|
2282
5568
|
name: "mask",
|
|
2283
|
-
dependencies: [
|
|
2284
|
-
vs:
|
|
2285
|
-
fs:
|
|
5569
|
+
dependencies: [project_default],
|
|
5570
|
+
vs: vs6,
|
|
5571
|
+
fs: fs5,
|
|
2286
5572
|
inject: inject5,
|
|
2287
5573
|
getUniforms: getMaskUniforms,
|
|
2288
5574
|
uniformTypes: {
|
|
@@ -2295,11 +5581,9 @@ var shader_module_default3 = {
|
|
|
2295
5581
|
};
|
|
2296
5582
|
|
|
2297
5583
|
// dist/mask/mask-effect.js
|
|
2298
|
-
var
|
|
2299
|
-
var import_core20 = require("@math.gl/core");
|
|
5584
|
+
var import_core26 = require("@math.gl/core");
|
|
2300
5585
|
|
|
2301
5586
|
// dist/mask/mask-pass.js
|
|
2302
|
-
var import_core17 = require("@deck.gl/core");
|
|
2303
5587
|
var MASK_BLENDING = {
|
|
2304
5588
|
blendColorOperation: "subtract",
|
|
2305
5589
|
blendColorSrcFactor: "zero",
|
|
@@ -2308,7 +5592,7 @@ var MASK_BLENDING = {
|
|
|
2308
5592
|
blendAlphaSrcFactor: "zero",
|
|
2309
5593
|
blendAlphaDstFactor: "one"
|
|
2310
5594
|
};
|
|
2311
|
-
var MaskPass = class extends
|
|
5595
|
+
var MaskPass = class extends LayersPass {
|
|
2312
5596
|
constructor(device, props) {
|
|
2313
5597
|
super(device, props);
|
|
2314
5598
|
const { mapSize = 2048 } = props;
|
|
@@ -2353,8 +5637,7 @@ var MaskPass = class extends import_core17._LayersPass {
|
|
|
2353
5637
|
};
|
|
2354
5638
|
|
|
2355
5639
|
// dist/utils/projection-utils.js
|
|
2356
|
-
var
|
|
2357
|
-
var MERCATOR_REFERENCE_VIEWPORT = new import_core18.WebMercatorViewport({
|
|
5640
|
+
var MERCATOR_REFERENCE_VIEWPORT = new WebMercatorViewport({
|
|
2358
5641
|
width: 1,
|
|
2359
5642
|
height: 1,
|
|
2360
5643
|
longitude: 0,
|
|
@@ -2416,7 +5699,7 @@ function makeViewport(opts) {
|
|
|
2416
5699
|
zoom += Math.log2(r);
|
|
2417
5700
|
}
|
|
2418
5701
|
}
|
|
2419
|
-
return isGeospatial ? new
|
|
5702
|
+
return isGeospatial ? new WebMercatorViewport({
|
|
2420
5703
|
id: viewport.id,
|
|
2421
5704
|
x: border,
|
|
2422
5705
|
y: border,
|
|
@@ -2426,7 +5709,7 @@ function makeViewport(opts) {
|
|
|
2426
5709
|
latitude: centerWorld[1],
|
|
2427
5710
|
zoom,
|
|
2428
5711
|
orthographic: true
|
|
2429
|
-
}) : new
|
|
5712
|
+
}) : new OrthographicViewport({
|
|
2430
5713
|
id: viewport.id,
|
|
2431
5714
|
x: border,
|
|
2432
5715
|
y: border,
|
|
@@ -2519,7 +5802,7 @@ var MaskEffect = class {
|
|
|
2519
5802
|
const viewport = viewports[0];
|
|
2520
5803
|
const viewportChanged = !this.lastViewport || !this.lastViewport.equals(viewport);
|
|
2521
5804
|
if (viewport.resolution !== void 0) {
|
|
2522
|
-
|
|
5805
|
+
log_default.warn("MaskExtension is not supported in GlobeView")();
|
|
2523
5806
|
return { didRender };
|
|
2524
5807
|
}
|
|
2525
5808
|
for (const maskId in channelMap) {
|
|
@@ -2562,7 +5845,7 @@ var MaskEffect = class {
|
|
|
2562
5845
|
this.lastViewport = viewport;
|
|
2563
5846
|
const layerBounds = joinLayerBounds(channelInfo.layers, viewport);
|
|
2564
5847
|
channelInfo.bounds = layerBounds && getRenderBounds(layerBounds, viewport);
|
|
2565
|
-
if (maskChanged || !(0,
|
|
5848
|
+
if (maskChanged || !(0, import_core26.equals)(channelInfo.bounds, oldChannelInfo.bounds)) {
|
|
2566
5849
|
const { maskPass, maskMap } = this;
|
|
2567
5850
|
const maskViewport = layerBounds && makeViewport({
|
|
2568
5851
|
bounds: channelInfo.bounds,
|
|
@@ -2613,7 +5896,7 @@ var MaskEffect = class {
|
|
|
2613
5896
|
let channelInfo = channelMap[id];
|
|
2614
5897
|
if (!channelInfo) {
|
|
2615
5898
|
if (++channelCount > 4) {
|
|
2616
|
-
|
|
5899
|
+
log_default.warn("Too many mask layers. The max supported is 4")();
|
|
2617
5900
|
continue;
|
|
2618
5901
|
}
|
|
2619
5902
|
channelInfo = {
|
|
@@ -2674,7 +5957,7 @@ var defaultProps7 = {
|
|
|
2674
5957
|
maskByInstance: void 0,
|
|
2675
5958
|
maskInverted: false
|
|
2676
5959
|
};
|
|
2677
|
-
var MaskExtension = class extends
|
|
5960
|
+
var MaskExtension = class extends LayerExtension {
|
|
2678
5961
|
initializeState() {
|
|
2679
5962
|
var _a;
|
|
2680
5963
|
(_a = this.context.deck) == null ? void 0 : _a._addDefaultEffect(new MaskEffect());
|
|
@@ -2702,8 +5985,8 @@ var MaskExtension = class extends import_core21.LayerExtension {
|
|
|
2702
5985
|
maskProps.enabled = true;
|
|
2703
5986
|
maskProps.channel = index;
|
|
2704
5987
|
maskProps.inverted = maskInverted;
|
|
2705
|
-
if (fromCoordinateSystem ===
|
|
2706
|
-
fromCoordinateSystem = viewport.isGeospatial ?
|
|
5988
|
+
if (fromCoordinateSystem === COORDINATE_SYSTEM.DEFAULT) {
|
|
5989
|
+
fromCoordinateSystem = viewport.isGeospatial ? COORDINATE_SYSTEM.LNGLAT : COORDINATE_SYSTEM.CARTESIAN;
|
|
2707
5990
|
}
|
|
2708
5991
|
const opts = { modelMatrix: null, fromCoordinateOrigin, fromCoordinateSystem };
|
|
2709
5992
|
const bl = this.projectPosition([bounds[0], bounds[1], 0], opts);
|
|
@@ -2711,7 +5994,7 @@ var MaskExtension = class extends import_core21.LayerExtension {
|
|
|
2711
5994
|
maskProps.bounds = [bl[0], bl[1], tr[0], tr[1]];
|
|
2712
5995
|
} else {
|
|
2713
5996
|
if (maskId) {
|
|
2714
|
-
|
|
5997
|
+
log_default.warn(`Could not find a mask layer with id: ${maskId}`)();
|
|
2715
5998
|
}
|
|
2716
5999
|
maskProps.enabled = false;
|
|
2717
6000
|
}
|
|
@@ -2722,14 +6005,7 @@ MaskExtension.defaultProps = defaultProps7;
|
|
|
2722
6005
|
MaskExtension.extensionName = "MaskExtension";
|
|
2723
6006
|
var mask_extension_default = MaskExtension;
|
|
2724
6007
|
|
|
2725
|
-
// dist/terrain/terrain-extension.js
|
|
2726
|
-
var import_core28 = require("@deck.gl/core");
|
|
2727
|
-
|
|
2728
|
-
// dist/terrain/terrain-effect.js
|
|
2729
|
-
var import_core27 = require("@deck.gl/core");
|
|
2730
|
-
|
|
2731
6008
|
// dist/terrain/shader-module.js
|
|
2732
|
-
var import_core22 = require("@deck.gl/core");
|
|
2733
6009
|
var TERRAIN_MODE = {
|
|
2734
6010
|
NONE: 0,
|
|
2735
6011
|
/** A terrain layer rendering encoded ground elevation into the height map */
|
|
@@ -2758,7 +6034,7 @@ uniform sampler2D terrain_map;
|
|
|
2758
6034
|
);
|
|
2759
6035
|
var terrainModule = {
|
|
2760
6036
|
name: "terrain",
|
|
2761
|
-
dependencies: [
|
|
6037
|
+
dependencies: [project_default],
|
|
2762
6038
|
vs: `${uniformBlock5}
|
|
2763
6039
|
out vec3 commonPos;
|
|
2764
6040
|
// In globe mode, absolute Mercator position for terrain FBO UV lookups
|
|
@@ -2856,7 +6132,7 @@ if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_US
|
|
|
2856
6132
|
}
|
|
2857
6133
|
if ("terrainSkipRender" in opts || "drawToTerrainHeightMap" in opts) {
|
|
2858
6134
|
const { drawToTerrainHeightMap, heightMap, heightMapBounds, dummyHeightMap, terrainCover, useTerrainHeightMap, terrainSkipRender } = opts;
|
|
2859
|
-
const projectUniforms =
|
|
6135
|
+
const projectUniforms = project_default.getUniforms(opts.project);
|
|
2860
6136
|
const { commonOrigin } = projectUniforms;
|
|
2861
6137
|
let mode = terrainSkipRender ? TERRAIN_MODE.SKIP : TERRAIN_MODE.NONE;
|
|
2862
6138
|
let sampler = dummyHeightMap;
|
|
@@ -2906,11 +6182,7 @@ if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_US
|
|
|
2906
6182
|
}
|
|
2907
6183
|
};
|
|
2908
6184
|
|
|
2909
|
-
// dist/terrain/terrain-cover.js
|
|
2910
|
-
var import_core23 = require("@deck.gl/core");
|
|
2911
|
-
|
|
2912
6185
|
// dist/terrain/utils.js
|
|
2913
|
-
var import_constants = require("@luma.gl/webgl/constants");
|
|
2914
6186
|
function createRenderTarget(device, opts) {
|
|
2915
6187
|
return device.createFramebuffer({
|
|
2916
6188
|
id: opts.id,
|
|
@@ -3024,7 +6296,7 @@ var TerrainCover = class {
|
|
|
3024
6296
|
} else {
|
|
3025
6297
|
const oldZoom = (_a = this.renderViewport) == null ? void 0 : _a.zoom;
|
|
3026
6298
|
shouldRedraw = shouldRedraw || newZoom !== oldZoom;
|
|
3027
|
-
const newBounds = viewport instanceof
|
|
6299
|
+
const newBounds = viewport instanceof GlobeViewport ? this.targetBoundsCommon : getRenderBounds(this.targetBoundsCommon, viewport);
|
|
3028
6300
|
const oldBounds = this.bounds;
|
|
3029
6301
|
shouldRedraw = shouldRedraw || !oldBounds || newBounds.some((x, i) => x !== oldBounds[i]);
|
|
3030
6302
|
this.bounds = newBounds;
|
|
@@ -3101,7 +6373,6 @@ function intersect(b1, b2) {
|
|
|
3101
6373
|
}
|
|
3102
6374
|
|
|
3103
6375
|
// dist/terrain/terrain-pass.js
|
|
3104
|
-
var import_core24 = require("@deck.gl/core");
|
|
3105
6376
|
var TERRAIN_BLENDING = {
|
|
3106
6377
|
blendColorOperation: "max",
|
|
3107
6378
|
blendColorSrcFactor: "one",
|
|
@@ -3110,7 +6381,7 @@ var TERRAIN_BLENDING = {
|
|
|
3110
6381
|
blendAlphaSrcFactor: "one",
|
|
3111
6382
|
blendAlphaDstFactor: "one"
|
|
3112
6383
|
};
|
|
3113
|
-
var TerrainPass = class extends
|
|
6384
|
+
var TerrainPass = class extends LayersPass {
|
|
3114
6385
|
getRenderableLayers(viewport, opts) {
|
|
3115
6386
|
const { layers } = opts;
|
|
3116
6387
|
const result = [];
|
|
@@ -3175,8 +6446,7 @@ var TerrainPass = class extends import_core24._LayersPass {
|
|
|
3175
6446
|
};
|
|
3176
6447
|
|
|
3177
6448
|
// dist/terrain/terrain-picking-pass.js
|
|
3178
|
-
var
|
|
3179
|
-
var TerrainPickingPass = class extends import_core25._PickLayersPass {
|
|
6449
|
+
var TerrainPickingPass = class extends PickLayersPass {
|
|
3180
6450
|
constructor() {
|
|
3181
6451
|
super(...arguments);
|
|
3182
6452
|
this.drawParameters = {};
|
|
@@ -3247,7 +6517,6 @@ var TerrainPickingPass = class extends import_core25._PickLayersPass {
|
|
|
3247
6517
|
};
|
|
3248
6518
|
|
|
3249
6519
|
// dist/terrain/height-map-builder.js
|
|
3250
|
-
var import_core26 = require("@deck.gl/core");
|
|
3251
6520
|
var MAP_MAX_SIZE = 2048;
|
|
3252
6521
|
var HeightMapBuilder = class {
|
|
3253
6522
|
static isSupported(device) {
|
|
@@ -3294,7 +6563,7 @@ var HeightMapBuilder = class {
|
|
|
3294
6563
|
if (!this.layersBoundsCommon) {
|
|
3295
6564
|
this.renderViewport = null;
|
|
3296
6565
|
} else if (layersChanged || viewportChanged) {
|
|
3297
|
-
const bounds = viewport instanceof
|
|
6566
|
+
const bounds = viewport instanceof GlobeViewport ? this.layersBoundsCommon : getRenderBounds(this.layersBoundsCommon, viewport);
|
|
3298
6567
|
if (bounds[2] <= bounds[0] || bounds[3] <= bounds[1]) {
|
|
3299
6568
|
this.renderViewport = null;
|
|
3300
6569
|
return false;
|
|
@@ -3352,7 +6621,7 @@ var TerrainEffect = class {
|
|
|
3352
6621
|
if (HeightMapBuilder.isSupported(device)) {
|
|
3353
6622
|
this.heightMap = new HeightMapBuilder(device);
|
|
3354
6623
|
} else {
|
|
3355
|
-
|
|
6624
|
+
log_default.warn("Terrain offset mode is not supported by this browser")();
|
|
3356
6625
|
}
|
|
3357
6626
|
deck._addDefaultShaderModule(terrainModule);
|
|
3358
6627
|
}
|
|
@@ -3520,7 +6789,7 @@ var TerrainEffect = class {
|
|
|
3520
6789
|
var defaultProps8 = {
|
|
3521
6790
|
terrainDrawMode: void 0
|
|
3522
6791
|
};
|
|
3523
|
-
var TerrainExtension = class extends
|
|
6792
|
+
var TerrainExtension = class extends LayerExtension {
|
|
3524
6793
|
getShaders() {
|
|
3525
6794
|
return {
|
|
3526
6795
|
modules: [terrainModule]
|