diff --git a/export_heightmaps.py b/export_heightmaps.py new file mode 100644 index 0000000..0a5395b --- /dev/null +++ b/export_heightmaps.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +import glob +import math +import os + +from osgeo import gdal + +RAW_DIR = "raw_dgm1" +VRT_PATH = "work/dgm.vrt" +OUT_DIR = "export_unity/height_png16" + +TILE_SIZE_M = 1000 # real-world tile size in meters +OUT_RES = 1025 # Unity Terrain-friendly resolution (2^n + 1) +RESAMPLE = "bilinear" + +os.makedirs("work", exist_ok=True) +os.makedirs(OUT_DIR, exist_ok=True) + +# Open VRT +ds = gdal.Open(VRT_PATH) +if ds is None: + raise SystemExit(f"Could not open {VRT_PATH}. Did you run gdalbuildvrt?") + +band = ds.GetRasterBand(1) + +# Strategy B: compute global min/max for CURRENT downloaded AOI +gmin, gmax = band.ComputeRasterMinMax(True) +print(f"GLOBAL_MIN={gmin}, GLOBAL_MAX={gmax}") + +# Export manifest for Unity placement later +manifest_path = os.path.join("export_unity", "tile_index.csv") +with open(manifest_path, "w", encoding="utf-8") as f: + f.write("tile_id,xmin,ymin,xmax,ymax,global_min,global_max,out_res\n") + + for tif in sorted(glob.glob(os.path.join(RAW_DIR, "*.tif"))): + tds = gdal.Open(tif) + if tds is None: + print(f"Skipping unreadable: {tif}") + continue + + gt = tds.GetGeoTransform() + ulx, xres, _, uly, _, yres = gt # yres typically negative in north-up rasters + + # Snap tile bounds to the 1000 m grid to avoid drift/seams. + # (This also neutralizes the 1001×1001 overlap nuance.) + xmin = math.floor(ulx / TILE_SIZE_M) * TILE_SIZE_M + ymax = math.ceil(uly / TILE_SIZE_M) * TILE_SIZE_M + xmax = xmin + TILE_SIZE_M + ymin = ymax - TILE_SIZE_M + + base = os.path.splitext(os.path.basename(tif))[0] + tile_id = base # keep stable naming = easy re-export + reimport + + tmp_path = os.path.join("work", f"{tile_id}_tmp.tif") + out_path = os.path.join(OUT_DIR, f"{tile_id}.png") + + warp_opts = gdal.WarpOptions( + outputBounds=(xmin, ymin, xmax, ymax), + width=OUT_RES, + height=OUT_RES, + resampleAlg=RESAMPLE, + dstNodata=-9999, + ) + gdal.Warp(tmp_path, ds, options=warp_opts) + + # Scale to UInt16 (0..65535) using Strategy-B global min/max + trans_opts = gdal.TranslateOptions( + outputType=gdal.GDT_UInt16, + scaleParams=[(gmin, gmax, 0, 65535)], + format="PNG", + ) + gdal.Translate(out_path, tmp_path, options=trans_opts) + + f.write(f"{tile_id},{xmin},{ymin},{xmax},{ymax},{gmin},{gmax},{OUT_RES}\n") + print(f"Wrote {out_path}") + +print(f"Manifest: {manifest_path}") diff --git a/export_unity/tile_index.csv b/export_unity/tile_index.csv new file mode 100644 index 0000000..9c71561 --- /dev/null +++ b/export_unity/tile_index.csv @@ -0,0 +1,11 @@ +tile_id,xmin,ymin,xmax,ymax,global_min,global_max,out_res +dgm1_32_328_5511,327000,5512000,328000,5513000,124.13099670410156,297.1679992675781,1025 +dgm1_32_328_5512,327000,5513000,328000,5514000,124.13099670410156,297.1679992675781,1025 +dgm1_32_328_5513,327000,5514000,328000,5515000,124.13099670410156,297.1679992675781,1025 +dgm1_32_328_5514,327000,5515000,328000,5516000,124.13099670410156,297.1679992675781,1025 +dgm1_32_328_5515,327000,5516000,328000,5517000,124.13099670410156,297.1679992675781,1025 +dgm1_32_329_5511,328000,5512000,329000,5513000,124.13099670410156,297.1679992675781,1025 +dgm1_32_329_5512,328000,5513000,329000,5514000,124.13099670410156,297.1679992675781,1025 +dgm1_32_329_5513,328000,5514000,329000,5515000,124.13099670410156,297.1679992675781,1025 +dgm1_32_329_5514,328000,5515000,329000,5516000,124.13099670410156,297.1679992675781,1025 +dgm1_32_329_5515,328000,5516000,329000,5517000,124.13099670410156,297.1679992675781,1025 diff --git a/work/dgm1_32_328_5511_tmp.tif b/work/dgm1_32_328_5511_tmp.tif new file mode 100644 index 0000000..c4d59cf Binary files /dev/null and b/work/dgm1_32_328_5511_tmp.tif differ diff --git a/work/dgm1_32_328_5512_tmp.tif b/work/dgm1_32_328_5512_tmp.tif new file mode 100644 index 0000000..d829517 Binary files /dev/null and b/work/dgm1_32_328_5512_tmp.tif differ diff --git a/work/dgm1_32_328_5513_tmp.tif b/work/dgm1_32_328_5513_tmp.tif new file mode 100644 index 0000000..c5e8c8c Binary files /dev/null and b/work/dgm1_32_328_5513_tmp.tif differ diff --git a/work/dgm1_32_328_5514_tmp.tif b/work/dgm1_32_328_5514_tmp.tif new file mode 100644 index 0000000..ff950c3 Binary files /dev/null and b/work/dgm1_32_328_5514_tmp.tif differ diff --git a/work/dgm1_32_328_5515_tmp.tif b/work/dgm1_32_328_5515_tmp.tif new file mode 100644 index 0000000..3954721 Binary files /dev/null and b/work/dgm1_32_328_5515_tmp.tif differ diff --git a/work/dgm1_32_329_5511_tmp.tif b/work/dgm1_32_329_5511_tmp.tif new file mode 100644 index 0000000..1057c9c Binary files /dev/null and b/work/dgm1_32_329_5511_tmp.tif differ diff --git a/work/dgm1_32_329_5512_tmp.tif b/work/dgm1_32_329_5512_tmp.tif new file mode 100644 index 0000000..721da05 Binary files /dev/null and b/work/dgm1_32_329_5512_tmp.tif differ diff --git a/work/dgm1_32_329_5513_tmp.tif b/work/dgm1_32_329_5513_tmp.tif new file mode 100644 index 0000000..ef58033 Binary files /dev/null and b/work/dgm1_32_329_5513_tmp.tif differ diff --git a/work/dgm1_32_329_5514_tmp.tif b/work/dgm1_32_329_5514_tmp.tif new file mode 100644 index 0000000..a76e389 Binary files /dev/null and b/work/dgm1_32_329_5514_tmp.tif differ diff --git a/work/dgm1_32_329_5515_tmp.tif b/work/dgm1_32_329_5515_tmp.tif new file mode 100644 index 0000000..445b6f3 Binary files /dev/null and b/work/dgm1_32_329_5515_tmp.tif differ diff --git a/work/tile_tmp.tif b/work/tile_tmp.tif new file mode 100644 index 0000000..510af82 Binary files /dev/null and b/work/tile_tmp.tif differ