diff --git a/src/main/java/org/dynmap/Color.java b/src/main/java/org/dynmap/Color.java index 8269c67c..4b0e2221 100644 --- a/src/main/java/org/dynmap/Color.java +++ b/src/main/java/org/dynmap/Color.java @@ -32,7 +32,7 @@ public class Color { return ((val >> 24) & 0xFF); } public final boolean isTransparent() { - return (val == TRANSPARENT); + return ((val & 0xFF000000) == TRANSPARENT); } public final void setTransparent() { val = TRANSPARENT; diff --git a/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java b/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java index ec5b1c2a..aeb90761 100644 --- a/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java +++ b/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java @@ -89,8 +89,18 @@ public class IsoHDPerspective implements HDPerspective { int x_inc, y_inc, z_inc; double t_next_y, t_next_x, t_next_z; boolean nonairhit; + /* Subblock tracer state */ + int mx, my, mz; + double xx, yy, zz; + double mdt_dx; + double mdt_dy; + double mdt_dz; + double togo; + double mt_next_x, mt_next_y, mt_next_z; int subalpha; double mt; + double mtend; + int[] subblock_xyz = new int[3]; MapIterator mapiter; boolean isnether; @@ -325,19 +335,31 @@ public class IsoHDPerspective implements HDPerspective { else if(blocktypeid == 54) { /* Special case for chest - need to fake data so we can render */ blockdata = generateChestBlockData(mapiter); } - boolean missed = false; /* Look up to see if block is modelled */ short[] model = scalemodels.getScaledModel(blocktypeid, blockdata); if(model != null) { - missed = raytraceSubblock(model); + boolean firststep = true; + + while(!raytraceSubblock(model, firststep)) { + boolean done = true; + skylevel = emitlevel = -1; + for(int i = 0; i < shaderstate.length; i++) { + if(!shaderdone[i]) + shaderdone[i] = shaderstate[i].processBlock(this); + done = done && shaderdone[i]; + } + /* If all are done, we're out */ + if(done) + return true; + nonairhit = true; + firststep = false; + } } else { - subalpha = -1; - } - if(!missed) { boolean done = true; skylevel = emitlevel = -1; + subalpha = -1; for(int i = 0; i < shaderstate.length; i++) { if(!shaderdone[i]) shaderdone[i] = shaderstate[i].processBlock(this); @@ -411,45 +433,53 @@ public class IsoHDPerspective implements HDPerspective { } } - private boolean raytraceSubblock(short[] model) { - int mx = 0, my = 0, mz = 0; - double xx, yy, zz; - 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); - mx = (int)((xx - Math.floor(xx)) * modscale); - my = (int)((yy - Math.floor(yy)) * modscale); - mz = (int)((zz - Math.floor(zz)) * modscale); - double mdt_dx = dt_dx / modscale; - double mdt_dy = dt_dy / modscale; - double mdt_dz = dt_dz / modscale; - double togo; - double mt_next_x = t_next_x, mt_next_y = t_next_y, mt_next_z = t_next_z; - if(mt_next_x != Double.MAX_VALUE) { - togo = ((t_next_x - t) / mdt_dx); - mt_next_x = mt + (togo - Math.floor(togo)) * mdt_dx; - } - if(mt_next_y != Double.MAX_VALUE) { - togo = ((t_next_y - t) / mdt_dy); - mt_next_y = mt + (togo - Math.floor(togo)) * mdt_dy; - } - if(mt_next_z != Double.MAX_VALUE) { - togo = ((t_next_z - t) / mdt_dz); - mt_next_z = mt + (togo - Math.floor(togo)) * mdt_dz; - } - double mtend = Math.min(t_next_x, Math.min(t_next_y, t_next_z)); - subalpha = -1; - while(mt < mtend) { - try { - int blkalpha = model[modscale*modscale*my + modscale*mz + mx]; - if(blkalpha > 0) { - subalpha = blkalpha; - return false; - } - } catch (ArrayIndexOutOfBoundsException aioobx) { /* We're outside the model, so miss */ - return true; + private boolean raytraceSubblock(short[] model, boolean firsttime) { + if(firsttime) { + 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); + mx = (int)((xx - Math.floor(xx)) * modscale); + my = (int)((yy - Math.floor(yy)) * modscale); + mz = (int)((zz - Math.floor(zz)) * modscale); + mdt_dx = dt_dx / modscale; + mdt_dy = dt_dy / modscale; + mdt_dz = dt_dz / modscale; + mt_next_x = t_next_x; + mt_next_y = t_next_y; + mt_next_z = t_next_z; + if(mt_next_x != Double.MAX_VALUE) { + togo = ((t_next_x - t) / mdt_dx); + mt_next_x = mt + (togo - Math.floor(togo)) * mdt_dx; } + if(mt_next_y != Double.MAX_VALUE) { + togo = ((t_next_y - t) / mdt_dy); + mt_next_y = mt + (togo - Math.floor(togo)) * mdt_dy; + } + if(mt_next_z != Double.MAX_VALUE) { + togo = ((t_next_z - t) / mdt_dz); + mt_next_z = mt + (togo - Math.floor(togo)) * mdt_dz; + } + mtend = Math.min(t_next_x, Math.min(t_next_y, t_next_z)); + } + subalpha = -1; + boolean skip = !firsttime; /* Skip first block on continue */ + while(mt < mtend) { + if(!skip) { + try { + int blkalpha = model[modscale*modscale*my + modscale*mz + mx]; + if(blkalpha > 0) { + subalpha = blkalpha; + return false; + } + } catch (ArrayIndexOutOfBoundsException aioobx) { /* We're outside the model, so miss */ + return true; + } + } + else { + skip = false; + } + /* If X step is next best */ if((mt_next_x <= mt_next_y) && (mt_next_x <= mt_next_z)) { mx += x_inc; diff --git a/src/main/java/org/dynmap/hdmap/TexturePackHDShader.java b/src/main/java/org/dynmap/hdmap/TexturePackHDShader.java index 9ef43125..38832bea 100644 --- a/src/main/java/org/dynmap/hdmap/TexturePackHDShader.java +++ b/src/main/java/org/dynmap/hdmap/TexturePackHDShader.java @@ -148,10 +148,13 @@ public class TexturePackHDShader implements HDShader { } /* Handle light level, if needed */ lighting.applyLighting(ps, this, c, tmpcolor); - /* If we got alpha from subblock model, use it instead */ + /* If we got alpha from subblock model, use it instead if it is lower */ if(subalpha >= 0) { - for(Color clr : tmpcolor) - clr.setAlpha(Math.max(subalpha,clr.getAlpha())); + for(Color clr : tmpcolor) { + int a = clr.getAlpha(); + if(subalpha < a) + clr.setAlpha(subalpha); + } } /* If no previous color contribution, use new color */ if(color[0].isTransparent()) { @@ -164,10 +167,15 @@ public class TexturePackHDShader implements HDShader { 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, + if(talpha > 0) + 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); + else + for(int i = 0; i < color.length; i++) + color[i].setTransparent(); + return (talpha >= 254); /* If only one short, no meaningful contribution left */ } }