Terrain: Parse-Fixes — PackedFloat32Array hat kein .min()/.max() (_min_h/_max_h), stray y += 1 in apply_brush entfernt, Default-Resolution 129 (Editor-MVP-Limit)

This commit is contained in:
Hermes (godot-vr) 2026-10-15 10:36:06 +00:00
parent 30379bcc7b
commit 10fdb4914c
5 changed files with 34 additions and 13 deletions

View file

@ -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:

View file

@ -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:

View file

@ -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

View file

@ -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:

View file

@ -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"