From 69a347bc68be2d861122d982505fbc88a27a7056 Mon Sep 17 00:00:00 2001 From: Molly Lloyd Date: Tue, 19 Sep 2017 18:04:49 -0700 Subject: [PATCH] use object instead of array for tile masks --- src/render/tile_mask.js | 11 ++-- src/source/tile.js | 18 +++--- test/unit/source/tile_mask.test.js | 90 +++++++++++++++--------------- 3 files changed, 62 insertions(+), 57 deletions(-) diff --git a/src/render/tile_mask.js b/src/render/tile_mask.js index 244c4b8c703..ec8a9d769dc 100644 --- a/src/render/tile_mask.js +++ b/src/render/tile_mask.js @@ -4,6 +4,9 @@ const TileCoord = require('../source/tile_coord'); import type Tile from './../source/tile'; +export type Mask = { + [number]: boolean +}; // Updates the TileMasks for all renderable tiles. A TileMask describes all regions // within that tile that are *not* covered by other renderable tiles. @@ -51,7 +54,7 @@ import type Tile from './../source/tile'; // │ │ │ // └─────────────────┴─────────────────┘ // -// Only other renterable tiles that are *children* of the tile we are generating the mask for will +// Only other renderable tiles that are *children* of the tile we are generating the mask for will // be considered. For example, adding TileID 4/8/13 to renderableTiles won't affect the TileMask for // 2/1/3, since it is not a descendant of it. @@ -60,7 +63,7 @@ module.exports = function(renderableTiles: Array, gl: WebGLRenderingContex const sortedRenderables = renderableTiles.sort((a, b) => { return a.coord.isLessThan(b.coord) ? -1 : b.coord.isLessThan(a.coord) ? 1 : 0; }); for (let i = 0; i < sortedRenderables.length; i++) { - const mask = []; + const mask = {}; const tile = sortedRenderables[i]; const childArray = sortedRenderables.slice(i + 1); // Try to add all remaining ids as children. We sorted the tile list @@ -73,7 +76,7 @@ module.exports = function(renderableTiles: Array, gl: WebGLRenderingContex } }; -function computeTileMasks(rootTile: TileCoord, ref: TileCoord, childArray: Array, lowerBound: TileCoord, mask: Array) { +function computeTileMasks(rootTile: TileCoord, ref: TileCoord, childArray: Array, lowerBound: TileCoord, mask: Mask) { // If the reference or any of its children is found in the list, we need to recurse. for (let i = 0; i < childArray.length; i++) { const childTile = childArray[i]; @@ -97,6 +100,6 @@ function computeTileMasks(rootTile: TileCoord, ref: TileCoord, childArray: Array // elements are always relative (see below for explanation). const diffZ = ref.z - rootTile.z; const maskTileId = new TileCoord(diffZ, ref.x - (rootTile.x << diffZ), ref.y - (rootTile.y << diffZ)).id; - if (mask.indexOf(maskTileId) < 0) mask.push(maskTileId); + mask[maskTileId] = mask[maskTileId] || true; } diff --git a/src/source/tile.js b/src/source/tile.js index bcba8fc99f9..e3bb0f4c5c7 100644 --- a/src/source/tile.js +++ b/src/source/tile.js @@ -25,7 +25,7 @@ import type {Bucket} from '../data/bucket'; import type StyleLayer from '../style/style_layer'; import type {WorkerTileResult} from './worker_source'; import type {RGBAImage, AlphaImage} from '../util/image'; - +import type Mask from '../render/tile_mask'; export type TileState = | 'loading' // Tile data is in the process of loading. | 'loaded' // Tile data has been loaded. Tile can be rendered. @@ -71,7 +71,7 @@ class Tile { placementSource: any; workerID: number; vtLayers: {[string]: VectorTileLayer}; - mask: Array; + mask: Mask; aborted: ?boolean; maskedBoundsBuffer: ?VertexBuffer; maskedBoundsVAO: ?VertexArrayObject; @@ -362,7 +362,7 @@ class Tile { } } - setMask(mask: Array, gl: WebGLRenderingContext) { + setMask(mask: Mask, gl: WebGLRenderingContext) { // don't redo buffer work if the mask is the same; if (util.deepEqual(this.mask, mask)) return; @@ -373,14 +373,16 @@ class Tile { // We want to render the full tile, and keeping the segments/vertices/indices empty means // using the global shared buffers for covering the entire tile. - if (util.deepEqual(mask, [0])) return; - + if (util.deepEqual(mask, {'0': true})) return; + const maskArray = Object.keys(mask); // mask is empty because all four children are loaded - if (mask.length === 0) return; + if (maskArray.length === 0) return; + const maskedBoundsArray = new RasterBoundsArray(); - for (let i = 0; i < mask.length; i++) { - const maskCoord = TileCoord.fromID(mask[i]); + + for (let i = 0; i < maskArray.length; i++) { + const maskCoord = TileCoord.fromID(+maskArray[i]); const vertexExtent = EXTENT >> maskCoord.z; const tlVertex = new Point(maskCoord.x * vertexExtent, maskCoord.y * vertexExtent); const brVertex = new Point(tlVertex.x + vertexExtent, tlVertex.y + vertexExtent); diff --git a/test/unit/source/tile_mask.test.js b/test/unit/source/tile_mask.test.js index e03c94482c3..d15a10225f2 100644 --- a/test/unit/source/tile_mask.test.js +++ b/test/unit/source/tile_mask.test.js @@ -27,26 +27,26 @@ test('computeTileMasks', (t) => { t.test('no children', (t) => { const renderables = [new Tile(0, 0, 0) ]; updateTileMasks(renderables); - t.deepEqual(renderables[0].mask, [new TileCoord(0, 0, 0).id]); + t.deepEqual(Object.keys(renderables[0].mask), [new TileCoord(0, 0, 0).id]); const renderables2 = [new Tile(4, 3, 8)]; updateTileMasks(renderables2); - t.deepEqual(renderables[0].mask, [new TileCoord(0, 0, 0).id]); + t.deepEqual(Object.keys(renderables2[0].mask), [new TileCoord(0, 0, 0).id]); const renderables3 = [new Tile(1, 0, 0), new Tile(1, 1, 1)]; updateTileMasks(renderables3); - t.deepEqual(renderables3.map((r)=>{ return r.mask; }), [[new TileCoord(0, 0, 0).id], [new TileCoord(0, 0, 0).id]]); + t.deepEqual(renderables3.map((r)=>{ return Object.keys(r.mask); }), [[new TileCoord(0, 0, 0).id], [new TileCoord(0, 0, 0).id]]); const renderables4 = [new Tile(1, 0, 0), new Tile(2, 2, 3)]; updateTileMasks(renderables4); - t.deepEqual(renderables4.map((r)=>{ return r.mask; }), [[new TileCoord(0, 0, 0).id], [new TileCoord(0, 0, 0).id]]); + t.deepEqual(renderables4.map((r)=>{ return Object.keys(r.mask); }), [[new TileCoord(0, 0, 0).id], [new TileCoord(0, 0, 0).id]]); t.end(); }); t.test('parents with all four children', (t) => { const renderables = [new Tile(0, 0, 0), new Tile(1, 0, 0), new Tile(1, 0, 1), new Tile(1, 1, 0), new Tile(1, 1, 1)]; updateTileMasks(renderables); - t.deepEqual(renderables.map((r)=>{ return r.mask; }), [ + t.deepEqual(renderables.map((r)=>{ return Object.keys(r.mask); }), [ // empty mask -- i.e. don't draw anything because child tiles cover the whole parent tile [], [new TileCoord(0, 0, 0).id], @@ -59,7 +59,7 @@ test('computeTileMasks', (t) => { t.test('parent and one child', (t) => { const renderables = [new Tile(0, 0, 0), new Tile(1, 0, 0)]; updateTileMasks(renderables); - t.deepEqual(renderables.map((r)=>{ return r.mask; }), [ + t.deepEqual(renderables.map((r)=>{ return Object.keys(r.mask); }), [ [ new TileCoord(1, 1, 0).id, new TileCoord(1, 0, 1).id, @@ -79,26 +79,26 @@ test('computeTileMasks', (t) => { new Tile(14, 4114, 5824), new Tile(14, 4114, 5825)]; updateTileMasks(renderables); - t.deepEqual(renderables.map((r)=>{ return r.mask; }), [ + t.deepEqual(renderables.map((r)=>{ return Object.keys(r.mask); }), [ [ - new TileCoord(2, 3, 0).id, - new TileCoord(2, 3, 1).id, - new TileCoord(1, 1, 1).id + new TileCoord(1, 1, 1).id.toString(), + new TileCoord(2, 3, 0).id.toString(), + new TileCoord(2, 3, 1).id.toString(), ], [ - new TileCoord(1, 1, 0).id, - new TileCoord(1, 0, 1).id, - new TileCoord(1, 1, 1).id + new TileCoord(1, 1, 0).id.toString(), + new TileCoord(1, 0, 1).id.toString(), + new TileCoord(1, 1, 1).id.toString() ], [ - new TileCoord(1, 0, 0).id, - new TileCoord(1, 1, 0).id, - new TileCoord(1, 1, 1).id + new TileCoord(1, 0, 0).id.toString(), + new TileCoord(1, 1, 0).id.toString(), + new TileCoord(1, 1, 1).id.toString() ], - [new TileCoord(0, 0, 0).id], - [new TileCoord(0, 0, 0).id], - [new TileCoord(0, 0, 0).id], - [new TileCoord(0, 0, 0).id] + [new TileCoord(0, 0, 0).id.toString()], + [new TileCoord(0, 0, 0).id.toString()], + [new TileCoord(0, 0, 0).id.toString()], + [new TileCoord(0, 0, 0).id.toString()] ]); t.end(); }); @@ -106,23 +106,23 @@ test('computeTileMasks', (t) => { t.test('deep descendent masks', (t)=>{ const renderables = [ new Tile(0, 0, 0), new Tile(4, 4, 4)]; updateTileMasks(renderables); - t.deepEqual(renderables.map((r)=>{ return r.mask; }), [ + t.deepEqual(renderables.map((r)=>{ return Object.keys(r.mask); }), [ [ - new TileCoord(2, 0, 0).id, - new TileCoord(2, 1, 0).id, - new TileCoord(2, 0, 1).id, - new TileCoord(4, 5, 4).id, - new TileCoord(4, 4, 5).id, - new TileCoord(4, 5, 5).id, - new TileCoord(3, 3, 2).id, - new TileCoord(3, 2, 3).id, - new TileCoord(3, 3, 3).id, - new TileCoord(1, 1, 0).id, - new TileCoord(1, 0, 1).id, - new TileCoord(1, 1, 1).id + new TileCoord(2, 0, 0).id.toString(), + new TileCoord(1, 1, 0).id.toString(), + new TileCoord(2, 1, 0).id.toString(), + new TileCoord(1, 0, 1).id.toString(), + new TileCoord(1, 1, 1).id.toString(), + new TileCoord(2, 0, 1).id.toString(), + new TileCoord(3, 3, 2).id.toString(), + new TileCoord(3, 2, 3).id.toString(), + new TileCoord(3, 3, 3).id.toString(), + new TileCoord(4, 5, 4).id.toString(), + new TileCoord(4, 4, 5).id.toString(), + new TileCoord(4, 5, 5).id.toString(), ], [ - new TileCoord(0, 0, 0).id + new TileCoord(0, 0, 0).id.toString() ] ]); t.end(); @@ -131,19 +131,19 @@ test('computeTileMasks', (t) => { t.test('wrapped tile masks', (t) =>{ const renderables = [new Tile(0, 0, 0, 1), new Tile(1, 0, 0, 1), new Tile(2, 2, 2, 1), new Tile(3, 7, 7, 1), new Tile(3, 6, 6, 1)]; updateTileMasks(renderables); - t.deepEqual(renderables.map((r)=>{ return r.mask; }), [ + t.deepEqual(renderables.map((r)=>{ return Object.keys(r.mask); }), [ [ - new TileCoord(1, 1, 0).id, - new TileCoord(1, 0, 1).id, - new TileCoord(2, 3, 2).id, - new TileCoord(2, 2, 3).id, - new TileCoord(3, 7, 6).id, - new TileCoord(3, 6, 7).id + new TileCoord(1, 1, 0).id.toString(), + new TileCoord(1, 0, 1).id.toString(), + new TileCoord(2, 3, 2).id.toString(), + new TileCoord(2, 2, 3).id.toString(), + new TileCoord(3, 7, 6).id.toString(), + new TileCoord(3, 6, 7).id.toString() ], - [new TileCoord(0, 0, 0).id], - [new TileCoord(0, 0, 0).id], - [new TileCoord(0, 0, 0).id], - [new TileCoord(0, 0, 0).id] + [new TileCoord(0, 0, 0).id.toString()], + [new TileCoord(0, 0, 0).id.toString()], + [new TileCoord(0, 0, 0).id.toString()], + [new TileCoord(0, 0, 0).id.toString()] ]); t.end();