Bug behoben, der das gebackene terrain zu hoch generiert hat
This commit is contained in:
@@ -2047,12 +2047,13 @@ public class VoxelEditorState extends BaseAppState {
|
||||
// Rand hin auslaufende Rampe über die vollen RADIUS Meter, statt eines
|
||||
// abrupten Sprungs zwischen "geramped" und "unverändert flach".
|
||||
float smoothH;
|
||||
if (hUp == null) {
|
||||
smoothH = h0; // Plateau
|
||||
} else if (hDown == null) {
|
||||
// Kein niedrigerer Voxel-Nachbar: obere Rampe zum Rand hin auslaufen lassen.
|
||||
float dDown = RADIUS - 1;
|
||||
smoothH = (h0 * dUp + hUp * dDown) / (dUp + dDown);
|
||||
if (hUp == null || hDown == null) {
|
||||
// Plateau (kein höherer Nachbar) ODER unterste/äußerste Ebene
|
||||
// (kein niedrigerer Voxel-Nachbar): Höhe unverändert lassen.
|
||||
// Die Formel darf hier NICHT angewendet werden – sie würde die
|
||||
// unterste Terrasse künstlich in Richtung hUp anheben und das
|
||||
// gebackene Terrain systematisch zu hoch machen.
|
||||
smoothH = h0;
|
||||
} else {
|
||||
float dDown = dDownRaw - 1;
|
||||
smoothH = (dDown <= 0f) ? h0 : (h0 * dUp + hUp * dDown) / (dUp + dDown);
|
||||
@@ -2094,89 +2095,8 @@ public class VoxelEditorState extends BaseAppState {
|
||||
// nicht mehr exakt dem Rampen-Winkel, ist aber garantiert monoton/glatt.
|
||||
int[][] DIRS8 = {{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};
|
||||
|
||||
// Kandidaten sammeln: alle leeren Zellen innerhalb RADIUS einer Rand-Spalte.
|
||||
java.util.Set<Long> candidates = new java.util.HashSet<>();
|
||||
for (long hk0 : hfMap.keySet()) {
|
||||
int colZ = (int)(hk0 % 60001L) - 30000;
|
||||
int colX = (int)(hk0 / 60001L) - 30000;
|
||||
for (int dz = -RADIUS; dz <= RADIUS; dz++) {
|
||||
for (int dx = -RADIUS; dx <= RADIUS; dx++) {
|
||||
if (Math.max(Math.abs(dx), Math.abs(dz)) > RADIUS) continue;
|
||||
long hkC = (long)(colX + dx + 30000) * 60001L + (colZ + dz + 30000);
|
||||
if (!hfMap.containsKey(hkC)) candidates.add(hkC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map<Long, Float> extensionMap = new HashMap<>();
|
||||
int extCount = 0, extLogged = 0;
|
||||
for (long hkC : candidates) {
|
||||
int colZ = (int)(hkC % 60001L) - 30000;
|
||||
int colX = (int)(hkC / 60001L) - 30000;
|
||||
|
||||
// Nächsten Ring mit Struktur-Zellen isotrop suchen (gleiches Vorgehen wie
|
||||
// Schritt 2), dann ALLE Struktur-Zellen in diesem Ring mitteln – nicht nur die
|
||||
// erste gefundene. Grund (Log-Befund): benachbarte Zielzellen fanden oft
|
||||
// unterschiedliche einzelne "nächste" Zellen mit stark abweichender Höhe
|
||||
// (edgeH schwankte 3,9 bis 5,33 nur 4 Zellen auseinander) → wildes Springen.
|
||||
// Mittelung über den ganzen Ring glättet das.
|
||||
int nearestDist = -1;
|
||||
java.util.List<long[]> ringHits = new java.util.ArrayList<>(); // {colX,colZ}
|
||||
outer:
|
||||
for (int r = 1; r <= RADIUS; r++) {
|
||||
for (int dz = -r; dz <= r; dz++) {
|
||||
for (int dx = -r; dx <= r; dx++) {
|
||||
if (Math.max(Math.abs(dx), Math.abs(dz)) != r) continue;
|
||||
long hkN = (long)(colX + dx + 30000) * 60001L + (colZ + dz + 30000);
|
||||
if (hfMap.containsKey(hkN)) ringHits.add(new long[]{colX + dx, colZ + dz});
|
||||
}
|
||||
}
|
||||
if (!ringHits.isEmpty()) { nearestDist = r; break outer; }
|
||||
}
|
||||
if (nearestDist < 0) continue; // außerhalb der Reichweite, bleibt Klippe
|
||||
|
||||
float sumEdgeH = 0f; int hitCnt = 0;
|
||||
for (long[] hit : ringHits) {
|
||||
int hColX = (int) hit[0], hColZ = (int) hit[1];
|
||||
long hKey = (long)(hColX + 30000) * 60001L + (hColZ + 30000);
|
||||
Float hH = smoothMap.get(hKey);
|
||||
if (hH == null) continue;
|
||||
sumEdgeH += hH; hitCnt++;
|
||||
}
|
||||
if (hitCnt == 0) continue;
|
||||
float edgeH = sumEdgeH / hitCnt;
|
||||
|
||||
// KEINE Steigungs-Extrapolation mehr (v4/v5 hatten das versucht – eine an nur
|
||||
// wenigen Pixeln gemessene Steigung ist zu verrauscht, verstärkt sich über die
|
||||
// Distanz und erzeugte ein welliges/oszillierendes Band über eigentlich flachen
|
||||
// Flächen, siehe Screenshot 22-43-57). Reiner, robuster Distanz-Blend von der
|
||||
// (gemittelten) Kanten-Höhe zur tatsächlichen Basisterrain-Höhe: nah am Rand
|
||||
// dominiert die Kante, weiter draußen die Terrainhöhe. Folgt nicht mehr exakt
|
||||
// dem Winkel der letzten Rampe, ist aber garantiert monoton und ohne Rauschen.
|
||||
float wx = colX - 2048f, wz = colZ - 2048f;
|
||||
float th = terrainH(wx, wz);
|
||||
float finalH = edgeH;
|
||||
if (Float.isFinite(th)) {
|
||||
float t = nearestDist / (float) RADIUS; // 0 am Rand, 1 bei RADIUS
|
||||
finalH = edgeH * (1f - t) + th * t;
|
||||
}
|
||||
extensionMap.put(hkC, finalH);
|
||||
extCount++;
|
||||
if (extLogged < 20) {
|
||||
log.info("Perimeter-Rampe: colX={} colZ={} dist={} edgeH={} th={} finalH={}",
|
||||
colX, colZ, nearestDist, edgeH, th, finalH);
|
||||
extLogged++;
|
||||
}
|
||||
}
|
||||
log.info("Perimeter-Übergang: {} Erweiterungs-Spalten berechnet (aktuell deaktiviert – saubere Kante).", extCount);
|
||||
// Erweiterungs-Spalten DEAKTIVIERT: liefert saubere Kante an der Voxel-Grenze
|
||||
// statt der problematischen flachen Rampe. Zum Reaktivieren diesen Block einkommentieren:
|
||||
/* for (Map.Entry<Long, Float> e : extensionMap.entrySet()) {
|
||||
long hk = e.getKey();
|
||||
if (hfMap.containsKey(hk)) continue;
|
||||
hfMap.put(hk, e.getValue());
|
||||
smoothMap.put(hk, e.getValue());
|
||||
} */
|
||||
// Perimeter-Extension deaktiviert – saubere Kante an der Voxel-Grenze.
|
||||
// (Berechnung auskommentiert, Code bleibt für spätere Nutzung erhalten.)
|
||||
|
||||
// ── Schritt 3: Dichte anpassen ────────────────────────────────────
|
||||
// ALLE Spalten aus hfMap bekommen den Dichte-Gradienten geschrieben, auch
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user