重新架构,限制最大下载数,避免卡顿。

This commit is contained in:
tengge1 2019-04-13 14:42:26 +08:00
parent 873e455607
commit 0612596fed
6 changed files with 123 additions and 80 deletions

View File

@ -33,11 +33,12 @@ function Globe(camera, renderer, options = {}) {
this.lat = 0;
this.alt = GeoUtils.zoomToAlt(0);
this.thread = 0;
this.matrixAutoUpdate = false;
// 不能命名为layers否则跟three.js的layers冲突
this.layerList = [
new GoogleTiledLayer(),
new GoogleTiledLayer(this),
];
this.renderers = new Renderers(this);

View File

@ -1,4 +1,5 @@
import ImageLayer from '../ImageLayer';
import TileCache from '../../utils/TileCache';
/**
* 图片瓦片图层
@ -8,13 +9,19 @@ import ImageLayer from '../ImageLayer';
function TiledImageLayer(globe) {
ImageLayer.call(this, globe);
this.tree = rbush();
this.cache = new TileCache();
}
TiledImageLayer.prototype = Object.create(ImageLayer.prototype);
TiledImageLayer.prototype.constructor = TiledImageLayer;
TiledImageLayer.prototype.get = function (aabb) {
/**
* 获取图片数据
* @param {*} x
* @param {*} y
* @param {*} z
*/
TiledImageLayer.prototype.get = function (x, y, z) {
};

View File

@ -14,21 +14,63 @@ GoogleTiledLayer.prototype = Object.create(TiledImageLayer.prototype);
GoogleTiledLayer.prototype.constructor = GoogleTiledLayer;
/**
* 获取某个经纬度范围内的资源
* @param {THREE.Box2} aabb
* @param {Number} z 层级
* 获取图片数据
* @param {*} x
* @param {*} y
* @param {*} z
*/
GoogleTiledLayer.prototype.get = function (aabb, z) {
var minLon = aabb.min.x,
minLat = GeoUtils._mercatorLat(aabb.min.y),
maxLon = aabb.max.x,
maxLat = GeoUtils._mercatorLat(aabb.max.y);
GoogleTiledLayer.prototype.get = function (x, y, z) {
var img = this.cache.get(x, y, z);
var size = Math.PI * 2 / 2 ** z,
minX = Math.floor(minLon / size),
minY = Math.floor(minLat / size),
maxX = Math.ceil(maxLon / size),
maxY = Math.ceil(maxLat / size);
if (img && img.loaded) {
return img;
}
if (img && (img.loading || img.error)) {
return null;
}
if (this.globe.thread < this.globe.options.maxThread) {
this._create(x, y, z);
}
return null;
};
GoogleTiledLayer.prototype._create = function (x, y, z) {
var img = document.createElement('img');
img._x = x;
img._y = y;
img._z = z;
img.crossOrigin = 'anonymous';
img.loading = true;
this.cache.set(x, y, z, img);
img.onload = () => {
img.onload = null;
img.onerror = null;
img.loaded = true;
delete img.loading;
this.globe.thread--;
};
img.onerror = () => {
img.onload = null;
img.onerror = null;
img.error = true;
delete img.loading;
this.globe.thread--;
};
img.src = `http://www.google.cn/maps/vt?lyrs=s@821&gl=cn&x=${x}&y=${y}&z=${z}`;
this.globe.thread++;
};
export default GoogleTiledLayer;

View File

@ -14,17 +14,16 @@ function TiledLayerRenderer(globe) {
this.creator = new SphereTileCreator(this.globe);
var geometry = new THREE.PlaneBufferGeometry(1, 1, 16, 16);
this.mesh = new THREE.Mesh(geometry, []);
this.mesh.matrix.copy(this.globe.matrix);
this.mesh.matrixAutoUpdate = false;
this.geometry = new THREE.PlaneBufferGeometry(1, 1, 16, 16);
this.modelMatrix = new THREE.Matrix4();
this.program = null;
this.attributes = {};
this.uniforms = {};
this.buffers = {};
this.tiles = [];
this.initProgram();
this.initBuffers();
}
@ -93,7 +92,7 @@ TiledLayerRenderer.prototype.initProgram = function () {
TiledLayerRenderer.prototype.initBuffers = function () {
var gl = this.gl;
var geometry = this.mesh.geometry;
var geometry = this.geometry;
var attributes = geometry.attributes;
var positionBuffer = gl.createBuffer();
@ -121,14 +120,7 @@ TiledLayerRenderer.prototype.initBuffers = function () {
};
TiledLayerRenderer.prototype.render = function () {
this.mesh.material.length = 0;
this.creator.get().forEach((n, i) => {
if (n.material) {
this.mesh.material.push(n.material);
}
});
this.creator.get(this.tiles);
this.renderMesh();
this.renderer.state.reset();
};
@ -136,8 +128,6 @@ TiledLayerRenderer.prototype.render = function () {
TiledLayerRenderer.prototype.renderMesh = function () {
var gl = this.gl;
var camera = this.camera;
var geometry = this.mesh.geometry;
var materials = this.mesh.material;
gl.useProgram(this.program);
@ -149,7 +139,7 @@ TiledLayerRenderer.prototype.renderMesh = function () {
// gl.depthFunc(gl.LEQUAL);
gl.depthMask(true);
gl.uniformMatrix4fv(this.uniforms.modelMatrix, false, this.mesh.matrix.elements);
gl.uniformMatrix4fv(this.uniforms.modelMatrix, false, this.modelMatrix.elements);
gl.uniformMatrix4fv(this.uniforms.viewMatrix, false, camera.matrixWorldInverse.elements);
gl.uniformMatrix4fv(this.uniforms.projectionMatrix, false, camera.projectionMatrix.elements);
@ -168,32 +158,32 @@ TiledLayerRenderer.prototype.renderMesh = function () {
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.buffers.index);
// x, y, z
materials.forEach(n => {
gl.uniform1i(this.uniforms.x, n.x);
gl.uniform1i(this.uniforms.y, n.y);
gl.uniform1i(this.uniforms.z, n.z);
this.tiles.forEach(tile => {
tile.images.forEach(n => {
gl.uniform1i(this.uniforms.x, n._x);
gl.uniform1i(this.uniforms.y, n._y);
gl.uniform1i(this.uniforms.z, n._z);
if (!n.texture && n.loaded) {
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, n.image);
if (!n.texture) {
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, n);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.bindTexture(gl.TEXTURE_2D, null);
gl.bindTexture(gl.TEXTURE_2D, null);
n.texture = texture;
}
n.texture = texture;
} else {
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, n.texture);
gl.uniform1i(this.uniforms.map, 0);
}
if (n.texture) {
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, n.texture);
gl.uniform1i(this.uniforms.map, 0);
}
gl.drawElements(gl.TRIANGLES, geometry.index.count, gl.UNSIGNED_SHORT, 0);
gl.drawElements(gl.TRIANGLES, this.geometry.index.count, gl.UNSIGNED_SHORT, 0);
});
});
gl.bindBuffer(gl.ARRAY_BUFFER, null);
@ -213,8 +203,6 @@ TiledLayerRenderer.prototype.dispose = function () {
this.buffers = {};
delete this.mesh;
this.creator.dispose();
Renderer.prototype.dispose.call(this);

View File

@ -1,7 +1,6 @@
import WGS84 from '../core/WGS84';
import TileCreator from './TileCreator';
import Tile from './Tile';
import TiledMaterial from '../render/tiled/TiledMaterial';
import GeoUtils from '../utils/GeoUtils';
/**
@ -15,24 +14,23 @@ function SphereTileCreator(globe) {
this.cache = new Map();
this._centerZoom = 0;
this.tiles = [];
}
SphereTileCreator.prototype = Object.create(TileCreator.prototype);
SphereTileCreator.prototype.constructor = SphereTileCreator;
SphereTileCreator.prototype.get = function () {
this.tiles.length = 0;
SphereTileCreator.prototype.get = function (tiles) {
tiles.length = 0;
this._centerZoom = ~~GeoUtils.altToZoom(this.camera.position.length() - WGS84.a) + 3;
this.fork(0, 0, 1);
this.fork(1, 0, 1);
this.fork(0, 1, 1);
this.fork(1, 1, 1);
this.fork(0, 0, 1, tiles);
this.fork(1, 0, 1, tiles);
this.fork(0, 1, 1, tiles);
this.fork(1, 1, 1, tiles);
this.tiles = this.tiles.sort((a, b) => {
// 排序
tiles = tiles.sort((a, b) => {
if (a.z > b.z) {
return 1;
} else if (a.z < b.z) {
@ -42,7 +40,18 @@ SphereTileCreator.prototype.get = function () {
}
});
return this.tiles;
// 获取图层数据
tiles.forEach(tile => {
tile.images.length = 0;
this.globe.layerList.forEach(n => {
var image = n.get(tile.x, tile.y, tile.z);
if (image) {
tile.images.push(image);
}
});
});
return tiles;
};
/**
@ -50,24 +59,25 @@ SphereTileCreator.prototype.get = function () {
* @param {*} x
* @param {*} y
* @param {*} z
* @param {*} tiles
*/
SphereTileCreator.prototype.fork = function (x, y, z) {
SphereTileCreator.prototype.fork = function (x, y, z, tiles) {
var tile = this.getTile(x, y, z);
if (!this.isVisible(tile)) {
return;
}
this.tiles.push(tile);
tiles.push(tile);
if (tile.z > this._centerZoom) {
return;
}
this.fork(x * 2, y * 2, z + 1);
this.fork(x * 2 + 1, y * 2, z + 1);
this.fork(x * 2, y * 2 + 1, z + 1);
this.fork(x * 2 + 1, y * 2 + 1, z + 1);
this.fork(x * 2, y * 2, z + 1, tiles);
this.fork(x * 2 + 1, y * 2, z + 1, tiles);
this.fork(x * 2, y * 2 + 1, z + 1, tiles);
this.fork(x * 2 + 1, y * 2 + 1, z + 1, tiles);
};
/**
@ -83,8 +93,6 @@ SphereTileCreator.prototype.getTile = function (x, y, z) {
if (!tile) {
tile = new Tile(x, y, z);
tile.material = new TiledMaterial(x, y, z, this.options);
tile.material.load();
this.cache.set(id, tile);
}
@ -98,15 +106,10 @@ SphereTileCreator.prototype.getTile = function (x, y, z) {
* @param {*} tile
*/
SphereTileCreator.prototype.isVisible = function (tile) {
if (!tile.material.loaded) {
return false;
}
return this.globe.viewer.aabb.intersectsBox(tile._aabb);
};
SphereTileCreator.prototype.dispose = function () {
this.tiles.length = 0;
this.cache.clear();
TileCreator.prototype.dispose.call(this);
};

View File

@ -13,6 +13,8 @@ function Tile(x = 0, y = 0, z = 0) {
this.y = y;
this.z = z;
this.images = [];
this._aabb = this._getBox(x, y, z);
this._center = this._getCenter(this._aabb);
this._vertices = this._getVertices(this._aabb, this._center);