Mehrere Probleme behoben
This commit is contained in:
@@ -7,7 +7,7 @@ import java.util.zip.*;
|
||||
/**
|
||||
* Konstanten, Datei-I/O und Hilfsmethoden für das chunk-basierte Terrain-System.
|
||||
*
|
||||
* Die Welt (4096 × 4096 m) wird in CHUNKS_PER_AXIS² = 32² = 1024 quadratische
|
||||
* Die Welt (2048 × 2048 m) wird in CHUNKS_PER_AXIS² = 16² = 256 quadratische
|
||||
* Chunks à CHUNK_SIZE = 128 m unterteilt. Jeder Chunk speichert CHUNK_VERTS² = 129²
|
||||
* Höhenwerte bei 1 m Auflösung (native Editor-Auflösung).
|
||||
*
|
||||
@@ -22,9 +22,9 @@ public final class ChunkTerrainIO {
|
||||
|
||||
// ── Welt / Chunk-Konfiguration ─────────────────────────────────────────────
|
||||
public static final int CHUNK_SIZE = 128;
|
||||
public static final int WORLD_SIZE = 4096;
|
||||
public static final int CHUNKS_PER_AXIS = WORLD_SIZE / CHUNK_SIZE; // 32
|
||||
public static final int CHUNK_COUNT = CHUNKS_PER_AXIS * CHUNKS_PER_AXIS; // 1024
|
||||
public static final int WORLD_SIZE = 2048;
|
||||
public static final int CHUNKS_PER_AXIS = WORLD_SIZE / CHUNK_SIZE; // 16
|
||||
public static final int CHUNK_COUNT = CHUNKS_PER_AXIS * CHUNKS_PER_AXIS; // 256
|
||||
/** Vertices pro Kante bei nativer 1-m-Auflösung (inklusiv). */
|
||||
public static final int CHUNK_VERTS = CHUNK_SIZE + 1; // 129
|
||||
|
||||
@@ -133,7 +133,7 @@ public final class ChunkTerrainIO {
|
||||
}
|
||||
|
||||
/**
|
||||
* Migriert eine alte MapData (16385 × 16385 Höhenwerte, 0,25 m/Vertex)
|
||||
* Migriert MapData (8193 × 8193 Höhenwerte, 0,25 m/Vertex)
|
||||
* in das Chunk-Format. Jeder Chunk enthält 129 × 129 Werte (jeder 4. Quell-Vertex).
|
||||
*/
|
||||
public static void exportFromMapData(MapData data) throws IOException {
|
||||
@@ -155,7 +155,7 @@ public final class ChunkTerrainIO {
|
||||
}
|
||||
}
|
||||
|
||||
/** Erzeugt leere (flache) Chunk-Dateien mit Höhe 1.0 für alle 1024 Chunks. */
|
||||
/** Erzeugt leere (flache) Chunk-Dateien mit Höhe 1.0 für alle 256 Chunks. */
|
||||
public static void exportBlankChunks() throws IOException {
|
||||
float[] flat = new float[CHUNK_VERTS * CHUNK_VERTS];
|
||||
java.util.Arrays.fill(flat, 1f);
|
||||
|
||||
@@ -3,10 +3,10 @@ package de.blight.common;
|
||||
/**
|
||||
* Serialisierbarer Zustand einer Blight-Weltkarte.
|
||||
*
|
||||
* Basis-Terrain : 16385 × 16385 Vertices (= 16384 × 16384 Zellen, 0,25 m/Vertex),
|
||||
* Welt −2048 .. +2048 m.
|
||||
* Obere Schicht : 513 × 513 Vertices (= 512 × 512 Zellen), gleiche Weltausdehnung.
|
||||
* Splatmap : 2049 × 2049 Pixel (≈ 2 m/Pixel).
|
||||
* Basis-Terrain : 8193 × 8193 Vertices (= 8192 × 8192 Zellen, 0,25 m/Vertex),
|
||||
* Welt −1024 .. +1024 m.
|
||||
* Obere Schicht : 257 × 257 Vertices (= 256 × 256 Zellen), gleiche Weltausdehnung.
|
||||
* Splatmap : 1025 × 1025 Pixel (≈ 2 m/Pixel).
|
||||
* Kanäle R/G/B/A = Gewicht für Tex1-Helligkeit / Tex2 / Tex3 / Tex4.
|
||||
*/
|
||||
public final class MapData {
|
||||
@@ -14,20 +14,20 @@ public final class MapData {
|
||||
// ── Terrain-Konstanten ────────────────────────────────────────────────────
|
||||
|
||||
/** Vertices pro Achse des Basis-Terrains (muss 2^n + 1 sein). */
|
||||
public static final int TERRAIN_VERTS = 16385;
|
||||
public static final int TERRAIN_VERTS = 8193;
|
||||
|
||||
// ── Upper-Layer-Konstanten ────────────────────────────────────────────────
|
||||
|
||||
/** Zellen pro Achse der oberen Schicht. */
|
||||
public static final int UPPER_CELLS = 512;
|
||||
public static final int UPPER_CELLS = 256;
|
||||
|
||||
/** Vertices pro Achse der oberen Schicht (UPPER_CELLS + 1). */
|
||||
public static final int UPPER_VERTS = 513;
|
||||
public static final int UPPER_VERTS = 257;
|
||||
|
||||
// ── Splatmap-Konstanten ────────────────────────────────────────────────────
|
||||
|
||||
/** Pixel pro Achse der Splatmap (≈ 2 m/Pixel bei 4096 m Weltkante). */
|
||||
public static final int SPLAT_SIZE = 2049;
|
||||
/** Pixel pro Achse der Splatmap (≈ 2 m/Pixel bei 2048 m Weltkante). */
|
||||
public static final int SPLAT_SIZE = 1025;
|
||||
|
||||
/** Anzahl konfigurierbarer Textur-Slots pro Terrain-Layer. */
|
||||
public static final int TEXTURE_SLOTS = 4;
|
||||
|
||||
@@ -27,6 +27,8 @@ import java.util.zip.*;
|
||||
* 9 – wie 8 + Gras-Textur-Map (SPLAT_SIZE² Bytes) + Slots (N×UTF)
|
||||
* 10 – wie 9, aber TERRAIN_VERTS=16385 (0,25 m/Vertex) + SPLAT_SIZE=2049 (2 m/Pixel)
|
||||
* Altes Format (v≤9) wird beim Laden bilinear hochskaliert.
|
||||
* 16 – Kartengröße halbiert: TERRAIN_VERTS=8193, SPLAT_SIZE=1025, UPPER_CELLS=256.
|
||||
* Format v10-v15 wird beim Laden bilinear auf neue Größe herunterskaliert.
|
||||
*/
|
||||
public final class MapIO {
|
||||
|
||||
@@ -63,11 +65,15 @@ public final class MapIO {
|
||||
}
|
||||
|
||||
private static final int MAGIC = 0x424C4947; // "BLIG"
|
||||
private static final int VERSION = 15;
|
||||
private static final int VERSION = 16;
|
||||
|
||||
// Größen älterer Saves (v≤9) – für Migrations-Upsampling
|
||||
private static final int OLD_TERRAIN_VERTS = 4097;
|
||||
private static final int OLD_SPLAT_SIZE = 513;
|
||||
// Größen alter Saves für Migration
|
||||
private static final int V10_TERRAIN_VERTS = 16385; // v10-v15
|
||||
private static final int V10_SPLAT_SIZE = 2049; // v10-v15
|
||||
private static final int V10_UPPER_VERTS = 513; // v10-v15
|
||||
private static final int V10_UPPER_CELLS = 512; // v10-v15
|
||||
private static final int OLD_TERRAIN_VERTS = 4097; // v≤9
|
||||
private static final int OLD_SPLAT_SIZE = 513; // v≤9
|
||||
|
||||
private MapIO() {}
|
||||
|
||||
@@ -178,20 +184,35 @@ public final class MapIO {
|
||||
}
|
||||
|
||||
public static MapData load() throws IOException {
|
||||
return loadFrom(MAP_PATH);
|
||||
}
|
||||
|
||||
public static MapData loadFrom(Path path) throws IOException {
|
||||
MapData data = new MapData();
|
||||
try (DataInputStream in = new DataInputStream(
|
||||
new BufferedInputStream(
|
||||
new GZIPInputStream(Files.newInputStream(MAP_PATH))))) {
|
||||
new GZIPInputStream(Files.newInputStream(path))))) {
|
||||
int magic = in.readInt();
|
||||
int version = in.readInt();
|
||||
if (magic != MAGIC) throw new IOException("Ungültige Map-Datei (falscher Magic)");
|
||||
if (version < 1 || version > VERSION)
|
||||
throw new IOException("Unbekannte Map-Version: " + version);
|
||||
|
||||
if (version >= 10) {
|
||||
if (version >= 16) {
|
||||
readFloats(in, data.terrainHeight);
|
||||
readFloats(in, data.upperTop);
|
||||
readFloats(in, data.upperBottom);
|
||||
} else if (version >= 10) {
|
||||
// v10-v15: Größe 16385/513 → bilinear auf 8193/257 herunterskalieren
|
||||
float[] v10H = new float[V10_TERRAIN_VERTS * V10_TERRAIN_VERTS];
|
||||
float[] v10UT = new float[V10_UPPER_VERTS * V10_UPPER_VERTS];
|
||||
float[] v10UB = new float[V10_UPPER_VERTS * V10_UPPER_VERTS];
|
||||
readFloats(in, v10H);
|
||||
readFloats(in, v10UT);
|
||||
readFloats(in, v10UB);
|
||||
downsampleFloats(v10H, V10_TERRAIN_VERTS, data.terrainHeight, MapData.TERRAIN_VERTS);
|
||||
downsampleFloats(v10UT, V10_UPPER_VERTS, data.upperTop, MapData.UPPER_VERTS);
|
||||
downsampleFloats(v10UB, V10_UPPER_VERTS, data.upperBottom, MapData.UPPER_VERTS);
|
||||
} else {
|
||||
// v≤9: alte Größen lesen und bilinear hochskalieren
|
||||
float[] oldH = new float[OLD_TERRAIN_VERTS * OLD_TERRAIN_VERTS];
|
||||
@@ -204,13 +225,21 @@ public final class MapIO {
|
||||
}
|
||||
|
||||
if (version <= 5) {
|
||||
// v5 had upperHole[UPPER_CELLS²]; read and discard
|
||||
in.skip((long) MapData.UPPER_CELLS * MapData.UPPER_CELLS);
|
||||
// v5 had upperHole[UPPER_CELLS²]; read and discard (old size = 512)
|
||||
in.skip((long) V10_UPPER_CELLS * V10_UPPER_CELLS);
|
||||
}
|
||||
|
||||
if (version >= 2) {
|
||||
if (version >= 10) {
|
||||
if (version >= 16) {
|
||||
in.readFully(data.splatR); in.readFully(data.splatG); in.readFully(data.splatB);
|
||||
} else if (version >= 10) {
|
||||
byte[] v10R = new byte[V10_SPLAT_SIZE*V10_SPLAT_SIZE];
|
||||
byte[] v10G = new byte[V10_SPLAT_SIZE*V10_SPLAT_SIZE];
|
||||
byte[] v10B = new byte[V10_SPLAT_SIZE*V10_SPLAT_SIZE];
|
||||
in.readFully(v10R); in.readFully(v10G); in.readFully(v10B);
|
||||
downsampleBytes(v10R, V10_SPLAT_SIZE, data.splatR, MapData.SPLAT_SIZE);
|
||||
downsampleBytes(v10G, V10_SPLAT_SIZE, data.splatG, MapData.SPLAT_SIZE);
|
||||
downsampleBytes(v10B, V10_SPLAT_SIZE, data.splatB, MapData.SPLAT_SIZE);
|
||||
} else {
|
||||
byte[] oR = new byte[OLD_SPLAT_SIZE*OLD_SPLAT_SIZE];
|
||||
byte[] oG = new byte[OLD_SPLAT_SIZE*OLD_SPLAT_SIZE];
|
||||
@@ -222,8 +251,12 @@ public final class MapIO {
|
||||
}
|
||||
}
|
||||
if (version >= 3) {
|
||||
if (version >= 10) {
|
||||
if (version >= 16) {
|
||||
in.readFully(data.grassDensity);
|
||||
} else if (version >= 10) {
|
||||
byte[] v10 = new byte[V10_SPLAT_SIZE*V10_SPLAT_SIZE];
|
||||
in.readFully(v10);
|
||||
downsampleBytes(v10, V10_SPLAT_SIZE, data.grassDensity, MapData.SPLAT_SIZE);
|
||||
} else {
|
||||
byte[] old = new byte[OLD_SPLAT_SIZE*OLD_SPLAT_SIZE];
|
||||
in.readFully(old);
|
||||
@@ -238,12 +271,27 @@ public final class MapIO {
|
||||
data.spawnYaw = in.readFloat();
|
||||
}
|
||||
if (version >= 5) {
|
||||
if (version >= 10) {
|
||||
if (version >= 16) {
|
||||
in.readFully(data.splatA);
|
||||
readStrings(in, data.terrainTextures);
|
||||
in.readFully(data.upperSplatR); in.readFully(data.upperSplatG);
|
||||
in.readFully(data.upperSplatB); in.readFully(data.upperSplatA);
|
||||
readStrings(in, data.upperTextures);
|
||||
} else if (version >= 10) {
|
||||
byte[] v10A = new byte[V10_SPLAT_SIZE*V10_SPLAT_SIZE];
|
||||
byte[] v10UR = new byte[V10_SPLAT_SIZE*V10_SPLAT_SIZE];
|
||||
byte[] v10UG = new byte[V10_SPLAT_SIZE*V10_SPLAT_SIZE];
|
||||
byte[] v10UB = new byte[V10_SPLAT_SIZE*V10_SPLAT_SIZE];
|
||||
byte[] v10UA = new byte[V10_SPLAT_SIZE*V10_SPLAT_SIZE];
|
||||
in.readFully(v10A);
|
||||
readStrings(in, data.terrainTextures);
|
||||
in.readFully(v10UR); in.readFully(v10UG); in.readFully(v10UB); in.readFully(v10UA);
|
||||
readStrings(in, data.upperTextures);
|
||||
downsampleBytes(v10A, V10_SPLAT_SIZE, data.splatA, MapData.SPLAT_SIZE);
|
||||
downsampleBytes(v10UR, V10_SPLAT_SIZE, data.upperSplatR, MapData.SPLAT_SIZE);
|
||||
downsampleBytes(v10UG, V10_SPLAT_SIZE, data.upperSplatG, MapData.SPLAT_SIZE);
|
||||
downsampleBytes(v10UB, V10_SPLAT_SIZE, data.upperSplatB, MapData.SPLAT_SIZE);
|
||||
downsampleBytes(v10UA, V10_SPLAT_SIZE, data.upperSplatA, MapData.SPLAT_SIZE);
|
||||
} else {
|
||||
byte[] oA = new byte[OLD_SPLAT_SIZE*OLD_SPLAT_SIZE];
|
||||
byte[] oUR = new byte[OLD_SPLAT_SIZE*OLD_SPLAT_SIZE];
|
||||
@@ -268,8 +316,12 @@ public final class MapIO {
|
||||
data.grassDefaultHeight = in.readFloat();
|
||||
}
|
||||
if (version >= 8) {
|
||||
if (version >= 10) {
|
||||
if (version >= 16) {
|
||||
in.readFully(data.grassHeightMap);
|
||||
} else if (version >= 10) {
|
||||
byte[] v10 = new byte[V10_SPLAT_SIZE*V10_SPLAT_SIZE];
|
||||
in.readFully(v10);
|
||||
downsampleBytes(v10, V10_SPLAT_SIZE, data.grassHeightMap, MapData.SPLAT_SIZE);
|
||||
} else {
|
||||
byte[] old = new byte[OLD_SPLAT_SIZE*OLD_SPLAT_SIZE];
|
||||
in.readFully(old);
|
||||
@@ -280,8 +332,12 @@ public final class MapIO {
|
||||
int n = in.readInt();
|
||||
data.grassTextureSlots = new String[n];
|
||||
for (int i = 0; i < n; i++) data.grassTextureSlots[i] = in.readUTF();
|
||||
if (version >= 10) {
|
||||
if (version >= 16) {
|
||||
in.readFully(data.grassTextureMap);
|
||||
} else if (version >= 10) {
|
||||
byte[] v10 = new byte[V10_SPLAT_SIZE*V10_SPLAT_SIZE];
|
||||
in.readFully(v10);
|
||||
downsampleBytes(v10, V10_SPLAT_SIZE, data.grassTextureMap, MapData.SPLAT_SIZE);
|
||||
} else {
|
||||
byte[] old = new byte[OLD_SPLAT_SIZE*OLD_SPLAT_SIZE];
|
||||
in.readFully(old);
|
||||
@@ -298,8 +354,20 @@ public final class MapIO {
|
||||
data.voxelCeilSlot = in.readInt();
|
||||
}
|
||||
if (version >= 13) {
|
||||
in.readFully(data.thirdSplatR); in.readFully(data.thirdSplatG);
|
||||
in.readFully(data.thirdSplatB); in.readFully(data.thirdSplatA);
|
||||
if (version >= 16) {
|
||||
in.readFully(data.thirdSplatR); in.readFully(data.thirdSplatG);
|
||||
in.readFully(data.thirdSplatB); in.readFully(data.thirdSplatA);
|
||||
} else {
|
||||
byte[] v10R = new byte[V10_SPLAT_SIZE*V10_SPLAT_SIZE];
|
||||
byte[] v10G = new byte[V10_SPLAT_SIZE*V10_SPLAT_SIZE];
|
||||
byte[] v10B = new byte[V10_SPLAT_SIZE*V10_SPLAT_SIZE];
|
||||
byte[] v10A = new byte[V10_SPLAT_SIZE*V10_SPLAT_SIZE];
|
||||
in.readFully(v10R); in.readFully(v10G); in.readFully(v10B); in.readFully(v10A);
|
||||
downsampleBytes(v10R, V10_SPLAT_SIZE, data.thirdSplatR, MapData.SPLAT_SIZE);
|
||||
downsampleBytes(v10G, V10_SPLAT_SIZE, data.thirdSplatG, MapData.SPLAT_SIZE);
|
||||
downsampleBytes(v10B, V10_SPLAT_SIZE, data.thirdSplatB, MapData.SPLAT_SIZE);
|
||||
downsampleBytes(v10A, V10_SPLAT_SIZE, data.thirdSplatA, MapData.SPLAT_SIZE);
|
||||
}
|
||||
readStrings(in, data.thirdTextures);
|
||||
readStrings(in, data.thirdNormalMaps);
|
||||
}
|
||||
@@ -353,6 +421,14 @@ public final class MapIO {
|
||||
for (int i = 0; i < len && i < arr.length; i++) arr[i] = in.readUTF();
|
||||
}
|
||||
|
||||
private static void downsampleFloats(float[] src, int srcSize, float[] dst, int dstSize) {
|
||||
upsampleFloats(src, srcSize, dst, dstSize);
|
||||
}
|
||||
|
||||
private static void downsampleBytes(byte[] src, int srcSize, byte[] dst, int dstSize) {
|
||||
upsampleBytes(src, srcSize, dst, dstSize);
|
||||
}
|
||||
|
||||
private static void upsampleFloats(float[] src, int srcSize, float[] dst, int dstSize) {
|
||||
float scale = (float)(srcSize - 1) / (dstSize - 1);
|
||||
for (int dz = 0; dz < dstSize; dz++) {
|
||||
|
||||
Reference in New Issue
Block a user