From 48b8b7ac2909ac0de7fb1f79d881c2016405c8af Mon Sep 17 00:00:00 2001 From: Xiaoji Chen Date: Mon, 6 Jan 2020 12:41:28 -0800 Subject: [PATCH 1/3] support repeated world at low zoom levels --- modules/core/src/passes/layers-pass.js | 12 ++++-- .../src/viewports/web-mercator-viewport.js | 39 ++++++++++++++++++- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/modules/core/src/passes/layers-pass.js b/modules/core/src/passes/layers-pass.js index 12943020e90..b6dde7cc173 100644 --- a/modules/core/src/passes/layers-pass.js +++ b/modules/core/src/passes/layers-pass.js @@ -31,12 +31,16 @@ export default class LayersPass extends Pass { // Update context to point to this viewport onViewportActive(viewport); - props.viewport = viewport; props.view = view; // render this viewport - const stats = this._drawLayersInViewport(gl, props); - renderStats.push(stats); + const subViewports = viewport.subViewports || [viewport]; + for (const subViewport of subViewports) { + props.viewport = subViewport; + + const stats = this._drawLayersInViewport(gl, props); + renderStats.push(stats); + } }); return renderStats; } @@ -92,6 +96,8 @@ export default class LayersPass extends Pass { const _moduleParameters = this._getModuleParameters(layer, effects, pass, moduleParameters); const uniforms = Object.assign({}, layer.context.uniforms, {layerIndex}); const layerParameters = this.getLayerParameters(layer, layerIndex); + // overwrite layer.context.viewport with the sub viewport + _moduleParameters.viewport = viewport; try { layer.drawLayer({ diff --git a/modules/core/src/viewports/web-mercator-viewport.js b/modules/core/src/viewports/web-mercator-viewport.js index 08c483dff46..7dba567ea60 100644 --- a/modules/core/src/viewports/web-mercator-viewport.js +++ b/modules/core/src/viewports/web-mercator-viewport.js @@ -32,6 +32,7 @@ import { // TODO - import from math.gl import * as vec2 from 'gl-matrix/vec2'; +import {Matrix4} from 'math.gl'; export default class WebMercatorViewport extends Viewport { /** @@ -50,7 +51,9 @@ export default class WebMercatorViewport extends Viewport { bearing = 0, nearZMultiplier = 0.1, farZMultiplier = 1.01, - orthographic = false + orthographic = false, + + worldOffset } = opts; let {width, height, altitude = 1.5} = opts; @@ -77,7 +80,7 @@ export default class WebMercatorViewport extends Viewport { // shader (cheap) which gives a coordinate system that has its center in // the layer's center position. This makes rotations and other modelMatrx // transforms much more useful. - const viewMatrixUncentered = getViewMatrix({ + let viewMatrixUncentered = getViewMatrix({ height, pitch, bearing, @@ -85,6 +88,11 @@ export default class WebMercatorViewport extends Viewport { altitude }); + if (worldOffset) { + const viewOffset = new Matrix4().translate([512 * worldOffset, 0, 0]); + viewMatrixUncentered = viewOffset.multiplyLeft(viewMatrixUncentered); + } + const viewportOpts = Object.assign({}, opts, { // x, y, width, @@ -117,11 +125,38 @@ export default class WebMercatorViewport extends Viewport { this.altitude = altitude; this.orthographic = orthographic; + this._subViewports = []; Object.freeze(this); } /* eslint-enable complexity, max-statements */ + get subViewports() { + if (!this._subViewports.length) { + const topLeft = this.unproject([0, 0]); + const topRight = this.unproject([this.width, 0]); + const bottomLeft = this.unproject([0, this.height]); + const bottomRight = this.unproject([this.width, this.height]); + + const minLon = Math.min(topLeft[0], topRight[0], bottomLeft[0], bottomRight[0]); + const maxLon = Math.max(topLeft[0], topRight[0], bottomLeft[0], bottomRight[0]); + + const minOffset = Math.floor((minLon + 180) / 360); + const maxOffset = Math.ceil((maxLon - 180) / 360); + + for (let x = minOffset; x <= maxOffset; x++) { + const offsetViewport = x + ? new WebMercatorViewport({ + ...this, + worldOffset: x + }) + : this; + this._subViewports.push(offsetViewport); + } + } + return this._subViewports; + } + /** * Add a meter delta to a base lnglat coordinate, returning a new lnglat array * From ab390756c00384716f55edfa71c5e9bf3b3ec7cb Mon Sep 17 00:00:00 2001 From: Xiaoji Chen Date: Mon, 6 Jan 2020 13:02:03 -0800 Subject: [PATCH 2/3] tests and docs --- docs/api-reference/map-view.md | 4 ++- .../src/viewports/web-mercator-viewport.js | 9 +++-- .../viewports/web-mercator-viewport.spec.js | 34 ++++++++++++++++++ test/render/golden-images/map-repeat.png | Bin 0 -> 13678 bytes test/render/test-cases.js | 21 +++++++++++ 5 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 test/render/golden-images/map-repeat.png diff --git a/docs/api-reference/map-view.md b/docs/api-reference/map-view.md index d8315de4124..37794b70753 100644 --- a/docs/api-reference/map-view.md +++ b/docs/api-reference/map-view.md @@ -11,7 +11,9 @@ import {MapView} from '@deck.gl/core'; const view = new MapView({id, ...}); ``` -`MapView` takes the same parameters as the [View](/docs/api-reference/view.md) superclass constructor. +`MapView` takes the same parameters as the [View](/docs/api-reference/view.md) superclass constructor, plus the following: + +- `repeat` (`Boolean`) - Whether to render multiple copies of the map at low zoom levels. Default `false`. ## View State diff --git a/modules/core/src/viewports/web-mercator-viewport.js b/modules/core/src/viewports/web-mercator-viewport.js index 7dba567ea60..a60bcca5215 100644 --- a/modules/core/src/viewports/web-mercator-viewport.js +++ b/modules/core/src/viewports/web-mercator-viewport.js @@ -53,7 +53,8 @@ export default class WebMercatorViewport extends Viewport { farZMultiplier = 1.01, orthographic = false, - worldOffset + repeat = false, + worldOffset = 0 } = opts; let {width, height, altitude = 1.5} = opts; @@ -125,14 +126,16 @@ export default class WebMercatorViewport extends Viewport { this.altitude = altitude; this.orthographic = orthographic; - this._subViewports = []; + + this._subViewports = repeat ? [] : null; Object.freeze(this); } /* eslint-enable complexity, max-statements */ get subViewports() { - if (!this._subViewports.length) { + if (this._subViewports && !this._subViewports.length) { + // Cache sub viewports so that we only calculate them once const topLeft = this.unproject([0, 0]); const topRight = this.unproject([this.width, 0]); const bottomLeft = this.unproject([0, this.height]); diff --git a/test/modules/core/viewports/web-mercator-viewport.spec.js b/test/modules/core/viewports/web-mercator-viewport.spec.js index 5c6a836d70e..de5dc147755 100644 --- a/test/modules/core/viewports/web-mercator-viewport.spec.js +++ b/test/modules/core/viewports/web-mercator-viewport.spec.js @@ -242,6 +242,40 @@ test('WebMercatorViewport.getFrustumPlanes', t => { t.end(); }); +test('WebMercatorViewport.subViewports', t => { + let viewport = new WebMercatorViewport(TEST_VIEWPORTS[0]); + t.deepEqual(viewport.subViewports, null, 'gets correct subViewports'); + + viewport = new WebMercatorViewport({...TEST_VIEWPORTS[0], repeat: true}); + t.deepEqual(viewport.subViewports, [viewport], 'gets correct subViewports'); + + viewport = new WebMercatorViewport({ + width: 800, + height: 400, + longitude: 0, + latitude: 0, + zoom: 0, + repeat: true + }); + const {subViewports} = viewport; + t.is(subViewports.length, 3, 'gets correct subViewports'); + t.deepEqual( + subViewports[0].project([0, 0]), + [400 - 512, 200], + 'center offset in subViewports[0]' + ); + t.deepEqual(subViewports[1].project([0, 0]), [400, 200], 'center offset in subViewports[1]'); + t.deepEqual( + subViewports[2].project([0, 0]), + [400 + 512, 200], + 'center offset in subViewports[2]' + ); + + t.is(viewport.subViewports, subViewports, 'subViewports are cached'); + + t.end(); +}); + function getCulling(p, planes) { let outDir = null; p = new Vector3(p); diff --git a/test/render/golden-images/map-repeat.png b/test/render/golden-images/map-repeat.png new file mode 100644 index 0000000000000000000000000000000000000000..fbbca6c126830595291d5a719b13c45ffadf5a6a GIT binary patch literal 13678 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 literal 0 HcmV?d00001 diff --git a/test/render/test-cases.js b/test/render/test-cases.js index b3f1d685ca5..9b2d20dd9ff 100644 --- a/test/render/test-cases.js +++ b/test/render/test-cases.js @@ -9,6 +9,7 @@ import { } from '@deck.gl/aggregation-layers'; import { COORDINATE_SYSTEM, + MapView, OrbitView, OrthographicView, FirstPersonView, @@ -1984,5 +1985,25 @@ export const TEST_CASES = [ }) ], goldenImage: './test/render/golden-images/binary.png' + }, + { + name: 'map-repeat', + views: new MapView({repeat: true}), + viewState: { + latitude: 0, + longitude: 0, + zoom: 0, + pitch: 0, + bearing: 0 + }, + layers: [ + new ScatterplotLayer({ + data: h3.getRes0Indexes(), + getPosition: d => h3.h3ToGeo(d).reverse(), + radiusMinPixels: 4, + getFillColor: [255, 0, 0] + }) + ], + goldenImage: './test/render/golden-images/map-repeat.png' } ]; From a67b2e67bc825eb1faac8aa9af54082766a3e449 Mon Sep 17 00:00:00 2001 From: Xiaoji Chen Date: Wed, 15 Jan 2020 13:21:34 -0800 Subject: [PATCH 3/3] use for loops --- modules/core/src/passes/layers-pass.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/modules/core/src/passes/layers-pass.js b/modules/core/src/passes/layers-pass.js index b6dde7cc173..ac4ed40728d 100644 --- a/modules/core/src/passes/layers-pass.js +++ b/modules/core/src/passes/layers-pass.js @@ -23,7 +23,7 @@ export default class LayersPass extends Pass { const renderStats = []; - viewports.forEach((viewportOrDescriptor, i) => { + for (const viewportOrDescriptor of viewports) { // Get a viewport from a viewport descriptor (which can be a plain viewport) const viewport = viewportOrDescriptor.viewport || viewportOrDescriptor; const view = views && views[viewport.id]; @@ -41,13 +41,14 @@ export default class LayersPass extends Pass { const stats = this._drawLayersInViewport(gl, props); renderStats.push(stats); } - }); + } return renderStats; } // Draws a list of layers in one viewport // TODO - when picking we could completely skip rendering viewports that dont // intersect with the picking rect + /* eslint-disable max-depth */ _drawLayersInViewport( gl, {layers, layerFilter, onError, viewport, view, pass = 'unknown', effects, moduleParameters} @@ -77,7 +78,8 @@ export default class LayersPass extends Pass { setParameters(gl, {viewport: glViewport}); // render layers in normal colors - layers.forEach((layer, layerIndex) => { + for (let layerIndex = 0; layerIndex < layers.length; layerIndex++) { + const layer = layers[layerIndex]; // Check if we should draw layer const shouldDrawLayer = this._shouldDrawLayer(layer, viewport, pass, layerFilter); @@ -94,7 +96,6 @@ export default class LayersPass extends Pass { renderStatus.visibleCount++; const _moduleParameters = this._getModuleParameters(layer, effects, pass, moduleParameters); - const uniforms = Object.assign({}, layer.context.uniforms, {layerIndex}); const layerParameters = this.getLayerParameters(layer, layerIndex); // overwrite layer.context.viewport with the sub viewport _moduleParameters.viewport = viewport; @@ -102,7 +103,7 @@ export default class LayersPass extends Pass { try { layer.drawLayer({ moduleParameters: _moduleParameters, - uniforms, + uniforms: {layerIndex}, parameters: layerParameters }); } catch (err) { @@ -113,10 +114,11 @@ export default class LayersPass extends Pass { } } } - }); + } return renderStatus; } + /* eslint-enable max-depth */ /* Methods for subclass overrides */ shouldDrawLayer(layer) {