From 02329673b2f991a4241e7d6f923799afbf404d4e Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Sat, 9 Jul 2011 17:01:40 -0500 Subject: [PATCH] Add adaptive zoomout levels for HDMaps, change zoomout processing to handle it properly --- src/main/java/org/dynmap/DynmapWorld.java | 51 ++++++++++++++----- src/main/java/org/dynmap/MapType.java | 3 +- src/main/java/org/dynmap/hdmap/HDMap.java | 15 ++++++ .../java/org/dynmap/hdmap/HDPerspective.java | 2 + .../org/dynmap/hdmap/IsoHDPerspective.java | 4 ++ web/js/hdmap.js | 13 ++--- 6 files changed, 67 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/dynmap/DynmapWorld.java b/src/main/java/org/dynmap/DynmapWorld.java index c815b239..c21dca2c 100644 --- a/src/main/java/org/dynmap/DynmapWorld.java +++ b/src/main/java/org/dynmap/DynmapWorld.java @@ -41,7 +41,8 @@ public class DynmapWorld { private int extrazoomoutlevels; /* Number of additional zoom out levels to generate */ public File worldtilepath; private Object lock = new Object(); - private HashSet zoomoutupdates[]; + @SuppressWarnings("unchecked") + private HashSet zoomoutupdates[] = new HashSet[0]; private boolean checkts = true; /* Check timestamps on first run with new configuration */ @SuppressWarnings("unchecked") @@ -59,15 +60,25 @@ public class DynmapWorld { } private void enqueueZoomOutUpdate(File f, int level) { - if(level >= extrazoomoutlevels) - return; synchronized(lock) { + if(level >= zoomoutupdates.length) { + @SuppressWarnings("unchecked") + HashSet 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(); + } + zoomoutupdates = new_zoomout; + } zoomoutupdates[level].add(f.getPath()); } } private boolean popQueuedUpdate(File f, int level) { - if(level >= extrazoomoutlevels) + if(level >= zoomoutupdates.length) return false; synchronized(lock) { return zoomoutupdates[level].remove(f.getPath()); @@ -97,8 +108,15 @@ public class DynmapWorld { } public void freshenZoomOutFiles() { - for(int i = 0; i < extrazoomoutlevels; i++) { - freshenZoomOutFilesByLevel(i); + boolean done = false; + 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 */ } @@ -114,20 +132,20 @@ public class DynmapWorld { String fnprefix; String zfnprefix; int bigworldshift; - boolean isbigworld; + boolean isbigmap; } - public void freshenZoomOutFilesByLevel(int zoomlevel) { + public boolean freshenZoomOutFilesByLevel(int zoomlevel) { int cnt = 0; Debug.debug("freshenZoomOutFiles(" + world.getName() + "," + zoomlevel + ")"); if(worldtilepath.exists() == false) /* Quit if not found */ - return; + return true; HashMap maptab = buildPrefixData(zoomlevel); DirFilter df = new DirFilter(); for(String pfx : maptab.keySet()) { /* Walk through prefixes */ 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); /* Now, go through subdirectories under this one, and process them */ String[] subdir = dname.list(df); @@ -142,12 +160,17 @@ public class DynmapWorld { } } 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 buildPrefixData(int zoomlevel) { HashMap maptab = new HashMap(); /* Build table of file prefixes and step sizes */ for(MapType mt : maps) { + /* If level is above top needed for this map, skip */ + if(zoomlevel > (this.extrazoomoutlevels + mt.getMapZoomOutLevels())) + continue; List pfx = mt.baseZoomFilePrefixes(); int stepsize = mt.baseZoomFileStepSize(); int bigworldshift = mt.getBigWorldShift(); @@ -175,10 +198,10 @@ public class DynmapWorld { pd.stepseq = stepseq; pd.baseprefix = p; pd.zoomlevel = zoomlevel; - pd.zoomprefix = "zzzzzzzzzzzz".substring(0, zoomlevel); + pd.zoomprefix = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz".substring(0, zoomlevel); pd.bigworldshift = bigworldshift; - pd.isbigworld = mt.isBigWorldMap(this); - if(pd.isbigworld) { + pd.isbigmap = mt.isBigWorldMap(this); + if(pd.isbigmap) { if(zoomlevel > 0) { 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) { - if(pd.isbigworld) + if(pd.isbigmap) return pd.baseprefix + "/" + (x >> pd.bigworldshift) + "_" + (y >> pd.bigworldshift) + "/" + (zoomed?pd.zfnprefix:pd.fnprefix) + x + "_" + y + ".png"; else return (zoomed?pd.zfnprefix:pd.fnprefix) + "_" + x + "_" + y + ".png"; diff --git a/src/main/java/org/dynmap/MapType.java b/src/main/java/org/dynmap/MapType.java index 55e58cfc..723dc5eb 100644 --- a/src/main/java/org/dynmap/MapType.java +++ b/src/main/java/org/dynmap/MapType.java @@ -34,7 +34,8 @@ public abstract class MapType { public abstract int getBigWorldShift(); /* Returns true if big world file structure is in effect for this map */ 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 * Values correspond to tile X,Y (0), X+step,Y (1), X,Y+step (2), X+step,Y+step (3) diff --git a/src/main/java/org/dynmap/hdmap/HDMap.java b/src/main/java/org/dynmap/hdmap/HDMap.java index b1f8b330..8ecd015f 100644 --- a/src/main/java/org/dynmap/hdmap/HDMap.java +++ b/src/main/java/org/dynmap/hdmap/HDMap.java @@ -24,6 +24,7 @@ public class HDMap extends MapType { private HDShader shader; private HDLighting lighting; private ConfigurationNode configuration; + private int mapzoomout; public HDMap(ConfigurationNode configuration) { name = configuration.getString("name", null); @@ -54,6 +55,14 @@ public class HDMap extends MapType { } prefix = configuration.getString("prefix", name); 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; } @@ -107,6 +116,11 @@ public class HDMap extends MapType { @Override 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 public String getName() { return name; @@ -129,6 +143,7 @@ public class HDMap extends MapType { s(o, "backgroundday", c.getString("backgroundday")); s(o, "backgroundnight", c.getString("backgroundnight")); s(o, "bigmap", true); + s(o, "mapzoomout", (world.getExtraZoomOutLevels()+mapzoomout)); perspective.addClientConfiguration(o); shader.addClientConfiguration(o); lighting.addClientConfiguration(o); diff --git a/src/main/java/org/dynmap/hdmap/HDPerspective.java b/src/main/java/org/dynmap/hdmap/HDPerspective.java index 718acfcf..af8b1d92 100644 --- a/src/main/java/org/dynmap/hdmap/HDPerspective.java +++ b/src/main/java/org/dynmap/hdmap/HDPerspective.java @@ -24,6 +24,8 @@ public interface HDPerspective { public boolean isHightestBlockYDataNeeded(); public boolean isRawBiomeDataNeeded(); public boolean isBlockTypeDataNeeded(); + + double getScale(); public void addClientConfiguration(JSONObject mapObject); } diff --git a/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java b/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java index 4b766f50..7ac227ca 100644 --- a/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java +++ b/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java @@ -661,6 +661,10 @@ public class IsoHDPerspective implements HDPerspective { public boolean isBlockTypeDataNeeded() { return true; } + + public double getScale() { + return scale; + } @Override public String getName() { diff --git a/web/js/hdmap.js b/web/js/hdmap.js index 5a922fbf..2640daa9 100644 --- a/web/js/hdmap.js +++ b/web/js/hdmap.js @@ -19,7 +19,7 @@ HDMapType.prototype = $.extend(new DynMapType(), { projection: new HDProjection(), tileSize: new google.maps.Size(128.0, 128.0), minZoom: 0, - maxZoom: 3, + maxZoom: 2, prefix: null, getTile: function(coord, zoom, doc) { var tileSize = 128; @@ -27,13 +27,14 @@ HDMapType.prototype = $.extend(new DynMapType(), { var tileName; 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'; - var extrazoom = this.dynmap.world.extrazoomout; + var extrazoom = map.mapzoomout; if(zoom < extrazoom) { 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) + '/' + zprefix + "_" + (scale*coord.x) + '_' + (-scale*coord.y) + '.png'; imgSize = 128; @@ -66,9 +67,9 @@ HDMapType.prototype = $.extend(new DynMapType(), { }, updateTileSize: function(zoom) { var size; - var extrazoom = this.dynmap.world.extrazoomout; + var extrazoom = this.mapzoomout; this.projection.extrazoom = extrazoom; - this.maxZoom = 3 + extrazoom; + this.maxZoom = 2 + extrazoom; if (zoom <= extrazoom) { size = 128; }