|
|
|
@ -36,10 +36,7 @@ public class HeightMap {
@@ -36,10 +36,7 @@ public class HeightMap {
|
|
|
|
|
|
|
|
|
|
public static final HashMap<Integer, HeightMap> heightmapByLoadNum = new HashMap<>(); |
|
|
|
|
|
|
|
|
|
public static final HashMap<Integer, byte[][]> _pixelData = new HashMap<>(); |
|
|
|
|
|
|
|
|
|
// Heightmap data for all zones.
|
|
|
|
|
public static float SCALEVALUE = 1.0f / 255; |
|
|
|
|
public static final HashMap<Integer, short[][]> _pixelData = new HashMap<>(); |
|
|
|
|
|
|
|
|
|
// Bootstrap Tracking
|
|
|
|
|
public static int heightMapsCreated = 0; |
|
|
|
@ -52,16 +49,17 @@ public class HeightMap {
@@ -52,16 +49,17 @@ public class HeightMap {
|
|
|
|
|
public final int fullExtentsY; |
|
|
|
|
public final int zoneLoadID; |
|
|
|
|
public BufferedImage heightmapImage; |
|
|
|
|
public float bucketWidthX; |
|
|
|
|
public float bucketWidthY; |
|
|
|
|
public float cell_size_x; |
|
|
|
|
public float cell_size_y; |
|
|
|
|
public float seaLevel = 0; |
|
|
|
|
public int[][] pixelColorValues; |
|
|
|
|
public int bucketCountX; |
|
|
|
|
public int bucketCountY; |
|
|
|
|
|
|
|
|
|
public short[][] pixelColorValues; |
|
|
|
|
public int cell_count_x; |
|
|
|
|
public int cell_count_y; |
|
|
|
|
public float zone_minBlend; |
|
|
|
|
public float zone_maxBlend; |
|
|
|
|
|
|
|
|
|
public float terrain_scale; |
|
|
|
|
|
|
|
|
|
public HeightMap(ResultSet rs) throws SQLException { |
|
|
|
|
|
|
|
|
|
this.heightMapID = rs.getInt("heightMapID"); |
|
|
|
@ -97,11 +95,13 @@ public class HeightMap {
@@ -97,11 +95,13 @@ public class HeightMap {
|
|
|
|
|
|
|
|
|
|
// Calculate the data we do not load from table
|
|
|
|
|
|
|
|
|
|
bucketCountX = this.heightmapImage.getWidth() - 1; |
|
|
|
|
this.bucketWidthX = this.fullExtentsX / (float) bucketCountX; |
|
|
|
|
this.cell_count_x = this.heightmapImage.getWidth() - 1; |
|
|
|
|
this.cell_size_x = this.fullExtentsX / (float) cell_count_x; |
|
|
|
|
|
|
|
|
|
bucketCountY = this.heightmapImage.getHeight() - 1; |
|
|
|
|
this.bucketWidthY = this.fullExtentsY / (float) bucketCountY; |
|
|
|
|
this.cell_count_y = this.heightmapImage.getHeight() - 1; |
|
|
|
|
this.cell_size_y = this.fullExtentsY / (float) cell_count_y; |
|
|
|
|
|
|
|
|
|
this.terrain_scale = this.maxHeight / 255f; |
|
|
|
|
|
|
|
|
|
// Generate pixel array from image data
|
|
|
|
|
|
|
|
|
@ -133,10 +133,10 @@ public class HeightMap {
@@ -133,10 +133,10 @@ public class HeightMap {
|
|
|
|
|
|
|
|
|
|
// Calculate the data we do not load from table
|
|
|
|
|
|
|
|
|
|
this.bucketWidthX = halfExtentsX; |
|
|
|
|
this.bucketWidthY = halfExtentsY; |
|
|
|
|
this.cell_size_x = halfExtentsX; |
|
|
|
|
this.cell_size_y = halfExtentsY; |
|
|
|
|
|
|
|
|
|
this.pixelColorValues = new int[this.fullExtentsX][this.fullExtentsY]; |
|
|
|
|
this.pixelColorValues = new short[this.fullExtentsX][this.fullExtentsY]; |
|
|
|
|
|
|
|
|
|
for (int y = 0; y < this.fullExtentsY; y++) { |
|
|
|
|
for (int x = 0; x < this.fullExtentsX; x++) { |
|
|
|
@ -144,8 +144,9 @@ public class HeightMap {
@@ -144,8 +144,9 @@ public class HeightMap {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bucketCountX = this.pixelColorValues.length - 1; |
|
|
|
|
bucketCountY = this.pixelColorValues[0].length - 1; |
|
|
|
|
cell_count_x = this.pixelColorValues.length - 1; |
|
|
|
|
cell_count_y = this.pixelColorValues[0].length - 1; |
|
|
|
|
this.terrain_scale = this.maxHeight / 255f; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public HeightMap(Zone zone) { |
|
|
|
@ -166,10 +167,10 @@ public class HeightMap {
@@ -166,10 +167,10 @@ public class HeightMap {
|
|
|
|
|
|
|
|
|
|
// Calculate the data we do not load from table
|
|
|
|
|
|
|
|
|
|
this.bucketWidthX = halfExtentsX; |
|
|
|
|
this.bucketWidthY = halfExtentsY; |
|
|
|
|
this.cell_size_x = halfExtentsX; |
|
|
|
|
this.cell_size_y = halfExtentsY; |
|
|
|
|
|
|
|
|
|
this.pixelColorValues = new int[this.fullExtentsX][this.fullExtentsY]; |
|
|
|
|
this.pixelColorValues = new short[this.fullExtentsX][this.fullExtentsY]; |
|
|
|
|
|
|
|
|
|
for (int y = 0; y < this.fullExtentsY; y++) { |
|
|
|
|
for (int x = 0; x < this.fullExtentsX; x++) { |
|
|
|
@ -177,8 +178,9 @@ public class HeightMap {
@@ -177,8 +178,9 @@ public class HeightMap {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bucketCountX = this.pixelColorValues.length - 1; |
|
|
|
|
bucketCountY = this.pixelColorValues[0].length - 1; |
|
|
|
|
cell_count_x = this.pixelColorValues.length - 1; |
|
|
|
|
cell_count_y = this.pixelColorValues[0].length - 1; |
|
|
|
|
this.terrain_scale = this.maxHeight / 255f; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static void GeneratePlayerCityHeightMap() { |
|
|
|
@ -239,13 +241,13 @@ public class HeightMap {
@@ -239,13 +241,13 @@ public class HeightMap {
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static float getWorldHeight(Vector3fImmutable worldLoc) { |
|
|
|
|
|
|
|
|
|
Zone currentZone = ZoneManager.findSmallestZone(worldLoc); |
|
|
|
|
|
|
|
|
|
if (currentZone == null) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
return getWorldHeight(currentZone, worldLoc); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
@ -260,12 +262,6 @@ public class HeightMap {
@@ -260,12 +262,6 @@ public class HeightMap {
|
|
|
|
|
|
|
|
|
|
HeightMap.GeneratePlayerCityHeightMap(); |
|
|
|
|
|
|
|
|
|
// Clear all heightmap image data as it's no longer needed.
|
|
|
|
|
|
|
|
|
|
for (HeightMap heightMap : HeightMap.heightmapByLoadNum.values()) { |
|
|
|
|
heightMap.heightmapImage = null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Logger.info(HeightMap.heightmapByLoadNum.size() + " Heightmaps cached."); |
|
|
|
|
|
|
|
|
|
// Load pixel data for heightmaps
|
|
|
|
@ -282,13 +278,13 @@ public class HeightMap {
@@ -282,13 +278,13 @@ public class HeightMap {
|
|
|
|
|
// Generate pixel data for this heightmap. RPG channels are all the same
|
|
|
|
|
// in this greyscale TGA heightmap. We will choose red.
|
|
|
|
|
|
|
|
|
|
byte[][] colorData = new byte[heightmapImage.getWidth()][heightmapImage.getHeight()]; |
|
|
|
|
short[][] colorData = new short[heightmapImage.getWidth()][heightmapImage.getHeight()]; |
|
|
|
|
|
|
|
|
|
for (int y = 0; y < heightmapImage.getHeight(); y++) |
|
|
|
|
for (int x = 0; x < heightmapImage.getWidth(); x++) { |
|
|
|
|
|
|
|
|
|
Color color = new Color(heightmapImage.getRGB(x, y)); |
|
|
|
|
colorData[x][y] = (byte) color.getRed(); |
|
|
|
|
colorData[x][y] = (short) color.getRed(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Insert color data into lookup table
|
|
|
|
@ -315,13 +311,13 @@ public class HeightMap {
@@ -315,13 +311,13 @@ public class HeightMap {
|
|
|
|
|
|
|
|
|
|
// Generate altitude lookup table for this heightmap
|
|
|
|
|
|
|
|
|
|
heightMap.pixelColorValues = new int[heightMap.heightmapImage.getWidth()][heightMap.heightmapImage.getHeight()]; |
|
|
|
|
heightMap.pixelColorValues = new short[heightMap.heightmapImage.getWidth()][heightMap.heightmapImage.getHeight()]; |
|
|
|
|
|
|
|
|
|
for (int y = 0; y < heightMap.heightmapImage.getHeight(); y++) { |
|
|
|
|
for (int x = 0; x < heightMap.heightmapImage.getWidth(); x++) { |
|
|
|
|
|
|
|
|
|
color = new Color(heightMap.heightmapImage.getRGB(x, y)); |
|
|
|
|
heightMap.pixelColorValues[x][y] = color.getRed(); |
|
|
|
|
heightMap.pixelColorValues[x][y] = (short) color.getRed(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -329,28 +325,31 @@ public class HeightMap {
@@ -329,28 +325,31 @@ public class HeightMap {
|
|
|
|
|
|
|
|
|
|
public Vector2f getGridSquare(Vector2f zoneLoc) { |
|
|
|
|
|
|
|
|
|
// Clamp values.
|
|
|
|
|
float xBucket = zoneLoc.x / this.cell_size_x; |
|
|
|
|
float yBucket = zoneLoc.y / this.cell_size_y; |
|
|
|
|
|
|
|
|
|
float xBucket = zoneLoc.x / this.bucketWidthX; |
|
|
|
|
float yBucket = zoneLoc.y / this.bucketWidthY; |
|
|
|
|
// Clamp values when standing directly on max pole
|
|
|
|
|
|
|
|
|
|
if (xBucket >= this.bucketCountX) |
|
|
|
|
if (xBucket >= this.cell_count_x) |
|
|
|
|
xBucket = xBucket - 1; |
|
|
|
|
|
|
|
|
|
if (yBucket >= this.bucketCountY) |
|
|
|
|
if (yBucket >= this.cell_count_y) |
|
|
|
|
yBucket = xBucket - 1; |
|
|
|
|
|
|
|
|
|
return new Vector2f(xBucket, yBucket); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public float getInterpolatedTerrainHeight(Vector2f zoneLoc) { |
|
|
|
|
public float getInterpolatedTerrainHeight(Vector2f terrainLoc) { |
|
|
|
|
|
|
|
|
|
float interpolatedHeight; |
|
|
|
|
|
|
|
|
|
Vector2f gridSquare = getGridSquare(zoneLoc); |
|
|
|
|
Vector2f gridSquare = getGridSquare(terrainLoc); |
|
|
|
|
|
|
|
|
|
int gridX = (int) gridSquare.x; |
|
|
|
|
int gridY = (int) gridSquare.y; |
|
|
|
|
int gridX = (int) Math.floor(gridSquare.x); |
|
|
|
|
int gridY = (int) Math.floor(gridSquare.y); |
|
|
|
|
|
|
|
|
|
float offsetX = gridSquare.x % 1; |
|
|
|
|
float offsetY = gridSquare.y % 1; |
|
|
|
|
|
|
|
|
|
//get 4 surrounding vertices from the pixel array.
|
|
|
|
|
|
|
|
|
@ -366,15 +365,12 @@ public class HeightMap {
@@ -366,15 +365,12 @@ public class HeightMap {
|
|
|
|
|
|
|
|
|
|
// Interpolate between the 4 vertices
|
|
|
|
|
|
|
|
|
|
float offsetX = (gridSquare.x - gridX); |
|
|
|
|
float offsetY = gridSquare.y - gridY; |
|
|
|
|
|
|
|
|
|
interpolatedHeight = topRightHeight * (1 - offsetY) * (offsetX); |
|
|
|
|
interpolatedHeight += (bottomRightHeight * offsetY * offsetX); |
|
|
|
|
interpolatedHeight += (bottomLeftHeight * (1 - offsetX) * offsetY); |
|
|
|
|
interpolatedHeight += (topLeftHeight * (1 - offsetX) * (1 - offsetY)); |
|
|
|
|
|
|
|
|
|
interpolatedHeight *= (float) this.maxHeight * SCALEVALUE; // Scale height
|
|
|
|
|
interpolatedHeight *= this.terrain_scale; // Scale height
|
|
|
|
|
|
|
|
|
|
return interpolatedHeight; |
|
|
|
|
} |
|
|
|
|