|
|
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
|
|
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
|
|
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
|
|
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
|
|
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
|
|
|
// Magicbane Emulator Project © 2013 - 2022
|
|
|
|
// www.magicbane.com
|
|
|
|
|
|
|
|
package engine.InterestManagement;
|
|
|
|
|
|
|
|
import engine.gameManager.ZoneManager;
|
|
|
|
import engine.math.Vector2f;
|
|
|
|
import engine.math.Vector3fImmutable;
|
|
|
|
import engine.objects.Zone;
|
|
|
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
|
|
|
public class Terrain {
|
|
|
|
|
|
|
|
// Class variables
|
|
|
|
|
|
|
|
public static final HashMap<Integer, short[][]> _heightmap_pixel_cache = new HashMap<>();
|
|
|
|
|
|
|
|
|
|
|
|
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 static int heightMapsCreated;
|
|
|
|
|
|
|
|
public Terrain() {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Zone getNextZoneWithTerrain(Zone zone) {
|
|
|
|
|
|
|
|
Zone terrain_zone = zone;
|
|
|
|
|
|
|
|
if (zone.getHeightMap() != null)
|
|
|
|
return zone;
|
|
|
|
|
|
|
|
if (zone.equals(ZoneManager.getSeaFloor()))
|
|
|
|
return zone;
|
|
|
|
|
|
|
|
while (terrain_zone.getHeightMap() == null)
|
|
|
|
terrain_zone = terrain_zone.parent;
|
|
|
|
|
|
|
|
return terrain_zone;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static float getWorldHeight(Zone currentZone, Vector3fImmutable worldLoc) {
|
|
|
|
|
|
|
|
Zone terrainZone;
|
|
|
|
|
|
|
|
// Seafloor is rather flat.
|
|
|
|
|
|
|
|
if (currentZone == ZoneManager.getSeaFloor())
|
|
|
|
return currentZone.worldAltitude;
|
|
|
|
|
|
|
|
// Retrieve the next zone with a heightmap attached.
|
|
|
|
// Zones without a heightmap use the next zone up the
|
|
|
|
// tree to calculate heights from.
|
|
|
|
|
|
|
|
terrainZone = getNextZoneWithTerrain(currentZone);
|
|
|
|
|
|
|
|
// Transform world loc into zone space coordinate system
|
|
|
|
|
|
|
|
Vector2f terrainLoc = ZoneManager.worldToZoneSpace(worldLoc, terrainZone);
|
|
|
|
|
|
|
|
// Interpolate height for this position using pixel array.
|
|
|
|
|
|
|
|
float interpolatedTerrainHeight = terrainZone.getHeightMap().getInterpolatedTerrainHeight(terrainLoc);
|
|
|
|
interpolatedTerrainHeight += terrainZone.worldAltitude;
|
|
|
|
|
|
|
|
return interpolatedTerrainHeight;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public static float getWorldHeight(Vector3fImmutable worldLoc) {
|
|
|
|
|
|
|
|
Zone currentZone = ZoneManager.findSmallestZone(worldLoc);
|
|
|
|
|
|
|
|
if (currentZone == null)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return getWorldHeight(currentZone, worldLoc);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public Vector2f getTerrainCell(Vector2f terrainLoc) {
|
|
|
|
|
|
|
|
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 (terrain_cell.x >= this.cell_count.x)
|
|
|
|
terrain_cell.x = terrain_cell.x - 1;
|
|
|
|
|
|
|
|
if (terrain_cell.x >= this.cell_count.y)
|
|
|
|
terrain_cell.y = terrain_cell.y - 1;
|
|
|
|
|
|
|
|
return terrain_cell;
|
|
|
|
}
|
|
|
|
|
|
|
|
public float getInterpolatedTerrainHeight(Vector2f terrainLoc) {
|
|
|
|
|
|
|
|
float interpolatedHeight;
|
|
|
|
|
|
|
|
Vector2f terrain_cell = getTerrainCell(terrainLoc);
|
|
|
|
|
|
|
|
int gridX = (int) Math.floor(terrain_cell.x);
|
|
|
|
int gridY = (int) Math.floor(terrain_cell.y);
|
|
|
|
|
|
|
|
float offsetX = terrain_cell.x % 1;
|
|
|
|
float offsetY = terrain_cell.y % 1;
|
|
|
|
|
|
|
|
//get 4 surrounding vertices from the pixel array.
|
|
|
|
|
|
|
|
float topLeftHeight;
|
|
|
|
float topRightHeight;
|
|
|
|
float bottomLeftHeight;
|
|
|
|
float bottomRightHeight;
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
interpolatedHeight = topRightHeight * (1 - offsetY) * (offsetX);
|
|
|
|
interpolatedHeight += (bottomRightHeight * offsetY * offsetX);
|
|
|
|
interpolatedHeight += (bottomLeftHeight * (1 - offsetX) * offsetY);
|
|
|
|
interpolatedHeight += (topLeftHeight * (1 - offsetX) * (1 - offsetY));
|
|
|
|
|
|
|
|
interpolatedHeight *= this.terrain_scale; // Scale height
|
|
|
|
|
|
|
|
return interpolatedHeight;
|
|
|
|
}
|
|
|
|
}
|