diff --git a/demos/vectorTile.html b/demos/vectorTile.html new file mode 100644 index 0000000000..40b4957717 --- /dev/null +++ b/demos/vectorTile.html @@ -0,0 +1,53 @@ + + + + + + + + + + + hexagon demo + + + + +
+ + + + + + + + diff --git a/package.json b/package.json index 43486efeb6..7721ec43f6 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@antv/l7", - "version": "1.1.10", + "version": "1.1.11", "description": "Large-scale WebGL-powered Geospatial Data Visualization", "main": "build/l7.js", "browser": "build/l7.js", diff --git a/src/core/engine/index.js b/src/core/engine/index.js index 9f04690f43..03ae64af2a 100644 --- a/src/core/engine/index.js +++ b/src/core/engine/index.js @@ -24,11 +24,14 @@ export default class Engine extends EventEmitter { }); } update() { + this._renderer.clear(); this._renderer.render(this._scene, this._camera); this._initPostProcessing(); } destroy() { - + } + renderScene(scene) { + this._renderer.render(scene, this._camera); } run() { this.update(); diff --git a/src/core/engine/renderer.js b/src/core/engine/renderer.js index fd4d64a6d5..4607a8fe3b 100644 --- a/src/core/engine/renderer.js +++ b/src/core/engine/renderer.js @@ -9,7 +9,8 @@ export default class Renderer { initRender() { this.renderer = new THREE.WebGLRenderer({ antialias: true, - alpha: true + alpha: true, + autoClear: false }); this.renderer.setClearColor(0xff0000, 0.0); this.pixelRatio = window.devicePixelRatio; diff --git a/src/core/layer.js b/src/core/layer.js index 9523aa21eb..0cac7b1228 100644 --- a/src/core/layer.js +++ b/src/core/layer.js @@ -309,7 +309,7 @@ export default class Layer extends Base { } createScale(field) { - const data = this.layerSource.data.dataArray; + const data = this.layerSource ? this.layerSource.data.dataArray : null; const scales = this.get('scales'); let scale = scales[field]; const scaleController = this.get('scaleController'); @@ -404,7 +404,7 @@ export default class Layer extends Base { const nextAttrs = this.get('attrOptions'); const preStyle = this.get('preStyleOption'); const nextStyle = this.get('styleOptions'); - if (preAttrs === undefined && preStyle === undefined) { + if (preAttrs === undefined && preStyle === undefined) { // 首次渲染 this._mapping(); this._setPreOption(); this._scaleByZoom(); @@ -490,12 +490,13 @@ export default class Layer extends Base { this.layerMesh.material.updateUninform(newOption); } - _mapping() { + _mapping(source) { const self = this; const attrs = self.get('attrs'); const mappedData = []; // const data = this.layerSource.propertiesData; - const data = this.layerSource.data.dataArray; + let data; + source ? data = source.data.dataArray : data = this.layerSource.data.dataArray; for (let i = 0; i < data.length; i++) { const record = data[i]; const newRecord = {}; @@ -528,14 +529,16 @@ export default class Layer extends Base { }); } this.layerData = mappedData; + return mappedData; } // 更新地图映射 - _updateMaping() { + _updateMaping(source, layer) { const self = this; const attrs = self.get('attrs'); - const data = this.layerSource.data.dataArray; + const data = source ? source.data.dataArray : this.layerSource.data.dataArray; + const layerData = layer || this.layerData; for (let i = 0; i < data.length; i++) { const record = data[i]; for (const attrName in attrs) { @@ -547,10 +550,10 @@ export default class Layer extends Base { for (let j = 0; j < values.length; j++) { const val = values[j]; const name = names[j]; - this.layerData[i][name] = (Util.isArray(val) && val.length === 1) ? val[0] : val; // 只有一个值时返回第一个属性值 + layerData[i][name] = (Util.isArray(val) && val.length === 1) ? val[0] : val; // 只有一个值时返回第一个属性值 } } else { - this.layerData[i][names[0]] = values.length === 1 ? values[0] : values; + layerData[i][names[0]] = values.length === 1 ? values[0] : values; } attr.neadUpdate = true; @@ -668,6 +671,7 @@ export default class Layer extends Base { pickAttr.needsUpdate = true; } _visibleWithZoom() { + if (this._object3D === null) return; const zoom = this.scene.getZoom(); const minZoom = this.get('minZoom'); const maxZoom = this.get('maxZoom'); @@ -751,7 +755,6 @@ export default class Layer extends Base { this.clearMapEvent(); if (this._object3D.type === 'composer') { this.remove(this._object3D); - return; } if (this._object3D && this._object3D.children) { @@ -778,8 +781,19 @@ export default class Layer extends Base { child = null; } } + this.layerMesh.geometry = null; + this.layerMesh.material.dispose(); + this.layerMesh.material = null; + if (this._pickingMesh) { + this._pickingMesh.children[0].geometry = null; + this._pickingMesh.children[0].material.dispose(); + this._pickingMesh.children[0].material = null; + } + this._buffer = null; this._object3D = null; this.scene._engine._scene.remove(this._object3D); + this.layerData.length = 0; + this.layerSource = null; this.scene._engine._picking.remove(this._pickingMesh); this.destroyed = true; } diff --git a/src/core/scene.js b/src/core/scene.js index 0789516806..b83e20fb99 100644 --- a/src/core/scene.js +++ b/src/core/scene.js @@ -25,7 +25,8 @@ export default class Scene extends Base { _initEngine(mapContainer) { this._engine = new Engine(mapContainer, this); - this.registerMapEvent(); + // this.registerMapEvent(); + this._engine.run(); // this.workerPool = new WorkerPool(); compileBuiltinModules(); } @@ -73,7 +74,6 @@ export default class Scene extends Base { } off(type, hander) { if (this.map) { this.map.off(type, hander); } - super.off(type, hander); } addImage() { diff --git a/src/geom/buffer/line.js b/src/geom/buffer/line.js index b86dac7895..ab6a47d22e 100644 --- a/src/geom/buffer/line.js +++ b/src/geom/buffer/line.js @@ -87,6 +87,7 @@ export default class LineBuffer extends BufferBase { layerData.forEach(item => { const props = item; const positionCount = positions.length / 3; + // TODO 处理多个线段的情况 const attr = lineShape.Line(item.coordinates, props, positionCount, (lineType !== 'soild')); positions.push(...attr.positions); normal.push(...attr.normal); diff --git a/src/geom/material/heatmapMateial.js b/src/geom/material/heatmapMaterial.js similarity index 100% rename from src/geom/material/heatmapMateial.js rename to src/geom/material/heatmapMaterial.js diff --git a/src/geom/material/tile/maskMaterial.js b/src/geom/material/tile/maskMaterial.js new file mode 100644 index 0000000000..36ddd9e098 --- /dev/null +++ b/src/geom/material/tile/maskMaterial.js @@ -0,0 +1,24 @@ +import Material from './../material'; +import { getModule } from '../../../util/shaderModule'; +export default class MaskMaterial extends Material { + getDefaultParameters() { + return { + uniforms: { + }, + defines: { + + } + }; + } + constructor(_uniforms, _defines, parameters) { + super(parameters); + const { uniforms, defines } = this.getDefaultParameters(); + const { vs, fs } = getModule('mask_quard'); + this.uniforms = Object.assign(uniforms, this.setUniform(_uniforms)); + this.type = 'MaskMaterial'; + this.defines = Object.assign(defines, _defines); + this.vertexShader = vs; + this.fragmentShader = fs; + this.transparent = true; + } +} diff --git a/src/geom/shader/index.js b/src/geom/shader/index.js index 0962214754..e67e880d91 100644 --- a/src/geom/shader/index.js +++ b/src/geom/shader/index.js @@ -45,6 +45,11 @@ import raster_frag from '../shader/raster_frag.glsl'; import tile_polygon_vert from '../shader/tile/polygon_vert.glsl'; import tile_polygon_frag from '../shader/tile/polygon_frag.glsl'; +// mask +import mask_quard_vert from '../shader/tile/mask_quard_vert.glsl'; +import mask_quard_frag from '../shader/tile/mask_quard_frag.glsl'; + + import common from './common.glsl'; import { registerModule } from '../../util/shaderModule'; import pick_color from './shaderChunks/pick_color.glsl'; @@ -65,5 +70,6 @@ export function compileBuiltinModules() { registerModule('image', { vs: image_vert, fs: image_frag }); registerModule('raster', { vs: raster_vert, fs: raster_frag }); registerModule('tilepolygon', { vs: tile_polygon_vert, fs: tile_polygon_frag }); + registerModule('mask_quard', { vs: mask_quard_vert, fs: mask_quard_frag }); } diff --git a/src/geom/shader/tile/mask_quard_frag.glsl b/src/geom/shader/tile/mask_quard_frag.glsl new file mode 100644 index 0000000000..6b4ceede8f --- /dev/null +++ b/src/geom/shader/tile/mask_quard_frag.glsl @@ -0,0 +1,4 @@ + precision highp float; + void main() { + gl_FragColor = vec4(1.0); +} \ No newline at end of file diff --git a/src/geom/shader/tile/mask_quard_vert.glsl b/src/geom/shader/tile/mask_quard_vert.glsl new file mode 100644 index 0000000000..b8988414c9 --- /dev/null +++ b/src/geom/shader/tile/mask_quard_vert.glsl @@ -0,0 +1,6 @@ +precision highp float; +void main(){ + mat4 matModelViewProjection=projectionMatrix*modelViewMatrix; + gl_Position = matModelViewProjection * vec4(position, 1.0); + +} \ No newline at end of file diff --git a/src/geom/shape/line.js b/src/geom/shape/line.js index f171c1f86c..ab266ba861 100644 --- a/src/geom/shape/line.js +++ b/src/geom/shape/line.js @@ -65,7 +65,10 @@ export function defaultLine(geo, index) { } // mesh line export function Line(path, props, positionsIndex) { - if (path.length === 1) path = path[0];// 面坐标转线坐标 + // 区分path是面还是线 + if (Array.isArray(path[0][0])) { + path = path[0]; // 面坐标转线坐标 + } const positions = []; const pickingIds = []; const normal = []; @@ -77,7 +80,8 @@ export function Line(path, props, positionsIndex) { const sizes = []; let c = 0; let index = positionsIndex; - const { size, color, id } = props; + let { size, color, id } = props; + !Array.isArray(size) && (size = [ size ]); path.forEach((point, pointIndex, list) => { const i = index; colors.push(...color); diff --git a/src/global.js b/src/global.js index f33666f102..b6f5e5341e 100644 --- a/src/global.js +++ b/src/global.js @@ -5,7 +5,7 @@ // const Global = {}; const FONT_FAMILY = '"-apple-system", BlinkMacSystemFont, "Segoe UI", Roboto,"Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",SimSun, "sans-serif"'; const Global = { - version: '1.0.0', + version: '1.11.1', scene: { mapType: 'AMAP', zoom: 5, diff --git a/src/layer/index.js b/src/layer/index.js index 8b33d8534e..04c572c984 100644 --- a/src/layer/index.js +++ b/src/layer/index.js @@ -7,6 +7,7 @@ import RasterLayer from './rasterLayer'; import HeatmapLayer from './heatmapLayer'; import TileLayer from './tile/tileLayer'; import ImageTileLayer from './tile/imageTileLayer'; +import VectorTileLayer from './tile/VectorTileLayer'; registerLayer('PolygonLayer', PolygonLayer); registerLayer('PointLayer', PointLayer); @@ -16,7 +17,8 @@ registerLayer('RasterLayer', RasterLayer); registerLayer('HeatmapLayer', HeatmapLayer); registerLayer('TileLayer', TileLayer); registerLayer('ImageTileLayer', ImageTileLayer); +registerLayer('VectorTileLayer', VectorTileLayer); -export { LAYER_MAP } from './factory'; +export { LAYER_MAP, getLayer } from './factory'; export { registerLayer }; diff --git a/src/layer/lineLayer.js b/src/layer/lineLayer.js index 4a2046686e..be0bef02c8 100644 --- a/src/layer/lineLayer.js +++ b/src/layer/lineLayer.js @@ -39,7 +39,7 @@ export default class LineLayer extends Layer { if (this.shapeType === 'arc') { DrawArc(attributes, layerCfg, this); } else { - DrawLine(attributes, layerCfg, this); + this.add(DrawLine(attributes, layerCfg, this)); } } } diff --git a/src/layer/render/heatmap/heatmap.js b/src/layer/render/heatmap/heatmap.js index c03d7f9b46..2a5bf555d5 100644 --- a/src/layer/render/heatmap/heatmap.js +++ b/src/layer/render/heatmap/heatmap.js @@ -1,6 +1,6 @@ import HeatmapBuffer from '../../../geom/buffer/heatmap/heatmap'; import { createColorRamp } from '../../../geom/buffer/heatmap/heatmap'; -import { HeatmapIntensityMaterial, HeatmapColorizeMaterial } from '../../../geom/material/heatmapMateial'; +import { HeatmapIntensityMaterial, HeatmapColorizeMaterial } from '../../../geom/material/heatmapMaterial'; // import Renderpass from '../../../core/engine/renderpass.bak'; import RenderPass from '../../../core/engine/render-pass'; import ShaderPass from '../../../core/engine/shader-pass'; diff --git a/src/layer/render/line/drawMeshLine.js b/src/layer/render/line/drawMeshLine.js index 37eaf2ad25..85da3b91b6 100644 --- a/src/layer/render/line/drawMeshLine.js +++ b/src/layer/render/line/drawMeshLine.js @@ -40,5 +40,5 @@ export default function DrawLine(attributes, cfg, layer) { }); lineMaterial.setDefinesvalue('ANIMATE', true); } - layer.add(lineMesh); + return lineMesh; } diff --git a/src/layer/tile/VectorTileLayer.js b/src/layer/tile/VectorTileLayer.js new file mode 100644 index 0000000000..73258a6e40 --- /dev/null +++ b/src/layer/tile/VectorTileLayer.js @@ -0,0 +1,7 @@ +import TileLayer from './tileLayer'; +import VectorTile from './vectorTile'; +export default class VectorTileLayer extends TileLayer { + _createTile(key, layer) { + return new VectorTile(key, this.url, layer); + } +} diff --git a/src/layer/tile/imageTile.js b/src/layer/tile/imageTile.js index d30e336385..563c65c933 100644 --- a/src/layer/tile/imageTile.js +++ b/src/layer/tile/imageTile.js @@ -23,7 +23,7 @@ export default class ImageTile extends Tile { const image = document.createElement('img'); image.addEventListener('load', () => { - + this._isLoaded = true; this._createMesh(image); this._ready = true; }, false); @@ -58,8 +58,8 @@ export default class ImageTile extends Tile { buffer.attributes.texture = buffer.texture; const style = this.layer.get('styleOptions'); const mesh = DrawImage(buffer.attributes, style); - this.Object3D.add(mesh); - return this.Object3D; + this._object3D.add(mesh); + return this._object3D; } _abortRequest() { if (!this._image) { diff --git a/src/layer/tile/tile.js b/src/layer/tile/tile.js index 261800150c..87770386f5 100644 --- a/src/layer/tile/tile.js +++ b/src/layer/tile/tile.js @@ -1,10 +1,12 @@ import * as THREE from '../../core/three'; +import EventEmitter from 'wolfy87-eventemitter'; import { toLngLatBounds, toBounds } from '@antv/geo-coord'; const r2d = 180 / Math.PI; const tileURLRegex = /\{([zxy])\}/g; -export default class Tile { +export default class Tile extends EventEmitter { constructor(key, url, layer) { + super(); this.layer = layer; this._tile = key.split('_').map(v => v * 1); this._path = url; @@ -15,7 +17,10 @@ export default class Tile { this._center = this._tileBounds.getCenter(); this._centerLnglat = this._tileLnglatBounds.getCenter(); - this.Object3D = new THREE.Object3D(); + this._object3D = new THREE.Object3D(); + this._object3D.onBeforeRender = () => { + }; + this._isLoaded = false; this.requestTileAsync(); @@ -34,12 +39,12 @@ export default class Tile { } // 经纬度范围转瓦片范围 _tileBounds(lnglatBound) { - const ne = this.layer.scene.project([ lnglatBound.getNorthWest().lng, lnglatBound.getNorthEast().lat ]); - const sw = this.layer.scene.project([ lnglatBound.getSouthEast().lng, lnglatBound.getSouthWest().lat ]); + const ne = this.layer.scene.project([ lnglatBound.getNorthEast().lng, lnglatBound.getNorthEast().lat ]); + const sw = this.layer.scene.project([ lnglatBound.getSouthWest().lng, lnglatBound.getSouthWest().lat ]); return toBounds(sw, ne); } getMesh() { - return this.Object3D; + return this._object3D; } @@ -60,6 +65,8 @@ export default class Tile { const n = Math.PI - 2 * Math.PI * y / Math.pow(2, z); return r2d * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))); } + _preRender() { + } destroy() { if (this._object3D && this._object3D.children) { let child; diff --git a/src/layer/tile/tileLayer.js b/src/layer/tile/tileLayer.js index a3bc44afc9..2182e95ed6 100644 --- a/src/layer/tile/tileLayer.js +++ b/src/layer/tile/tileLayer.js @@ -1,5 +1,7 @@ import Layer from '../../core/layer'; +import source from '../../core/source'; import * as THREE from '../../core/three'; +import Util from '../../util'; import TileCache from './tileCache'; import { throttle } from '@antv/util'; import { toLngLat } from '@antv/geo-coord'; @@ -12,16 +14,28 @@ export default class TileLayer extends Layer { this._tiles = new THREE.Object3D(); this._tileKeys = []; this.tileList = []; - - } - source(url) { + source(url, cfg = {}) { this.url = url; + this.sourceCfg = cfg; return this; } + tileSource(data) { + super.source(data, this.sourceCfg); + if (data instanceof source) { + return data; + } + this.sourceCfg.data = data; + this.sourceCfg.mapType = this.scene.mapType; + this.sourceCfg.zoom = this.scene.getZoom(); + return new source(this.sourceCfg); + } render() { + this._initControllers(); this._initMapEvent(); + this._initAttrs(); this.draw(); + return this; } draw() { this._object3D.add(this._tiles); @@ -29,6 +43,44 @@ export default class TileLayer extends Layer { } drawTile() { + } + _mapping(source) { + + const attrs = this.get('attrs'); + const mappedData = []; + // const data = this.layerSource.propertiesData; + const data = source.data.dataArray; + for (let i = 0; i < data.length; i++) { + const record = data[i]; + const newRecord = {}; + newRecord.id = data[i]._id; + for (const k in attrs) { + if (attrs.hasOwnProperty(k)) { + const attr = attrs[k]; + const names = attr.names; + const values = this._getAttrValues(attr, record); + if (names.length > 1) { // position 之类的生成多个字段的属性 + for (let j = 0; j < values.length; j++) { + const val = values[j]; + const name = names[j]; + newRecord[name] = (Util.isArray(val) && val.length === 1) ? val[0] : val; // 只有一个值时返回第一个属性值 + } + } else { + newRecord[names[0]] = values.length === 1 ? values[0] : values; + + } + } + } + newRecord.coordinates = record.coordinates; + mappedData.push(newRecord); + } + // 通过透明度过滤数据 + if (attrs.hasOwnProperty('filter')) { + mappedData.forEach(item => { + item.filter === false && (item.color[3] = 0); + }); + } + return mappedData; } zoomchange(ev) { super.zoomchange(ev); @@ -56,8 +108,9 @@ export default class TileLayer extends Layer { // console.log(NW.lng, NW.lat, SE.lng, SE.lat, NWPonint, SEPonint); let updateTileList = []; this.tileList = []; - const halfx = Math.floor((maxXY.x - minXY.x) / 2) + 1; - const halfy = Math.floor((maxXY.y - minXY.y) / 2) + 1; + const halfx = 1; + const halfy = 1; + if (!(centerPoint.x > NWPoint.x && centerPoint.x < SEPoint.x)) { // 地图循环的问题 for (let i = 0; i < minXY.x; i++) { for (let j = Math.min(0, minXY.y - halfy); j < Math.max(maxXY.y + halfy, tileCount); j++) { @@ -90,10 +143,11 @@ export default class TileLayer extends Layer { }); this._removeOutTiles(); } + _updateTileList(updateTileList, x, y, z) { const key = [ x, y, z ].join('_'); this.tileList.push(key); - if (this._tileKeys.indexOf(key) === -1) { + if (this._tileKeys.indexOf(key) === -1 && updateTileList.indexOf(key) === -1) { updateTileList.push(key); } } @@ -101,14 +155,21 @@ export default class TileLayer extends Layer { let tile = this._tileCache.getTile(key); if (!tile) { tile = this._createTile(key, layer); - const mesh = tile.getMesh(); - mesh.name = key; - this._tileCache.setTile(tile, key); + tile.on('tileLoaded', () => { + if (this.tileList.indexOf(key) === -1) { + return; + } + const mesh = tile.getMesh(); + mesh.name = key; + this._tileCache.setTile(tile, key); + this._tileKeys.push(key); + mesh.children.length !== 0 && this._tiles.add(tile.getMesh()); + this.scene._engine.update(); + }); + } else { + this._tiles.add(tile.getMesh()); this._tileKeys.push(key); - // this.scene._engine.update(); } - this._tiles.add(tile.getMesh()); - this._tileKeys.push(key); } // 移除视野外的tile _removeOutTiles() { @@ -116,6 +177,8 @@ export default class TileLayer extends Layer { const tile = this._tiles.children[i]; const key = tile.name; if (this.tileList.indexOf(key) === -1) { + const tileObj = this._tileCache.getTile(key); + tileObj && tileObj._abortRequest(); this._tiles.remove(tile); } this._tileKeys = [].concat(this.tileList); diff --git a/src/layer/tile/vectorTile.js b/src/layer/tile/vectorTile.js new file mode 100644 index 0000000000..30ded2ab04 --- /dev/null +++ b/src/layer/tile/vectorTile.js @@ -0,0 +1,141 @@ +import Tile from './tile'; +import { getArrayBuffer } from '../../util/ajax'; +import PBF from 'pbf'; +import * as VectorParser from '@mapbox/vector-tile'; +import * as THREE from '../../core/three'; +import MaskMaterial from '../../geom/material/tile/maskMaterial'; +import { LineBuffer } from '../../geom/buffer/index'; +import DrawLine from '../../layer/render/line/drawMeshLine'; + +export default class VectorTile extends Tile { + requestTileAsync() { + // Making this asynchronous really speeds up the LOD framerate + setTimeout(() => { + if (!this._mesh) { + // this._mesh = this._createMesh(); + this._requestTile(); + } + }, 0); + } + _requestTile() { + const urlParams = { + x: this._tile[0], + y: this._tile[1], + z: this._tile[2] + }; + + const url = this._getTileURL(urlParams); + this.xhrRequest = getArrayBuffer({ url }, (err, data) => { + if (err) { + this._noData = true; + return; + } + this._isLoaded = true; + this._parserData(data.data); + }); + } + _creatSource(data) { + this.source = this.layer.tileSource(data); + } + _parserData(data) { + const tile = new VectorParser.VectorTile(new PBF(data)); + // CHN_Cities_L CHN_Cities CHN_L + const layerName = 'county4326'; + const features = []; + const vectorLayer = tile.layers[layerName]; + for (let i = 0; i < vectorLayer.length; i++) { + const feature = vectorLayer.feature(i); + features.push(feature.toGeoJSON(this._tile[0], this._tile[1], this._tile[2])); + } + const geodata = { + type: 'FeatureCollection', + features + }; + this._creatSource(geodata); + this._createMesh(); + } + _createMesh() { + this.layerData = this.layer._mapping(this.source); + const style = this.layer.get('styleOptions'); + const buffer = new LineBuffer({ + layerData: this.layerData, + style, + shapeType: 'line' + + }); + const animateOptions = this.layer.get('animateOptions'); + const activeOption = this.layer.get('activedOptions'); + const layerCfg = { + zoom: this.layer.scene.getZoom(), + style, + animateOptions, + activeOption + }; + this.mesh = new DrawLine(buffer.attributes, layerCfg, this.layer); + this.mesh.onBeforeRender = renderer => { + this._renderMask(renderer); + }; + this.mesh.onAfterRender = renderer => { + const context = renderer.context; + context.disable(context.STENCIL_TEST); + }; + this._object3D.add(this.mesh); + this.emit('tileLoaded'); + return this._object3D; + } + _renderMask(renderer) { + const maskScene = new THREE.Scene(); + this.maskScene = maskScene; + const tileMesh = this._tileMaskMesh(); + maskScene.add(tileMesh); + const context = renderer.context; + renderer.autoClear = false; + renderer.clearDepth(); + context.enable(context.STENCIL_TEST); + context.stencilOp(context.REPLACE, context.REPLACE, context.REPLACE); + context.stencilFunc(context.ALWAYS, 1, 0xffffffff); + context.clearStencil(0); + context.clear(context.STENCIL_BUFFER_BIT); + context.colorMask(false, false, false, false); + + // config the stencil buffer to collect data for testing + this.layer.scene._engine.renderScene(maskScene); + context.colorMask(true, true, true, true); + context.depthMask(true); + renderer.clearDepth(); + + // only render where stencil is set to 1 + + context.stencilFunc(context.EQUAL, 1, 0xffffffff); // draw if == 1 + context.stencilOp(context.KEEP, context.KEEP, context.KEEP); + } + _tileMaskMesh() { + const tilebound = this._tileBounds; + const bl = [ tilebound.getBottomLeft().x, tilebound.getBottomLeft().y, 0 ]; + const br = [ tilebound.getBottomRight().x, tilebound.getBottomRight().y, 0 ]; + const tl = [ tilebound.getTopLeft().x, tilebound.getTopLeft().y, 0 ]; + const tr = [ tilebound.getTopRight().x, tilebound.getTopRight().y, 0 ]; + const positions = [ ...bl, ...tr, ...br, ...bl, ...tl, ...tr ]; + const geometry = new THREE.BufferGeometry(); + geometry.addAttribute('position', new THREE.Float32BufferAttribute(positions, 3)); + const maskMaterial = new MaskMaterial(); + const maskMesh = new THREE.Mesh(geometry, maskMaterial); + return maskMesh; + } + _abortRequest() { + if (!this.xhrRequest) { + return; + } + + this.xhrRequest.abort(); + } + destroy() { + + this.mesh.destroy(); + // if (this.maskScene) { + // this.maskScene.children[0].geometry = null; + // this.maskScene.children[0].material.dispose(); + // this.maskScene.children[0].material = null; + // } + } +} diff --git a/src/util/lru-cache.js b/src/util/lru-cache.js index ab7a78339b..d44c2626dc 100644 --- a/src/util/lru-cache.js +++ b/src/util/lru-cache.js @@ -48,10 +48,10 @@ export default class LRUCache { delete(key) { const value = this._cache[key]; - this.destroy(value); if (value) { this._deleteCache(key); this._deleteOrder(key); + this.destroy(value); } }