Skip to content

Commit 6a972e7

Browse files
authored
Heightmaps used for brushes etc. should be normalised to zero. (#1522)
* Heightmaps used for brushes etc. should be normalised to zero. Fixes #1508 * chars are unsigned * Add scale paramer to javadoc
1 parent 9e40b97 commit 6a972e7

File tree

5 files changed

+33
-53
lines changed

5 files changed

+33
-53
lines changed

worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush/HeightBrush.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,14 @@ public HeightBrush(
5151
this.smooth = smooth;
5252
if (stream != null) {
5353
try {
54-
heightMap = ScalableHeightMap.fromPNG(stream, minY, maxY);
54+
heightMap = ScalableHeightMap.fromPNG(stream);
5555
} catch (IOException e) {
5656
throw new FaweException(Caption.of("fawe.worldedit.brush.brush.height.invalid"));
5757
}
5858
} else if (clipboard != null) {
5959
heightMap = ScalableHeightMap.fromClipboard(clipboard, minY, maxY);
6060
} else {
61-
heightMap = ScalableHeightMap.fromShape(shape, minY, maxY);
61+
heightMap = ScalableHeightMap.fromShape(shape);
6262
}
6363
}
6464

worldedit-core/src/main/java/com/fastasyncworldedit/core/math/heightmap/ArrayHeightMap.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,29 @@
33
public class ArrayHeightMap extends ScalableHeightMap {
44

55
// The heights
6-
private final byte[][] height;
6+
private final char[][] height;
77
// The height map width/length
88
private final int width;
99
private final int length;
10+
private final double scale;
1011
// The size to width/length ratio
1112
private double rx;
1213
private double rz;
1314

1415
/**
15-
* New height map represented by byte array[][] of values x*z to be scaled given a set size
16+
* New height map represented by char array[][] of values x*z to be scaled given a set size.
17+
* Limited 0->65535
1618
*
1719
* @param height array of height values
18-
* @param minY min y value allowed to be set. Inclusive.
19-
* @param maxY max y value allowed to be set. Inclusive.
20+
* @param scale "scale" of the heightmap. Typically the normalised height of the world, or the maximum possible value (256
21+
* for a PNG heightmap)
2022
*/
21-
public ArrayHeightMap(byte[][] height, int minY, int maxY) {
22-
super(minY, maxY);
23+
public ArrayHeightMap(char[][] height, double scale) {
2324
setSize(5);
2425
this.height = height;
2526
this.width = height.length;
2627
this.length = height[0].length;
28+
this.scale = scale;
2729
}
2830

2931
@Override
@@ -38,7 +40,7 @@ public void setSize(int size) {
3840
public double getHeight(int x, int z) {
3941
x = (int) Math.max(0, Math.min(width - 1, (x + size) * rx));
4042
z = (int) Math.max(0, Math.min(length - 1, (z + size) * rz));
41-
return ((height[x][z] & 0xFF) * size) / 256d;
43+
return (height[x][z] * size) / scale;
4244

4345
}
4446

worldedit-core/src/main/java/com/fastasyncworldedit/core/math/heightmap/FlatScalableHeightMap.java

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,13 @@
22

33
public class FlatScalableHeightMap extends ScalableHeightMap {
44

5-
/**
6-
* New height map where the returned height is the minmum height value if outside the size, otherwise returns height equal
7-
* to size.
8-
*
9-
* @param minY min y value allowed to be set. Inclusive.
10-
* @param maxY max y value allowed to be set. Inclusive.
11-
*/
12-
public FlatScalableHeightMap(int minY, int maxY) {
13-
super(minY, maxY);
14-
}
15-
165
@Override
176
public double getHeight(int x, int z) {
187
int dx = Math.abs(x);
198
int dz = Math.abs(z);
209
int d2 = dx * dx + dz * dz;
2110
if (d2 > size2) {
22-
return minY;
11+
return 0;
2312
}
2413
return size;
2514
}

worldedit-core/src/main/java/com/fastasyncworldedit/core/math/heightmap/HeightMap.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ default int[][] generateHeightData(
115115
height = tmpY = session.getNearestSurfaceLayer(xx, zz, tmpY, minY, maxY);
116116
} else {
117117
height = tmpY = session.getNearestSurfaceTerrainBlock(xx, zz, tmpY, minY, maxY);
118-
if (height == -1) {
118+
if (height < minY) {
119119
continue;
120120
}
121121
}
@@ -129,9 +129,9 @@ default int[][] generateHeightData(
129129
double raiseScaled = diff * (raisePow * sizePowInv);
130130
double raiseScaledAbs = Math.abs(raiseScaled);
131131
int random =
132-
ThreadLocalRandom
132+
(ThreadLocalRandom
133133
.current()
134-
.nextInt(maxY + 1 - minY) - minY < (int) ((Math.ceil(raiseScaledAbs) - Math.floor(
134+
.nextInt(maxY + 1 - minY) - minY) < (int) ((Math.ceil(raiseScaledAbs) - Math.floor(
135135
raiseScaledAbs)) * (maxY + 1 - minY)) ? (diff > 0 ? 1 : -1) : 0;
136136
int raiseScaledInt = (int) raiseScaled + random;
137137
newData[index] = height + raiseScaledInt;
@@ -154,7 +154,7 @@ default int[][] generateHeightData(
154154
height = session.getNearestSurfaceLayer(xx, zz, height, minY, maxY);
155155
} else {
156156
height = session.getNearestSurfaceTerrainBlock(xx, zz, height, minY, maxY);
157-
if (height == minY - 1) {
157+
if (height < minY) {
158158
continue;
159159
}
160160
}
@@ -165,9 +165,9 @@ default int[][] generateHeightData(
165165
}
166166
raise = (yscale * raise);
167167
int random =
168-
ThreadLocalRandom
168+
(ThreadLocalRandom
169169
.current()
170-
.nextInt(maxY + 1 - minY) - minY < (int) ((raise - (int) raise) * (maxY - minY + 1))
170+
.nextInt(maxY + 1 - minY) - minY) < (int) ((raise - (int) raise) * (maxY - minY + 1))
171171
? 1 : 0;
172172
int newHeight = height + (int) raise + random;
173173
newData[index] = newHeight;

worldedit-core/src/main/java/com/fastasyncworldedit/core/math/heightmap/ScalableHeightMap.java

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import com.sk89q.worldedit.world.block.BlockState;
1010

1111
import java.awt.image.BufferedImage;
12-
import java.awt.image.Raster;
1312
import java.io.IOException;
1413
import java.io.InputStream;
1514
import java.util.HashSet;
@@ -18,23 +17,16 @@ public class ScalableHeightMap implements HeightMap {
1817

1918
public int size2;
2019
public int size;
21-
protected int minY;
22-
protected int maxY;
2320

2421
public enum Shape {
2522
CONE,
2623
CYLINDER,
2724
}
2825

2926
/**
30-
* New height map.
31-
*
32-
* @param minY min y value allowed to be set. Inclusive.
33-
* @param maxY max y value allowed to be set. Inclusive.
27+
* New height map. "Normalised" to a min Y of zero.
3428
*/
35-
public ScalableHeightMap(final int minY, final int maxY) {
36-
this.minY = minY;
37-
this.maxY = maxY;
29+
public ScalableHeightMap() {
3830
setSize(5);
3931
}
4032

@@ -50,21 +42,21 @@ public double getHeight(int x, int z) {
5042
int dz = Math.abs(z);
5143
int d2 = dx * dx + dz * dz;
5244
if (d2 > size2) {
53-
return minY;
45+
return 0;
5446
}
55-
return Math.max(minY, size - MathMan.sqrtApprox(d2));
47+
return Math.max(0, size - MathMan.sqrtApprox(d2));
5648
}
5749

58-
public static ScalableHeightMap fromShape(Shape shape, int minY, int maxY) {
50+
public static ScalableHeightMap fromShape(Shape shape) {
5951
return switch (shape) {
60-
case CONE -> new ScalableHeightMap(minY, maxY);
61-
case CYLINDER -> new FlatScalableHeightMap(minY, maxY);
52+
case CONE -> new ScalableHeightMap();
53+
case CYLINDER -> new FlatScalableHeightMap();
6254
};
6355
}
6456

6557
public static ScalableHeightMap fromClipboard(Clipboard clipboard, int minY, int maxY) {
6658
BlockVector3 dim = clipboard.getDimensions();
67-
byte[][] heightArray = new byte[dim.getBlockX()][dim.getBlockZ()];
59+
char[][] heightArray = new char[dim.getBlockX()][dim.getBlockZ()];
6860
int clipMinX = clipboard.getMinimumPoint().getBlockX();
6961
int clipMinZ = clipboard.getMinimumPoint().getBlockZ();
7062
int clipMinY = clipboard.getMinimumPoint().getBlockY();
@@ -89,34 +81,31 @@ public static ScalableHeightMap fromClipboard(Clipboard clipboard, int minY, int
8981
highestY = y + 1;
9082
}
9183
}
92-
int pointHeight = Math.min(clipMaxY, ((maxY - minY + 1) * (highestY - clipMinY)) / clipHeight);
9384
int x = xx - clipMinX;
9485
int z = zz - clipMinZ;
95-
heightArray[x][z] = (byte) pointHeight;
86+
heightArray[x][z] = (char) Math.min(clipMaxY, ((maxY - minY + 1) * (highestY - clipMinY)) / clipHeight);
9687
}
97-
return new ArrayHeightMap(heightArray, minY, maxY);
88+
return new ArrayHeightMap(heightArray, maxY - minY + 1);
9889
}
9990

100-
public static ScalableHeightMap fromPNG(InputStream stream, int minY, int maxY) throws IOException {
91+
public static ScalableHeightMap fromPNG(InputStream stream) throws IOException {
10192
BufferedImage heightFile = MainUtil.readImage(stream);
10293
int width = heightFile.getWidth();
10394
int length = heightFile.getHeight();
104-
Raster data = heightFile.getData();
105-
byte[][] array = new byte[width][length];
95+
char[][] array = new char[width][length];
10696
double third = 1 / 3.0;
10797
double alphaInverse = 1 / 255.0;
10898
for (int x = 0; x < width; x++) {
10999
for (int z = 0; z < length; z++) {
110100
int pixel = heightFile.getRGB(x, z);
111101
int red = pixel >> 16 & 0xFF;
112102
int green = pixel >> 8 & 0xFF;
113-
int blue = pixel >> 0 & 0xFF;
103+
int blue = pixel & 0xFF;
114104
int alpha = pixel >> 24 & 0xFF;
115-
int intensity = (int) (alpha * ((red + green + blue) * third) * alphaInverse);
116-
array[x][z] = (byte) intensity;
105+
array[x][z] = (char) (alpha * ((red + green + blue) * third) * alphaInverse);
117106
}
118107
}
119-
return new ArrayHeightMap(array, minY, maxY);
108+
return new ArrayHeightMap(array, 256d);
120109
}
121110

122111
}

0 commit comments

Comments
 (0)