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/HDBlockModels.java b/src/main/java/org/dynmap/hdmap/HDBlockModels.java index 0f071461..60b13789 100644 --- a/src/main/java/org/dynmap/hdmap/HDBlockModels.java +++ b/src/main/java/org/dynmap/hdmap/HDBlockModels.java @@ -189,6 +189,7 @@ public class HDBlockModels { } } /* Now, use weights and indices to fill in scaled map */ + long accum[] = new long[map.length]; for(int y = 0; y < nativeres; y++) { int ind_y = offsets[y]; int wgt_y = weights[y]; @@ -208,7 +209,7 @@ public class HDBlockModels { for(int zz = 0; zz < 2; zz++) { int wz = (zz==0)?wgt_z:(res-wgt_z); if(wz == 0) continue; - map[(ind_y+yy)*res*res + (ind_z+zz)*res + (ind_x+xx)] += + accum[(ind_y+yy)*res*res + (ind_z+zz)*res + (ind_x+xx)] += wx*wy*wz; } } @@ -218,7 +219,7 @@ public class HDBlockModels { } } for(int i = 0; i < map.length; i++) { - map[i] = (short)(255*map[i]/(nativeres*nativeres*nativeres)); + map[i] = (short)(accum[i]*255/nativeres/nativeres/nativeres); if(map[i] > 255) map[i] = 255; if(map[i] < 0) map[i] = 0; } @@ -249,6 +250,18 @@ public class HDBlockModels { if((m.databits & (1 << i)) != 0) { if(smod == null) smod = m.getScaledMap(scale); row[i] = smod; +/* if((m.blockid == 50) && (i == 5)) { + String v0 = ""; + String v = ""; + for(int x = 0; x < m.blockflags.length; x++) + v0 = v0 + " " + m.blockflags[x]; + for(int x = 0; x < smod.length; x++) { + v = v + " " + smod[x]; + if((x%scale) == (scale-1)) v += "|"; + } + Log.info("src=" + v0); + Log.info("scaled=" + v); + } */ } } } 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 */ } }