| … | … | @@ -14,7 +14,7 @@ would read as success. |
| 14 | 14 | |
| 15 | 15 | python3 gate_dc_vs_lookdev.py [--bin /tmp/erosion_render4] |
| 16 | 16 | """ |
| 17 | | import argparse, os, subprocess, sys |
| 17 | import argparse, os, re, subprocess, sys |
| 18 | 18 | import numpy as np |
| 19 | 19 | |
| 20 | 20 | DC = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "dc-terrain")) |
| … | … | @@ -23,6 +23,49 @@ HBLK = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", |
| 23 | 23 | "diffusion_gully_30km.hblk")) |
| 24 | 24 | |
| 25 | 25 | |
| 26 | MAP_GD = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "hyper-tps", |
| 27 | "scenes", "maps", "map_dc_diffusion.gd")) |
| 28 | |
| 29 | |
| 30 | def map_params(): |
| 31 | """The MAP's parameters, READ FROM THE MAP. |
| 32 | |
| 33 | The first version of this gate rendered the lookdev half at erosion_render's |
| 34 | OWN defaults -- strength 0.22, erosion_scale 0.15 -- while the Godot half ran |
| 35 | the map's 0.0057 / 0.0014. Two different terrains, reported as a 904 m |
| 36 | disagreement between engine and lookdev. It was neither. |
| 37 | |
| 38 | So these are PARSED from map_dc_diffusion.gd rather than copied. A gate that |
| 39 | keeps its own copy of the numbers it is checking drifts from them silently, |
| 40 | which is the whole failure being fixed here. |
| 41 | """ |
| 42 | src = open(MAP_GD, encoding="utf-8").read() |
| 43 | |
| 44 | def const(name): |
| 45 | m = re.search(r"^const\s+" + name + r"\s*:=\s*(-?[\d.]+)", src, re.M) |
| 46 | if not m: |
| 47 | raise SystemExit(f"cannot read {name} from {MAP_GD}") |
| 48 | return float(m.group(1)) |
| 49 | |
| 50 | floor_y, ceil_y = const("FLOOR_Y"), const("CEILING_Y") |
| 51 | th, cell = const("TERRAIN_HEIGHT"), const("EROSION_CELL_SCALE") |
| 52 | gully, depth = const("EROSION_GULLY_METRES"), const("EROSION_DEPTH_METRES") |
| 53 | k = const("EROSION_AMPLITUDE_K") |
| 54 | hs, gain = const("EROSION_HEIGHT_SCALE"), const("EROSION_GAIN") |
| 55 | oct_ = const("EROSION_OCTAVES") |
| 56 | # The map's own two derivations, mirrored (map :602 and the erosion_scale line). |
| 57 | strength = depth * th * cell / (k * gully) |
| 58 | escale = gully / (th * cell) |
| 59 | vals = [("floor_y", floor_y), ("ceiling_y", ceil_y), ("terrain_height", th), |
| 60 | ("en_height_scale", hs), ("en_strength", strength), |
| 61 | ("en_erosion_scale", escale), ("en_cell_scale", cell), |
| 62 | ("en_octaves", int(oct_)), ("en_gain", gain)] |
| 63 | out = [] |
| 64 | for kk, vv in vals: |
| 65 | out += ["--set", kk, str(vv)] |
| 66 | return out, depth, strength |
| 67 | |
| 68 | |
| 26 | 69 | def render(binpath, ox, oz, n, mpp, out, extra=()): |
| 27 | 70 | cmd = [binpath, "--heightmap", HBLK, "--ox", str(ox), "--oz", str(oz), |
| 28 | 71 | "--n", str(n), "--mpp", str(mpp), "--out", out] + list(extra) |
| … | … | @@ -54,14 +97,17 @@ def main(): |
| 54 | 97 | print(f"Godot surface: {n}x{len(zs)} columns from ({xs[0]:.0f}, {zs[0]:.0f}) " |
| 55 | 98 | f"at {mpp:.0f} m spacing") |
| 56 | 99 | |
| 57 | | look = render(a.bin, xs[0], zs[0], n, mpp, "/tmp/lk_surface.f32") |
| 100 | mp, depth, strength = map_params() |
| 101 | print(f"lookdev half at the MAP's parameters: depth {depth:g} m rms, " |
| 102 | f"strength {strength:.6g}") |
| 103 | look = render(a.bin, xs[0], zs[0], n, mpp, "/tmp/lk_surface.f32", mp) |
| 58 | 104 | d = np.abs(godot - look) |
| 59 | 105 | ok = d.max() <= a.tol |
| 60 | 106 | print(f"\n MATCH max |godot - lookdev| = {d.max():8.3f} m " |
| 61 | 107 | f"rms {np.sqrt((d**2).mean()):7.3f} m {'PASS' if ok else 'FAIL'}") |
| 62 | 108 | |
| 63 | 109 | zero = render(a.bin, xs[0], zs[0], n, mpp, "/tmp/lk_zero.f32", |
| 64 | | ["--set", "en_strength", "0"]) |
| 110 | mp + ["--set", "en_strength", "0"]) |
| 65 | 111 | dz = np.abs(godot - zero) |
| 66 | 112 | ctl = dz.max() > a.tol |
| 67 | 113 | print(f" CONTROL erosion off: max diff {dz.max():8.1f} m " |