Voxel-Backen: Tunnel- und Höhlen-Support
Tunnel-Spalten werden im Gradientenschreiben jetzt vollständig geschützt: Pre-Scan erkennt echte Tunnel (void ≥ Terrain-Höhe mit festem Voxel darüber) und überspringt dann sämtliche negativen Zellen in dieser Spalte – auch unter-terrain-liegende. Damit erzeugt MC keinen Plateau-Boden mehr am Tunnel-Eingang. Terrain-Übergang-Extrapolation bekommt zusätzlich einen hasVoidBelow-Check: existieren leere Zellen unterhalb von yBot im geblurrten Chunk, wird die Extrapolation übersprungen, statt den Hohlraum zuzuschütten. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -597,6 +597,11 @@ public class VoxelEditorState extends BaseAppState {
|
||||
return (h & 0x7FFFFFFF) / (float) 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
/** Gibt eine Momentaufnahme aller aktuell geladenen Chunks zurück (thread-safe). */
|
||||
public List<VoxelChunk> getChunksSnapshot() {
|
||||
return new java.util.ArrayList<>(chunks.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Speichert alle dirty Chunks synchron.
|
||||
* Kann von außen aufgerufen werden (z.B. beim globalen Speichern).
|
||||
@@ -2476,20 +2481,45 @@ public class VoxelEditorState extends BaseAppState {
|
||||
Float smoothH = smoothMap.get(hk0);
|
||||
if (h0 == null || smoothH == null) continue;
|
||||
|
||||
// Wichtig: colX ist chunk-global (cx*CELLS+bx), kein World-X.
|
||||
// World-X = colX - 2048 (VoxelChunk.toWorldX-Konvention).
|
||||
float th = terrainH((float)(colX - 2048), (float)(colZ - 2048));
|
||||
|
||||
// Pre-Scan: hat diese Spalte einen echten Tunnel?
|
||||
// (negative Zelle auf/über Terrain-Höhe mit festem Voxel darüber)
|
||||
// Tunnel-Spalten bekommen gar keinen positiven Gradienten in
|
||||
// negative Zellen – weder Tunnel-Void noch Unter-Terrain-Cells –
|
||||
// damit kein Plateau auf dem Tunnelboden entsteht.
|
||||
boolean hasTunnelVoid = false;
|
||||
outer:
|
||||
for (int ly = 0; ly < blurN; ly++) {
|
||||
if ((wiyBase + ly) >= th
|
||||
&& origChunk.getDensity(bx, ly, bz) < 0) {
|
||||
for (int ly2 = ly + 1; ly2 < blurN; ly2++) {
|
||||
if (origChunk.getDensity(bx, ly2, bz) > 0) {
|
||||
hasTunnelVoid = true; break outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sub-voxel-genauen Dichte-Gradienten schreiben, damit MC die
|
||||
// Isofläche auf die exakte smoothH-Höhe interpoliert.
|
||||
// Ausnahme: manuell ausgegrabene Voxel (Tunnel/Höhlen) behalten
|
||||
// ihren MIN_VALUE – erkennbar daran dass Gradient solid will (d>0)
|
||||
// aber die Original-Dichte bereits Luft ist (MIN_VALUE).
|
||||
for (int by = 0; by < blurN; by++) {
|
||||
float d = (smoothH - (wiyBase + by)) * 127f;
|
||||
// Tunnel/Höhlen-Voxel schützen: Gradient will Solid (d>0),
|
||||
// aber der Voxel wurde ausgegraben (Dichte negativ) →
|
||||
// nicht mit Solid-Gradient überschreiben.
|
||||
// Gilt sowohl für Byte.MIN_VALUE (setDensity) als auch für
|
||||
// partiell-reduzierte Werte (reduceDensity im Cave-Modus).
|
||||
float worldY = wiyBase + by;
|
||||
float d = (smoothH - worldY) * 127f;
|
||||
if (d > 0f && origChunk.getDensity(bx, by, bz) < 0) {
|
||||
continue;
|
||||
if (hasTunnelVoid) continue; // Tunnel-Spalte: alle negativen Zellen schützen
|
||||
if (worldY >= th) {
|
||||
// Über Terrain, kein Tunnel-Flag → offene Höhle prüfen
|
||||
boolean solidAbove = false;
|
||||
for (int ly = by + 1; ly < blurN; ly++) {
|
||||
if (origChunk.getDensity(bx, ly, bz) > 0) {
|
||||
solidAbove = true; break;
|
||||
}
|
||||
}
|
||||
if (solidAbove) continue;
|
||||
}
|
||||
}
|
||||
next[c.idx(bx, by, bz)] = Math.max(-128f, Math.min(127f, d));
|
||||
}
|
||||
@@ -2604,6 +2634,15 @@ public class VoxelEditorState extends BaseAppState {
|
||||
}
|
||||
if (hasVoid) continue;
|
||||
|
||||
// Tunnel-Check: gibt es negative (leere) Zellen UNTERHALB von yBot?
|
||||
// Das passiert bei Tunneln/Höhlen, deren Decke yBot ist, aber das
|
||||
// Innere darunter liegt. Extrapolation würde den Hohlraum zuschütten.
|
||||
boolean hasVoidBelow = false;
|
||||
for (int ly = 0; ly < yBot; ly++) {
|
||||
if (blurred.getDensity(lx, ly, lz) < 0) { hasVoidBelow = true; break; }
|
||||
}
|
||||
if (hasVoidBelow) continue;
|
||||
|
||||
// Steigung aus den zwei Voxeln darüber bestimmen.
|
||||
// slope < 0: Dichte nimmt nach unten ab (typisch für eine Oberfläche).
|
||||
float d1 = blurred.getDensity(lx, yBot + 1, lz);
|
||||
|
||||
Reference in New Issue
Block a user