From 10fdb4914ce9d014b98719111494e65121406a24 Mon Sep 17 00:00:00 2001 From: "Hermes (godot-vr)" Date: Thu, 15 Oct 2026 10:36:06 +0000 Subject: [PATCH] =?UTF-8?q?Terrain:=20Parse-Fixes=20=E2=80=94=20PackedFloa?= =?UTF-8?q?t32Array=20hat=20kein=20.min()/.max()=20(=5Fmin=5Fh/=5Fmax=5Fh)?= =?UTF-8?q?,=20stray=20y=20+=3D=201=20in=20apply=5Fbrush=20entfernt,=20Def?= =?UTF-8?q?ault-Resolution=20129=20(Editor-MVP-Limit)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/editor/terrain_tool.gd | 4 ++-- src/svmap/terrain_field.gd | 22 +++++++++++++++++++--- src/viewport/terrain_mesh.gd | 9 +++++++-- tests/test_editor_svmap.gd | 4 ++-- tests/test_terrain.gd | 8 ++++---- 5 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/editor/terrain_tool.gd b/src/editor/terrain_tool.gd index 3b1b1a7..5fe2329 100644 --- a/src/editor/terrain_tool.gd +++ b/src/editor/terrain_tool.gd @@ -222,8 +222,8 @@ func _process(delta: float) -> void: ## Die Range gehört zum terrain-Block → Undo stellt sie mit zurück. Spannweite ## bleibt ≤ 500 m (V6). func _expand_range_if_needed() -> void: - var lo := _heights.min() - var hi := _heights.max() + var lo := TerrainField._min_h(_heights) + var hi := TerrainField._max_h(_heights) if lo < _hmin: _hmin = floorf(lo - 1.0) if hi > _hmax: diff --git a/src/svmap/terrain_field.gd b/src/svmap/terrain_field.gd index b94ef90..bbf9722 100644 --- a/src/svmap/terrain_field.gd +++ b/src/svmap/terrain_field.gd @@ -82,7 +82,6 @@ static func apply_brush(heights: PackedFloat32Array, res: int, size_x: float, si heights[idx] = nh changed = true x += 1 - y += 1 return changed @@ -185,13 +184,30 @@ static func raycast(heights: PackedFloat32Array, res: int, size_x: float, size_z prev_t = t # Nichts getroffen → Basis-Ebene als Fallback (wie interaction._ground_point). if absf(d.y) > 0.0001: - var plane_y := heights.min() - var t_plane := (plane_y - origin.y) / d.y + var plane_y: float = _min_h(heights) + var t_plane: float = (plane_y - origin.y) / d.y if t_plane > 0.0: return origin + d * t_plane return null +## Minimum/Maximum des Feldes (PackedFloat32Array hat kein .min()/.max()). +static func _min_h(heights: PackedFloat32Array) -> float: + var out := INF + for v in heights: + if v < out: + out = v + return out + + +static func _max_h(heights: PackedFloat32Array) -> float: + var out := -INF + for v in heights: + if v > out: + out = v + return out + + ## f(t) < 0 → Strahl unter dem Terrain. (prev_f-Nutzung vermieden Godot-Warnung.) static func _ray_error(heights: PackedFloat32Array, res: int, size_x: float, size_z: float, origin: Vector3, dir: Vector3, t: float) -> float: diff --git a/src/viewport/terrain_mesh.gd b/src/viewport/terrain_mesh.gd index b4a872a..37fe8b2 100644 --- a/src/viewport/terrain_mesh.gd +++ b/src/viewport/terrain_mesh.gd @@ -67,8 +67,13 @@ func update_heights(heights: PackedFloat32Array, res: int = 0, size_x: float = 0 normals.resize(res * res) colors.resize(res * res) - var hmin := heights.min() - var hmax := heights.max() + var hmin := INF + var hmax := -INF + for v in heights: + if v < hmin: + hmin = v + if v > hmax: + hmax = v var span := maxf(hmax - hmin, 0.0001) var cell_x := size_x / last var cell_z := size_z / last diff --git a/tests/test_editor_svmap.gd b/tests/test_editor_svmap.gd index b245498..49de6f1 100644 --- a/tests/test_editor_svmap.gd +++ b/tests/test_editor_svmap.gd @@ -53,9 +53,9 @@ func _run_tests() -> void: _check((doc["spawn_zones"]["0"]["points"] as Array).size() == 4, "Team 0: 4 Default-Spawns") _check((doc["spawn_zones"]["1"]["points"] as Array).size() == 4, "Team 1: 4 Default-Spawns") var terrain: Dictionary = doc["terrain"] - _check(int(terrain["resolution"]) == 257, "Default-Auflösung 257") + _check(int(terrain["resolution"]) == 129, "Default-Auflösung 129 (Editor-MVP-Perf-Limit, Karte t_9aba04f1)") var raw := Marshalls.base64_to_raw(str(terrain["heightmap_r16_b64"])) - _check(raw.size() == 257 * 257 * 2, "Höhenfeld-Länge = resolution² × 2") + _check(raw.size() == 129 * 129 * 2, "Höhenfeld-Länge = resolution² × 2") var flat := true for i in raw.size(): if raw[i] != 0: diff --git a/tests/test_terrain.gd b/tests/test_terrain.gd index d063482..c70c48e 100644 --- a/tests/test_terrain.gd +++ b/tests/test_terrain.gd @@ -157,8 +157,8 @@ func _test_range_expansion() -> void: TerrainField.apply_brush(heights, 129, 1024.0, 1024.0, -100000.0, 100000.0, 0.0, 0.0, 50.0, TerrainField.Mode.LOWER, 6.0) _check(heights[64 * 129 + 64] < -5.0, "Senken UNTER 0 m möglich (kein Clamp an min_height)") - var hmin := floorf(heights.min() - 1.0) - var hmax := maxf(float(terrain["max_height_m"]), ceilf(heights.max() + 1.0)) + var hmin := floorf(TerrainField._min_h(heights) - 1.0) + var hmax := maxf(float(terrain["max_height_m"]), ceilf(TerrainField._max_h(heights) + 1.0)) terrain["min_height_m"] = hmin terrain["max_height_m"] = hmax terrain["heightmap_r16_b64"] = TerrainField.encode(heights, hmin, hmax) @@ -183,8 +183,8 @@ func _test_svmap_roundtrip() -> void: -200.0, 100.0, 80.0, TerrainField.Mode.RAISE, 18.0) TerrainField.apply_brush(heights, 129, 1024.0, 1024.0, -100000.0, 100000.0, 300.0, -300.0, 60.0, TerrainField.Mode.LOWER, 9.0) - terrain["min_height_m"] = floorf(heights.min() - 1.0) - terrain["max_height_m"] = ceilf(heights.max() + 1.0) + terrain["min_height_m"] = floorf(TerrainField._min_h(heights) - 1.0) + terrain["max_height_m"] = ceilf(TerrainField._max_h(heights) + 1.0) terrain["heightmap_r16_b64"] = TerrainField.encode(heights, float(terrain["min_height_m"]), float(terrain["max_height_m"])) var path := "/tmp/scopedvr_test_terrain_roundtrip.svmap"