Add adaptive zoomout levels for HDMaps, change zoomout processing to handle it properly

This commit is contained in:
Mike Primm 2011-07-09 17:01:40 -05:00
parent 898f4a6740
commit 02329673b2
6 changed files with 67 additions and 21 deletions

View File

@ -41,7 +41,8 @@ public class DynmapWorld {
private int extrazoomoutlevels; /* Number of additional zoom out levels to generate */ private int extrazoomoutlevels; /* Number of additional zoom out levels to generate */
public File worldtilepath; public File worldtilepath;
private Object lock = new Object(); private Object lock = new Object();
private HashSet<String> zoomoutupdates[]; @SuppressWarnings("unchecked")
private HashSet<String> zoomoutupdates[] = new HashSet[0];
private boolean checkts = true; /* Check timestamps on first run with new configuration */ private boolean checkts = true; /* Check timestamps on first run with new configuration */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -59,15 +60,25 @@ public class DynmapWorld {
} }
private void enqueueZoomOutUpdate(File f, int level) { private void enqueueZoomOutUpdate(File f, int level) {
if(level >= extrazoomoutlevels)
return;
synchronized(lock) { synchronized(lock) {
if(level >= zoomoutupdates.length) {
@SuppressWarnings("unchecked")
HashSet<String> new_zoomout[] = new HashSet[level+1];
System.arraycopy(zoomoutupdates, 0, new_zoomout, 0, zoomoutupdates.length);
for(int i = 0; i < new_zoomout.length; i++) {
if(i < zoomoutupdates.length)
new_zoomout[i] = zoomoutupdates[i];
else
new_zoomout[i] = new HashSet<String>();
}
zoomoutupdates = new_zoomout;
}
zoomoutupdates[level].add(f.getPath()); zoomoutupdates[level].add(f.getPath());
} }
} }
private boolean popQueuedUpdate(File f, int level) { private boolean popQueuedUpdate(File f, int level) {
if(level >= extrazoomoutlevels) if(level >= zoomoutupdates.length)
return false; return false;
synchronized(lock) { synchronized(lock) {
return zoomoutupdates[level].remove(f.getPath()); return zoomoutupdates[level].remove(f.getPath());
@ -97,8 +108,15 @@ public class DynmapWorld {
} }
public void freshenZoomOutFiles() { public void freshenZoomOutFiles() {
for(int i = 0; i < extrazoomoutlevels; i++) { boolean done = false;
freshenZoomOutFilesByLevel(i); int last_done = 0;
for(int i = 0; (!done); i++) {
done = freshenZoomOutFilesByLevel(i);
last_done = i;
}
/* Purge updates for levels above what any map needs */
for(int i = last_done; i < zoomoutupdates.length; i++) {
zoomoutupdates[i].clear();
} }
checkts = false; /* Just handle queued updates after first scan */ checkts = false; /* Just handle queued updates after first scan */
} }
@ -114,20 +132,20 @@ public class DynmapWorld {
String fnprefix; String fnprefix;
String zfnprefix; String zfnprefix;
int bigworldshift; int bigworldshift;
boolean isbigworld; boolean isbigmap;
} }
public void freshenZoomOutFilesByLevel(int zoomlevel) { public boolean freshenZoomOutFilesByLevel(int zoomlevel) {
int cnt = 0; int cnt = 0;
Debug.debug("freshenZoomOutFiles(" + world.getName() + "," + zoomlevel + ")"); Debug.debug("freshenZoomOutFiles(" + world.getName() + "," + zoomlevel + ")");
if(worldtilepath.exists() == false) /* Quit if not found */ if(worldtilepath.exists() == false) /* Quit if not found */
return; return true;
HashMap<String, PrefixData> maptab = buildPrefixData(zoomlevel); HashMap<String, PrefixData> maptab = buildPrefixData(zoomlevel);
DirFilter df = new DirFilter(); DirFilter df = new DirFilter();
for(String pfx : maptab.keySet()) { /* Walk through prefixes */ for(String pfx : maptab.keySet()) { /* Walk through prefixes */
PrefixData pd = maptab.get(pfx); PrefixData pd = maptab.get(pfx);
if(pd.isbigworld) { /* If big world, next directories are map name specific */ if(pd.isbigmap) { /* If big world, next directories are map name specific */
File dname = new File(worldtilepath, pfx); File dname = new File(worldtilepath, pfx);
/* Now, go through subdirectories under this one, and process them */ /* Now, go through subdirectories under this one, and process them */
String[] subdir = dname.list(df); String[] subdir = dname.list(df);
@ -142,12 +160,17 @@ public class DynmapWorld {
} }
} }
Debug.debug("freshenZoomOutFiles(" + world.getName() + "," + zoomlevel + ") - done (" + cnt + " updated files)"); Debug.debug("freshenZoomOutFiles(" + world.getName() + "," + zoomlevel + ") - done (" + cnt + " updated files)");
/* Return true when we have none left at the level */
return (maptab.size() == 0);
} }
private HashMap<String, PrefixData> buildPrefixData(int zoomlevel) { private HashMap<String, PrefixData> buildPrefixData(int zoomlevel) {
HashMap<String, PrefixData> maptab = new HashMap<String, PrefixData>(); HashMap<String, PrefixData> maptab = new HashMap<String, PrefixData>();
/* Build table of file prefixes and step sizes */ /* Build table of file prefixes and step sizes */
for(MapType mt : maps) { for(MapType mt : maps) {
/* If level is above top needed for this map, skip */
if(zoomlevel > (this.extrazoomoutlevels + mt.getMapZoomOutLevels()))
continue;
List<String> pfx = mt.baseZoomFilePrefixes(); List<String> pfx = mt.baseZoomFilePrefixes();
int stepsize = mt.baseZoomFileStepSize(); int stepsize = mt.baseZoomFileStepSize();
int bigworldshift = mt.getBigWorldShift(); int bigworldshift = mt.getBigWorldShift();
@ -175,10 +198,10 @@ public class DynmapWorld {
pd.stepseq = stepseq; pd.stepseq = stepseq;
pd.baseprefix = p; pd.baseprefix = p;
pd.zoomlevel = zoomlevel; pd.zoomlevel = zoomlevel;
pd.zoomprefix = "zzzzzzzzzzzz".substring(0, zoomlevel); pd.zoomprefix = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz".substring(0, zoomlevel);
pd.bigworldshift = bigworldshift; pd.bigworldshift = bigworldshift;
pd.isbigworld = mt.isBigWorldMap(this); pd.isbigmap = mt.isBigWorldMap(this);
if(pd.isbigworld) { if(pd.isbigmap) {
if(zoomlevel > 0) { if(zoomlevel > 0) {
pd.zoomprefix += "_"; pd.zoomprefix += "_";
pd.zfnprefix = "z" + pd.zoomprefix; pd.zfnprefix = "z" + pd.zoomprefix;
@ -206,7 +229,7 @@ public class DynmapWorld {
} }
private String makeFilePath(PrefixData pd, int x, int y, boolean zoomed) { private String makeFilePath(PrefixData pd, int x, int y, boolean zoomed) {
if(pd.isbigworld) if(pd.isbigmap)
return pd.baseprefix + "/" + (x >> pd.bigworldshift) + "_" + (y >> pd.bigworldshift) + "/" + (zoomed?pd.zfnprefix:pd.fnprefix) + x + "_" + y + ".png"; return pd.baseprefix + "/" + (x >> pd.bigworldshift) + "_" + (y >> pd.bigworldshift) + "/" + (zoomed?pd.zfnprefix:pd.fnprefix) + x + "_" + y + ".png";
else else
return (zoomed?pd.zfnprefix:pd.fnprefix) + "_" + x + "_" + y + ".png"; return (zoomed?pd.zfnprefix:pd.fnprefix) + "_" + x + "_" + y + ".png";

View File

@ -34,7 +34,8 @@ public abstract class MapType {
public abstract int getBigWorldShift(); public abstract int getBigWorldShift();
/* Returns true if big world file structure is in effect for this map */ /* Returns true if big world file structure is in effect for this map */
public abstract boolean isBigWorldMap(DynmapWorld w); public abstract boolean isBigWorldMap(DynmapWorld w);
/* Return number of zoom levels needed by this map (before extra levels from extrazoomout) */
public int getMapZoomOutLevels() { return 0; }
/** /**
* Step sequence for creating zoomed file: first index is top-left, second top-right, third bottom-left, forth bottom-right * Step sequence for creating zoomed file: first index is top-left, second top-right, third bottom-left, forth bottom-right
* Values correspond to tile X,Y (0), X+step,Y (1), X,Y+step (2), X+step,Y+step (3) * Values correspond to tile X,Y (0), X+step,Y (1), X,Y+step (2), X+step,Y+step (3)

View File

@ -24,6 +24,7 @@ public class HDMap extends MapType {
private HDShader shader; private HDShader shader;
private HDLighting lighting; private HDLighting lighting;
private ConfigurationNode configuration; private ConfigurationNode configuration;
private int mapzoomout;
public HDMap(ConfigurationNode configuration) { public HDMap(ConfigurationNode configuration) {
name = configuration.getString("name", null); name = configuration.getString("name", null);
@ -54,6 +55,14 @@ public class HDMap extends MapType {
} }
prefix = configuration.getString("prefix", name); prefix = configuration.getString("prefix", name);
this.configuration = configuration; this.configuration = configuration;
/* Compute extra zoom outs needed for this map */
double scale = perspective.getScale();
mapzoomout = 0;
while(scale >= 1.0) {
mapzoomout++;
scale = scale / 2.0;
}
} }
public HDShader getShader() { return shader; } public HDShader getShader() { return shader; }
@ -107,6 +116,11 @@ public class HDMap extends MapType {
@Override @Override
public boolean isBigWorldMap(DynmapWorld w) { return true; } /* We always use it on these maps */ public boolean isBigWorldMap(DynmapWorld w) { return true; } /* We always use it on these maps */
/* Return number of zoom levels needed by this map (before extra levels from extrazoomout) */
public int getMapZoomOutLevels() {
return mapzoomout;
}
@Override @Override
public String getName() { public String getName() {
return name; return name;
@ -129,6 +143,7 @@ public class HDMap extends MapType {
s(o, "backgroundday", c.getString("backgroundday")); s(o, "backgroundday", c.getString("backgroundday"));
s(o, "backgroundnight", c.getString("backgroundnight")); s(o, "backgroundnight", c.getString("backgroundnight"));
s(o, "bigmap", true); s(o, "bigmap", true);
s(o, "mapzoomout", (world.getExtraZoomOutLevels()+mapzoomout));
perspective.addClientConfiguration(o); perspective.addClientConfiguration(o);
shader.addClientConfiguration(o); shader.addClientConfiguration(o);
lighting.addClientConfiguration(o); lighting.addClientConfiguration(o);

View File

@ -25,5 +25,7 @@ public interface HDPerspective {
public boolean isRawBiomeDataNeeded(); public boolean isRawBiomeDataNeeded();
public boolean isBlockTypeDataNeeded(); public boolean isBlockTypeDataNeeded();
double getScale();
public void addClientConfiguration(JSONObject mapObject); public void addClientConfiguration(JSONObject mapObject);
} }

View File

@ -662,6 +662,10 @@ public class IsoHDPerspective implements HDPerspective {
return true; return true;
} }
public double getScale() {
return scale;
}
@Override @Override
public String getName() { public String getName() {
return name; return name;

View File

@ -19,7 +19,7 @@ HDMapType.prototype = $.extend(new DynMapType(), {
projection: new HDProjection(), projection: new HDProjection(),
tileSize: new google.maps.Size(128.0, 128.0), tileSize: new google.maps.Size(128.0, 128.0),
minZoom: 0, minZoom: 0,
maxZoom: 3, maxZoom: 2,
prefix: null, prefix: null,
getTile: function(coord, zoom, doc) { getTile: function(coord, zoom, doc) {
var tileSize = 128; var tileSize = 128;
@ -27,13 +27,14 @@ HDMapType.prototype = $.extend(new DynMapType(), {
var tileName; var tileName;
var dnprefix = ''; var dnprefix = '';
if(this.dynmap.map.mapTypes[this.dynmap.map.mapTypeId].nightandday && this.dynmap.serverday) var map = this.dynmap.map.mapTypes[this.dynmap.map.mapTypeId];
if(map.nightandday && this.dynmap.serverday)
dnprefix = '_day'; dnprefix = '_day';
var extrazoom = this.dynmap.world.extrazoomout; var extrazoom = map.mapzoomout;
if(zoom < extrazoom) { if(zoom < extrazoom) {
var scale = 1 << (extrazoom-zoom); var scale = 1 << (extrazoom-zoom);
var zprefix = "zzzzzzzzzzzz".substring(0, extrazoom-zoom); var zprefix = "zzzzzzzzzzzzzzzzzzzzzz".substring(0, extrazoom-zoom);
tileName = this.prefix + dnprefix + '/' + ((scale*coord.x) >> 5) + '_' + ((-scale*coord.y) >> 5) + tileName = this.prefix + dnprefix + '/' + ((scale*coord.x) >> 5) + '_' + ((-scale*coord.y) >> 5) +
'/' + zprefix + "_" + (scale*coord.x) + '_' + (-scale*coord.y) + '.png'; '/' + zprefix + "_" + (scale*coord.x) + '_' + (-scale*coord.y) + '.png';
imgSize = 128; imgSize = 128;
@ -66,9 +67,9 @@ HDMapType.prototype = $.extend(new DynMapType(), {
}, },
updateTileSize: function(zoom) { updateTileSize: function(zoom) {
var size; var size;
var extrazoom = this.dynmap.world.extrazoomout; var extrazoom = this.mapzoomout;
this.projection.extrazoom = extrazoom; this.projection.extrazoom = extrazoom;
this.maxZoom = 3 + extrazoom; this.maxZoom = 2 + extrazoom;
if (zoom <= extrazoom) { if (zoom <= extrazoom) {
size = 128; size = 128;
} }