diff --git a/shaders.txt b/shaders.txt index 0754d1d6..1ed6eb86 100644 --- a/shaders.txt +++ b/shaders.txt @@ -34,3 +34,8 @@ shaders: - class: org.dynmap.hdmap.CaveHDShader name: cave + + - class: org.dynmap.hdmap.TexturePackHDShader + name: stdtexture + texturepack: standard + \ No newline at end of file diff --git a/src/main/assembly/package.xml b/src/main/assembly/package.xml index 94ef0e8c..417ad924 100644 --- a/src/main/assembly/package.xml +++ b/src/main/assembly/package.xml @@ -34,6 +34,9 @@ configuration.txt.sample-hd models.txt texture.txt + + ${project.basedir}/texturepacks + /dynmap/texturepacks diff --git a/src/main/java/org/dynmap/Color.java b/src/main/java/org/dynmap/Color.java index 636d5267..8269c67c 100644 --- a/src/main/java/org/dynmap/Color.java +++ b/src/main/java/org/dynmap/Color.java @@ -55,4 +55,20 @@ public class Color { public final void setAlpha(int v) { val = (val & 0x00FFFFFF) | (v << 24); } + /** + * Scale each color component, based on the corresponding component + */ + public final void blendColor(Color c) { + blendColor(c.val); + } + /** + * Scale each color component, based on the corresponding component + */ + public final void blendColor(int argb) { + int nval = (((((val >> 24) & 0xFF) * ((argb >> 24) & 0xFF)) / 255) << 24); + nval = nval | (((((val >> 16) & 0xFF) * ((argb >> 16) & 0xFF)) / 255) << 16); + nval = nval | (((((val >> 8) & 0xFF) * ((argb >> 8) & 0xFF)) / 255) << 8); + nval = nval | (((val & 0xFF) * (argb & 0xFF)) / 255); + val = nval; + } } diff --git a/src/main/java/org/dynmap/DynmapPlugin.java b/src/main/java/org/dynmap/DynmapPlugin.java index 6e9a7fb5..c61f8ff5 100644 --- a/src/main/java/org/dynmap/DynmapPlugin.java +++ b/src/main/java/org/dynmap/DynmapPlugin.java @@ -35,6 +35,7 @@ import org.bukkit.plugin.java.JavaPlugin; import org.dynmap.debug.Debug; import org.dynmap.debug.Debugger; import org.dynmap.hdmap.HDBlockModels; +import org.dynmap.hdmap.TexturePack; import org.dynmap.permissions.NijikokunPermissions; import org.dynmap.permissions.OpPermissions; import org.dynmap.permissions.PermissionProvider; @@ -79,6 +80,9 @@ public class DynmapPlugin extends JavaPlugin { dataDirectory = this.getDataFolder(); /* Load block models */ HDBlockModels.loadModels(dataDirectory); + /* Load texture mappings */ + TexturePack.loadTextureMapping(dataDirectory); + org.bukkit.util.config.Configuration bukkitConfiguration = new org.bukkit.util.config.Configuration(new File(this.getDataFolder(), "configuration.txt")); bukkitConfiguration.load(); configuration = new ConfigurationNode(bukkitConfiguration); diff --git a/src/main/java/org/dynmap/hdmap/HDPerspective.java b/src/main/java/org/dynmap/hdmap/HDPerspective.java index af8b1d92..b6bbe31a 100644 --- a/src/main/java/org/dynmap/hdmap/HDPerspective.java +++ b/src/main/java/org/dynmap/hdmap/HDPerspective.java @@ -26,6 +26,7 @@ public interface HDPerspective { public boolean isBlockTypeDataNeeded(); double getScale(); + int getModelScale(); public void addClientConfiguration(JSONObject mapObject); } diff --git a/src/main/java/org/dynmap/hdmap/HDPerspectiveState.java b/src/main/java/org/dynmap/hdmap/HDPerspectiveState.java index 4903766c..6791a4fd 100644 --- a/src/main/java/org/dynmap/hdmap/HDPerspectiveState.java +++ b/src/main/java/org/dynmap/hdmap/HDPerspectiveState.java @@ -56,4 +56,8 @@ public interface HDPerspectiveState { * Return submodel alpha value (-1 if no submodel rendered) */ int getSubmodelAlpha(); + /** + * Return subblock coordinates of current ray position + */ + void getSubblockCoord(int[] xyz); } diff --git a/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java b/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java index 012030fa..83127146 100644 --- a/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java +++ b/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java @@ -88,6 +88,7 @@ public class IsoHDPerspective implements HDPerspective { double t_next_y, t_next_x, t_next_z; boolean nonairhit; int subalpha; + double mt; /** * Get sky light level - only available if shader requested it */ @@ -363,7 +364,7 @@ public class IsoHDPerspective implements HDPerspective { private boolean raytraceSubblock(short[] model) { int mx = 0, my = 0, mz = 0; double xx, yy, zz; - double mt = t + 0.0000001; + mt = t + 0.0000001; xx = top.x + mt *(bottom.x - top.x); yy = top.y + mt *(bottom.y - top.y); zz = top.z + mt *(bottom.z - top.z); @@ -453,7 +454,17 @@ public class IsoHDPerspective implements HDPerspective { } return true; } - + public void getSubblockCoord(int[] v) { + double tt = t + 0.000001; + if(subalpha >= 0) + tt = mt; + double xx = top.x + tt * (bottom.x - top.x); + double yy = top.y + tt * (bottom.y - top.y); + double zz = top.z + tt * (bottom.z - top.z); + v[0] = (int)((xx - Math.floor(xx)) * modscale); + v[1] = (int)((yy - Math.floor(yy)) * modscale); + v[2] = (int)((zz - Math.floor(zz)) * modscale); + } } public IsoHDPerspective(ConfigurationNode configuration) { @@ -856,6 +867,10 @@ public class IsoHDPerspective implements HDPerspective { return scale; } + public int getModelScale() { + return modscale; + } + @Override public String getName() { return name; diff --git a/src/main/java/org/dynmap/hdmap/TexturePack.java b/src/main/java/org/dynmap/hdmap/TexturePack.java index a114dfd4..3c866124 100644 --- a/src/main/java/org/dynmap/hdmap/TexturePack.java +++ b/src/main/java/org/dynmap/hdmap/TexturePack.java @@ -22,16 +22,17 @@ import org.dynmap.DynmapPlugin; import org.dynmap.Log; import org.dynmap.hdmap.HDPerspectiveState.BlockStep; import org.dynmap.kzedmap.KzedMap; +import org.dynmap.utils.MapIterator; /** * Loader and processor class for minecraft texture packs * Texture packs are found in dynmap/texturepacks directory, and either are either ZIP files * or are directories whose content matches the structure of a zipped texture pack: * ./terrain.png - main color data (required) - * misc/water.png - still water tile? (optional) - * misc/grasscolor.png - tone for grass color, biome sensitive (optional) - * misc/foliagecolor.png - tone for leaf color, biome sensitive (optional) - * misc/watercolor.png - tone for water color, biome sensitive (optional) + * misc/water.png - still water tile (required)) + * misc/grasscolor.png - tone for grass color, biome sensitive (required) + * misc/foliagecolor.png - tone for leaf color, biome sensitive (required) + * misc/watercolor.png - tone for water color, biome sensitive (required) * custom_lava_still.png - custom still lava animation (optional) * custom_lava_flowing.png - custom flowing lava animation (optional) * custom_water_still.png - custom still water animation (optional) @@ -45,17 +46,37 @@ public class TexturePack { private static final String TERRAIN_PNG = "terrain.png"; private static final String GRASSCOLOR_PNG = "misc/grasscolor.png"; private static final String FOLIAGECOLOR_PNG = "misc/foliagecolor.png"; + private static final String WATERCOLOR_PNG = "misc/watercolor.png"; private static final String WATER_PNG = "misc/water.png"; - - private int[] terrain_argb; + + /* Color modifier codes (x1000 for value in mapping code) */ + private static final short COLORMOD_GRASSTONED = 1; + private static final short COLORMOD_FOLIAGETONED = 2; + private static final short COLORMOD_WATERTONED = 3; + /* Special tile index values */ + private static final short BLOCKINDEX_BLANK = -1; + private static final short BLOCKINDEX_STATIONARYWATER = 257; + private static final short BLOCKINDEX_MOVINGWATER = 258; + private static final short BLOCKINDEX_STATIONARYLAVA = 259; + private static final short BLOCKINDEX_MOVINGLAVA = 260; + private static final int MAX_BLOCKINDEX = 260; + private static final int BLOCKTABLELEN = MAX_BLOCKINDEX+1; + + private int[][] terrain_argb; private int terrain_width, terrain_height; private int native_scale; private int[] grasscolor_argb; private int grasscolor_width, grasscolor_height; + private int trivial_grasscolor; private int[] foliagecolor_argb; private int foliagecolor_width, foliagecolor_height; + private int trivial_foliagecolor; + + private int[] watercolor_argb; + private int watercolor_width, watercolor_height; + private int trivial_watercolor; private int[] water_argb; private int water_width, water_height; @@ -70,7 +91,7 @@ public class TexturePack { private static HDTextureMap[] texmaps; private static void initializeTable() { - texmaps = new HDTextureMap[16*256]; + texmaps = new HDTextureMap[16*BLOCKTABLELEN]; HDTextureMap blank = new HDTextureMap(); for(int i = 0; i < texmaps.length; i++) texmaps[i] = blank; @@ -102,6 +123,10 @@ public class TexturePack { } } } + + public static HDTextureMap getMap(int blkid, int blkdata) { + return texmaps[(blkid<<4) + blkdata]; + } } /** Get or load texture pack */ public static TexturePack getTexturePack(String tpname) { @@ -136,25 +161,33 @@ public class TexturePack { is.close(); /* Try to find and load misc/grasscolor.png */ ze = zf.getEntry(GRASSCOLOR_PNG); - if(ze != null) { /* Found it, so load it */ - is = zf.getInputStream(ze); - loadGrassColorPNG(is); - is.close(); - } + if(ze == null) + throw new FileNotFoundException(); + is = zf.getInputStream(ze); + loadGrassColorPNG(is); + is.close(); /* Try to find and load misc/foliagecolor.png */ ze = zf.getEntry(FOLIAGECOLOR_PNG); - if(ze != null) { /* Found it, so load it */ - is = zf.getInputStream(ze); - loadFoliageColorPNG(is); - is.close(); - } + if(ze == null) + throw new FileNotFoundException(); + is = zf.getInputStream(ze); + loadFoliageColorPNG(is); + is.close(); + /* Try to find and load misc/watercolor.png */ + ze = zf.getEntry(WATERCOLOR_PNG); + if(ze == null) + throw new FileNotFoundException(); + is = zf.getInputStream(ze); + loadWaterColorPNG(is); + is.close(); /* Try to find and load misc/water.png */ ze = zf.getEntry(WATER_PNG); - if(ze != null) { /* Found it, so load it */ - is = zf.getInputStream(ze); - loadWaterPNG(is); - is.close(); - } + if(ze == null) + throw new FileNotFoundException(); + is = zf.getInputStream(ze); + loadWaterPNG(is); + is.close(); + zf.close(); return; } catch (IOException iox) { @@ -174,25 +207,24 @@ public class TexturePack { fis.close(); /* Check for misc/grasscolor.png */ f = new File(texturedir, tpname + "/" + GRASSCOLOR_PNG); - if(f.canRead()) { - fis = new FileInputStream(f); - loadGrassColorPNG(fis); - fis.close(); - } + fis = new FileInputStream(f); + loadGrassColorPNG(fis); + fis.close(); /* Check for misc/foliagecolor.png */ f = new File(texturedir, tpname + "/" + FOLIAGECOLOR_PNG); - if(f.canRead()) { - fis = new FileInputStream(f); - loadFoliageColorPNG(fis); - fis.close(); - } + fis = new FileInputStream(f); + loadFoliageColorPNG(fis); + fis.close(); + /* Check for misc/waterecolor.png */ + f = new File(texturedir, tpname + "/" + WATERCOLOR_PNG); + fis = new FileInputStream(f); + loadWaterColorPNG(fis); + fis.close(); /* Check for misc/water.png */ f = new File(texturedir, tpname + "/" + WATER_PNG); - if(f.canRead()) { - fis = new FileInputStream(f); - loadWaterPNG(fis); - fis.close(); - } + fis = new FileInputStream(f); + loadWaterPNG(fis); + fis.close(); } catch (IOException iox) { if(fis != null) { try { fis.close(); } catch (IOException io) {} @@ -202,7 +234,8 @@ public class TexturePack { } /* Copy texture pack */ private TexturePack(TexturePack tp) { - this.terrain_argb = tp.terrain_argb; + this.terrain_argb = new int[tp.terrain_argb.length][]; + System.arraycopy(tp.terrain_argb, 0, this.terrain_argb, 0, this.terrain_argb.length); this.terrain_width = tp.terrain_width; this.terrain_height = tp.terrain_height; this.native_scale = tp.native_scale; @@ -210,11 +243,18 @@ public class TexturePack { this.grasscolor_argb = tp.grasscolor_argb; this.grasscolor_height = tp.grasscolor_height; this.grasscolor_width = tp.grasscolor_width; + this.trivial_grasscolor = tp.trivial_grasscolor; + + this.watercolor_argb = tp.watercolor_argb; + this.watercolor_height = tp.watercolor_height; + this.watercolor_width = tp.watercolor_width; + this.trivial_watercolor = tp.trivial_watercolor; this.foliagecolor_argb = tp.foliagecolor_argb; this.foliagecolor_height = tp.foliagecolor_height; this.foliagecolor_width = tp.foliagecolor_width; - + this.trivial_foliagecolor = tp.trivial_foliagecolor; + this.water_argb = tp.water_argb; this.water_height = tp.water_height; this.water_width = tp.water_width; @@ -222,15 +262,23 @@ public class TexturePack { /* Load terrain.png */ private void loadTerrainPNG(InputStream is) throws IOException { + int i; /* Load image */ BufferedImage img = ImageIO.read(is); if(img == null) { throw new FileNotFoundException(); } terrain_width = img.getWidth(); terrain_height = img.getHeight(); - terrain_argb = new int[terrain_width * terrain_height]; - img.getRGB(0, 0, terrain_width, terrain_height, terrain_argb, 0, terrain_width); - img.flush(); native_scale = terrain_width / 16; + terrain_argb = new int[BLOCKTABLELEN][]; + for(i = 0; i < 256; i++) { + terrain_argb[i] = new int[native_scale*native_scale]; + img.getRGB((i & 0xF)*native_scale, (i>>4)*native_scale, native_scale, native_scale, terrain_argb[i], 0, native_scale); + } + int[] blank = new int[native_scale*native_scale]; + for(i = 256; i < BLOCKTABLELEN; i++) { + terrain_argb[i] = blank; + } + img.flush(); } /* Load misc/grasscolor.png */ @@ -242,7 +290,19 @@ public class TexturePack { grasscolor_height = img.getHeight(); grasscolor_argb = new int[grasscolor_width * grasscolor_height]; img.getRGB(0, 0, grasscolor_width, grasscolor_height, grasscolor_argb, 0, grasscolor_width); - img.flush(); + img.flush(); + /* Figure out trivial color */ + trivial_grasscolor = grasscolor_argb[grasscolor_height*grasscolor_width*3/4 + grasscolor_width/2]; + boolean same = true; + for(int j = 0; same && (j < grasscolor_height); j++) { + for(int i = 0; same && (i <= j); i++) { + if(grasscolor_argb[grasscolor_width*j+i] != trivial_grasscolor) + same = false; + } + } + /* All the same - no biome lookup needed */ + if(same) + grasscolor_argb = null; } /* Load misc/foliagecolor.png */ @@ -255,8 +315,44 @@ public class TexturePack { foliagecolor_argb = new int[foliagecolor_width * foliagecolor_height]; img.getRGB(0, 0, foliagecolor_width, foliagecolor_height, foliagecolor_argb, 0, foliagecolor_width); img.flush(); + /* Figure out trivial color */ + trivial_foliagecolor = foliagecolor_argb[foliagecolor_height*foliagecolor_width*3/4 + foliagecolor_width/2]; + boolean same = true; + for(int j = 0; same && (j < foliagecolor_height); j++) { + for(int i = 0; same && (i <= j); i++) { + if(foliagecolor_argb[foliagecolor_width*j+i] != trivial_foliagecolor) + same = false; + } + } + /* All the same - no biome lookup needed */ + if(same) + foliagecolor_argb = null; } - + + /* Load misc/watercolor.png */ + private void loadWaterColorPNG(InputStream is) throws IOException { + /* Load image */ + BufferedImage img = ImageIO.read(is); + if(img == null) { throw new FileNotFoundException(); } + watercolor_width = img.getWidth(); + watercolor_height = img.getHeight(); + watercolor_argb = new int[watercolor_width * watercolor_height]; + img.getRGB(0, 0, watercolor_width, watercolor_height, watercolor_argb, 0, watercolor_width); + img.flush(); + /* Figure out trivial color */ + trivial_watercolor = watercolor_argb[watercolor_height*watercolor_width*3/4 + watercolor_width/2]; + boolean same = true; + for(int j = 0; same && (j < watercolor_height); j++) { + for(int i = 0; same && (i <= j); i++) { + if(watercolor_argb[watercolor_width*j+i] != trivial_watercolor) + same = false; + } + } + /* All the same - no biome lookup needed */ + if(same) + watercolor_argb = null; + } + /* Load misc/water.png */ private void loadWaterPNG(InputStream is) throws IOException { /* Load image */ @@ -266,13 +362,16 @@ public class TexturePack { water_height = img.getHeight(); water_argb = new int[water_width * water_height]; img.getRGB(0, 0, water_width, water_height, water_argb, 0, water_width); - img.flush(); + img.flush(); + /* Now, patch in to block table */ + int new_water_argb[] = new int[native_scale*native_scale]; + scaleTerrainPNGSubImage(water_width, native_scale, water_argb, new_water_argb); + terrain_argb[BLOCKINDEX_STATIONARYWATER] = new_water_argb; + terrain_argb[BLOCKINDEX_MOVINGWATER] = new_water_argb; } - /* Get texture pack directory */ private static File getTexturePackDirectory() { -// return new File(DynmapPlugin.dataDirectory, "texturepacks"); - return new File("texturepacks"); + return new File(DynmapPlugin.dataDirectory, "texturepacks"); } /** @@ -289,7 +388,6 @@ public class TexturePack { stp.native_scale = scale; stp.terrain_height = 16*scale; stp.terrain_width = 16*scale; - stp.terrain_argb = new int[stp.terrain_height*stp.terrain_width]; scaleTerrainPNG(stp); } /* Remember it */ @@ -301,23 +399,25 @@ public class TexturePack { * @param tp */ private void scaleTerrainPNG(TexturePack tp) { + tp.terrain_argb = new int[256][]; /* Terrain.png is 16x16 array of images : process one at a time */ - for(int ty = 0; ty < 16; ty++) { - for(int tx = 0; tx < 16; tx++) { - int srcoff = ty*native_scale*terrain_width + tx*native_scale; - int destoff = ty*tp.native_scale*tp.terrain_width + tx*tp.native_scale; - scaleTerrainPNGSubImage(tp, srcoff, destoff); - } + for(int idx = 0; idx < 256; idx++) { + tp.terrain_argb[idx] = new int[tp.native_scale*tp.native_scale]; + scaleTerrainPNGSubImage(native_scale, tp.native_scale, terrain_argb[idx], tp.terrain_argb[idx]); } } - private void scaleTerrainPNGSubImage(TexturePack tp, int srcoff, int destoff) { - int nativeres = native_scale; - int res = tp.native_scale; + private static void scaleTerrainPNGSubImage(int srcscale, int destscale, int[] src_argb, int[] dest_argb) { + int nativeres = srcscale; + int res = destscale; Color c = new Color(); + /* Same size, so just copy */ + if(res == nativeres) { + System.arraycopy(src_argb, 0, dest_argb, 0, src_argb.length); + } /* If we're scaling larger source pixels into smaller pixels, each destination pixel * receives input from 1 or 2 source pixels on each axis */ - if(res > nativeres) { + else if(res > nativeres) { int weights[] = new int[res]; int offsets[] = new int[res]; /* LCM of resolutions is used as length of line (res * nativeres) @@ -352,7 +452,7 @@ public class TexturePack { int wy = (yy==0)?wgt_y:(nativeres-wgt_y); if(wy == 0) continue; /* Accumulate */ - c.setARGB(terrain_argb[srcoff + (ind_y+yy)*terrain_width + ind_x + xx]); + c.setARGB(src_argb[(ind_y+yy)*nativeres + ind_x + xx]); accum_red += c.getRed() * wx * wy; accum_green += c.getGreen() * wx * wy; accum_blue += c.getBlue() * wx * wy; @@ -362,7 +462,7 @@ public class TexturePack { /* Generate weighted compnents into color */ c.setRGBA(accum_red / (nativeres*nativeres), accum_green / (nativeres*nativeres), accum_blue / (nativeres*nativeres), accum_alpha / (nativeres*nativeres)); - tp.terrain_argb[destoff + (y*tp.terrain_width) + x] = c.getARGB(); + dest_argb[(y*res) + x] = c.getARGB(); } } } @@ -395,7 +495,7 @@ public class TexturePack { for(int x = 0; x < nativeres; x++) { int ind_x = offsets[x]; int wgt_x = weights[x]; - c.setARGB(terrain_argb[srcoff + (y*terrain_width) + x]); + c.setARGB(src_argb[(y*nativeres) + x]); for(int xx = 0; xx < 2; xx++) { int wx = (xx==0)?wgt_x:(res-wgt_x); if(wx == 0) continue; @@ -416,13 +516,19 @@ public class TexturePack { int off = (y*res) + x; c.setRGBA(accum_red[off]/(nativeres*nativeres), accum_green[off]/(nativeres*nativeres), accum_blue[off]/(nativeres*nativeres), accum_alpha[off]/(nativeres*nativeres)); - tp.terrain_argb[destoff + y*tp.terrain_width + x] = c.getARGB(); + dest_argb[y*res + x] = c.getARGB(); } } } } public void saveTerrainPNG(File f) throws IOException { - BufferedImage img = KzedMap.createBufferedImage(terrain_argb, terrain_width, terrain_height); + int[] outbuf = new int[256*native_scale*native_scale]; + for(int i = 0; i < 256; i++) { + for(int y = 0; y < native_scale; y++) { + System.arraycopy(terrain_argb[i],native_scale*y,outbuf,((i>>4)*native_scale+y)*terrain_width + (i & 0xF)*native_scale, native_scale); + } + } + BufferedImage img = KzedMap.createBufferedImage(outbuf, terrain_width, terrain_height); ImageIO.write(img, "png", f); } @@ -514,9 +620,89 @@ public class TexturePack { } } } + /** + * Read color for given subblock coordinate, with given block id and data and face + */ + public void readColor(HDPerspectiveState ps, MapIterator mapiter, Color rslt) { + int blkid = ps.getBlockTypeID(); + int blkdata = ps.getBlockData(); + HDTextureMap map = HDTextureMap.getMap(blkid, blkdata); + BlockStep laststep = ps.getLastBlockStep(); + int textid = map.faces[laststep.ordinal()]; /* Get index of texture source */ + if(textid < 0) { + rslt.setTransparent(); + return; + } + /* See if not basic block texture */ + int textop = textid / 1000; + textid = textid % 1000; + int[] texture = terrain_argb[textid]; + int clrval = 0; + int[] xyz = new int[3]; + ps.getSubblockCoord(xyz); + switch(laststep) { + case X_MINUS: + clrval = texture[(native_scale-xyz[1]-1)*native_scale + xyz[2]]; + break; + case X_PLUS: + clrval = texture[(native_scale-xyz[1]-1)*native_scale + (native_scale-xyz[2]-1)]; + break; + case Z_MINUS: + clrval = texture[(native_scale-xyz[1]-1)*native_scale + xyz[0]]; + break; + case Z_PLUS: + clrval = texture[(native_scale-xyz[1]-1)*native_scale + (native_scale-xyz[0]-1)]; + break; + case Y_MINUS: + clrval = texture[xyz[2]*native_scale + xyz[0]]; + break; + case Y_PLUS: + clrval = texture[xyz[2]*native_scale + (native_scale-xyz[0]-1)]; + break; + } + rslt.setARGB(clrval); + if(textop > 0) { + int tone = 0xFFFFFFFF; + /* Switch based on texture modifier */ + switch(textop) { + case COLORMOD_GRASSTONED: + if(grasscolor_argb == null) { + tone = trivial_grasscolor; + } + else { + tone = biomeLookup(grasscolor_argb, grasscolor_width, mapiter.getRawBiomeRainfall(), mapiter.getRawBiomeTemperature()); + } + break; + case COLORMOD_FOLIAGETONED: + if(foliagecolor_argb == null) { + tone = trivial_foliagecolor; + } + else { + tone = biomeLookup(foliagecolor_argb, foliagecolor_width, mapiter.getRawBiomeRainfall(), mapiter.getRawBiomeTemperature()); + } + break; + case COLORMOD_WATERTONED: + if(watercolor_argb == null) { + tone = trivial_watercolor; + } + else { + tone = biomeLookup(watercolor_argb, watercolor_width, mapiter.getRawBiomeRainfall(), mapiter.getRawBiomeTemperature()); + } + break; + } + rslt.blendColor(tone); + } + } + + private static final int biomeLookup(int[] argb, int width, double rainfall, double temp) { + int t = (int)((1.0-temp)*(width-1)); + int h = width - (int)(temp*rainfall*(width-1)) - 1; + return argb[width*h + t]; + } public static void main(String[] args) { - TexturePack tp = TexturePack.getTexturePack("test"); + TexturePack.loadTextureMapping(new File(".")); + TexturePack tp = TexturePack.getTexturePack("standard"); TexturePack tp2 = tp.resampleTexturePack(4); try { tp2.saveTerrainPNG(new File("test_terrain_4.png")); diff --git a/src/main/java/org/dynmap/hdmap/TexturePackHDShader.java b/src/main/java/org/dynmap/hdmap/TexturePackHDShader.java index 13f5c48a..85ff2549 100644 --- a/src/main/java/org/dynmap/hdmap/TexturePackHDShader.java +++ b/src/main/java/org/dynmap/hdmap/TexturePackHDShader.java @@ -6,6 +6,7 @@ import org.dynmap.Color; import org.dynmap.ColorScheme; import org.dynmap.ConfigurationNode; import org.dynmap.Log; +import org.dynmap.hdmap.HDPerspectiveState.BlockStep; import org.dynmap.utils.MapChunkCache; import org.dynmap.utils.MapIterator; import org.json.simple.JSONObject; @@ -31,7 +32,7 @@ public class TexturePackHDShader implements HDShader { @Override public boolean isRawBiomeDataNeeded() { - return false; + return true; } @Override @@ -60,15 +61,28 @@ public class TexturePackHDShader implements HDShader { } private class OurShaderState implements HDShaderState { - private Color color; + private Color color[]; + private Color tmpcolor[]; + private Color c; protected MapIterator mapiter; protected HDMap map; - private boolean air; + private TexturePack scaledtp; + private HDLighting lighting; private OurShaderState(MapIterator mapiter, HDMap map) { this.mapiter = mapiter; this.map = map; - this.color = new Color(); + this.lighting = map.getLighting(); + if(lighting.isNightAndDayEnabled()) { + color = new Color[] { new Color(), new Color() }; + tmpcolor = new Color[] { new Color(), new Color() }; + } + else { + color = new Color[] { new Color() }; + tmpcolor = new Color[] { new Color() }; + } + c = new Color(); + scaledtp = tp.resampleTexturePack(map.getPerspective().getModelScale()); } /** * Get our shader @@ -88,15 +102,15 @@ public class TexturePackHDShader implements HDShader { * Get our lighting */ public HDLighting getLighting() { - return map.getLighting(); + return lighting; } /** * Reset renderer state for new ray */ public void reset(HDPerspectiveState ps) { - color.setTransparent(); - air = true; + for(Color c: color) + c.setTransparent(); } /** @@ -105,8 +119,54 @@ public class TexturePackHDShader implements HDShader { */ public boolean processBlock(HDPerspectiveState ps) { int blocktype = ps.getBlockTypeID(); - color.setRGBA(0, 0, 0, 255); + if(blocktype == 0) + return false; + /* Get color from textures */ + scaledtp.readColor(ps, mapiter, c); + if (c.getAlpha() > 0) { + int subalpha = ps.getSubmodelAlpha(); + /* Scale brightness depending upon face */ + switch(ps.getLastBlockStep()) { + case X_MINUS: + case X_PLUS: + /* 60% brightness */ + c.blendColor(0xFFA0A0A0); + break; + case Y_MINUS: + case Y_PLUS: + /* 85% brightness for even, 90% for even*/ + if((mapiter.getY() & 0x01) == 0) + c.blendColor(0xFFD9D9D9); + else + c.blendColor(0xFFE6E6E6); + break; + } + /* Handle light level, if needed */ + lighting.applyLighting(ps, this, c, tmpcolor); + /* If we got alpha from subblock model, use it instead */ + if(subalpha >= 0) { + for(Color clr : tmpcolor) + clr.setAlpha(Math.max(subalpha,clr.getAlpha())); + } + /* If no previous color contribution, use new color */ + if(color[0].isTransparent()) { + for(int i = 0; i < color.length; i++) + color[i].setColor(tmpcolor[i]); + return (color[0].getAlpha() == 255); + } + /* Else, blend and generate new alpha */ + else { + int alpha = color[0].getAlpha(); + int alpha2 = tmpcolor[0].getAlpha() * (255-alpha) / 255; + int talpha = alpha + alpha2; + for(int i = 0; i < color.length; i++) + color[i].setRGBA((tmpcolor[i].getRed()*alpha2 + color[i].getRed()*alpha) / talpha, + (tmpcolor[i].getGreen()*alpha2 + color[i].getGreen()*alpha) / talpha, + (tmpcolor[i].getBlue()*alpha2 + color[i].getBlue()*alpha) / talpha, talpha); + return (talpha >= 254); /* If only one short, no meaningful contribution left */ + } + } return true; } /** @@ -120,7 +180,7 @@ public class TexturePackHDShader implements HDShader { * @param index - index of color to request (renderer specific - 0=default, 1=day for night/day renderer */ public void getRayColor(Color c, int index) { - c.setColor(color); + c.setColor(color[index]); } /** * Clean up state object - called after last ray completed diff --git a/texture.txt b/texture.txt index 63469ca2..9acc04fd 100644 --- a/texture.txt +++ b/texture.txt @@ -1,13 +1,12 @@ # Mapping of texture resources to block ID and data values # block:id=,data=,top=,bottom=,north=,south=,east=,west=,allfaces=,allsides= -# =0-255 (index of patch in terrain.png), -1=clear, 256=patch(38)+biome tint from grasscolor.png,257=stationary water,258=moving water, -# 259=stationary lava,260=moving lava,261=patch(52)+biome tint from foliagecolor.png,262=patch(132)+biome tint from foliagecolor.png, -# 263=patch( +# =0-255 (index of patch in terrain.png), -1=clear, 1xxx=biome tint from grasscolor.png,257=stationary water,258=moving water, +# 259=stationary lava,260=moving lava,2xxx=biome tint from foliagecolor.png,3xxx=biome tint from watercolor.png ###### # Stone block:id=1,data=*,allfaces=1 # Grass -block:id=2,data=*,allsides=3,top=256,bottom=2 +block:id=2,data=*,allsides=3,top=1000,bottom=2 # Dirt block:id=3,data=*,allfaces=2 # Cobblestone @@ -47,11 +46,11 @@ block:id=17,data=1,allsides=116,top=21,bottom=21 # Wood (birch) block:id=17,data=2,allsides=117,top=21,bottom=21 # Leaves (std) -block:id=18,data=0,allfaces=261 +block:id=18,data=0,allfaces=2052 # Leaves (spruce/pine) -block:id=18,data=1,allfaces=262 +block:id=18,data=1,allfaces=2132 # Leaves (birch) -block:id=18,data=2,allfaces=261 +block:id=18,data=2,allfaces=2052 # Sponge block:id=19,data=*,allfaces=48 # Glass @@ -70,3 +69,8 @@ block:id=23,data=4,top=62,north=46,south=45,east=45,west=45,bottom=62 block:id=23,data=5,top=62,south=46,north=45,east=45,west=45,bottom=62 # Sandstone block:id=24,data=*,top=176,bottom=208,allsides=192 +# Snow +block:id=78,data=*,allfaces=66 +# Ice +block:id=79,data=*,allfaces=67 + diff --git a/texturepacks/standard/misc/foliagecolor.png b/texturepacks/standard/misc/foliagecolor.png new file mode 100644 index 00000000..81673cae Binary files /dev/null and b/texturepacks/standard/misc/foliagecolor.png differ diff --git a/texturepacks/standard/misc/grasscolor.png b/texturepacks/standard/misc/grasscolor.png new file mode 100644 index 00000000..a6d9c209 Binary files /dev/null and b/texturepacks/standard/misc/grasscolor.png differ diff --git a/texturepacks/standard/misc/water.png b/texturepacks/standard/misc/water.png new file mode 100644 index 00000000..8b92f9bc Binary files /dev/null and b/texturepacks/standard/misc/water.png differ diff --git a/texturepacks/standard/misc/watercolor.png b/texturepacks/standard/misc/watercolor.png new file mode 100644 index 00000000..38bff05e Binary files /dev/null and b/texturepacks/standard/misc/watercolor.png differ diff --git a/texturepacks/standard/terrain.png b/texturepacks/standard/terrain.png new file mode 100644 index 00000000..244f7668 Binary files /dev/null and b/texturepacks/standard/terrain.png differ