diff --git a/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockModel.java b/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockModel.java index ac14820c..3904ea0e 100644 --- a/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockModel.java +++ b/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockModel.java @@ -19,7 +19,8 @@ public abstract class HDBlockModel { for (int i = 0; i < bblk.getStateCount(); i++) { if (databits.isEmpty() || databits.get(i)) { DynmapBlockState bs = bblk.getState(i); - HDBlockModel prev = HDBlockModels.models_by_id_data.put(bs.globalStateIndex, this); + HDBlockModel prev = HDBlockModels.models_by_id_data[bs.globalStateIndex]; + HDBlockModels.models_by_id_data[bs.globalStateIndex] = this; if((prev != null) && (prev != this)) { prev.removed(bs); } diff --git a/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockModels.java b/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockModels.java index 09f2e326..3af90062 100644 --- a/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockModels.java +++ b/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockModels.java @@ -41,7 +41,7 @@ import org.dynmap.utils.Vector3D; */ public class HDBlockModels { private static int max_patches; - static HashMap models_by_id_data = new HashMap(); + static HDBlockModel[] models_by_id_data = new HDBlockModel[0]; static PatchDefinitionFactory pdf = new PatchDefinitionFactory(); static BitSet customModelsRequestingTileData = new BitSet(); // Index by globalStateIndex static BitSet changeIgnoredBlocks = new BitSet(); // Index by globalStateIndex @@ -53,17 +53,19 @@ public class HDBlockModels { /* Reset model if defined by different block set */ public static boolean resetIfNotBlockSet(DynmapBlockState blk, String blockset) { - HDBlockModel bm = models_by_id_data.get(blk.globalStateIndex); + int idx = blk.globalStateIndex; + HDBlockModel bm = (idx < models_by_id_data.length) ? models_by_id_data[idx] : null; if((bm != null) && (bm.getBlockSet().equals(blockset) == false)) { Debug.debug("Reset block model for " + blk + " from " + bm.getBlockSet() + " due to new def from " + blockset); - models_by_id_data.remove(blk.globalStateIndex); + models_by_id_data[idx] = null; return true; } return false; } /* Get texture count needed for model */ public static int getNeededTextureCount(DynmapBlockState blk) { - HDBlockModel bm = models_by_id_data.get(blk.globalStateIndex); + int idx = blk.globalStateIndex; + HDBlockModel bm = (idx < models_by_id_data.length) ? models_by_id_data[idx] : null; if(bm != null) { return bm.getTextureCount(); } @@ -88,18 +90,12 @@ public class HDBlockModels { private static void remapModel(String bn, String newbn) { DynmapBlockState frombs = DynmapBlockState.getBaseStateByName(bn); - DynmapBlockState tobs = DynmapBlockState.getBaseStateByName(bn); + DynmapBlockState tobs = DynmapBlockState.getBaseStateByName(newbn); int fcnt = frombs.getStateCount(); for (int bs = 0; bs < tobs.getStateCount(); bs++) { DynmapBlockState tb = tobs.getState(bs); - DynmapBlockState fs = tobs.getState(bs % fcnt); - HDBlockModel m = models_by_id_data.get(fs.globalStateIndex); - if (m != null) { - models_by_id_data.put(tb.globalStateIndex, m); - } - else { - models_by_id_data.remove(tb.globalStateIndex); - } + DynmapBlockState fs = frombs.getState(bs % fcnt); + models_by_id_data[tb.globalStateIndex] = models_by_id_data[fs.globalStateIndex]; customModelsRequestingTileData.set(tb.globalStateIndex, customModelsRequestingTileData.get(fs.globalStateIndex)); changeIgnoredBlocks.set(tb.globalStateIndex, changeIgnoredBlocks.get(fs.globalStateIndex)); } @@ -113,7 +109,7 @@ public class HDBlockModels { public static final String[] getTileEntityFieldsNeeded(DynmapBlockState blk) { int idx = blk.globalStateIndex; if(customModelsRequestingTileData.get(idx)) { - HDBlockModel mod = models_by_id_data.get(idx); + HDBlockModel mod = (idx < models_by_id_data.length) ? models_by_id_data[idx] : null; if(mod instanceof CustomBlockModel) { return ((CustomBlockModel)mod).render.getTileEntityFieldsNeeded(); } @@ -166,7 +162,7 @@ public class HDBlockModels { File datadir = core.getDataFolder(); max_patches = 6; /* Reset to default */ /* Reset models-by-ID-Data cache */ - models_by_id_data.clear(); + models_by_id_data = new HDBlockModel[DynmapBlockState.getGlobalIndexMax()]; /* Reset scaled models by scale cache */ scaled_models_by_scale.clear(); /* Reset change-ignored flags */ @@ -455,7 +451,7 @@ public class HDBlockModels { Log.severe("Invalid rotate ID: " + bs + " on line " + lineNum + " of file: " + fname); continue; } - HDBlockModel mod = models_by_id_data.get(bs.globalStateIndex); + HDBlockModel mod = models_by_id_data[bs.globalStateIndex]; if (modlist.isEmpty()) { } else if ((mod != null) && ((rot%90) == 0) && (mod instanceof HDBlockVolumetricModel)) { @@ -524,7 +520,7 @@ public class HDBlockModels { Log.severe("Invalid patchrotate ID: " + bs + " on line " + lineNum + "of file: " + fname); continue; } - HDBlockModel mod = models_by_id_data.get(bs.globalStateIndex); + HDBlockModel mod = models_by_id_data[bs.globalStateIndex]; if (pmodlist.isEmpty()) { } else if ((mod != null) && (mod instanceof HDBlockPatchModel)) { diff --git a/DynmapCore/src/main/java/org/dynmap/hdmap/HDScaledBlockModels.java b/DynmapCore/src/main/java/org/dynmap/hdmap/HDScaledBlockModels.java index 71c1423c..9779ee0a 100644 --- a/DynmapCore/src/main/java/org/dynmap/hdmap/HDScaledBlockModels.java +++ b/DynmapCore/src/main/java/org/dynmap/hdmap/HDScaledBlockModels.java @@ -21,9 +21,10 @@ public class HDScaledBlockModels { newcustom = new CustomBlockModel[DynmapBlockState.getGlobalIndexMax()]; custom = newcustom; } - for(Integer gidx : HDBlockModels.models_by_id_data.keySet()) { - HDBlockModel m = HDBlockModels.models_by_id_data.get(gidx); - + for(int gidx = 0; gidx < HDBlockModels.models_by_id_data.length; gidx++) { + HDBlockModel m = HDBlockModels.models_by_id_data[gidx]; + if(m == null) continue; + if(m instanceof HDBlockVolumetricModel) { HDBlockVolumetricModel vm = (HDBlockVolumetricModel)m; short[] smod = vm.getScaledMap(scale); @@ -58,37 +59,34 @@ public class HDScaledBlockModels { } public final short[] getScaledModel(DynmapBlockState blk) { - short[] m = null; - try { - m = modelvectors[blk.globalStateIndex]; - } catch (ArrayIndexOutOfBoundsException aioobx) { - short[][] newmodels = new short[blk.globalStateIndex+1][]; + int idx = blk.globalStateIndex; + if(idx >= modelvectors.length) { + short[][] newmodels = new short[idx + 1][]; System.arraycopy(modelvectors, 0, newmodels, 0, modelvectors.length); modelvectors = newmodels; + return null; } - return m; + return modelvectors[idx]; } public PatchDefinition[] getPatchModel(DynmapBlockState blk) { - PatchDefinition[] p = null; - try { - p = patches[blk.globalStateIndex]; - } catch (ArrayIndexOutOfBoundsException aioobx) { - PatchDefinition[][] newpatches = new PatchDefinition[blk.globalStateIndex+1][]; + int idx = blk.globalStateIndex; + if(idx >= patches.length) { + PatchDefinition[][] newpatches = new PatchDefinition[idx + 1][]; System.arraycopy(patches, 0, newpatches, 0, patches.length); patches = newpatches; + return null; } - return p; + return patches[idx]; } - + public CustomBlockModel getCustomBlockModel(DynmapBlockState blk) { - CustomBlockModel m = null; - try { - m = custom[blk.globalStateIndex]; - } catch (ArrayIndexOutOfBoundsException aioobx) { - CustomBlockModel[] newcustom = new CustomBlockModel[blk.globalStateIndex+1]; + int idx = blk.globalStateIndex; + if(idx >= custom.length) { + CustomBlockModel[] newcustom = new CustomBlockModel[idx + 1]; System.arraycopy(custom, 0, newcustom, 0, custom.length); custom = newcustom; - } - return m; + return null; + } + return custom[idx]; } } diff --git a/DynmapCore/src/main/java/org/dynmap/hdmap/ShadowHDLighting.java b/DynmapCore/src/main/java/org/dynmap/hdmap/ShadowHDLighting.java index 4302918b..369a5b28 100644 --- a/DynmapCore/src/main/java/org/dynmap/hdmap/ShadowHDLighting.java +++ b/DynmapCore/src/main/java/org/dynmap/hdmap/ShadowHDLighting.java @@ -45,208 +45,119 @@ public class ShadowHDLighting extends DefaultHDLighting { smooth = configuration.getBoolean("smooth-lighting", MapManager.mapman.getSmoothLighting()); } - private void applySmoothLighting(HDPerspectiveState ps, HDShaderState ss, Color incolor, Color[] outcolor, int[] shadowscale) { + private void applySmoothLighting(HDPerspectiveState ps, HDShaderState ss, Color incolor, Color[] outcolor, int[] shadowscale) { int[] xyz = ps.getSubblockCoord(); int scale = (int)ps.getScale(); - int mid = scale/2; + int mid = scale / 2; BlockStep s1, s2; int w1, w2; - /* Figure out which directions to look */ + /* Figure out which two neighbor directions to sample */ switch(ps.getLastBlockStep()) { case X_MINUS: case X_PLUS: - if(xyz[1] < mid) { - s1 = BlockStep.Y_MINUS; - w1 = mid - xyz[1]; - } - else { - s1 = BlockStep.Y_PLUS; - w1 = xyz[1] - mid; - } - if(xyz[2] < mid) { - s2 = BlockStep.Z_MINUS; - w2 = mid - xyz[2]; - } - else { - s2 = BlockStep.Z_PLUS; - w2 = xyz[2] - mid; - } + s1 = (xyz[1] < mid) ? BlockStep.Y_MINUS : BlockStep.Y_PLUS; + w1 = Math.abs(xyz[1] - mid); + s2 = (xyz[2] < mid) ? BlockStep.Z_MINUS : BlockStep.Z_PLUS; + w2 = Math.abs(xyz[2] - mid); break; case Z_MINUS: case Z_PLUS: - if(xyz[0] < mid) { - s1 = BlockStep.X_MINUS; - w1 = mid - xyz[0]; - } - else { - s1 = BlockStep.X_PLUS; - w1 = xyz[0] - mid; - } - if(xyz[1] < mid) { - s2 = BlockStep.Y_MINUS; - w2 = mid - xyz[1]; - } - else { - s2 = BlockStep.Y_PLUS; - w2 = xyz[1] - mid; - } + s1 = (xyz[0] < mid) ? BlockStep.X_MINUS : BlockStep.X_PLUS; + w1 = Math.abs(xyz[0] - mid); + s2 = (xyz[1] < mid) ? BlockStep.Y_MINUS : BlockStep.Y_PLUS; + w2 = Math.abs(xyz[1] - mid); break; default: - if(xyz[0] < mid) { - s1 = BlockStep.X_MINUS; - w1 = mid - xyz[0]; - } - else { - s1 = BlockStep.X_PLUS; - w1 = xyz[0] - mid; - } - if(xyz[2] < mid) { - s2 = BlockStep.Z_MINUS; - w2 = mid - xyz[2]; - } - else { - s2 = BlockStep.Z_PLUS; - w2 = xyz[2] - mid; - } + s1 = (xyz[0] < mid) ? BlockStep.X_MINUS : BlockStep.X_PLUS; + w1 = Math.abs(xyz[0] - mid); + s2 = (xyz[2] < mid) ? BlockStep.Z_MINUS : BlockStep.Z_PLUS; + w2 = Math.abs(xyz[2] - mid); break; } - /* Now get the 3 needed light levels */ - LightLevels skyemit0 = ps.getCachedLightLevels(0); - ps.getLightLevels(skyemit0); - LightLevels skyemit1 = ps.getCachedLightLevels(1); - ps.getLightLevelsAtStep(s1, skyemit1); - LightLevels skyemit2 = ps.getCachedLightLevels(2); - ps.getLightLevelsAtStep(s2, skyemit2); + /* Fetch the 3 needed light levels (once, shared by both night and day passes) */ + LightLevels ll0 = ps.getCachedLightLevels(0); + ps.getLightLevels(ll0); + LightLevels ll1 = ps.getCachedLightLevels(1); + ps.getLightLevelsAtStep(s1, ll1); + LightLevels ll2 = ps.getCachedLightLevels(2); + ps.getLightLevelsAtStep(s2, ll2); - /* Get light levels */ - int ll0 = getLightLevel(skyemit0, true); - int ll1 = getLightLevel(skyemit1, true); - int weight = 0; - if(ll1 < ll0) - weight -= w1; - else if(ll1 > ll0) - weight += w1; - int ll2 = getLightLevel(skyemit2, true); - if(ll2 < ll0) - weight -= w2; - else if(ll2 > ll0) - weight += w2; - outcolor[0].setColor(incolor); - int cscale = 256; - if(weight == 0) { - cscale = shadowscale[ll0]; - } - else if(weight < 0) { /* If negative, interpolate down */ - weight = -weight; - if(ll0 > 0) { - cscale = (shadowscale[ll0] * (scale-weight) + shadowscale[ll0-1] * weight)/scale; - } - else { - cscale = shadowscale[ll0]; - } - } - else { - if(ll0 < 15) { - cscale = (shadowscale[ll0] * (scale-weight) + shadowscale[ll0+1] * weight)/scale; - } - else { - cscale = shadowscale[ll0]; - } - } - if(cscale < 256) { - outcolor[0].scaleRGB(cscale); - } + /* Night (ambient) pass */ + applySmoothedLightToColor(outcolor[0], incolor, ll0, ll1, ll2, true, w1, w2, scale, shadowscale); + /* Day pass (only when night/day rendering is active) */ if(outcolor.length > 1) { - ll0 = getLightLevel(skyemit0, false); - ll1 = getLightLevel(skyemit1, false); - weight = 0; - if(ll1 < ll0) - weight -= w1; - else if(ll1 > ll0) - weight += w1; - ll2 = getLightLevel(skyemit2, false); - if(ll2 < ll0) - weight -= w2; - else if(ll2 > ll0) - weight += w2; - outcolor[1].setColor(incolor); - cscale = 256; - if(weight == 0) { - cscale = shadowscale[ll0]; - } - else if(weight < 0) { /* If negative, interpolate down */ - weight = -weight; - if(ll0 > 0) { - cscale = (shadowscale[ll0] * (scale-weight) + shadowscale[ll0-1] * weight)/scale; - } - else { - cscale = shadowscale[ll0]; - } - } - else { - if(ll0 < 15) { - cscale = (shadowscale[ll0] * (scale-weight) + shadowscale[ll0+1] * weight)/scale; - } - else { - cscale = shadowscale[ll0]; - } - } - if(cscale < 256) { - outcolor[1].scaleRGB(cscale); - } + applySmoothedLightToColor(outcolor[1], incolor, ll0, ll1, ll2, false, w1, w2, scale, shadowscale); } } - + + /** Apply smooth lighting to a single output color for one pass (ambient or day). */ + private void applySmoothedLightToColor(Color out, Color incolor, + LightLevels ll0, LightLevels ll1, LightLevels ll2, + boolean useambient, int w1, int w2, int scale, int[] shadowscale) { + int lv0 = getLightLevel(ll0, useambient); + int lv1 = getLightLevel(ll1, useambient); + int weight = 0; + if(lv1 < lv0) weight -= w1; + else if(lv1 > lv0) weight += w1; + int lv2 = getLightLevel(ll2, useambient); + if(lv2 < lv0) weight -= w2; + else if(lv2 > lv0) weight += w2; + out.setColor(incolor); + int cscale = computeSmoothedCscale(lv0, weight, scale, shadowscale); + if(cscale < 256) { + out.scaleRGB(cscale); + } + } + + /** Interpolate the shadow scale for a light level, blending toward the adjacent level by weight/scale. */ + private int computeSmoothedCscale(int ll0, int weight, int scale, int[] shadowscale) { + if(weight == 0) { + return shadowscale[ll0]; + } + if(weight < 0) { + weight = -weight; + return (ll0 > 0) + ? (shadowscale[ll0] * (scale - weight) + shadowscale[ll0 - 1] * weight) / scale + : shadowscale[ll0]; + } + return (ll0 < 15) + ? (shadowscale[ll0] * (scale - weight) + shadowscale[ll0 + 1] * weight) / scale + : shadowscale[ll0]; + } + private final int getLightLevel(final LightLevels ll, boolean useambient) { - int lightlevel; - /* If ambient light, adjust base lighting for it */ - if(useambient) - lightlevel = lightscale[ll.sky]; - else - lightlevel = ll.sky; - /* If we're below max, see if emitted light helps */ + int lightlevel = useambient ? lightscale[ll.sky] : ll.sky; if(lightlevel < 15) { - lightlevel = Math.max(ll.emitted, lightlevel); + lightlevel = Math.max(ll.emitted, lightlevel); } return lightlevel; } - + /* Apply lighting to given pixel colors (1 outcolor if normal, 2 if night/day) */ - public void applyLighting(HDPerspectiveState ps, HDShaderState ss, Color incolor, Color[] outcolor) { - int[] shadowscale = null; - if (smooth && ps.getShade()) { - shadowscale = ss.getLightingTable(); - if (shadowscale == null) { - shadowscale = defLightingTable; - } + public void applyLighting(HDPerspectiveState ps, HDShaderState ss, Color incolor, Color[] outcolor) { + int[] shadowscale = ss.getLightingTable(); + if(shadowscale == null) { + shadowscale = defLightingTable; + } + if(smooth && ps.getShade()) { applySmoothLighting(ps, ss, incolor, outcolor, shadowscale); checkGrayscale(outcolor); return; } - LightLevels ll = null; - int lightlevel = 15, lightlevel_day = 15; - /* If processing for shadows, use sky light level as base lighting */ - if(defLightingTable != null) { - shadowscale = ss.getLightingTable(); - if (shadowscale == null) { - shadowscale = defLightingTable; - } - ll = ps.getCachedLightLevels(0); - ps.getLightLevels(ll); - lightlevel = lightlevel_day = ll.sky; - } - /* If ambient light, adjust base lighting for it */ - lightlevel = lightscale[lightlevel]; - /* If we're below max, see if emitted light helps */ + /* Non-smooth: fetch light levels and apply flat shadow */ + LightLevels ll = ps.getCachedLightLevels(0); + ps.getLightLevels(ll); + int lightlevel = lightscale[ll.sky]; // apply ambient scale immediately + int lightlevel_day = ll.sky; if((lightlevel < 15) || (lightlevel_day < 15)) { int emitted = ll.emitted; - lightlevel = Math.max(emitted, lightlevel); - lightlevel_day = Math.max(emitted, lightlevel_day); + lightlevel = Math.max(emitted, lightlevel); + lightlevel_day = Math.max(emitted, lightlevel_day); } - /* Figure out our color, with lighting if needed */ outcolor[0].setColor(incolor); if(lightlevel < 15) { - shadowColor(outcolor[0], lightlevel, shadowscale); + int s = shadowscale[lightlevel]; + if(s < 256) outcolor[0].scaleRGB(s); } if(outcolor.length > 1) { if(lightlevel_day == lightlevel) { @@ -255,19 +166,14 @@ public class ShadowHDLighting extends DefaultHDLighting { else { outcolor[1].setColor(incolor); if(lightlevel_day < 15) { - shadowColor(outcolor[1], lightlevel_day, shadowscale); + int s = shadowscale[lightlevel_day]; + if(s < 256) outcolor[1].scaleRGB(s); } } } checkGrayscale(outcolor); } - private final void shadowColor(Color c, int lightlevel, int[] shadowscale) { - int scale = shadowscale[lightlevel]; - if(scale < 256) - c.scaleRGB(scale); - } - /* Test if night/day is enabled for this renderer */ public boolean isNightAndDayEnabled() { return night_and_day; }