Files
magicbane/src/engine/InterestManagement/Terrain.java
T

145 lines
4.6 KiB
Java
Raw Normal View History

2022-04-30 09:41:17 -04:00
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// 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;
2023-10-08 09:18:43 -04:00
public class Terrain {
2022-04-30 09:41:17 -04:00
// Class variables
2023-10-08 09:49:49 -04:00
public static final HashMap<Integer, short[][]> _heightmap_pixel_cache = new HashMap<>();
2023-09-20 11:59:43 -04:00
2022-04-30 09:41:17 -04:00
2023-10-08 09:49:49 -04:00
public int template;
public short[][] terrain_pixel_data;
2023-10-08 09:49:49 -04:00
public Vector2f terrain_size = new Vector2f();
public Vector2f cell_size = new Vector2f();
public Vector2f cell_count = new Vector2f();
2023-10-08 09:04:15 -04:00
public float terrain_scale;
2023-10-08 09:49:49 -04:00
public static int heightMapsCreated;
2022-04-30 09:41:17 -04:00
2023-10-08 09:18:43 -04:00
public Terrain() {
2022-04-30 09:41:17 -04:00
}
2023-03-22 05:41:39 -04:00
public static Zone getNextZoneWithTerrain(Zone zone) {
2023-10-08 09:09:50 -04:00
Zone terrain_zone = zone;
2023-03-22 05:41:39 -04:00
2023-10-08 09:59:13 -04:00
if (zone.terrain != null)
2023-03-22 05:41:39 -04:00
return zone;
if (zone.equals(ZoneManager.getSeaFloor()))
return zone;
2023-10-08 09:59:13 -04:00
while (terrain_zone.terrain == null)
2023-10-08 09:09:50 -04:00
terrain_zone = terrain_zone.parent;
2023-03-22 05:41:39 -04:00
2023-10-08 09:09:50 -04:00
return terrain_zone;
2023-03-22 05:41:39 -04:00
}
2023-09-11 11:01:09 -04:00
public static float getWorldHeight(Zone currentZone, Vector3fImmutable worldLoc) {
2022-04-30 09:41:17 -04:00
2023-10-08 09:09:50 -04:00
Zone terrainZone;
2022-04-30 09:41:17 -04:00
2023-09-16 13:18:36 -04:00
// Seafloor is rather flat.
2022-04-30 09:41:17 -04:00
2023-03-22 05:41:39 -04:00
if (currentZone == ZoneManager.getSeaFloor())
2023-09-16 13:18:36 -04:00
return currentZone.worldAltitude;
2023-03-22 05:41:39 -04:00
2023-09-16 13:18:36 -04:00
// Retrieve the next zone with a heightmap attached.
// Zones without a heightmap use the next zone up the
// tree to calculate heights from.
2022-04-30 09:41:17 -04:00
2023-10-08 09:09:50 -04:00
terrainZone = getNextZoneWithTerrain(currentZone);
2023-09-11 11:01:09 -04:00
2023-09-16 13:18:36 -04:00
// Transform world loc into zone space coordinate system
2022-04-30 09:41:17 -04:00
2023-10-08 09:09:50 -04:00
Vector2f terrainLoc = ZoneManager.worldToZoneSpace(worldLoc, terrainZone);
2022-04-30 09:41:17 -04:00
2023-09-16 13:18:36 -04:00
// Interpolate height for this position using pixel array.
2022-04-30 09:41:17 -04:00
2023-10-08 09:59:13 -04:00
float interpolatedTerrainHeight = terrainZone.terrain.getInterpolatedTerrainHeight(terrainLoc);
2023-10-08 09:09:50 -04:00
interpolatedTerrainHeight += terrainZone.worldAltitude;
2023-09-16 13:18:36 -04:00
2023-09-18 03:19:00 -04:00
return interpolatedTerrainHeight;
2023-10-07 20:04:26 -04:00
2022-04-30 09:41:17 -04:00
}
public static float getWorldHeight(Vector3fImmutable worldLoc) {
Zone currentZone = ZoneManager.findSmallestZone(worldLoc);
if (currentZone == null)
return 0;
2023-10-08 09:04:15 -04:00
2023-09-11 11:01:09 -04:00
return getWorldHeight(currentZone, worldLoc);
2022-04-30 09:41:17 -04:00
}
2023-10-08 09:09:50 -04:00
public Vector2f getTerrainCell(Vector2f terrainLoc) {
2023-07-15 09:23:48 -04:00
2023-10-08 09:49:49 -04:00
Vector2f terrain_cell = new Vector2f(terrainLoc.x / this.cell_size.x, terrainLoc.y / this.cell_size.y);
2023-07-15 09:23:48 -04:00
2023-10-08 09:04:15 -04:00
// Clamp values when standing directly on max pole
2023-10-07 20:32:08 -04:00
2023-10-08 09:49:49 -04:00
if (terrain_cell.x >= this.cell_count.x)
terrain_cell.x = terrain_cell.x - 1;
2023-10-07 20:47:35 -04:00
2023-10-08 09:49:49 -04:00
if (terrain_cell.x >= this.cell_count.y)
terrain_cell.y = terrain_cell.y - 1;
2023-10-07 20:47:35 -04:00
2023-10-08 09:49:49 -04:00
return terrain_cell;
2023-07-15 09:23:48 -04:00
}
2023-10-08 09:04:15 -04:00
public float getInterpolatedTerrainHeight(Vector2f terrainLoc) {
2023-07-15 09:23:48 -04:00
2023-09-20 14:20:22 -04:00
float interpolatedHeight;
2023-07-15 09:23:48 -04:00
2023-10-08 09:09:50 -04:00
Vector2f terrain_cell = getTerrainCell(terrainLoc);
2023-07-15 09:23:48 -04:00
2023-10-08 09:09:50 -04:00
int gridX = (int) Math.floor(terrain_cell.x);
int gridY = (int) Math.floor(terrain_cell.y);
2023-10-08 09:04:15 -04:00
2023-10-08 09:09:50 -04:00
float offsetX = terrain_cell.x % 1;
float offsetY = terrain_cell.y % 1;
2023-07-15 09:23:48 -04:00
2023-09-20 14:20:22 -04:00
//get 4 surrounding vertices from the pixel array.
2023-07-15 09:23:48 -04:00
2023-09-20 14:14:55 -04:00
float topLeftHeight;
float topRightHeight;
float bottomLeftHeight;
float bottomRightHeight;
2023-07-15 09:23:48 -04:00
2023-10-08 09:49:49 -04:00
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];
2023-07-15 09:23:48 -04:00
2023-09-20 14:20:22 -04:00
// Interpolate between the 4 vertices
2023-07-15 09:23:48 -04:00
interpolatedHeight = topRightHeight * (1 - offsetY) * (offsetX);
interpolatedHeight += (bottomRightHeight * offsetY * offsetX);
interpolatedHeight += (bottomLeftHeight * (1 - offsetX) * offsetY);
interpolatedHeight += (topLeftHeight * (1 - offsetX) * (1 - offsetY));
2023-10-08 09:04:15 -04:00
interpolatedHeight *= this.terrain_scale; // Scale height
2023-07-15 09:23:48 -04:00
return interpolatedHeight;
}
2022-04-30 09:41:17 -04:00
}