Fix angle mask

Fixes #923
Fixes #884
Fixes #804
This commit is contained in:
Jesse Boyd 2018-04-27 14:19:04 +10:00
parent eaa8fbfc9d
commit e8feaa9204
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
3 changed files with 34 additions and 23 deletions

View File

@ -210,7 +210,7 @@ public class LocalBlockVectorSet implements Set<Vector> {
if (relX > 1023 || relX < -1024 || relZ > 1023 || relZ < -1024) { if (relX > 1023 || relX < -1024 || relZ > 1023 || relZ < -1024) {
throw new UnsupportedOperationException("LocalVectorSet can only contain vectors within 1024 blocks (cuboid) of the first entry. "); throw new UnsupportedOperationException("LocalVectorSet can only contain vectors within 1024 blocks (cuboid) of the first entry. ");
} }
if (y < 0 || y > 256) { if (y < 0 || y > 255) {
throw new UnsupportedOperationException("LocalVectorSet can only contain vectors from y elem:[0,255]"); throw new UnsupportedOperationException("LocalVectorSet can only contain vectors from y elem:[0,255]");
} }
int index = getIndex(x, y, z); int index = getIndex(x, y, z);

View File

@ -16,6 +16,7 @@ public class AngleMask extends SolidBlockMask implements ResettableMask {
private final double max; private final double max;
private final double min; private final double min;
private final boolean overlay; private final boolean overlay;
private final boolean checkFirst;
private int maxY; private int maxY;
private transient MutableBlockVector mutable = new MutableBlockVector(); private transient MutableBlockVector mutable = new MutableBlockVector();
@ -25,6 +26,7 @@ public class AngleMask extends SolidBlockMask implements ResettableMask {
this.mask = new CachedMask(new SolidBlockMask(extent)); this.mask = new CachedMask(new SolidBlockMask(extent));
this.min = min; this.min = min;
this.max = max; this.max = max;
this.checkFirst = max >= (Math.tan(90 * (Math.PI / 180)));
this.maxY = extent.getMaximumPoint().getBlockY(); this.maxY = extent.getMaximumPoint().getBlockY();
this.overlay = overlay; this.overlay = overlay;
} }
@ -36,6 +38,7 @@ public class AngleMask extends SolidBlockMask implements ResettableMask {
cacheBotZ = Integer.MIN_VALUE; cacheBotZ = Integer.MIN_VALUE;
lastX = Integer.MIN_VALUE; lastX = Integer.MIN_VALUE;
lastX = Integer.MIN_VALUE; lastX = Integer.MIN_VALUE;
lastY = Integer.MIN_VALUE;
if (cacheHeights != null) { if (cacheHeights != null) {
Arrays.fill(cacheHeights, (byte) 0); Arrays.fill(cacheHeights, (byte) 0);
} }
@ -48,7 +51,6 @@ public class AngleMask extends SolidBlockMask implements ResettableMask {
private transient int cacheCenterZ; private transient int cacheCenterZ;
private transient byte[] cacheHeights; private transient byte[] cacheHeights;
private transient byte[] cacheDistance;
private transient int lastY; private transient int lastY;
private transient int lastX = Integer.MIN_VALUE; private transient int lastX = Integer.MIN_VALUE;
@ -70,19 +72,15 @@ public class AngleMask extends SolidBlockMask implements ResettableMask {
index = rx + (rz << 8); index = rx + (rz << 8);
if (cacheHeights == null) { if (cacheHeights == null) {
cacheHeights = new byte[65536]; cacheHeights = new byte[65536];
cacheDistance = new byte[65536];
} else { } else {
Arrays.fill(cacheHeights, (byte) 0); Arrays.fill(cacheHeights, (byte) 0);
Arrays.fill(cacheDistance, (byte) 0);
} }
} else { } else {
index = rx + (rz << 8); index = rx + (rz << 8);
} }
int result = cacheHeights[index] & 0xFF; int result = cacheHeights[index] & 0xFF;
int distance = cacheDistance[index] & 0xFF; if (y > result) {
if (result == 0 || distance < Math.abs(result - y)) {
cacheHeights[index] = (byte) (result = lastY = getExtent().getNearestSurfaceTerrainBlock(x, z, lastY, 0, maxY)); cacheHeights[index] = (byte) (result = lastY = getExtent().getNearestSurfaceTerrainBlock(x, z, lastY, 0, maxY));
cacheDistance[index] = (byte) Math.abs(result - y);
} }
return result; return result;
} catch (Throwable e) { } catch (Throwable e) {
@ -94,18 +92,23 @@ public class AngleMask extends SolidBlockMask implements ResettableMask {
private boolean testSlope(int x, int y, int z) { private boolean testSlope(int x, int y, int z) {
double slope; double slope;
boolean aboveMin; boolean aboveMin;
if ((lastX == (lastX = x) & lastZ == (lastZ = z))) { lastY = y;
return lastValue;
}
slope = Math.abs(getHeight(x + 1, y, z) - getHeight(x - 1, y, z)) * ADJACENT_MOD; slope = Math.abs(getHeight(x + 1, y, z) - getHeight(x - 1, y, z)) * ADJACENT_MOD;
if (slope >= min && max >= Math.max(maxY - y, y)) { if (checkFirst) {
if (slope >= min) {
return lastValue = true; return lastValue = true;
} }
slope = Math.max(slope, Math.abs(getHeight(x, y, z + 1) - getHeight(x, y, z - 1)) * ADJACENT_MOD);
slope = Math.max(slope, Math.abs(getHeight(x + 1, y, z + 1) - getHeight(x - 1, y, z - 1)) * DIAGONAL_MOD);
slope = Math.max(slope, Math.abs(getHeight(x - 1, y, z + 1) - getHeight(x + 1, y, z - 1)) * DIAGONAL_MOD);
return lastValue = (slope >= min);
} else {
slope = Math.max(slope, Math.abs(getHeight(x, y, z + 1) - getHeight(x, y, z - 1)) * ADJACENT_MOD); slope = Math.max(slope, Math.abs(getHeight(x, y, z + 1) - getHeight(x, y, z - 1)) * ADJACENT_MOD);
slope = Math.max(slope, Math.abs(getHeight(x + 1, y, z + 1) - getHeight(x - 1, y, z - 1)) * DIAGONAL_MOD); slope = Math.max(slope, Math.abs(getHeight(x + 1, y, z + 1) - getHeight(x - 1, y, z - 1)) * DIAGONAL_MOD);
slope = Math.max(slope, Math.abs(getHeight(x - 1, y, z + 1) - getHeight(x + 1, y, z - 1)) * DIAGONAL_MOD); slope = Math.max(slope, Math.abs(getHeight(x - 1, y, z + 1) - getHeight(x + 1, y, z - 1)) * DIAGONAL_MOD);
return lastValue = (slope >= min && slope <= max); return lastValue = (slope >= min && slope <= max);
} }
}
public boolean adjacentAir(Vector v) { public boolean adjacentAir(Vector v) {
int x = v.getBlockX(); int x = v.getBlockX();
@ -137,6 +140,12 @@ public class AngleMask extends SolidBlockMask implements ResettableMask {
int x = vector.getBlockX(); int x = vector.getBlockX();
int y = vector.getBlockY(); int y = vector.getBlockY();
int z = vector.getBlockZ(); int z = vector.getBlockZ();
if ((lastX == (lastX = x) & lastZ == (lastZ = z))) {
int height = getHeight(x, y, z);
if (y <= height) return overlay ? (lastValue && y == height) : lastValue;
}
if (!mask.test(x, y, z)) { if (!mask.test(x, y, z)) {
return false; return false;
} }

View File

@ -46,21 +46,23 @@ public class CachedMask extends AbstractDelegateMask implements ResettableMask {
} }
public boolean test(int x, int y, int z) { public boolean test(int x, int y, int z) {
if (y < 0 || y > 255) return getMask().test(mutable.setComponents(x, y, z)); try {
if (cache_checked.contains(x, y, z)) { boolean check = cache_checked.add(x, y, z);
if (!check) {
return cache_results.contains(x, y, z); return cache_results.contains(x, y, z);
} }
boolean result = getMask().test(mutable.setComponents(x, y, z)); boolean result = getMask().test(mutable.setComponents(x, y, z));
try {
cache_checked.add(x, y, z);
if (result) cache_results.add(x, y, z); if (result) cache_results.add(x, y, z);
return result;
} catch (UnsupportedOperationException ignore) { } catch (UnsupportedOperationException ignore) {
boolean result = getMask().test(mutable.setComponents(x, y, z));
if (y < 0 || y > 255) return result;
resetCache(); resetCache();
cache_checked.setOffset(x, z); cache_checked.setOffset(x, z);
cache_results.setOffset(x, z); cache_results.setOffset(x, z);
cache_checked.add(x, y, z); cache_checked.add(x, y, z);
if (result) cache_results.add(x, y, z); if (result) cache_results.add(x, y, z);
}
return result; return result;
} }
}
} }