2016-02-14 19:10:28 +00:00
|
|
|
|
import Layer from '../Layer';
|
2016-02-19 21:25:16 +00:00
|
|
|
|
import extend from 'lodash.assign';
|
2016-02-15 22:55:25 +00:00
|
|
|
|
import TileCache from './TileCache';
|
2019-02-16 14:49:50 +00:00
|
|
|
|
import * as THREE from 'three';
|
2016-02-14 19:10:28 +00:00
|
|
|
|
|
2016-02-29 20:45:10 +00:00
|
|
|
|
// TODO: Consider removing picking from TileLayer instances as there aren't
|
|
|
|
|
// (m)any situations where it would be practical
|
|
|
|
|
//
|
|
|
|
|
// For example, how would you even know what picking IDs to listen to and what
|
|
|
|
|
// to do with them?
|
|
|
|
|
|
2016-02-28 18:40:51 +00:00
|
|
|
|
// TODO: Make sure nothing is left behind in the heap after calling destroy()
|
|
|
|
|
|
2016-02-19 13:55:35 +00:00
|
|
|
|
// TODO: Consider keeping a single TileLayer / LOD instance running by default
|
|
|
|
|
// that keeps a standard LOD grid for other layers to utilise, rather than
|
|
|
|
|
// having to create their own, unique LOD grid and duplicate calculations when
|
|
|
|
|
// they're going to use the same grid setup anyway
|
|
|
|
|
//
|
|
|
|
|
// It still makes sense to be able to have a custom LOD grid for some layers as
|
|
|
|
|
// they may want to customise things, maybe not even using a quadtree at all!
|
|
|
|
|
//
|
|
|
|
|
// Perhaps it makes sense to split out the quadtree stuff into a singleton and
|
|
|
|
|
// pass in the necessary parameters each time for the calculation step.
|
|
|
|
|
//
|
|
|
|
|
// Either way, it seems silly to force layers to have to create a new LOD grid
|
|
|
|
|
// each time and create extra, duplicated processing every frame.
|
|
|
|
|
|
|
|
|
|
// TODO: Allow passing in of options to define min/max LOD and a distance to use
|
|
|
|
|
// for culling tiles beyond that distance.
|
|
|
|
|
|
2016-02-17 22:45:25 +00:00
|
|
|
|
// DONE: Prevent tiles from being loaded if they are further than a certain
|
2016-02-15 13:21:48 +00:00
|
|
|
|
// distance from the camera and are unlikely to be seen anyway
|
|
|
|
|
|
2016-02-16 13:32:31 +00:00
|
|
|
|
// TODO: Avoid performing LOD calculation when it isn't required. For example,
|
|
|
|
|
// when nothing has changed since the last frame and there are no tiles to be
|
|
|
|
|
// loaded or in need of rendering
|
|
|
|
|
|
|
|
|
|
// TODO: Only remove tiles from the layer that aren't to be rendered in the
|
|
|
|
|
// current frame – it seems excessive to remove all tiles and re-add them on
|
|
|
|
|
// every single frame, even if it's just array manipulation
|
|
|
|
|
|
|
|
|
|
// TODO: Fix LOD calculation so min and max LOD can be changed without causing
|
|
|
|
|
// problems (eg. making min above 5 causes all sorts of issues)
|
|
|
|
|
|
|
|
|
|
// TODO: Reuse THREE objects where possible instead of creating new instances
|
|
|
|
|
// on every LOD calculation
|
|
|
|
|
|
|
|
|
|
// TODO: Consider not using THREE or LatLon / Point objects in LOD calculations
|
|
|
|
|
// to avoid creating unnecessary memory for garbage collection
|
|
|
|
|
|
2016-02-17 22:45:25 +00:00
|
|
|
|
// TODO: Prioritise loading of tiles at highest level in the quadtree (those
|
|
|
|
|
// closest to the camera) so visual inconsistancies during loading are minimised
|
|
|
|
|
|
2016-02-18 22:03:56 +00:00
|
|
|
|
class TileLayer extends Layer {
|
2016-02-19 21:25:16 +00:00
|
|
|
|
constructor(options) {
|
|
|
|
|
var defaults = {
|
2016-02-29 20:45:10 +00:00
|
|
|
|
picking: false,
|
2016-02-19 21:25:16 +00:00
|
|
|
|
maxCache: 1000,
|
|
|
|
|
maxLOD: 18
|
|
|
|
|
};
|
|
|
|
|
|
2016-03-07 19:25:11 +00:00
|
|
|
|
var _options = extend({}, defaults, options);
|
|
|
|
|
|
|
|
|
|
super(_options);
|
2016-02-19 21:25:16 +00:00
|
|
|
|
|
2016-10-26 11:41:24 +00:00
|
|
|
|
this._destroy = false;
|
|
|
|
|
|
2016-03-01 20:51:38 +00:00
|
|
|
|
this._tileCache = new TileCache(this._options.maxCache, tile => {
|
2016-02-18 18:42:19 +00:00
|
|
|
|
this._destroyTile(tile);
|
|
|
|
|
});
|
2016-02-15 22:55:25 +00:00
|
|
|
|
|
2016-02-27 11:04:40 +00:00
|
|
|
|
// List of tiles from the previous LOD calculation
|
|
|
|
|
this._tileList = [];
|
|
|
|
|
|
2016-02-15 22:55:25 +00:00
|
|
|
|
// TODO: Work out why changing the minLOD causes loads of issues
|
2019-02-16 14:49:50 +00:00
|
|
|
|
this._minLOD = this._options.minLOD || 3;
|
2016-02-19 21:25:16 +00:00
|
|
|
|
this._maxLOD = this._options.maxLOD;
|
2016-02-15 22:55:25 +00:00
|
|
|
|
|
2016-02-14 19:10:28 +00:00
|
|
|
|
this._frustum = new THREE.Frustum();
|
2016-02-18 22:03:56 +00:00
|
|
|
|
this._tiles = new THREE.Object3D();
|
2016-02-29 18:49:21 +00:00
|
|
|
|
this._tilesPicking = new THREE.Object3D();
|
2016-02-14 19:10:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_onAdd(world) {
|
2016-02-29 18:49:21 +00:00
|
|
|
|
this.addToPicking(this._tilesPicking);
|
2016-02-25 23:00:16 +00:00
|
|
|
|
this.add(this._tiles);
|
2016-08-30 15:46:04 +00:00
|
|
|
|
|
|
|
|
|
return Promise.resolve();
|
2016-02-14 19:10:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_updateFrustum() {
|
|
|
|
|
var camera = this._world.getCamera();
|
|
|
|
|
var projScreenMatrix = new THREE.Matrix4();
|
|
|
|
|
projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
|
|
|
|
|
|
|
|
|
|
this._frustum.setFromMatrix(camera.projectionMatrix);
|
|
|
|
|
this._frustum.setFromMatrix(new THREE.Matrix4().multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse));
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-15 22:55:25 +00:00
|
|
|
|
_tileInFrustum(tile) {
|
|
|
|
|
var bounds = tile.getBounds();
|
|
|
|
|
return this._frustum.intersectsBox(new THREE.Box3(new THREE.Vector3(bounds[0], 0, bounds[3]), new THREE.Vector3(bounds[2], 0, bounds[1])));
|
2016-02-14 19:10:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-27 11:04:40 +00:00
|
|
|
|
// Update and output tiles from the previous LOD checklist
|
|
|
|
|
_outputTiles() {
|
2016-10-26 11:41:24 +00:00
|
|
|
|
if (!this._tiles || this._destroy) {
|
2016-02-29 09:17:22 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-27 11:04:40 +00:00
|
|
|
|
// Remove all tiles from layer
|
|
|
|
|
this._removeTiles();
|
|
|
|
|
|
|
|
|
|
// Add / re-add tiles
|
|
|
|
|
this._tileList.forEach(tile => {
|
|
|
|
|
// Are the mesh and texture ready?
|
|
|
|
|
//
|
|
|
|
|
// If yes, continue
|
|
|
|
|
// If no, skip
|
|
|
|
|
if (!tile.isReady()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add tile to layer (and to scene) if not already there
|
|
|
|
|
this._tiles.add(tile.getMesh());
|
2016-02-29 18:49:21 +00:00
|
|
|
|
|
|
|
|
|
if (tile.getPickingMesh()) {
|
|
|
|
|
this._tilesPicking.add(tile.getPickingMesh());
|
|
|
|
|
}
|
2016-02-27 11:04:40 +00:00
|
|
|
|
});
|
2016-09-13 14:23:55 +00:00
|
|
|
|
|
|
|
|
|
// Emit event notifying of new tiles
|
2016-09-16 09:08:35 +00:00
|
|
|
|
this.emit('tilesList', this._tileList.map((tile) => tile));
|
2016-02-27 11:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Works out tiles in the view frustum and stores them in an array
|
|
|
|
|
//
|
|
|
|
|
// Does not output the tiles, deferring this to _outputTiles()
|
2016-02-14 19:10:28 +00:00
|
|
|
|
_calculateLOD() {
|
2016-10-26 11:41:24 +00:00
|
|
|
|
if (this._stop || !this._world || this._destroy) {
|
2016-02-15 22:55:25 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-19 14:37:05 +00:00
|
|
|
|
// var start = (performance || Date).now();
|
2016-02-15 22:55:25 +00:00
|
|
|
|
|
2016-02-14 19:10:28 +00:00
|
|
|
|
var camera = this._world.getCamera();
|
|
|
|
|
|
|
|
|
|
// 1. Update and retrieve camera frustum
|
|
|
|
|
this._updateFrustum(this._frustum, camera);
|
|
|
|
|
|
|
|
|
|
// 2. Add the four root items of the quadtree to a check list
|
|
|
|
|
var checkList = this._checklist;
|
|
|
|
|
checkList = [];
|
2016-02-18 22:03:56 +00:00
|
|
|
|
checkList.push(this._requestTile('0', this));
|
|
|
|
|
checkList.push(this._requestTile('1', this));
|
|
|
|
|
checkList.push(this._requestTile('2', this));
|
|
|
|
|
checkList.push(this._requestTile('3', this));
|
2016-02-14 19:10:28 +00:00
|
|
|
|
|
|
|
|
|
// 3. Call Divide, passing in the check list
|
|
|
|
|
this._divide(checkList);
|
|
|
|
|
|
2016-02-27 11:04:40 +00:00
|
|
|
|
// // 4. Remove all tiles from layer
|
|
|
|
|
//
|
|
|
|
|
// Moved to _outputTiles() for now
|
|
|
|
|
// this._removeTiles();
|
2016-02-15 22:55:25 +00:00
|
|
|
|
|
2016-03-14 22:45:45 +00:00
|
|
|
|
// Order tile-list by zoom so nearest tiles are requested first
|
|
|
|
|
checkList.sort((a, b) => {
|
|
|
|
|
return a._quadcode.length < b._quadcode.length;
|
|
|
|
|
});
|
|
|
|
|
|
2016-02-27 11:04:40 +00:00
|
|
|
|
// 5. Filter the tiles remaining in the check list
|
2016-10-06 09:11:32 +00:00
|
|
|
|
var tileList = checkList.filter((tile, index) => {
|
2016-02-15 22:55:25 +00:00
|
|
|
|
// Skip tile if it's not in the current view frustum
|
|
|
|
|
if (!this._tileInFrustum(tile)) {
|
2016-02-27 11:04:40 +00:00
|
|
|
|
return false;
|
2016-02-14 19:10:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-19 21:25:16 +00:00
|
|
|
|
if (this._options.distance && this._options.distance > 0) {
|
|
|
|
|
// TODO: Can probably speed this up
|
|
|
|
|
var center = tile.getCenter();
|
|
|
|
|
var dist = (new THREE.Vector3(center[0], 0, center[1])).sub(camera.position).length();
|
2016-02-14 19:10:28 +00:00
|
|
|
|
|
2016-02-19 21:25:16 +00:00
|
|
|
|
// Manual distance limit to cut down on tiles so far away
|
|
|
|
|
if (dist > this._options.distance) {
|
2016-02-27 11:04:40 +00:00
|
|
|
|
return false;
|
2016-02-19 21:25:16 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-02-15 22:55:25 +00:00
|
|
|
|
|
|
|
|
|
// Does the tile have a mesh?
|
|
|
|
|
//
|
|
|
|
|
// If yes, continue
|
|
|
|
|
// If no, generate tile mesh, request texture and skip
|
2016-10-06 09:11:32 +00:00
|
|
|
|
if (!tile.getMesh() || tile.isAborted()) {
|
2016-02-15 22:55:25 +00:00
|
|
|
|
tile.requestTileAsync();
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-27 11:04:40 +00:00
|
|
|
|
return true;
|
|
|
|
|
|
2016-02-15 22:55:25 +00:00
|
|
|
|
// Are the mesh and texture ready?
|
|
|
|
|
//
|
|
|
|
|
// If yes, continue
|
|
|
|
|
// If no, skip
|
2016-02-27 11:04:40 +00:00
|
|
|
|
// if (!tile.isReady()) {
|
|
|
|
|
// return;
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// // Add tile to layer (and to scene)
|
|
|
|
|
// this._tiles.add(tile.getMesh());
|
2016-02-14 19:10:28 +00:00
|
|
|
|
});
|
2016-02-15 22:55:25 +00:00
|
|
|
|
|
2016-10-06 09:11:32 +00:00
|
|
|
|
// Get list of tiles that were in the previous update but not the
|
|
|
|
|
// current one (for aborting requests, etc)
|
|
|
|
|
var missingTiles = this._tileList.filter((item) => {
|
2016-12-21 11:47:51 +00:00
|
|
|
|
return tileList.indexOf(item) < 0;
|
2016-10-06 09:11:32 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Abort tiles that are no longer in view
|
|
|
|
|
missingTiles.forEach((tile) => tile._abortRequest());
|
|
|
|
|
|
|
|
|
|
this._tileList = tileList;
|
|
|
|
|
|
2016-12-19 14:37:05 +00:00
|
|
|
|
// console.log((performance || Date).now() - start);
|
2016-02-14 19:10:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_divide(checkList) {
|
|
|
|
|
var count = 0;
|
|
|
|
|
var currentItem;
|
2016-02-15 22:55:25 +00:00
|
|
|
|
var quadcode;
|
2016-02-14 19:10:28 +00:00
|
|
|
|
|
|
|
|
|
// 1. Loop until count equals check list length
|
|
|
|
|
while (count != checkList.length) {
|
|
|
|
|
currentItem = checkList[count];
|
2016-02-15 22:55:25 +00:00
|
|
|
|
quadcode = currentItem.getQuadcode();
|
2016-02-14 19:10:28 +00:00
|
|
|
|
|
2016-02-15 22:55:25 +00:00
|
|
|
|
// 2. Increase count and continue loop if quadcode equals max LOD / zoom
|
2016-02-14 19:10:28 +00:00
|
|
|
|
if (currentItem.length === this._maxLOD) {
|
|
|
|
|
count++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-15 22:55:25 +00:00
|
|
|
|
// 3. Else, calculate screen-space error metric for quadcode
|
2016-02-14 19:10:28 +00:00
|
|
|
|
if (this._screenSpaceError(currentItem)) {
|
|
|
|
|
// 4. If error is sufficient...
|
|
|
|
|
|
|
|
|
|
// 4a. Remove parent item from the check list
|
|
|
|
|
checkList.splice(count, 1);
|
|
|
|
|
|
|
|
|
|
// 4b. Add 4 child items to the check list
|
2016-02-18 22:03:56 +00:00
|
|
|
|
checkList.push(this._requestTile(quadcode + '0', this));
|
|
|
|
|
checkList.push(this._requestTile(quadcode + '1', this));
|
|
|
|
|
checkList.push(this._requestTile(quadcode + '2', this));
|
|
|
|
|
checkList.push(this._requestTile(quadcode + '3', this));
|
2016-02-14 19:10:28 +00:00
|
|
|
|
|
|
|
|
|
// 4d. Continue the loop without increasing count
|
|
|
|
|
continue;
|
|
|
|
|
} else {
|
|
|
|
|
// 5. Else, increase count and continue loop
|
|
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-15 22:55:25 +00:00
|
|
|
|
_screenSpaceError(tile) {
|
2016-02-14 19:10:28 +00:00
|
|
|
|
var minDepth = this._minLOD;
|
|
|
|
|
var maxDepth = this._maxLOD;
|
|
|
|
|
|
2016-02-15 22:55:25 +00:00
|
|
|
|
var quadcode = tile.getQuadcode();
|
|
|
|
|
|
2016-02-14 19:10:28 +00:00
|
|
|
|
var camera = this._world.getCamera();
|
|
|
|
|
|
|
|
|
|
// Tweak this value to refine specific point that each quad is subdivided
|
2016-02-14 23:19:20 +00:00
|
|
|
|
//
|
2016-02-15 22:55:25 +00:00
|
|
|
|
// It's used to multiple the dimensions of the tile sides before
|
|
|
|
|
// comparing against the tile distance from camera
|
2016-02-14 23:19:20 +00:00
|
|
|
|
var quality = 3.0;
|
2016-02-14 19:10:28 +00:00
|
|
|
|
|
2016-02-19 21:25:16 +00:00
|
|
|
|
// 1. Return false if quadcode length equals maxDepth (stop dividing)
|
|
|
|
|
if (quadcode.length === maxDepth) {
|
2016-02-14 19:10:28 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-15 22:55:25 +00:00
|
|
|
|
// 2. Return true if quadcode length is less than minDepth
|
|
|
|
|
if (quadcode.length < minDepth) {
|
2016-02-14 19:10:28 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-15 22:55:25 +00:00
|
|
|
|
// 3. Return false if quadcode bounds are not in view frustum
|
|
|
|
|
if (!this._tileInFrustum(tile)) {
|
2016-02-14 19:10:28 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-15 22:55:25 +00:00
|
|
|
|
var center = tile.getCenter();
|
2016-02-14 19:10:28 +00:00
|
|
|
|
|
2016-02-15 22:55:25 +00:00
|
|
|
|
// 4. Calculate screen-space error metric
|
|
|
|
|
// TODO: Use closest distance to one of the 4 tile corners
|
|
|
|
|
var dist = (new THREE.Vector3(center[0], 0, center[1])).sub(camera.position).length();
|
2016-02-14 19:10:28 +00:00
|
|
|
|
|
2016-02-15 22:55:25 +00:00
|
|
|
|
var error = quality * tile.getSide() / dist;
|
2016-02-14 19:10:28 +00:00
|
|
|
|
|
|
|
|
|
// 5. Return true if error is greater than 1.0, else return false
|
|
|
|
|
return (error > 1.0);
|
|
|
|
|
}
|
2016-02-15 22:55:25 +00:00
|
|
|
|
|
|
|
|
|
_removeTiles() {
|
2016-02-29 09:17:22 +00:00
|
|
|
|
if (!this._tiles || !this._tiles.children) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-18 22:03:56 +00:00
|
|
|
|
for (var i = this._tiles.children.length - 1; i >= 0; i--) {
|
|
|
|
|
this._tiles.remove(this._tiles.children[i]);
|
|
|
|
|
}
|
2016-02-29 18:49:21 +00:00
|
|
|
|
|
|
|
|
|
if (!this._tilesPicking || !this._tilesPicking.children) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (var i = this._tilesPicking.children.length - 1; i >= 0; i--) {
|
|
|
|
|
this._tilesPicking.remove(this._tilesPicking.children[i]);
|
|
|
|
|
}
|
2016-02-18 22:03:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Return a new tile instance
|
|
|
|
|
_createTile(quadcode, layer) {}
|
|
|
|
|
|
|
|
|
|
// Get a cached tile or request a new one if not in cache
|
|
|
|
|
_requestTile(quadcode, layer) {
|
|
|
|
|
var tile = this._tileCache.getTile(quadcode);
|
|
|
|
|
|
|
|
|
|
if (!tile) {
|
|
|
|
|
// Set up a brand new tile
|
|
|
|
|
tile = this._createTile(quadcode, layer);
|
|
|
|
|
|
|
|
|
|
// Add tile to cache, though it won't be ready yet as the data is being
|
|
|
|
|
// requested from various places asynchronously
|
|
|
|
|
this._tileCache.setTile(quadcode, tile);
|
2016-02-15 22:55:25 +00:00
|
|
|
|
}
|
2016-02-18 22:03:56 +00:00
|
|
|
|
|
|
|
|
|
return tile;
|
2016-02-15 22:55:25 +00:00
|
|
|
|
}
|
2016-02-18 18:42:19 +00:00
|
|
|
|
|
|
|
|
|
_destroyTile(tile) {
|
|
|
|
|
// Remove tile from scene
|
2016-02-25 23:00:16 +00:00
|
|
|
|
this._tiles.remove(tile.getMesh());
|
2016-02-18 18:42:19 +00:00
|
|
|
|
|
|
|
|
|
// Delete any references to the tile within this component
|
|
|
|
|
|
|
|
|
|
// Call destory on tile instance
|
|
|
|
|
tile.destroy();
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-07 12:58:45 +00:00
|
|
|
|
show() {
|
|
|
|
|
this._stop = false;
|
2016-10-21 13:30:52 +00:00
|
|
|
|
|
|
|
|
|
if (this._tilesPicking) {
|
|
|
|
|
this._tilesPicking.visible = true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-07 12:58:45 +00:00
|
|
|
|
this._calculateLOD();
|
|
|
|
|
super.show();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hide() {
|
|
|
|
|
this._stop = true;
|
2016-10-21 13:30:52 +00:00
|
|
|
|
|
|
|
|
|
if (this._tilesPicking) {
|
|
|
|
|
this._tilesPicking.visible = false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-07 12:58:45 +00:00
|
|
|
|
super.hide();
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-18 18:42:19 +00:00
|
|
|
|
// Destroys the layer and removes it from the scene and memory
|
|
|
|
|
destroy() {
|
2016-10-26 11:41:24 +00:00
|
|
|
|
this._destroy = true;
|
|
|
|
|
|
2016-02-29 09:17:22 +00:00
|
|
|
|
if (this._tiles.children) {
|
|
|
|
|
// Remove all tiles
|
|
|
|
|
for (var i = this._tiles.children.length - 1; i >= 0; i--) {
|
|
|
|
|
this._tiles.remove(this._tiles.children[i]);
|
|
|
|
|
}
|
2016-02-18 22:03:56 +00:00
|
|
|
|
}
|
2016-02-18 19:33:12 +00:00
|
|
|
|
|
2016-02-29 18:49:21 +00:00
|
|
|
|
// Remove tile from picking scene
|
|
|
|
|
this.removeFromPicking(this._tilesPicking);
|
|
|
|
|
|
|
|
|
|
if (this._tilesPicking.children) {
|
|
|
|
|
// Remove all tiles
|
|
|
|
|
for (var i = this._tilesPicking.children.length - 1; i >= 0; i--) {
|
|
|
|
|
this._tilesPicking.remove(this._tilesPicking.children[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-18 18:42:19 +00:00
|
|
|
|
this._tileCache.destroy();
|
|
|
|
|
this._tileCache = null;
|
|
|
|
|
|
2016-02-18 22:03:56 +00:00
|
|
|
|
this._tiles = null;
|
2016-02-29 18:49:21 +00:00
|
|
|
|
this._tilesPicking = null;
|
2016-02-18 18:42:19 +00:00
|
|
|
|
this._frustum = null;
|
2016-02-25 23:00:16 +00:00
|
|
|
|
|
|
|
|
|
super.destroy();
|
2016-02-18 18:42:19 +00:00
|
|
|
|
}
|
2016-02-14 19:10:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-18 22:03:56 +00:00
|
|
|
|
export default TileLayer;
|