Improvements to tile-loading and other fixes

This commit is contained in:
Lukas Rieger (Blue) 2022-08-14 20:34:54 +02:00
parent d9ffe6453f
commit bb4928c72f
No known key found for this signature in database
GPG Key ID: 2D09EC5ED2687FF2
8 changed files with 50 additions and 22 deletions

View File

@ -369,7 +369,11 @@ export class MapViewer {
updateLoadedMapArea = () => {
if (!this.map) return;
this.map.loadMapArea(this.data.loadedCenter.x, this.data.loadedCenter.y, this.data.loadedHiresViewDistance, this.data.loadedLowresViewDistance);
if (this.controlsManager.distance < 1000) {
this.map.loadMapArea(this.data.loadedCenter.x, this.data.loadedCenter.y, this.data.loadedHiresViewDistance, this.data.loadedLowresViewDistance);
} else {
this.map.loadMapArea(this.data.loadedCenter.x, this.data.loadedCenter.y, 0, this.data.loadedLowresViewDistance);
}
}
clearTileCache(newTileCacheHash) {

View File

@ -58,6 +58,7 @@ export class ControlsManager {
this.lastTilt = this.tilt;
this.lastMapUpdatePosition = this.position.clone();
this.lastMapUpdateDistance = this.distance;
this.averageDeltaTime = 16;
@ -156,9 +157,11 @@ export class ControlsManager {
if (
Math.abs(this.lastMapUpdatePosition.x - this.position.x) >= triggerDistance ||
Math.abs(this.lastMapUpdatePosition.z - this.position.z) >= triggerDistance
Math.abs(this.lastMapUpdatePosition.z - this.position.z) >= triggerDistance ||
(this.distance < 1000 && this.lastMapUpdateDistance > 1000)
) {
this.lastMapUpdatePosition = this.position.clone();
this.lastMapUpdateDistance = this.distance;
this.mapViewer.loadMapArea(this.position.x, this.position.z);
}
}

View File

@ -38,13 +38,13 @@ import {
export class LowresTileLoader {
constructor(tilePath, tileSettings, lod, vertexShader, fragmentShader, uniforms, tileCacheHash = 0, layer = 0) {
constructor(tilePath, tileSettings, lod, vertexShader, fragmentShader, uniforms, loadBlocker = () => Promise.resolve(), tileCacheHash = 0) {
Object.defineProperty( this, 'isLowresTileLoader', { value: true } );
this.tilePath = tilePath;
this.tileSettings = tileSettings;
this.lod = lod;
this.layer = layer;
this.loadBlocker = loadBlocker;
this.tileCacheHash = tileCacheHash;
this.vertexShader = vertexShader;
@ -62,12 +62,13 @@ export class LowresTileLoader {
this.geometry.translate(tileSettings.tileSize.x / 2 + 1, 0, tileSettings.tileSize.x / 2 + 1);
}
load = (tileX, tileZ) => {
load = (tileX, tileZ, cancelCheck = () => false) => {
let tileUrl = this.tilePath + this.lod + "/" + pathFromCoords(tileX, tileZ) + '.png';
//await this.loadBlocker();
return new Promise((resolve, reject) => {
this.textureLoader.load(tileUrl + '?' + this.tileCacheHash,
texture => {
async texture => {
texture.anisotropy = 1;
texture.generateMipmaps = false;
texture.magFilter = NearestFilter;
@ -77,6 +78,13 @@ export class LowresTileLoader {
texture.flipY = false;
texture.flatShading = true;
await this.loadBlocker();
if (cancelCheck()){
texture.dispose();
reject({status: "cancelled"});
return;
}
let material = new ShaderMaterial({
uniforms: {
...this.uniforms,
@ -102,7 +110,6 @@ export class LowresTileLoader {
});
let object = new Mesh(this.geometry, material);
if (this.layer) object.layers.set(this.layer);
const scale = Math.pow(this.tileSettings.lodFactor, this.lod - 1);
object.position.set(tileX * this.tileSettings.tileSize.x * scale, 0, tileZ * this.tileSettings.tileSize.z * scale);

View File

@ -46,11 +46,13 @@ export class Map {
/**
* @param id {string}
* @param dataUrl {string}
* @param loadBlocker {function: Promise<void>}
* @param events {EventTarget}
*/
constructor(id, dataUrl, events = null) {
constructor(id, dataUrl, loadBlocker, events = null) {
Object.defineProperty( this, 'isMap', { value: true } );
this.loadBlocker = loadBlocker;
this.events = events;
this.data = {
@ -115,12 +117,12 @@ export class Map {
this.hiresMaterial = this.createHiresMaterial(hiresVertexShader, hiresFragmentShader, uniforms, textures);
this.hiresTileManager = new TileManager(new Scene(), new TileLoader(`${this.data.dataUrl}tiles/0/`, this.hiresMaterial, this.data.hires, tileCacheHash), this.onTileLoad("hires"), this.onTileUnload("hires"), this.events);
this.hiresTileManager = new TileManager(new Scene(), new TileLoader(`${this.data.dataUrl}tiles/0/`, this.hiresMaterial, this.data.hires, this.loadBlocker, tileCacheHash), this.onTileLoad("hires"), this.onTileUnload("hires"), this.events);
this.hiresTileManager.scene.autoUpdate = false;
this.lowresTileManager = [];
for (let i = 0; i < this.data.lowres.lodCount; i++) {
this.lowresTileManager[i] = new TileManager(new Scene(), new LowresTileLoader(`${this.data.dataUrl}tiles/`, this.data.lowres, i + 1, lowresVertexShader, lowresFragmentShader, uniforms, tileCacheHash), this.onTileLoad("lowres"), this.onTileUnload("lowres"), this.events);
this.lowresTileManager[i] = new TileManager(new Scene(), new LowresTileLoader(`${this.data.dataUrl}tiles/`, this.data.lowres, i + 1, lowresVertexShader, lowresFragmentShader, uniforms, async () => {}, tileCacheHash), this.onTileLoad("lowres"), this.onTileUnload("lowres"), this.events);
this.lowresTileManager[i].scene.autoUpdate = false;
}

View File

@ -57,7 +57,7 @@ export class Tile {
this.unload();
this.unloaded = false;
return tileLoader.load(this.x, this.z)
return tileLoader.load(this.x, this.z, () => this.unloaded)
.then(model => {
if (this.unloaded){
Tile.disposeModel(model);

View File

@ -35,42 +35,48 @@ export class TileLoader {
* scale: {x: number, z: number},
* translate: {x: number, z: number}
* }}
* @param loadBlocker {function: Promise}
* @param tileCacheHash {number}
* @param layer {number}
*/
constructor(tilePath, material, tileSettings, tileCacheHash = 0, layer = 0) {
constructor(tilePath, material, tileSettings, loadBlocker = () => Promise.resolve(), tileCacheHash = 0) {
Object.defineProperty( this, 'isTileLoader', { value: true } );
this.tilePath = tilePath;
this.material = material;
this.tileSettings = tileSettings;
this.layer = layer;
this.tileCacheHash = tileCacheHash;
this.loadBlocker = loadBlocker;
this.fileLoader = new FileLoader();
this.fileLoader.setResponseType('json');
this.bufferGeometryLoader = new BufferGeometryLoader();
}
load = (tileX, tileZ) => {
load = (tileX, tileZ, cancelCheck = () => false) => {
let tileUrl = this.tilePath + pathFromCoords(tileX, tileZ) + '.json';
//await this.loadBlocker();
return new Promise((resolve, reject) => {
this.fileLoader.load(tileUrl + '?' + this.tileCacheHash,
json => {
async json => {
let geometryJson = json.tileGeometry || {};
if (!geometryJson.type || geometryJson.type !== 'BufferGeometry'){
reject({status: "empty"});
return;
}
await this.loadBlocker();
if (cancelCheck()){
reject({status: "cancelled"});
return;
}
let geometry = this.bufferGeometryLoader.parse(geometryJson);
let object = new Mesh(geometry, this.material);
if (this.layer) object.layers.set(this.layer);
let tileSize = this.tileSettings.tileSize;
let translate = this.tileSettings.translate;

View File

@ -82,13 +82,18 @@ export class TileManager {
this.viewDistanceX = viewDistanceX;
this.viewDistanceZ = viewDistanceZ;
if (viewDistanceX <= 0 || viewDistanceZ <= 0) {
this.removeAllTiles();
return;
}
if (unloadTiles || this.centerTile.x !== x || this.centerTile.y !== z) {
this.centerTile.set(x, z);
this.removeFarTiles();
this.tileMap.setAll(TileMap.EMPTY);
this.tiles.forEach(tile => {
if (!tile.loading) {
if (!tile.loading && !tile.unloaded) {
this.tileMap.setTile(tile.x - this.centerTile.x + TileManager.tileMapHalfSize, tile.z - this.centerTile.y + TileManager.tileMapHalfSize, TileMap.LOADED);
}
});
@ -187,7 +192,8 @@ export class TileManager {
this.tiles.set(tileHash, tile);
tile.load(this.tileLoader)
.then(() => {
this.tileMap.setTile(tile.x - this.centerTile.x + TileManager.tileMapHalfSize, tile.z - this.centerTile.y + TileManager.tileMapHalfSize, TileMap.LOADED);
if (!tile.unloaded)
this.tileMap.setTile(tile.x - this.centerTile.x + TileManager.tileMapHalfSize, tile.z - this.centerTile.y + TileManager.tileMapHalfSize, TileMap.LOADED);
if (this.loadTimeout) clearTimeout(this.loadTimeout);
this.loadTimeout = setTimeout(this.loadCloseTiles, 0);
@ -200,7 +206,7 @@ export class TileManager {
//alert(this.events, "Failed to load tile: " + error.type, "warning");
})
.finally(() => {
this.tileMap.setTile(tile.x - this.centerTile.x + TileManager.tileMapHalfSize, tile.z - this.centerTile.y + TileManager.tileMapHalfSize, TileMap.LOADED);
//this.tileMap.setTile(tile.x - this.centerTile.x + TileManager.tileMapHalfSize, tile.z - this.centerTile.y + TileManager.tileMapHalfSize, TileMap.LOADED);
this.currentlyLoading--;
});

View File

@ -73,7 +73,7 @@ vec2 posToMetaUV(vec2 pos) {
void main() {
//discard if hires tile is loaded at that position
//if (vDistance < 900.0 && texture(hiresTileMap.map, ((vWorldPosition.xz - hiresTileMap.translate) / hiresTileMap.scale - hiresTileMap.pos) / hiresTileMap.size + 0.5).r > 0.75) discard;
if (vDistance < 900.0 && texture(hiresTileMap.map, ((vWorldPosition.xz - hiresTileMap.translate) / hiresTileMap.scale - hiresTileMap.pos) / hiresTileMap.size + 0.5).r > 0.75) discard;
vec4 color = texture(textureImage, posToColorUV(vPosition.xz));
vec4 meta = texture(textureImage, posToMetaUV(vPosition.xz));