Start work on new water model - shift over to using basic version

This commit is contained in:
Mike Primm 2018-09-01 16:55:00 -05:00
parent 88816b176e
commit 6da97c5e3f
20 changed files with 325 additions and 182 deletions

View File

@ -251,6 +251,9 @@ public class CaveHDShader implements HDShader {
public int[] getLightingTable() { public int[] getLightingTable() {
return lightingTable; return lightingTable;
} }
@Override
public void setLastBlockState(DynmapBlockState new_lastbs) {
}
} }
/** /**

View File

@ -12,18 +12,18 @@ import org.dynmap.renderer.RenderPatch;
public class CustomBlockModel extends HDBlockModel { public class CustomBlockModel extends HDBlockModel {
public CustomRenderer render; public CustomRenderer render;
public CustomBlockModel(String blockname, BitSet databits, String classname, Map<String,String> classparm, String blockset) { public CustomBlockModel(DynmapBlockState bstate, BitSet databits, String classname, Map<String,String> classparm, String blockset) {
super(blockname, databits, blockset); super(bstate, databits, blockset);
try { try {
Class<?> cls = Class.forName(classname); /* Get class */ Class<?> cls = Class.forName(classname); /* Get class */
render = (CustomRenderer) cls.newInstance(); render = (CustomRenderer) cls.newInstance();
if(render.initializeRenderer(HDBlockModels.pdf, blockname, databits, classparm) == false) { if(render.initializeRenderer(HDBlockModels.pdf, bstate.blockName, databits, classparm) == false) {
Log.severe("Error loading custom renderer - " + classname); Log.severe("Error loading custom renderer - " + classname);
render = null; render = null;
} }
else { else {
if(render.getTileEntityFieldsNeeded() != null) { if(render.getTileEntityFieldsNeeded() != null) {
DynmapBlockState bbs = DynmapBlockState.getBaseStateByName(blockname); DynmapBlockState bbs = bstate.baseState;
for(int i = 0; i < bbs.getStateCount(); i++) { for(int i = 0; i < bbs.getStateCount(); i++) {
if (databits.isEmpty() || databits.get(i)) { if (databits.isEmpty() || databits.get(i)) {
DynmapBlockState bs = bbs.getState(i); DynmapBlockState bs = bbs.getState(i);

View File

@ -245,6 +245,9 @@ public class DefaultHDShader implements HDShader {
public int[] getLightingTable() { public int[] getLightingTable() {
return lightingTable; return lightingTable;
} }
@Override
public void setLastBlockState(DynmapBlockState new_lastbs) {
}
} }
private class OurBiomeShaderState extends OurShaderState { private class OurBiomeShaderState extends OurShaderState {

View File

@ -8,13 +8,13 @@ public abstract class HDBlockModel {
private String blockset; private String blockset;
/** /**
* Block definition - positions correspond to Bukkit coordinates (+X is south, +Y is up, +Z is west) * Block definition - positions correspond to Bukkit coordinates (+X is south, +Y is up, +Z is west)
* @param blockname - block name * @param bstate - block state
* @param databits - bitmap of block data bits matching this model (bit N is set if data=N would match) * @param databits - bitmap of block data bits matching this model (bit N is set if data=N would match)
* @param blockset - ID of block definition set * @param blockset - ID of block definition set
*/ */
protected HDBlockModel(String blockname, BitSet databits, String blockset) { protected HDBlockModel(DynmapBlockState bstate, BitSet databits, String blockset) {
this.blockset = blockset; this.blockset = blockset;
DynmapBlockState bblk = DynmapBlockState.getBaseStateByName(blockname); DynmapBlockState bblk = bstate.baseState;
if (bblk.isNotAir()) { if (bblk.isNotAir()) {
for (int i = 0; i < bblk.getStateCount(); i++) { for (int i = 0; i < bblk.getStateCount(); i++) {
if (databits.isEmpty() || databits.get(i)) { if (databits.isEmpty() || databits.get(i)) {

View File

@ -43,7 +43,7 @@ public class HDBlockModels {
private static HashSet<String> loadedmods = new HashSet<String>(); private static HashSet<String> loadedmods = new HashSet<String>();
private static HashMap<Integer, HDScaledBlockModels> scaled_models_by_scale = new HashMap<Integer, HDScaledBlockModels>(); private static HashMap<Integer, HDScaledBlockModels> scaled_models_by_scale = new HashMap<Integer, HDScaledBlockModels>();
public static final int getMaxPatchCount() { return max_patches; } public static final int getMaxPatchCount() { return max_patches; }
public static final PatchDefinitionFactory getPatchDefinitionFactory() { return pdf; } public static final PatchDefinitionFactory getPatchDefinitionFactory() { return pdf; }
/* Reset model if defined by different block set */ /* Reset model if defined by different block set */
@ -390,7 +390,7 @@ public class HDBlockModels {
for(String bname : blknames) { for(String bname : blknames) {
DynmapBlockState bblk = DynmapBlockState.getBaseStateByName(bname); DynmapBlockState bblk = DynmapBlockState.getBaseStateByName(bname);
if (bblk.isNotAir()) { if (bblk.isNotAir()) {
modlist.add(new HDBlockVolumetricModel(bblk.blockName, databits, scale, new long[0], blockset)); modlist.add(new HDBlockVolumetricModel(bblk, databits, scale, new long[0], blockset));
cnt++; cnt++;
} }
else { else {
@ -740,7 +740,7 @@ public class HDBlockModels {
for(String nm : blknames) { for(String nm : blknames) {
DynmapBlockState bs = DynmapBlockState.getBaseStateByName(nm); DynmapBlockState bs = DynmapBlockState.getBaseStateByName(nm);
if (bs.isNotAir()) { if (bs.isNotAir()) {
pmodlist.add(new HDBlockPatchModel(bs.blockName, databits, patcharray, blockset)); pmodlist.add(new HDBlockPatchModel(bs, databits, patcharray, blockset));
cnt++; cnt++;
} }
else { else {
@ -804,7 +804,7 @@ public class HDBlockModels {
for(String nm : blknames) { for(String nm : blknames) {
DynmapBlockState bs = DynmapBlockState.getBaseStateByName(nm); DynmapBlockState bs = DynmapBlockState.getBaseStateByName(nm);
if (bs.isNotAir()) { if (bs.isNotAir()) {
pmodlist.add(new HDBlockPatchModel(bs.blockName, databits, patcharray, blockset)); pmodlist.add(new HDBlockPatchModel(bs, databits, patcharray, blockset));
cnt++; cnt++;
} }
else { else {
@ -852,7 +852,7 @@ public class HDBlockModels {
for (String nm : blknames) { for (String nm : blknames) {
DynmapBlockState bs = DynmapBlockState.getBaseStateByName(nm); DynmapBlockState bs = DynmapBlockState.getBaseStateByName(nm);
if (bs.isNotAir()) { if (bs.isNotAir()) {
CustomBlockModel cbm = new CustomBlockModel(bs.blockName, databits, cls, custargs, blockset); CustomBlockModel cbm = new CustomBlockModel(bs, databits, cls, custargs, blockset);
if(cbm.render == null) { if(cbm.render == null) {
Log.severe("Custom block model failed to initialize = line " + rdr.getLineNumber() + " of " + fname); Log.severe("Custom block model failed to initialize = line " + rdr.getLineNumber() + " of " + fname);
} }

View File

@ -2,6 +2,7 @@ package org.dynmap.hdmap;
import java.util.BitSet; import java.util.BitSet;
import org.dynmap.renderer.DynmapBlockState;
import org.dynmap.utils.PatchDefinition; import org.dynmap.utils.PatchDefinition;
public class HDBlockPatchModel extends HDBlockModel { public class HDBlockPatchModel extends HDBlockModel {
@ -11,13 +12,13 @@ public class HDBlockPatchModel extends HDBlockModel {
/** /**
* Block definition - positions correspond to Bukkit coordinates (+X is south, +Y is up, +Z is west) * Block definition - positions correspond to Bukkit coordinates (+X is south, +Y is up, +Z is west)
* (for patch models) * (for patch models)
* @param blockname - block name * @param bs - block state
* @param databits - bitmap of block data bits matching this model (bit N is set if data=N would match) * @param databits - bitmap of block data bits matching this model (bit N is set if data=N would match)
* @param patches - list of patches (surfaces composing model) * @param patches - list of patches (surfaces composing model)
* @param blockset - ID of set of blocks defining model * @param blockset - ID of set of blocks defining model
*/ */
public HDBlockPatchModel(String blockname, BitSet databits, PatchDefinition[] patches, String blockset) { public HDBlockPatchModel(DynmapBlockState bs, BitSet databits, PatchDefinition[] patches, String blockset) {
super(blockname, databits, blockset); super(bs, databits, blockset);
this.patches = patches; this.patches = patches;
int max = 0; int max = 0;
for(int i = 0; i < patches.length; i++) { for(int i = 0; i < patches.length; i++) {

View File

@ -3,6 +3,8 @@ package org.dynmap.hdmap;
import java.util.BitSet; import java.util.BitSet;
import java.util.HashMap; import java.util.HashMap;
import org.dynmap.renderer.DynmapBlockState;
public class HDBlockVolumetricModel extends HDBlockModel { public class HDBlockVolumetricModel extends HDBlockModel {
/* Volumetric model specific attributes */ /* Volumetric model specific attributes */
private long blockflags[]; private long blockflags[];
@ -11,15 +13,15 @@ public class HDBlockVolumetricModel extends HDBlockModel {
/** /**
* Block definition - positions correspond to Bukkit coordinates (+X is south, +Y is up, +Z is west) * Block definition - positions correspond to Bukkit coordinates (+X is south, +Y is up, +Z is west)
* (for volumetric models) * (for volumetric models)
* @param blockname - block name * @param bs - block state
* @param databits - bitmap of block data bits matching this model (bit N is set if data=N would match) * @param databits - bitmap of block data bits matching this model (bit N is set if data=N would match)
* @param nativeres - native subblocks per edge of cube (up to 64) * @param nativeres - native subblocks per edge of cube (up to 64)
* @param blockflags - array of native^2 long integers representing volume of block (bit X of element (nativeres*Y+Z) is set if that subblock is filled) * @param blockflags - array of native^2 long integers representing volume of block (bit X of element (nativeres*Y+Z) is set if that subblock is filled)
* if array is short, other elements area are assumed to be zero (fills from bottom of block up) * if array is short, other elements area are assumed to be zero (fills from bottom of block up)
* @param blockset - ID of set of blocks defining model * @param blockset - ID of set of blocks defining model
*/ */
public HDBlockVolumetricModel(String blockname, BitSet databits, int nativeres, long[] blockflags, String blockset) { public HDBlockVolumetricModel(DynmapBlockState bs, BitSet databits, int nativeres, long[] blockflags, String blockset) {
super(blockname, databits, blockset); super(bs, databits, blockset);
this.nativeres = nativeres; this.nativeres = nativeres;
this.blockflags = new long[nativeres * nativeres]; this.blockflags = new long[nativeres * nativeres];

View File

@ -63,6 +63,10 @@ public interface HDPerspectiveState {
* @return coordinates of ray * @return coordinates of ray
*/ */
int[] getSubblockCoord(); int[] getSubblockCoord();
/**
* Check if point is on face
*/
boolean isOnFace();
/** /**
* Get map iterator * Get map iterator
* @return iterator * @return iterator

View File

@ -1,6 +1,7 @@
package org.dynmap.hdmap; package org.dynmap.hdmap;
import org.dynmap.Color; import org.dynmap.Color;
import org.dynmap.renderer.DynmapBlockState;
import org.dynmap.utils.DynLongHashMap; import org.dynmap.utils.DynLongHashMap;
/** /**
@ -59,4 +60,8 @@ public interface HDShaderState {
* @return array of lighting values * @return array of lighting values
*/ */
int[] getLightingTable(); int[] getLightingTable();
/**
* Update last block state (called before moving to next block)
*/
void setLastBlockState(DynmapBlockState new_lastbs);
} }

View File

@ -210,6 +210,9 @@ public class InhabitedHDShader implements HDShader {
public int[] getLightingTable() { public int[] getLightingTable() {
return lightingTable; return lightingTable;
} }
@Override
public void setLastBlockState(DynmapBlockState new_lastbs) {
}
} }
/** /**

View File

@ -80,6 +80,7 @@ public class IsoHDPerspective implements HDPerspective {
private static final BlockStep [] semi_steps = { BlockStep.Y_PLUS, BlockStep.X_MINUS, BlockStep.X_PLUS, BlockStep.Z_MINUS, BlockStep.Z_PLUS }; private static final BlockStep [] semi_steps = { BlockStep.Y_PLUS, BlockStep.X_MINUS, BlockStep.X_PLUS, BlockStep.Z_MINUS, BlockStep.Z_PLUS };
private DynmapBlockState full_water = null; private DynmapBlockState full_water = null;
private RenderPatch full_water_patch = null;
private class OurPerspectiveState implements HDPerspectiveState { private class OurPerspectiveState implements HDPerspectiveState {
DynmapBlockState blocktype = DynmapBlockState.AIR; DynmapBlockState blocktype = DynmapBlockState.AIR;
@ -122,11 +123,12 @@ public class IsoHDPerspective implements HDPerspective {
Vector3D v0 = new Vector3D(); Vector3D v0 = new Vector3D();
Vector3D vS = new Vector3D(); Vector3D vS = new Vector3D();
Vector3D d_cross_uv = new Vector3D(); Vector3D d_cross_uv = new Vector3D();
double patch_t[] = new double[HDBlockModels.getMaxPatchCount()]; // Double max patch count to be safe for patches + water patches
double patch_u[] = new double[HDBlockModels.getMaxPatchCount()]; double patch_t[] = new double[2*HDBlockModels.getMaxPatchCount()];
double patch_v[] = new double[HDBlockModels.getMaxPatchCount()]; double patch_u[] = new double[2*HDBlockModels.getMaxPatchCount()];
BlockStep patch_step[] = new BlockStep[HDBlockModels.getMaxPatchCount()]; double patch_v[] = new double[2*HDBlockModels.getMaxPatchCount()];
int patch_id[] = new int[HDBlockModels.getMaxPatchCount()]; BlockStep patch_step[] = new BlockStep[2*HDBlockModels.getMaxPatchCount()];
int patch_id[] = new int[2*HDBlockModels.getMaxPatchCount()];
int cur_patch = -1; int cur_patch = -1;
double cur_patch_u; double cur_patch_u;
double cur_patch_v; double cur_patch_v;
@ -142,6 +144,7 @@ public class IsoHDPerspective implements HDPerspective {
/* Cache for custom model patch lists */ /* Cache for custom model patch lists */
private final DynLongHashMap custom_meshes; private final DynLongHashMap custom_meshes;
private final DynLongHashMap custom_fluid_meshes;
public OurPerspectiveState(MapIterator mi, boolean isnether, int scaled) { public OurPerspectiveState(MapIterator mi, boolean isnether, int scaled) {
mapiter = mi; mapiter = mi;
@ -154,6 +157,7 @@ public class IsoHDPerspective implements HDPerspective {
for(int i = 0; i < llcache.length; i++) for(int i = 0; i < llcache.length; i++)
llcache[i] = new LightLevels(); llcache[i] = new LightLevels();
custom_meshes = new DynLongHashMap(); custom_meshes = new DynLongHashMap();
custom_fluid_meshes = new DynLongHashMap();
modscale = basemodscale << scaled; modscale = basemodscale << scaled;
scalemodels = HDBlockModels.getModelsForScale(basemodscale << scaled); scalemodels = HDBlockModels.getModelsForScale(basemodscale << scaled);
} }
@ -394,83 +398,112 @@ public class IsoHDPerspective implements HDPerspective {
nonairhit = true; nonairhit = true;
firststep = false; firststep = false;
} }
// Set current block as last block for any incomplete shaders
for(int i = 0; i < shaderstate.length; i++) {
if(!shaderdone[i])
// Update with current block as last block
shaderstate[i].setLastBlockState(blocktype);
}
return false; return false;
} }
private final boolean handlePatches(RenderPatch[] patches, HDShaderState[] shaderstate, boolean[] shaderdone) { private final int handlePatch(PatchDefinition pd, int hitcnt) {
/* Compute origin of patch */
v0.x = (double)x + pd.x0;
v0.y = (double)y + pd.y0;
v0.z = (double)z + pd.z0;
/* Compute cross product of direction and V vector */
d_cross_uv.set(direction);
d_cross_uv.crossProduct(pd.v);
/* Compute determinant - inner product of this with U */
double det = pd.u.innerProduct(d_cross_uv);
/* If parallel to surface, no intercept */
switch(pd.sidevis) {
case TOP:
if (det < 0.000001) {
return hitcnt;
}
break;
case BOTTOM:
if (det > -0.000001) {
return hitcnt;
}
break;
case BOTH:
case FLIP:
if((det > -0.000001) && (det < 0.000001)) {
return hitcnt;
}
break;
}
double inv_det = 1.0 / det; /* Calculate inverse determinant */
/* Compute distance from patch to ray origin */
vS.set(top);
vS.subtract(v0);
/* Compute u - slope times inner product of offset and cross product */
double u = inv_det * vS.innerProduct(d_cross_uv);
if((u <= pd.umin) || (u >= pd.umax)) {
return hitcnt;
}
/* Compute cross product of offset and U */
vS.crossProduct(pd.u);
/* Compute V using slope times inner product of direction and cross product */
double v = inv_det * direction.innerProduct(vS);
if((v <= pd.vmin) || (v >= pd.vmax) || ((u + v) >= pd.uplusvmax)) {
return hitcnt;
}
/* Compute parametric value of intercept */
double t = inv_det * pd.v.innerProduct(vS);
if (t > 0.000001) { /* We've got a hit */
patch_t[hitcnt] = t;
patch_u[hitcnt] = u;
patch_v[hitcnt] = v;
patch_id[hitcnt] = pd.textureindex;
if(det > 0) {
patch_step[hitcnt] = pd.step.opposite();
}
else {
if (pd.sidevis == SideVisible.FLIP) {
patch_u[hitcnt] = 1 - u;
}
patch_step[hitcnt] = pd.step;
}
hitcnt++;
}
return hitcnt;
}
private final boolean handlePatches(RenderPatch[] patches, HDShaderState[] shaderstate, boolean[] shaderdone, RenderPatch[] fluidpatches) {
int hitcnt = 0; int hitcnt = 0;
int water_hit = Integer.MAX_VALUE; // hit index of first water hit
/* Loop through patches : compute intercept values for each */ /* Loop through patches : compute intercept values for each */
for(int i = 0; i < patches.length; i++) { for(int i = 0; i < patches.length; i++) {
PatchDefinition pd = (PatchDefinition)patches[i]; hitcnt = handlePatch((PatchDefinition)patches[i], hitcnt);
/* Compute origin of patch */ }
v0.x = (double)x + pd.x0; if ((fluidpatches != null) && (fluidpatches.length > 0)) {
v0.y = (double)y + pd.y0; if (full_water == null) {
v0.z = (double)z + pd.z0; full_water = DynmapBlockState.getBaseStateByName(DynmapBlockState.WATER_BLOCK);
/* Compute cross product of direction and V vector */
d_cross_uv.set(direction);
d_cross_uv.crossProduct(pd.v);
/* Compute determinant - inner product of this with U */
double det = pd.u.innerProduct(d_cross_uv);
/* If parallel to surface, no intercept */
switch(pd.sidevis) {
case TOP:
if (det < 0.000001) {
continue;
}
break;
case BOTTOM:
if (det > -0.000001) {
continue;
}
break;
case BOTH:
case FLIP:
if((det > -0.000001) && (det < 0.000001)) {
continue;
}
break;
} }
double inv_det = 1.0 / det; /* Calculate inverse determinant */ int prev_hitcnt = hitcnt;
/* Compute distance from patch to ray origin */ for(int i = 0; i < fluidpatches.length; i++) {
vS.set(top); hitcnt = handlePatch((PatchDefinition)fluidpatches[i], hitcnt);
vS.subtract(v0);
/* Compute u - slope times inner product of offset and cross product */
double u = inv_det * vS.innerProduct(d_cross_uv);
if((u <= pd.umin) || (u >= pd.umax)) {
continue;
} }
/* Compute cross product of offset and U */ if (prev_hitcnt < hitcnt) { // At least one water hit?
vS.crossProduct(pd.u); water_hit = prev_hitcnt; // Remember index
/* Compute V using slope times inner product of direction and cross product */
double v = inv_det * direction.innerProduct(vS);
if((v <= pd.vmin) || (v >= pd.vmax) || ((u + v) >= pd.uplusvmax)) {
continue;
}
/* Compute parametric value of intercept */
double t = inv_det * pd.v.innerProduct(vS);
if (t > 0.000001) { /* We've got a hit */
patch_t[hitcnt] = t;
patch_u[hitcnt] = u;
patch_v[hitcnt] = v;
patch_id[hitcnt] = pd.textureindex;
if(det > 0) {
patch_step[hitcnt] = pd.step.opposite();
}
else {
if (pd.sidevis == SideVisible.FLIP) {
patch_u[hitcnt] = 1 - u;
}
patch_step[hitcnt] = pd.step;
}
hitcnt++;
} }
} }
/* If no hits, we're done */ /* If no hits, we're done */
if(hitcnt == 0) { if(hitcnt == 0) {
// Set current block as last block for any incomplete shaders
for(int i = 0; i < shaderstate.length; i++) {
if(!shaderdone[i])
// Update with current block as last block
shaderstate[i].setLastBlockState(blocktype);
}
return false; return false;
} }
BlockStep old_laststep = laststep; /* Save last step */ BlockStep old_laststep = laststep; /* Save last step */
DynmapBlockState cur_bt = blocktype;
for(int i = 0; i < hitcnt; i++) { for(int i = 0; i < hitcnt; i++) {
/* Find closest hit (lowest parametric value) */ /* Find closest hit (lowest parametric value) */
double best_t = Double.MAX_VALUE; double best_t = Double.MAX_VALUE;
@ -486,6 +519,10 @@ public class IsoHDPerspective implements HDPerspective {
cur_patch_v = patch_v[best_patch]; cur_patch_v = patch_v[best_patch];
laststep = patch_step[best_patch]; laststep = patch_step[best_patch];
cur_patch_t = best_t; cur_patch_t = best_t;
// If the water patch, switch to water state and patch index
if (best_patch >= water_hit) {
blocktype = full_water;
}
/* Process the shaders */ /* Process the shaders */
boolean done = true; boolean done = true;
for(int j = 0; j < shaderstate.length; j++) { for(int j = 0; j < shaderstate.length; j++) {
@ -493,6 +530,10 @@ public class IsoHDPerspective implements HDPerspective {
shaderdone[j] = shaderstate[j].processBlock(this); shaderdone[j] = shaderstate[j].processBlock(this);
done = done && shaderdone[j]; done = done && shaderdone[j];
} }
// If water, restore block type
if (best_patch >= water_hit) {
blocktype = cur_bt;
}
cur_patch = -1; cur_patch = -1;
/* If all are done, we're out */ /* If all are done, we're out */
if(done) { if(done) {
@ -504,10 +545,41 @@ public class IsoHDPerspective implements HDPerspective {
patch_t[best_patch] = Double.MAX_VALUE; patch_t[best_patch] = Double.MAX_VALUE;
} }
laststep = old_laststep; laststep = old_laststep;
// Set current block as last block for any incomplete shaders
for(int i = 0; i < shaderstate.length; i++) {
if(!shaderdone[i])
// Update with current block as last block
shaderstate[i].setLastBlockState(blocktype);
}
return false; return false;
} }
private RenderPatch[] getPatches(DynmapBlockState bt, boolean isFluid) {
RenderPatch[] patches = scalemodels.getPatchModel(bt);
/* If no patches, see if custom model */
if (patches == null) {
CustomBlockModel cbm = scalemodels.getCustomBlockModel(bt);
if (cbm != null) { /* If found, see if cached already */
if (isFluid) {
patches = this.getCustomFluidMesh();
if (patches == null) {
patches = cbm.getMeshForBlock(mapiter);
this.setCustomFluidMesh(patches);
}
}
else {
patches = this.getCustomMesh();
if (patches == null) {
patches = cbm.getMeshForBlock(mapiter);
this.setCustomMesh(patches);
}
}
}
}
return patches;
}
/** /**
* Process visit of ray to block * Process visit of ray to block
*/ */
@ -520,45 +592,17 @@ public class IsoHDPerspective implements HDPerspective {
} }
} }
else if(nonairhit || blocktype.isNotAir()) { else if(nonairhit || blocktype.isNotAir()) {
// If waterlogged, start by rendering as if full water block
if (blocktype.isWaterlogged()) {
boolean done = true;
DynmapBlockState saved_type = blocktype;
if (full_water == null) {
full_water = DynmapBlockState.getBaseStateByName(DynmapBlockState.WATER_BLOCK);
}
blocktype = full_water; // Switch to water state
subalpha = -1;
for (int i = 0; i < shaderstate.length; i++) {
if(!shaderdone[i]) {
shaderdone[i] = shaderstate[i].processBlock(this);
}
done = done && shaderdone[i];
}
// Restore block type
blocktype = saved_type;
/* If all are done, we're out */
if (done) {
return true;
}
nonairhit = true;
}
short[] model; short[] model;
RenderPatch[] patches = scalemodels.getPatchModel(blocktype); RenderPatch[] patches = getPatches(blocktype, false);
/* If no patches, see if custom model */
if (patches == null) {
CustomBlockModel cbm = scalemodels.getCustomBlockModel(blocktype);
if (cbm != null) { /* If found, see if cached already */
patches = this.getCustomMesh();
if (patches == null) {
patches = cbm.getMeshForBlock(mapiter);
this.setCustomMesh(patches);
}
}
}
/* Look up to see if block is modelled */ /* Look up to see if block is modelled */
if(patches != null) { if(patches != null) {
return handlePatches(patches, shaderstate, shaderdone); RenderPatch[] fluidpatches = null;
// If so, check for waterlogged
DynmapBlockState fluidstate = blocktype.getLiquidState();
if (fluidstate != null) {
fluidpatches = getPatches(fluidstate, true);
}
return handlePatches(patches, shaderstate, shaderdone, fluidpatches);
} }
else if ((model = scalemodels.getScaledModel(blocktype)) != null) { else if ((model = scalemodels.getScaledModel(blocktype)) != null) {
return handleSubModel(model, shaderstate, shaderdone); return handleSubModel(model, shaderstate, shaderdone);
@ -569,6 +613,8 @@ public class IsoHDPerspective implements HDPerspective {
for(int i = 0; i < shaderstate.length; i++) { for(int i = 0; i < shaderstate.length; i++) {
if(!shaderdone[i]) { if(!shaderdone[i]) {
shaderdone[i] = shaderstate[i].processBlock(this); shaderdone[i] = shaderstate[i].processBlock(this);
// Update with current block as last block
shaderstate[i].setLastBlockState(blocktype);
} }
done = done && shaderdone[i]; done = done && shaderdone[i];
} }
@ -825,6 +871,27 @@ public class IsoHDPerspective implements HDPerspective {
return subblock_xyz; return subblock_xyz;
} }
// Is the hit on a cullable face?
public final boolean isOnFace() {
double tt;
if(cur_patch >= 0) { /* If patch hit */
tt = cur_patch_t;
}
else if(subalpha < 0) {
tt = t + 0.0000001;
}
else { // Full blocks always on face
return true;
}
double xx = top.x + tt * direction.x;
double yy = top.y + tt * direction.y;
double zz = top.z + tt * direction.z;
double xoff = xx - fastFloor(xx);
double yoff = yy - fastFloor(yy);
double zoff = zz - fastFloor(zz);
return ((xoff < 0.0001) || (xoff > 0.9999) || (yoff < 0.0001) || (yoff > 0.9999) || (zoff < 0.0001) || (zoff > 0.9999));
}
/** /**
* Get current texture index * Get current texture index
*/ */
@ -870,6 +937,20 @@ public class IsoHDPerspective implements HDPerspective {
long key = this.mapiter.getBlockKey(); /* Get key for current block */ long key = this.mapiter.getBlockKey(); /* Get key for current block */
custom_meshes.put(key, mesh); custom_meshes.put(key, mesh);
} }
/**
* Get custom fluid mesh for block, if defined (null if not)
*/
public final RenderPatch[] getCustomFluidMesh() {
long key = this.mapiter.getBlockKey(); /* Get key for current block */
return (RenderPatch[])custom_fluid_meshes.get(key);
}
/**
* Save custom mesh for block
*/
public final void setCustomFluidMesh(RenderPatch[] mesh) {
long key = this.mapiter.getBlockKey(); /* Get key for current block */
custom_fluid_meshes.put(key, mesh);
}
} }
public IsoHDPerspective(DynmapCore core, ConfigurationNode configuration) { public IsoHDPerspective(DynmapCore core, ConfigurationNode configuration) {

View File

@ -2652,6 +2652,7 @@ public class TexturePack {
} }
} }
} }
/** /**
* Read color for given subblock coordinate, with given block id and data and face * Read color for given subblock coordinate, with given block id and data and face
*/ */
@ -2664,6 +2665,7 @@ public class TexturePack {
boolean hasblockcoloring = ss.do_biome_shading && this.blockColoring.hasBlkStateValue(blk); boolean hasblockcoloring = ss.do_biome_shading && this.blockColoring.hasBlkStateValue(blk);
// Test if we have no texture modifications // Test if we have no texture modifications
boolean simplemap = (textid < COLORMOD_MULT_INTERNAL) && (!hasblockcoloring); boolean simplemap = (textid < COLORMOD_MULT_INTERNAL) && (!hasblockcoloring);
int[] xyz = null;
if (simplemap) { /* If simple mapping */ if (simplemap) { /* If simple mapping */
int[] texture = getTileARGB(textid); int[] texture = getTileARGB(textid);
@ -2671,7 +2673,7 @@ public class TexturePack {
int u = 0, v = 0; int u = 0, v = 0;
/* If not patch, compute U and V */ /* If not patch, compute U and V */
if(patchid < 0) { if(patchid < 0) {
int[] xyz = ps.getSubblockCoord(); xyz = ps.getSubblockCoord();
switch(laststep) { switch(laststep) {
case X_MINUS: /* South face: U = East (Z-), V = Down (Y-) */ case X_MINUS: /* South face: U = East (Z-), V = Down (Y-) */
@ -2729,7 +2731,7 @@ public class TexturePack {
/* If clear-inside op, get out early */ /* If clear-inside op, get out early */
if((textop == COLORMOD_CLEARINSIDE) || (textop == COLORMOD_MULTTONED_CLEARINSIDE)) { if((textop == COLORMOD_CLEARINSIDE) || (textop == COLORMOD_MULTTONED_CLEARINSIDE)) {
/* Check if previous block is same block type as we are: surface is transparent if it is */ /* Check if previous block is same block type as we are: surface is transparent if it is */
if (blk.matchingBaseState(lastblocktype) || (blk.isWater() && lastblocktype.isWaterlogged())) { if ((blk.matchingBaseState(lastblocktype) || (blk.isWater() && lastblocktype.isWaterlogged())) && ps.isOnFace()) {
rslt.setTransparent(); rslt.setTransparent();
return; return;
} }
@ -2747,8 +2749,7 @@ public class TexturePack {
int u = 0, v = 0, tmp; int u = 0, v = 0, tmp;
if(patchid < 0) { if(patchid < 0) {
int[] xyz = ps.getSubblockCoord(); if (xyz == null) xyz = ps.getSubblockCoord();
switch(laststep) { switch(laststep) {
case X_MINUS: /* South face: U = East (Z-), V = Down (Y-) */ case X_MINUS: /* South face: U = East (Z-), V = Down (Y-) */
u = native_scale-xyz[2]-1; v = native_scale-xyz[1]-1; u = native_scale-xyz[2]-1; v = native_scale-xyz[1]-1;

View File

@ -172,7 +172,7 @@ public class TexturePackHDShader implements HDShader {
public void reset(HDPerspectiveState ps) { public void reset(HDPerspectiveState ps) {
for(int i = 0; i < color.length; i++) for(int i = 0; i < color.length; i++)
color[i].setTransparent(); color[i].setTransparent();
lastblk = DynmapBlockState.AIR; setLastBlockState(DynmapBlockState.AIR);
} }
/** /**
@ -184,13 +184,13 @@ public class TexturePackHDShader implements HDShader {
if ((hiddenids != null) && hiddenids.get(blocktype.globalStateIndex)) { if ((hiddenids != null) && hiddenids.get(blocktype.globalStateIndex)) {
blocktype = DynmapBlockState.AIR; blocktype = DynmapBlockState.AIR;
} }
DynmapBlockState lastblocktype = lastblk;
lastblk = blocktype;
if (blocktype.isAir()) { if (blocktype.isAir()) {
return false; return false;
} }
DynmapBlockState lastblocktype = lastblk;
/* Get color from textures */ /* Get color from textures */
if (scaledtp != null) { if (scaledtp != null) {
scaledtp.readColor(ps, mapiter, c, blocktype, lastblocktype, ShaderState.this); scaledtp.readColor(ps, mapiter, c, blocktype, lastblocktype, ShaderState.this);
@ -314,6 +314,10 @@ public class TexturePackHDShader implements HDShader {
public int[] getLightingTable() { public int[] getLightingTable() {
return lightingTable; return lightingTable;
} }
@Override
public void setLastBlockState(DynmapBlockState new_lastbs) {
lastblk = new_lastbs;
}
} }
/** /**

View File

@ -318,6 +318,9 @@ public class TopoHDShader implements HDShader {
public int[] getLightingTable() { public int[] getLightingTable() {
return lightingTable; return lightingTable;
} }
@Override
public void setLastBlockState(DynmapBlockState new_lastbs) {
}
} }
/** /**

View File

@ -0,0 +1,58 @@
package org.dynmap.hdmap.renderer;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Map;
import org.dynmap.renderer.CustomRenderer;
import org.dynmap.renderer.DynmapBlockState;
import org.dynmap.renderer.MapDataContext;
import org.dynmap.renderer.RenderPatch;
import org.dynmap.renderer.RenderPatchFactory;
/**
* Renderer for vanilla fluids - will attempt to emulate vanilla rendering behavior, but still WIP
*/
public class FluidStateRenderer extends CustomRenderer {
private RenderPatch[][] flat_meshes = new RenderPatch[8][]; // Meshes for each level from 0 (full) to 7 (most empty), no surface incline
private RenderPatch[] full_mesh;
private static final int PATCH_STILL = 0;
private static final int PATCH_FLOWING = 1;
private static final int[] still_patches = { PATCH_STILL, PATCH_STILL, PATCH_FLOWING, PATCH_FLOWING, PATCH_FLOWING, PATCH_FLOWING };
@Override
public boolean initializeRenderer(RenderPatchFactory rpf, String blkname, BitSet blockdatamask, Map<String,String> custparm) {
if(!super.initializeRenderer(rpf, blkname, blockdatamask, custparm))
return false;
ArrayList<RenderPatch> list = new ArrayList<RenderPatch>();
// Create meshes for flat topped blocks
for (int i = 0; i < 8; i++) {
list.clear();
CustomRenderer.addBox(rpf, list, 0.0, 1.0, 0.0, 0.875 - (0.12 * i), 0.0, 1.0, still_patches);
flat_meshes[i] = list.toArray(new RenderPatch[list.size()]);
}
list.clear();
CustomRenderer.addBox(rpf, list, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, still_patches);
full_mesh = list.toArray(new RenderPatch[list.size()]);
return true;
}
@Override
public int getMaximumTextureCount() {
return 2;
}
@Override
public RenderPatch[] getRenderPatchList(MapDataContext ctx) {
int idx = ctx.getBlockType().stateIndex;
if ((idx == 0) || (idx >= 8)) {
DynmapBlockState up = ctx.getBlockTypeAt(0, 1, 0);
if (up.isWater() || up.isWaterlogged())
return full_mesh;
}
return (idx < 8) ? flat_meshes[idx] : flat_meshes[0];
}
}

View File

@ -763,27 +763,9 @@ layer:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
---------------- ----------------
# Lily pad # Lily pad
patchblock:id=waterlily,data=*,patch0=HorizY001ZTop patchblock:id=waterlily,data=*,patch0=HorizY001ZTop
# Water (1 down) # Water
# Lava (1 down) # Lava
boxblock:id=flowing_water,id=water,id=flowing_lava,id=lava,data=1,ymax=0.875 customblock:id=flowing_water,id=water,id=flowing_lava,id=lava,class=org.dynmap.hdmap.renderer.FluidStateRenderer
# Water (2 down)
# Lava (2 down)
boxblock:id=flowing_water,id=water,id=flowing_lava,id=lava,data=2,ymax=0.75
# Water (3 down)
# Lava (3 down)
boxblock:id=flowing_water,id=water,id=flowing_lava,id=lava,data=3,ymax=0.625
# Water (4 down)
# Lava (4 down)
boxblock:id=flowing_water,id=water,id=flowing_lava,id=lava,data=4,ymax=0.5
# Water (5 down)
# Lava (5 down)
boxblock:id=flowing_water,id=water,id=flowing_lava,id=lava,data=5,ymax=0.375
# Water (6 down)
# Lava (6 down)
boxblock:id=flowing_water,id=water,id=flowing_lava,id=lava,data=6,ymax=0.25
# Water (7 down)
# Lava (7 down)
boxblock:id=flowing_water,id=water,id=flowing_lava,id=lava,data=7,ymax=0.125
# Enchantment Table # Enchantment Table
boxblock:id=enchanting_table,data=*,ymax=0.75 boxblock:id=enchanting_table,data=*,ymax=0.75

View File

@ -804,27 +804,9 @@ layer:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
---------------- ----------------
# Lily pad # Lily pad
patchblock:id=lily_pad,patch0=HorizY001ZTop patchblock:id=lily_pad,patch0=HorizY001ZTop
# Water (1 down) # Water
# Lava (1 down) customblock:id=water,id=lava,class=org.dynmap.hdmap.renderer.FluidStateRenderer
boxblock:id=water,id=lava,data=1,ymax=0.875
# Water (2 down)
# Lava (2 down)
boxblock:id=water,id=lava,data=2,ymax=0.75
# Water (3 down)
# Lava (3 down)
boxblock:id=water,id=lava,data=3,ymax=0.625
# Water (4 down)
# Lava (4 down)
boxblock:id=water,id=lava,data=4,ymax=0.5
# Water (5 down)
# Lava (5 down)
boxblock:id=water,id=lava,data=5,ymax=0.375
# Water (6 down)
# Lava (6 down)
boxblock:id=water,id=lava,data=6,ymax=0.25
# Water (7 down)
# Lava (7 down)
boxblock:id=water,id=lava,data=7,ymax=0.125
# Enchantment Table # Enchantment Table
boxblock:id=enchanting_table,ymax=0.75 boxblock:id=enchanting_table,ymax=0.75

View File

@ -390,14 +390,11 @@ block:id=sapling,data=3,data=11,patch0-1=0:sapling_jungle,transparency=TRANSPARE
# Bedrock # Bedrock
block:id=bedrock,allfaces=0:bedrock,stdrot=true block:id=bedrock,allfaces=0:bedrock,stdrot=true
# Water # Water
block:id=flowing_water,allfaces=12000:water_flow,stdrot=true,transparency=SEMITRANSPARENT
# Stationary water # Stationary water
block:id=water,data=0,data=8,data=9,data=10,data=11,data=12,data=13,data=14,data=15,topbottom=12000:water_still,allsides=12000:water_flow,stdrot=true,transparency=SEMITRANSPARENT block:id=water,id=flowing_water,patch0=12000:water_still,patch1=12000:water_flow,transparency=SEMITRANSPARENT
block:id=water,data=1,data=2,data=3,data=4,data=5,data=6,data=7,allfaces=12000:water_flow,stdrot=true,transparency=SEMITRANSPARENT
# Lava # Lava
block:id=flowing_lava,allfaces=0:lava_flow,stdrot=true,transparency=SEMITRANSPARENT
# Stationary Lava # Stationary Lava
block:id=lava,allfaces=0:lava_still,stdrot=true,transparency=SEMITRANSPARENT block:id=lava,id=flowing_lava,patch0=0:lava_still,patch1=0:lava_flow,transparency=SEMITRANSPARENT
# Sand # Sand
block:id=sand,allfaces=0:sand,stdrot=true block:id=sand,allfaces=0:sand,stdrot=true
[1.7.0-]block:id=sand,data=1,allfaces=0:red_sand,stdrot=true [1.7.0-]block:id=sand,data=1,allfaces=0:red_sand,stdrot=true

View File

@ -133,10 +133,7 @@ texture:id=birch_sapling
texture:id=jungle_sapling texture:id=jungle_sapling
texture:id=bedrock texture:id=bedrock
texture:id=water_still,material=WATER texture:id=water_still,material=WATER
#TODO: fix when I figure out 1.13 biome shading logic
#texturefile:id=water_still,filename=assets/minecraft/textures/blocks/water_still.png,xcount=1,ycount=1
texture:id=water_flow,material=WATER texture:id=water_flow,material=WATER
#texturefile:id=water_flow,filename=assets/minecraft/textures/blocks/water_flow.png,xcount=1,ycount=1
texture:id=lava_still texture:id=lava_still
texture:id=lava_flow texture:id=lava_flow
texture:id=sand texture:id=sand
@ -599,9 +596,11 @@ block:id=dark_oak_sapling,data=1,patch0-1=0:dark_oak_sapling,transparency=TRANSP
# Bedrock # Bedrock
block:id=bedrock,allfaces=0:bedrock,stdrot=true block:id=bedrock,allfaces=0:bedrock,stdrot=true
# Water # Water
block:id=water,topbottom=12000:water_still,allsides=12000:water_flow,stdrot=true,transparency=SEMITRANSPARENT #block:id=water,topbottom=12000:water_still,allsides=12000:water_flow,stdrot=true,transparency=SEMITRANSPARENT
block:id=water,patch0=12000:water_still,patch1=12000:water_flow,transparency=SEMITRANSPARENT
# Lava # Lava
block:id=lava,allfaces=0:lava_still,stdrot=true,transparency=SEMITRANSPARENT #block:id=lava,allfaces=0:lava_still,stdrot=true,transparency=SEMITRANSPARENT
block:id=lava,patch0=0:lava_still,patch1=0:lava_flow,transparency=SEMITRANSPARENT
# Sand # Sand
block:id=sand,allfaces=0:sand,stdrot=true block:id=sand,allfaces=0:sand,stdrot=true
# Red Sand # Red Sand

View File

@ -76,6 +76,8 @@ public class DynmapBlockState {
// Well known base blocks - air // Well known base blocks - air
public static final DynmapBlockState AIR = new DynmapBlockState(null, 0, AIR_BLOCK, ""); public static final DynmapBlockState AIR = new DynmapBlockState(null, 0, AIR_BLOCK, "");
private static DynmapBlockState still_water = null;
/** /**
* Constructor for block state * Constructor for block state
* @param base - base block state (null if first/only state for block) * @param base - base block state (null if first/only state for block)
@ -126,6 +128,10 @@ public class DynmapBlockState {
matchflags |= (blockName.equals(SNOW_BLOCK) || blockName.equals(SNOW_LAYER_BLOCK)) ? MATCH_SNOW : 0; matchflags |= (blockName.equals(SNOW_BLOCK) || blockName.equals(SNOW_LAYER_BLOCK)) ? MATCH_SNOW : 0;
matchflags |= blockName.equals(GRASS_BLOCK) ? MATCH_GRASS : 0; matchflags |= blockName.equals(GRASS_BLOCK) ? MATCH_GRASS : 0;
matchflags |= log_blocks.contains(blockName) ? MATCH_LOG : 0; matchflags |= log_blocks.contains(blockName) ? MATCH_LOG : 0;
// If water block, set singleton
if (this.blockName.equals(WATER_BLOCK) && (this == this.baseState)) {
still_water = this;
}
} }
/** /**
* Get state for same base block with given index * Get state for same base block with given index
@ -310,6 +316,15 @@ public class DynmapBlockState {
public boolean matchingBaseState(DynmapBlockState blk) { public boolean matchingBaseState(DynmapBlockState blk) {
return this.baseState == blk.baseState; return this.baseState == blk.baseState;
} }
/**
* Get liquid state (null if not waterlogged or otherwise immmersed)
*/
public DynmapBlockState getLiquidState() {
if (isWaterlogged()) {
return still_water;
}
return null;
}
/** /**
* To printable string * To printable string
*/ */