wip coordinate resolver
parent
7b5c4346b6
commit
51313efd99
|
@ -94,7 +94,7 @@ public class TileRenderer {
|
|||
int x2 = mapblockInfo.x + (int)mapblockInfo.width;
|
||||
|
||||
int z1 = mapblockInfo.z;
|
||||
int z2 = mapblockInfo.z + ((int)mapblockInfo.height * -1);
|
||||
int z2 = (mapblockInfo.z *-1) + ((int)mapblockInfo.height);
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
|
@ -117,7 +117,7 @@ public class TileRenderer {
|
|||
}
|
||||
|
||||
if (firstResult.isEmpty()) {
|
||||
logger.debug("Fail-fast, got zero mapblock count for x={}-{} z={}-{}", x1,x2, z1,z2);
|
||||
logger.debug("Fail-fast, got zero mapblock count for x=({})-({}) z=({})-({})", x1,x2, z1,z2);
|
||||
|
||||
byte[] data = WhiteTile.getPNG();
|
||||
|
||||
|
@ -260,7 +260,7 @@ public class TileRenderer {
|
|||
|
||||
long diff = System.currentTimeMillis() - start;
|
||||
|
||||
logger.debug("Timings of cross-stitched tile X={} Y={} Zoom={}: render={} ms", tileX, tileY, zoom, diff);
|
||||
logger.trace("Timings of cross-stitched tile X={} Y={} Zoom={}: render={} ms", tileX, tileY, zoom, diff);
|
||||
|
||||
cache.put(layer.id, tileX, tileY, zoom, data);
|
||||
|
||||
|
@ -314,6 +314,7 @@ public class TileRenderer {
|
|||
long timingRender = 0;
|
||||
|
||||
if (!countList.isEmpty()) {
|
||||
logger.debug("Rendering tile for mapblock: X={}, Z={}", mapblockX, mapblockZ);
|
||||
blockRenderer.render(layer.from, layer.to, mapblockX, mapblockZ, graphics, 16);
|
||||
|
||||
now = System.currentTimeMillis();
|
||||
|
@ -330,7 +331,7 @@ public class TileRenderer {
|
|||
long timingBufferOutput = now - start;
|
||||
|
||||
|
||||
logger.debug("Timings of tile X={} Y={} Zoom={}: setup={} ms, zeroCheck={} ms, render={} ms, output={} ms",
|
||||
logger.trace("Timings of tile X={} Y={} Zoom={}: setup={} ms, zeroCheck={} ms, render={} ms, output={} ms",
|
||||
tileX, tileY, zoom,
|
||||
timingImageSetup, timingZeroCountCheck, timingRender, timingBufferOutput
|
||||
);
|
||||
|
|
|
@ -106,12 +106,46 @@ public class UpdateChangedTilesJob implements Runnable {
|
|||
|
||||
private final Map<Integer, Long> timestampMap = new HashMap<>();
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
//Run without parsing summary
|
||||
updateChangedTiles();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execution summory of changed tiles
|
||||
*/
|
||||
public static class ChangedTilesResult {
|
||||
public Map<Integer, Integer> renderedTilesPerLayer = new HashMap<>();
|
||||
public Map<Integer, Integer> skippedTilesPerLayer = new HashMap<>();
|
||||
public Map<Integer, Integer> changedBlocksPerLayer = new HashMap<>();
|
||||
public double executionTime;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ChangedTilesResult{" +
|
||||
"renderedTilesPerLayer=" + renderedTilesPerLayer +
|
||||
", skippedTilesPerLayer=" + skippedTilesPerLayer +
|
||||
", changedBlocksPerLayer=" + changedBlocksPerLayer +
|
||||
", executionTime=" + executionTime +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the changed tiles and returns a summary of all actions
|
||||
* @return
|
||||
*/
|
||||
public ChangedTilesResult updateChangedTiles(){
|
||||
|
||||
ChangedTilesResult result = new ChangedTilesResult();
|
||||
|
||||
if (running) {
|
||||
//skip multiple invocations
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (timestampMap.isEmpty()) {
|
||||
|
@ -179,6 +213,10 @@ public class UpdateChangedTilesJob implements Runnable {
|
|||
int count = blocks.size();
|
||||
int invalidatedTiles = 0;
|
||||
|
||||
//internal summary
|
||||
result.changedBlocksPerLayer.put(layer.id, count);
|
||||
|
||||
//prometheus
|
||||
layerBlockQueryTimingGaugeMap.get(layer.id).set(queryTime);
|
||||
layerBlockChangeGaugeMap.get(layer.id).set(count);
|
||||
|
||||
|
@ -207,32 +245,8 @@ public class UpdateChangedTilesJob implements Runnable {
|
|||
|
||||
logger.debug("Starting rendering of changed tiles");
|
||||
|
||||
//run with rendering of highest zoom level without cache
|
||||
for (BlocksRecord record : blocks) {
|
||||
|
||||
Integer x = record.getPosx();
|
||||
Integer z = record.getPosz();
|
||||
|
||||
TileInfo tileInfo = CoordinateResolver.fromCoordinates(x, z);
|
||||
|
||||
TileInfo zoomedTile = tileInfo.toZoom(CoordinateResolver.MAX_ZOOM);
|
||||
String tileKey = getTileKey(zoomedTile);
|
||||
|
||||
logger.debug("Rendering tile x={} y={} zoom={}", zoomedTile.x, zoomedTile.y, zoomedTile.zoom);
|
||||
tileRenderer.render(layer, zoomedTile.x, zoomedTile.y, zoomedTile.zoom, false); //render without cache
|
||||
|
||||
logger.debug("Dispatching tile-changed-event for tile: {}/{}", zoomedTile.x, zoomedTile.y);
|
||||
|
||||
EventBus.TileChangedEvent event = new EventBus.TileChangedEvent();
|
||||
event.layerId = layer.id;
|
||||
event.x = zoomedTile.x;
|
||||
event.y = zoomedTile.y;
|
||||
event.zoom = zoomedTile.zoom;
|
||||
event.mapblockX = x;
|
||||
event.mapblockZ = z;
|
||||
eventBus.post(event);
|
||||
|
||||
}
|
||||
int changedTileCount = 0;
|
||||
int skippedTileCount = 0;
|
||||
|
||||
List<String> updatedTileKeys = new ArrayList<>();
|
||||
|
||||
|
@ -244,7 +258,7 @@ public class UpdateChangedTilesJob implements Runnable {
|
|||
|
||||
TileInfo tileInfo = CoordinateResolver.fromCoordinates(x, z);
|
||||
|
||||
for (int i = CoordinateResolver.MAX_ZOOM-1; i >= CoordinateResolver.MIN_ZOOM+2; i--) {
|
||||
for (int i = CoordinateResolver.MAX_ZOOM; i >= CoordinateResolver.MIN_ZOOM+2; i--) {
|
||||
TileInfo zoomedTile = tileInfo.toZoom(i);
|
||||
String tileKey = getTileKey(zoomedTile);
|
||||
|
||||
|
@ -252,7 +266,7 @@ public class UpdateChangedTilesJob implements Runnable {
|
|||
|
||||
//Generate tiles now
|
||||
logger.debug("Rendering tile x={} y={} zoom={}", zoomedTile.x, zoomedTile.y, zoomedTile.zoom);
|
||||
tileRenderer.render(layer, zoomedTile.x, zoomedTile.y, zoomedTile.zoom, false); //render without cache
|
||||
tileRenderer.render(layer, zoomedTile.x, zoomedTile.y, zoomedTile.zoom);
|
||||
|
||||
logger.debug("Dispatching tile-changed-event for tile: {}/{}", zoomedTile.x, zoomedTile.y);
|
||||
|
||||
|
@ -265,13 +279,21 @@ public class UpdateChangedTilesJob implements Runnable {
|
|||
event.mapblockZ = z;
|
||||
eventBus.post(event);
|
||||
|
||||
changedTileCount++;
|
||||
updatedTileKeys.add(tileKey);
|
||||
|
||||
} else {
|
||||
skippedTileCount++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
result.renderedTilesPerLayer.put(layer.id, changedTileCount);
|
||||
result.skippedTilesPerLayer.put(layer.id, skippedTileCount);
|
||||
|
||||
final String msg = "Tile update job took {} ms for {} blocks in layer: '{}' (invalidated {} tiles)";
|
||||
final Object[] params = new Object[]{
|
||||
System.currentTimeMillis() - start,
|
||||
|
@ -293,9 +315,10 @@ public class UpdateChangedTilesJob implements Runnable {
|
|||
changedTiles.set(tileCount);
|
||||
|
||||
running = false;
|
||||
timer.observeDuration();
|
||||
result.executionTime = timer.observeDuration();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -143,7 +143,25 @@ public class DatabaseTileCache implements TileCache {
|
|||
|
||||
} else {
|
||||
//fallback
|
||||
record.store();
|
||||
TilesRecord existingRecord = ctx.selectFrom(TILES)
|
||||
.where(TILES.X.eq(record.getX()))
|
||||
.and(TILES.Y.eq(record.getY()))
|
||||
.and(TILES.Z.eq(record.getZ()))
|
||||
.and(TILES.LAYERID.eq(record.getLayerid()))
|
||||
.fetchOne();
|
||||
|
||||
if (existingRecord != null){
|
||||
//update
|
||||
existingRecord.setTile(record.getTile());
|
||||
existingRecord.setMtime(record.getMtime());
|
||||
existingRecord.update();
|
||||
|
||||
} else {
|
||||
//insert
|
||||
record.insert();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,7 +8,10 @@ public class CoordinateResolver {
|
|||
public static final int MAX_ZOOM = 13;
|
||||
public static final int MIN_ZOOM = 1;
|
||||
public static final int ONE_TO_ONE_ZOOM = 13; // 1 tile == 1 mapblock
|
||||
|
||||
|
||||
/**
|
||||
* Tile information
|
||||
*/
|
||||
public static class TileInfo {
|
||||
public int x, y;
|
||||
public int zoom;
|
||||
|
@ -31,8 +34,25 @@ public class CoordinateResolver {
|
|||
|
||||
return info;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TileInfo{" +
|
||||
"x=" + x +
|
||||
", y=" + y +
|
||||
", zoom=" + zoom +
|
||||
", width=" + width +
|
||||
", height=" + height +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tile coordinates from mapblock coords
|
||||
* @param x
|
||||
* @param z
|
||||
* @return
|
||||
*/
|
||||
public static TileInfo fromCoordinates(int x, int z) {
|
||||
TileInfo info = new TileInfo();
|
||||
|
||||
|
@ -48,6 +68,8 @@ public class CoordinateResolver {
|
|||
|
||||
public static class MapBlockCoordinateInfo {
|
||||
public int x, z;
|
||||
|
||||
@Deprecated //area
|
||||
public double width, height; //in map-blocks
|
||||
|
||||
@Override
|
||||
|
@ -60,22 +82,35 @@ public class CoordinateResolver {
|
|||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ...
|
||||
* 7 == 0.25
|
||||
* 8 == 0.5
|
||||
* 9 == 1 (16x16 mapblocks)
|
||||
* 10 == 2 (8x8 mapblocks)
|
||||
* 11 == 4 (4x4 mapblocks)
|
||||
* 12 == 8 (2x2 mapblocks)
|
||||
* 13 == 16 (1 mapblock)
|
||||
* ...
|
||||
|
||||
/**
|
||||
* An area defined by two mapblock "points"
|
||||
*/
|
||||
public static double getZoomFactor(int zoom) {
|
||||
return Math.pow(2, zoom - 9);
|
||||
public static class MapBlockArea {
|
||||
public MapBlockCoordinateInfo pos1, pos2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static MapBlockArea getMapBlockArea(int x, int y, int zoom){
|
||||
MapBlockArea area = new MapBlockArea();
|
||||
|
||||
MapBlockCoordinateInfo pos1 = new MapBlockCoordinateInfo();
|
||||
MapBlockCoordinateInfo pos2 = new MapBlockCoordinateInfo();
|
||||
|
||||
double factor = Math.pow(2, ONE_TO_ONE_ZOOM - zoom);
|
||||
|
||||
pos1.x = (int)(x * factor);
|
||||
pos1.z = (int)((y-1) * factor * -1);
|
||||
|
||||
//TODO
|
||||
|
||||
area.pos1 = pos1;
|
||||
area.pos2 = pos2;
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static MapBlockCoordinateInfo fromTile(int x, int y, int zoom) {
|
||||
MapBlockCoordinateInfo info = new MapBlockCoordinateInfo();
|
||||
|
||||
|
@ -96,7 +131,7 @@ public class CoordinateResolver {
|
|||
|
||||
// tile with 1:1 map resolution
|
||||
info.x = (int)(x * factor);
|
||||
info.z = (int)(y * factor * -1) - 1; //offset hack
|
||||
info.z = (int)((y-1) * factor * -1);
|
||||
info.height = factor;
|
||||
info.width = factor;
|
||||
|
||||
|
|
|
@ -175,12 +175,17 @@ Zoom: 8
|
|||
public void testTileZoomIterate() {
|
||||
TileInfo tileInfo = CoordinateResolver.fromCoordinates(32, -32);
|
||||
|
||||
for (int i=CoordinateResolver.MIN_ZOOM; i<=CoordinateResolver.MAX_ZOOM; i++) {
|
||||
for (int i=CoordinateResolver.MAX_ZOOM; i>=CoordinateResolver.MIN_ZOOM; i--) {
|
||||
TileInfo zoomedTile = tileInfo.toZoom(i);
|
||||
|
||||
System.out.println("Zoom: " + i + " x=" + zoomedTile.x + " y=" + zoomedTile.y + " width=" + zoomedTile.width);
|
||||
|
||||
MapBlockCoordinateInfo coordinateInfo = CoordinateResolver.fromTile(zoomedTile.x, zoomedTile.y, zoomedTile.zoom);
|
||||
|
||||
System.out.println("Zoom: " + i);
|
||||
System.out.println("+Tile: " + zoomedTile);
|
||||
System.out.println("+MapBlock: " + coordinateInfo);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -8,9 +8,12 @@ import io.rudin.minetest.tileserver.job.UpdateChangedTilesJob;
|
|||
import io.rudin.minetest.tileserver.qualifier.MapDB;
|
||||
import io.rudin.minetest.tileserver.service.BlocksRecordService;
|
||||
import io.rudin.minetest.tileserver.service.TileCache;
|
||||
import io.rudin.minetest.tileserver.util.CoordinateResolver;
|
||||
import org.jooq.DSLContext;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.io.IOException;
|
||||
|
@ -25,28 +28,39 @@ public class UpdateChangedTilesTest extends TileServerTest {
|
|||
@Inject TileCache tileCache;
|
||||
@Inject @MapDB DSLContext ctx;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(TileServerTest.class);
|
||||
|
||||
@Test
|
||||
public void test() throws IOException {
|
||||
|
||||
byte[] tile = tileCache.get(0, 0, 1, 13);
|
||||
final int mapblockX = 0;
|
||||
final int mapblockZ = 0;
|
||||
|
||||
CoordinateResolver.TileInfo coordinates = CoordinateResolver.fromCoordinates(mapblockX, mapblockZ);
|
||||
|
||||
logger.debug("Mapblock X={} Z={} / Tile X={} Y={} Zoom={} Width={} Height={}",
|
||||
mapblockX, mapblockZ,
|
||||
coordinates.x, coordinates.y, coordinates.zoom, coordinates.width, coordinates.height);
|
||||
|
||||
|
||||
byte[] tile = tileCache.get(0, coordinates.x, coordinates.y, 13);
|
||||
Assert.assertNull(tile);
|
||||
|
||||
changedTilesJob.run();
|
||||
logger.debug("First result: {}", changedTilesJob.updateChangedTiles());
|
||||
|
||||
tile = tileCache.get(0, 0, 1, 13);
|
||||
tile = tileCache.get(0, coordinates.x, coordinates.y, 13);
|
||||
Assert.assertNotNull(tile);
|
||||
|
||||
BlocksRecord block = ctx.selectFrom(BLOCKS)
|
||||
.where(BLOCKS.POSX.eq(0).and(BLOCKS.POSY.eq(0).and(BLOCKS.POSZ.eq(0))))
|
||||
.where(BLOCKS.POSX.eq(mapblockX).and(BLOCKS.POSY.eq(0).and(BLOCKS.POSZ.eq(mapblockZ))))
|
||||
.fetchOne();
|
||||
|
||||
block.setMtime(System.currentTimeMillis());
|
||||
block.update();
|
||||
|
||||
changedTilesJob.run();
|
||||
logger.debug("Second result: {}", changedTilesJob.updateChangedTiles());
|
||||
|
||||
tile = tileCache.get(0, 0, 1, 13);
|
||||
tile = tileCache.get(0, coordinates.x, coordinates.y, 13);
|
||||
Assert.assertNotNull(tile);
|
||||
|
||||
|
||||
|
|
|
@ -3,22 +3,17 @@ package io.rudin.minetest.tileserver.base;
|
|||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Key;
|
||||
import com.google.inject.Provider;
|
||||
import io.rudin.minetest.tileserver.DBMigration;
|
||||
import io.rudin.minetest.tileserver.blockdb.tables.Blocks;
|
||||
import io.rudin.minetest.tileserver.blockdb.tables.records.BlocksRecord;
|
||||
import io.rudin.minetest.tileserver.config.TileServerConfig;
|
||||
import io.rudin.minetest.tileserver.module.ConfigModule;
|
||||
import io.rudin.minetest.tileserver.module.DBModule;
|
||||
import io.rudin.minetest.tileserver.module.ServiceModule;
|
||||
import io.rudin.minetest.tileserver.module.TestServiceModule;
|
||||
import io.rudin.minetest.tileserver.qualifier.MapDB;
|
||||
import io.rudin.minetest.tileserver.qualifier.TileDB;
|
||||
import io.rudin.minetest.tileserver.util.StreamUtil;
|
||||
import org.aeonbits.owner.ConfigFactory;
|
||||
import org.jooq.DSLContext;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
package io.rudin.minetest.tileserver.module;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import io.rudin.minetest.tileserver.ColorTable;
|
||||
import io.rudin.minetest.tileserver.config.LayerConfig;
|
||||
import io.rudin.minetest.tileserver.config.TileServerConfig;
|
||||
import io.rudin.minetest.tileserver.provider.ColorTableProvider;
|
||||
import io.rudin.minetest.tileserver.provider.ExecutorProvider;
|
||||
import io.rudin.minetest.tileserver.provider.LayerConfigProvider;
|
||||
import io.rudin.minetest.tileserver.service.*;
|
||||
import io.rudin.minetest.tileserver.service.impl.*;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
public class TestServiceModule extends AbstractModule {
|
||||
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
|
||||
bind(TileCache.class).to(FileTileCache.class);
|
||||
bind(EventBus.class).to(EventBusImpl.class);
|
||||
bind(ColorTable.class).toProvider(ColorTableProvider.class);
|
||||
bind(ExecutorService.class).toProvider(ExecutorProvider.class);
|
||||
bind(ScheduledExecutorService.class).toProvider(ExecutorProvider.class);
|
||||
bind(LayerConfig.class).toProvider(LayerConfigProvider.class);
|
||||
bind(MapBlockRenderService.class).to(DefaultMapBlockRenderService.class);
|
||||
|
||||
bind(BlocksRecordService.class).to(BlocksRecordDatabaseService.class);
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
<logger name="org.jooq.Constants" level="WARN"></logger>
|
||||
<logger name="io.rudin.minetest.tileserver.TileRenderer" level="DEBUG"/>
|
||||
<logger name="io.rudin.minetest" level="DEBUG"/>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="console" />
|
||||
|
|
Loading…
Reference in New Issue