mirror of
https://github.com/tengge1/ShadowEditor.git
synced 2026-01-25 15:08:11 +00:00
重新架构,限制最大下载数,避免卡顿。
This commit is contained in:
parent
873e455607
commit
0612596fed
@ -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);
|
||||
|
||||
@ -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) {
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -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;
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user