From 0cf46ba95b7af11fc525969f7109b7c3bab99543 Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Wed, 30 Jun 2021 16:24:20 +0200 Subject: [PATCH 1/7] WebMercatorViewport support external projectionMatrix Provide fov rather than scaleMultiplier Use projectionMatrix rather than fov for altitude Add this.fovy to WebMercatorViewport Fix path to math.gl/web-mercator Remove altitudeFromProjection variable --- examples/webpack.config.local.js | 2 +- .../src/viewports/web-mercator-viewport.js | 6 +++++- .../viewports/web-mercator-viewport.spec.js | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/examples/webpack.config.local.js b/examples/webpack.config.local.js index a3b8bce869d..8c88f253f51 100644 --- a/examples/webpack.config.local.js +++ b/examples/webpack.config.local.js @@ -61,7 +61,7 @@ function makeLocalDevConfig(EXAMPLE_DIR = LIB_DIR, linkToLuma, linkToMath) { 'geoid', 'geospatial', 'main', - 'mercator', + 'web-mercator', 'polygon', 'proj4', 'sun', diff --git a/modules/core/src/viewports/web-mercator-viewport.js b/modules/core/src/viewports/web-mercator-viewport.js index 453d410e871..a6fc43e771a 100644 --- a/modules/core/src/viewports/web-mercator-viewport.js +++ b/modules/core/src/viewports/web-mercator-viewport.js @@ -35,6 +35,8 @@ import { import * as vec2 from 'gl-matrix/vec2'; import {Matrix4} from 'math.gl'; +const RADIANS_TO_DEGREES = 180 / Math.PI; + export default class WebMercatorViewport extends Viewport { /** * @classdesc @@ -52,6 +54,7 @@ export default class WebMercatorViewport extends Viewport { bearing = 0, nearZMultiplier = 0.1, farZMultiplier = 1.01, + projectionMatrix, orthographic = false, repeat = false, @@ -73,7 +76,7 @@ export default class WebMercatorViewport extends Viewport { width, height, pitch, - altitude, + altitude: projectionMatrix ? projectionMatrix[5] / 2 : altitude, nearZMultiplier, farZMultiplier }); @@ -123,6 +126,7 @@ export default class WebMercatorViewport extends Viewport { this.pitch = pitch; this.bearing = bearing; this.altitude = altitude; + this.fovy = fov * RADIANS_TO_DEGREES; this.orthographic = orthographic; diff --git a/test/modules/core/viewports/web-mercator-viewport.spec.js b/test/modules/core/viewports/web-mercator-viewport.spec.js index de5dc147755..bc51d4a2337 100644 --- a/test/modules/core/viewports/web-mercator-viewport.spec.js +++ b/test/modules/core/viewports/web-mercator-viewport.spec.js @@ -21,12 +21,15 @@ import test from 'tape-catch'; import {equals, config, Vector3} from 'math.gl'; import {WebMercatorViewport} from 'deck.gl'; +import {Matrix4} from 'math.gl'; // Adjust sensitivity of math.gl's equals const LNGLAT_TOLERANCE = 1e-6; const ALT_TOLERANCE = 1e-5; const OFFSET_TOLERANCE = 1e-5; +const DEGREES_TO_RADIANS = Math.PI / 180; + /* eslint-disable */ const TEST_VIEWPORTS = [ { @@ -276,6 +279,21 @@ test('WebMercatorViewport.subViewports', t => { t.end(); }); +test('WebMercatorViewport.projectionMatrix', t => { + const opts = {...TEST_VIEWPORTS[0]}; + + const fovy = 25; + const projectionMatrix = new Matrix4().perspective({ + fovy: fovy * DEGREES_TO_RADIANS, + aspect: opts.width / opts.height, + near: 0.1, + far: 10 + }); + let viewport = new WebMercatorViewport({projectionMatrix, ...opts}); + t.deepEqual(viewport.fovy, fovy, 'fovy is passed through'); + t.end(); +}); + function getCulling(p, planes) { let outDir = null; p = new Vector3(p); From ccac757f23900c50734eaf72a380ce5d3d491e42 Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Fri, 16 Jul 2021 15:25:25 +0200 Subject: [PATCH 2/7] Docs on projectionMatrix in WebMercatorViewport --- docs/api-reference/core/web-mercator-viewport.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/api-reference/core/web-mercator-viewport.md b/docs/api-reference/core/web-mercator-viewport.md index 9d9c65be4b5..d6a94a5a783 100644 --- a/docs/api-reference/core/web-mercator-viewport.md +++ b/docs/api-reference/core/web-mercator-viewport.md @@ -51,6 +51,7 @@ Parameters: + `nearZMultiplier` (Number, optional) - Scaler for the near plane, 1 unit equals to the height of the viewport. Default to `0.1`. + `farZMultiplier` (Number, optional) - Scaler for the far plane, 1 unit equals to the distance from the camera to the top edge of the screen. Default to `1.01`. + `orthographic` (Boolean, optional) - Default `false`. + + `projectionMatrix` (Array, optional) - Optional 16-element 4x4 projection matrix, that overrides the matrix created from the parameters above. Remarks: @@ -58,6 +59,7 @@ Remarks: * `width` and `height` are forced to 1 if supplied as 0, to avoid division by zero. This is intended to reduce the burden of apps to check values before instantiating a `Viewport`. * When using Mercator projection, per cartographic tradition, longitudes and latitudes are specified as degrees. * `latitude` of `90` or `-90` are projected to infinity in [Web Mercator projection](https://en.wikipedia.org/wiki/Web_Mercator_projection). Using pole locations with this viewport may result in `NaN`s. Many base map providers cut off at `85.051129` at which the full world becomes a square. +* When constructing the viewport, a field of view is not specified, but rather is calculated from the `altitude` or (if present) the `projectionMatrix`. The value can be obtained from `this.fovy` (in radians). Inherits all [Viewport methods](/docs/api-reference/core/viewport.md#methods). From cdd49c42c7cacaa1371456d0a869032f35556f89 Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Mon, 19 Jul 2021 13:04:35 +0200 Subject: [PATCH 3/7] Use new getProjectionParameters signature with fov --- modules/core/src/viewports/web-mercator-viewport.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/core/src/viewports/web-mercator-viewport.js b/modules/core/src/viewports/web-mercator-viewport.js index a6fc43e771a..2a73734c642 100644 --- a/modules/core/src/viewports/web-mercator-viewport.js +++ b/modules/core/src/viewports/web-mercator-viewport.js @@ -27,6 +27,7 @@ import { getViewMatrix, addMetersToLngLat, getProjectionParameters, + altitudeToFovy, fitBounds, getBounds } from '@math.gl/web-mercator'; @@ -35,8 +36,6 @@ import { import * as vec2 from 'gl-matrix/vec2'; import {Matrix4} from 'math.gl'; -const RADIANS_TO_DEGREES = 180 / Math.PI; - export default class WebMercatorViewport extends Viewport { /** * @classdesc @@ -72,11 +71,12 @@ export default class WebMercatorViewport extends Viewport { // TODO - just throw an Error instead? altitude = Math.max(0.75, altitude); - const {fov, aspect, focalDistance, near, far} = getProjectionParameters({ + const fovy = altitudeToFovy(projectionMatrix ? projectionMatrix[5] / 2 : altitude); + const {aspect, fov: fovyRadians, focalDistance, near, far} = getProjectionParameters({ width, height, pitch, - altitude: projectionMatrix ? projectionMatrix[5] / 2 : altitude, + fovy, nearZMultiplier, farZMultiplier }); @@ -112,7 +112,7 @@ export default class WebMercatorViewport extends Viewport { // projection matrix parameters orthographic, - fovyRadians: fov, + fovyRadians, aspect, focalDistance, near, @@ -126,7 +126,7 @@ export default class WebMercatorViewport extends Viewport { this.pitch = pitch; this.bearing = bearing; this.altitude = altitude; - this.fovy = fov * RADIANS_TO_DEGREES; + this.fovy = fovy; this.orthographic = orthographic; From 5251d2298895f2d3e7e6bfdc05fbb0d850b61128 Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Tue, 20 Jul 2021 11:29:39 +0200 Subject: [PATCH 4/7] Set focalDistance equal to altitude --- modules/core/src/viewports/web-mercator-viewport.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/core/src/viewports/web-mercator-viewport.js b/modules/core/src/viewports/web-mercator-viewport.js index 2a73734c642..e76ee214fed 100644 --- a/modules/core/src/viewports/web-mercator-viewport.js +++ b/modules/core/src/viewports/web-mercator-viewport.js @@ -72,7 +72,7 @@ export default class WebMercatorViewport extends Viewport { altitude = Math.max(0.75, altitude); const fovy = altitudeToFovy(projectionMatrix ? projectionMatrix[5] / 2 : altitude); - const {aspect, fov: fovyRadians, focalDistance, near, far} = getProjectionParameters({ + const {aspect, fov: fovyRadians, near, far} = getProjectionParameters({ width, height, pitch, @@ -80,6 +80,7 @@ export default class WebMercatorViewport extends Viewport { nearZMultiplier, farZMultiplier }); + const focalDistance = altitude; // The uncentered matrix allows us two move the center addition to the // shader (cheap) which gives a coordinate system that has its center in From f53b7384468c903de957faae9732601ba6a33455 Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Tue, 20 Jul 2021 18:44:02 +0200 Subject: [PATCH 5/7] =?UTF-8?q?Don=E2=80=99t=20get=20projection=20paramete?= =?UTF-8?q?rs=20if=20we=20have=20matrix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/viewports/web-mercator-viewport.js | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/modules/core/src/viewports/web-mercator-viewport.js b/modules/core/src/viewports/web-mercator-viewport.js index e76ee214fed..ee2e6d6d5c9 100644 --- a/modules/core/src/viewports/web-mercator-viewport.js +++ b/modules/core/src/viewports/web-mercator-viewport.js @@ -53,8 +53,8 @@ export default class WebMercatorViewport extends Viewport { bearing = 0, nearZMultiplier = 0.1, farZMultiplier = 1.01, - projectionMatrix, orthographic = false, + projectionMatrix, repeat = false, worldOffset = 0 @@ -71,16 +71,30 @@ export default class WebMercatorViewport extends Viewport { // TODO - just throw an Error instead? altitude = Math.max(0.75, altitude); - const fovy = altitudeToFovy(projectionMatrix ? projectionMatrix[5] / 2 : altitude); - const {aspect, fov: fovyRadians, near, far} = getProjectionParameters({ - width, - height, - pitch, - fovy, - nearZMultiplier, - farZMultiplier - }); - const focalDistance = altitude; + let fovy; + let projectionParameters; + if (projectionMatrix) { + fovy = altitudeToFovy(projectionMatrix[5] / 2); + projectionParameters = {focalDistance: altitude, projectionMatrix}; + } else { + fovy = altitudeToFovy(altitude); + const {aspect, fov: fovyRadians, near, far} = getProjectionParameters({ + width, + height, + pitch, + fovy, + nearZMultiplier, + farZMultiplier + }); + projectionParameters = { + orthographic, + fovyRadians, + aspect, + focalDistance: altitude, + near, + far + }; + } // The uncentered matrix allows us two move the center addition to the // shader (cheap) which gives a coordinate system that has its center in @@ -112,12 +126,7 @@ export default class WebMercatorViewport extends Viewport { zoom, // projection matrix parameters - orthographic, - fovyRadians, - aspect, - focalDistance, - near, - far + ...projectionParameters }); // Save parameters From 51de24647e354be1ac8dc741746fb88a9190d7dc Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Wed, 21 Jul 2021 12:35:58 +0200 Subject: [PATCH 6/7] Correct radians to degrees --- docs/api-reference/core/web-mercator-viewport.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api-reference/core/web-mercator-viewport.md b/docs/api-reference/core/web-mercator-viewport.md index d6a94a5a783..937c46d7893 100644 --- a/docs/api-reference/core/web-mercator-viewport.md +++ b/docs/api-reference/core/web-mercator-viewport.md @@ -59,7 +59,7 @@ Remarks: * `width` and `height` are forced to 1 if supplied as 0, to avoid division by zero. This is intended to reduce the burden of apps to check values before instantiating a `Viewport`. * When using Mercator projection, per cartographic tradition, longitudes and latitudes are specified as degrees. * `latitude` of `90` or `-90` are projected to infinity in [Web Mercator projection](https://en.wikipedia.org/wiki/Web_Mercator_projection). Using pole locations with this viewport may result in `NaN`s. Many base map providers cut off at `85.051129` at which the full world becomes a square. -* When constructing the viewport, a field of view is not specified, but rather is calculated from the `altitude` or (if present) the `projectionMatrix`. The value can be obtained from `this.fovy` (in radians). +* When constructing the viewport, a field of view is not specified, but rather is calculated from the `altitude` or (if present) the `projectionMatrix`. The value can be obtained from `this.fovy` (in degrees). Inherits all [Viewport methods](/docs/api-reference/core/viewport.md#methods). From d371963367f34b40b16283254efae76b5d228b13 Mon Sep 17 00:00:00 2001 From: Felix Palmer Date: Wed, 21 Jul 2021 12:44:40 +0200 Subject: [PATCH 7/7] Avoid needless destructuring --- modules/core/src/viewports/web-mercator-viewport.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/modules/core/src/viewports/web-mercator-viewport.js b/modules/core/src/viewports/web-mercator-viewport.js index ee2e6d6d5c9..6f1bb9187e8 100644 --- a/modules/core/src/viewports/web-mercator-viewport.js +++ b/modules/core/src/viewports/web-mercator-viewport.js @@ -72,10 +72,9 @@ export default class WebMercatorViewport extends Viewport { altitude = Math.max(0.75, altitude); let fovy; - let projectionParameters; + let projectionParameters = null; if (projectionMatrix) { fovy = altitudeToFovy(projectionMatrix[5] / 2); - projectionParameters = {focalDistance: altitude, projectionMatrix}; } else { fovy = altitudeToFovy(altitude); const {aspect, fov: fovyRadians, near, far} = getProjectionParameters({ @@ -87,10 +86,8 @@ export default class WebMercatorViewport extends Viewport { farZMultiplier }); projectionParameters = { - orthographic, fovyRadians, aspect, - focalDistance: altitude, near, far }; @@ -126,7 +123,9 @@ export default class WebMercatorViewport extends Viewport { zoom, // projection matrix parameters - ...projectionParameters + ...projectionParameters, + fovy, + focalDistance: altitude }); // Save parameters