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

View File

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