Partial refactor.

This commit is contained in:
2023-10-08 09:49:49 -04:00
parent 0ce9ec3ae2
commit 4b62517d99
5 changed files with 69 additions and 258 deletions
+17 -243
View File
@@ -8,185 +8,32 @@
package engine.InterestManagement;
import engine.Enum;
import engine.gameManager.ConfigManager;
import engine.gameManager.DbManager;
import engine.gameManager.ZoneManager;
import engine.math.Vector2f;
import engine.math.Vector3fImmutable;
import engine.objects.Zone;
import org.pmw.tinylog.Logger;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.stream.Stream;
public class Terrain {
// Class variables
public static final HashMap<Integer, Terrain> heightmapByLoadNum = new HashMap<>();
public static final HashMap<Integer, short[][]> _heightmap_pixel_cache = new HashMap<>();
public static final HashMap<Integer, short[][]> _pixelData = new HashMap<>();
// Bootstrap Tracking
public static int heightMapsCreated = 0;
public static Terrain playerCityTerrain;
// Heightmap data for this heightmap
public final int heightMapID;
public final int maxHeight;
public final int fullExtentsX;
public final int fullExtentsY;
public final int zoneLoadID;
public BufferedImage heightmapImage;
public float cell_size_x;
public float cell_size_y;
public float seaLevel = 0;
public short[][] pixelColorValues;
public int cell_count_x;
public int cell_count_y;
public int template;
public short[][] terrain_pixel_data;
public Vector2f terrain_size = new Vector2f();
public Vector2f cell_size = new Vector2f();
public Vector2f cell_count = new Vector2f();
public float terrain_scale;
public Terrain(ResultSet rs) throws SQLException {
public static int heightMapsCreated;
this.heightMapID = rs.getInt("heightMapID");
this.maxHeight = rs.getInt("maxHeight");
int halfExtentsX = rs.getInt("xRadius");
int halfExtentsY = rs.getInt("zRadius");
this.zoneLoadID = rs.getInt("zoneLoadID");
this.seaLevel = rs.getFloat("seaLevel");
// Cache the full extents to avoid the calculation
this.fullExtentsX = halfExtentsX * 2;
this.fullExtentsY = halfExtentsY * 2;
this.heightmapImage = null;
File imageFile = new File(ConfigManager.DEFAULT_DATA_DIR + "heightmaps/" + this.heightMapID + ".bmp");
// early exit if no image file was found. Will log in caller.
if (!imageFile.exists())
return;
// load the heightmap image.
try {
this.heightmapImage = ImageIO.read(imageFile);
} catch (IOException e) {
Logger.error("***Error loading heightmap data for heightmap " + this.heightMapID + e);
}
// Calculate the data we do not load from table
this.cell_count_x = this.heightmapImage.getWidth() - 1;
this.cell_size_x = this.fullExtentsX / (float) cell_count_x;
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
generatePixelData(this);
Terrain.heightmapByLoadNum.put(this.zoneLoadID, this);
heightMapsCreated++;
}
//Created for PlayerCities
public Terrain() {
this.heightMapID = 999999;
this.maxHeight = 5; // for real...
int halfExtentsX = (int) Enum.CityBoundsType.ZONE.halfExtents;
int halfExtentsY = (int) Enum.CityBoundsType.ZONE.halfExtents;
this.zoneLoadID = 0;
this.seaLevel = 0;
// Cache the full extents to avoid the calculation
this.fullExtentsX = halfExtentsX * 2;
this.fullExtentsY = halfExtentsY * 2;
this.heightmapImage = null;
// Calculate the data we do not load from table
this.cell_size_x = halfExtentsX;
this.cell_size_y = halfExtentsY;
this.pixelColorValues = new short[this.fullExtentsX][this.fullExtentsY];
for (int y = 0; y < this.fullExtentsY; y++) {
for (int x = 0; x < this.fullExtentsX; x++) {
pixelColorValues[x][y] = 255;
}
}
cell_count_x = this.pixelColorValues.length - 1;
cell_count_y = this.pixelColorValues[0].length - 1;
this.terrain_scale = this.maxHeight / 255f;
}
public Terrain(Zone zone) {
this.heightMapID = 999999;
this.maxHeight = 0;
int halfExtentsX = (int) zone.bounds.getHalfExtents().x;
int halfExtentsY = (int) zone.bounds.getHalfExtents().y;
this.zoneLoadID = 0;
this.seaLevel = 0;
// Cache the full extents to avoid the calculation
this.fullExtentsX = halfExtentsX * 2;
this.fullExtentsY = halfExtentsY * 2;
this.heightmapImage = null;
// Calculate the data we do not load from table
this.cell_size_x = halfExtentsX;
this.cell_size_y = halfExtentsY;
this.pixelColorValues = new short[this.fullExtentsX][this.fullExtentsY];
for (int y = 0; y < this.fullExtentsY; y++) {
for (int x = 0; x < this.fullExtentsX; x++) {
pixelColorValues[x][y] = 0;
}
}
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() {
Terrain.playerCityTerrain = new Terrain();
}
public static void GenerateCustomHeightMap(Zone zone) {
Terrain heightMap = new Terrain(zone);
Terrain.heightmapByLoadNum.put(zone.template, heightMap);
}
@@ -245,91 +92,19 @@ public class Terrain {
}
public static void loadAlHeightMaps() {
// Load the heightmaps into staging hashmap keyed by HashMapID
DbManager.HeightMapQueries.LOAD_ALL_HEIGHTMAPS();
//generate static player city heightmap.
Terrain.GeneratePlayerCityHeightMap();
Logger.info(Terrain.heightmapByLoadNum.size() + " Heightmaps cached.");
// Load pixel data for heightmaps
try (Stream<Path> filePathStream = Files.walk(Paths.get(ConfigManager.DEFAULT_DATA_DIR + "heightmaps/TARGA/"))) {
filePathStream.forEach(filePath -> {
if (Files.isRegularFile(filePath)) {
File imageFile = filePath.toFile();
try {
BufferedImage heightmapImage = ImageIO.read(imageFile);
// Generate pixel data for this heightmap. RPG channels are all the same
// in this greyscale TGA heightmap. We will choose red.
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] = (short) color.getRed();
}
// Insert color data into lookup table
int heightMapID = Integer.parseInt(imageFile.getName().substring(0, imageFile.getName().lastIndexOf(".")));
_pixelData.put(heightMapID, colorData);
} catch (IOException e) {
Logger.error(e);
}
}
}); // Try with resources block
} catch (IOException e) {
Logger.error(e);
}
}
private static void generatePixelData(Terrain terrain) {
Color color;
// Generate altitude lookup table for this heightmap
terrain.pixelColorValues = new short[terrain.heightmapImage.getWidth()][terrain.heightmapImage.getHeight()];
for (int y = 0; y < terrain.heightmapImage.getHeight(); y++) {
for (int x = 0; x < terrain.heightmapImage.getWidth(); x++) {
color = new Color(terrain.heightmapImage.getRGB(x, y));
terrain.pixelColorValues[x][y] = (short) color.getRed();
}
}
}
public Vector2f getTerrainCell(Vector2f terrainLoc) {
float terrainCell_x = terrainLoc.x / this.cell_size_x;
float terrainCell_y = terrainLoc.y / this.cell_size_y;
Vector2f terrain_cell = new Vector2f(terrainLoc.x / this.cell_size.x, terrainLoc.y / this.cell_size.y);
// Clamp values when standing directly on max pole
if (terrainCell_x >= this.cell_count_x)
terrainCell_x = terrainCell_x - 1;
if (terrain_cell.x >= this.cell_count.x)
terrain_cell.x = terrain_cell.x - 1;
if (terrainCell_y >= this.cell_count_y)
terrainCell_y = terrainCell_x - 1;
if (terrain_cell.x >= this.cell_count.y)
terrain_cell.y = terrain_cell.y - 1;
return new Vector2f(terrainCell_x, terrainCell_y);
return terrain_cell;
}
public float getInterpolatedTerrainHeight(Vector2f terrainLoc) {
@@ -351,10 +126,10 @@ public class Terrain {
float bottomLeftHeight;
float bottomRightHeight;
topLeftHeight = pixelColorValues[gridX][gridY];
topRightHeight = pixelColorValues[gridX + 1][gridY];
bottomLeftHeight = pixelColorValues[gridX][gridY + 1];
bottomRightHeight = pixelColorValues[gridX + 1][gridY + 1];
topLeftHeight = terrain_pixel_data[gridX][gridY];
topRightHeight = terrain_pixel_data[gridX + 1][gridY];
bottomLeftHeight = terrain_pixel_data[gridX][gridY + 1];
bottomRightHeight = terrain_pixel_data[gridX + 1][gridY + 1];
// Interpolate between the 4 vertices
@@ -367,5 +142,4 @@ public class Terrain {
return interpolatedHeight;
}
}