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
|
// Rand hin auslaufende Rampe über die vollen RADIUS Meter, statt eines
|
||||||
// abrupten Sprungs zwischen "geramped" und "unverändert flach".
|
// abrupten Sprungs zwischen "geramped" und "unverändert flach".
|
||||||
float smoothH;
|
float smoothH;
|
||||||
if (hUp == null) {
|
if (hUp == null || hDown == null) {
|
||||||
smoothH = h0; // Plateau
|
// Plateau (kein höherer Nachbar) ODER unterste/äußerste Ebene
|
||||||
} else if (hDown == null) {
|
// (kein niedrigerer Voxel-Nachbar): Höhe unverändert lassen.
|
||||||
// Kein niedrigerer Voxel-Nachbar: obere Rampe zum Rand hin auslaufen lassen.
|
// Die Formel darf hier NICHT angewendet werden – sie würde die
|
||||||
float dDown = RADIUS - 1;
|
// unterste Terrasse künstlich in Richtung hUp anheben und das
|
||||||
smoothH = (h0 * dUp + hUp * dDown) / (dUp + dDown);
|
// gebackene Terrain systematisch zu hoch machen.
|
||||||
|
smoothH = h0;
|
||||||
} else {
|
} else {
|
||||||
float dDown = dDownRaw - 1;
|
float dDown = dDownRaw - 1;
|
||||||
smoothH = (dDown <= 0f) ? h0 : (h0 * dUp + hUp * dDown) / (dUp + dDown);
|
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.
|
// 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}};
|
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.
|
// Perimeter-Extension deaktiviert – saubere Kante an der Voxel-Grenze.
|
||||||
java.util.Set<Long> candidates = new java.util.HashSet<>();
|
// (Berechnung auskommentiert, Code bleibt für spätere Nutzung erhalten.)
|
||||||
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());
|
|
||||||
} */
|
|
||||||
|
|
||||||
// ── Schritt 3: Dichte anpassen ────────────────────────────────────
|
// ── Schritt 3: Dichte anpassen ────────────────────────────────────
|
||||||
// ALLE Spalten aus hfMap bekommen den Dichte-Gradienten geschrieben, auch
|
// 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