8.5 KiB
8.5 KiB
GeoData Toolkit
This repository converts DGM1 elevation tiles into Unity-ready 16-bit PNG heightmaps and a placement manifest. It relies on GDAL for mosaicking, resampling, and scaling to UInt16 ranges Unity expects.
Prerequisites
uvinstalled. Use Python 3.10–3.12 for now (triangle2fromcjio[export]has no CPython 3.13 wheels).- Optional: Java 17+ if you want to experiment with the bundled
citygml-toolsutilities (not needed for heightmaps/orthophotos).
Environment setup (uv)
- Install deps (creates
.venvif missing):uv sync. You can skip manual activation by prefixing commands withuv run ...; if you prefer activation, runuv venv && source .venv/bin/activate. uv run <cmd>executes with the project environment (e.g.,uv run python geodata_to_unity.py --setup). Use--directoryto target another path if needed;--offlinedisables network fetches.- If wheels fail to resolve, ensure system GDAL is present (e.g.,
brew install gdalorapt-get install gdal-bin libgdal-dev), then rerunuv sync. - Create the default directory tree and config:
uv run python geodata_to_unity.py --setup(orbash scripts/setup_dirs.shfor directories only).
Repository Layout
raw/— working inputs (not versioned):raw/dgm1/,raw/dop20/jp2/,raw/citygml/lod1/,raw/citygml/lod2/.archive/— offline storage for untouched downloads (e.g., zipped DOP/CityGML tiles, dop20 filelist).work/— intermediates such asdgm.vrtand_tmp.tiffiles; safe to delete/regenerate.export_unity/height_png16/— final 16-bit PNG heightmaps for Unity import.export_unity/tile_index.csv— manifest mapping tile IDs to world bounds and global min/max used for scaling; built during heightmap export and required by orthophotos.export_unity/ortho_jpg/— cropped orthophoto tiles aligned to the terrain grid (JPEG + worldfiles).geodata_to_unity.py— main CLI (usesgeodata_pipeline/library modules).scripts/— helpers to create the directory tree and fetch DOP20 inputs.geodata_config.json— generated config (seegeodata_config.example.jsonfor defaults).AGENTS.md— contributor guide.
Quick Start
- Activate the uv venv (
source .venv/bin/activate) or prefix commands withuv run. - Initialize config + directories:
uv run python geodata_to_unity.py --setup. - Export assets (builds VRTs automatically if missing):
uv run python geodata_to_unity.py --export all # heightmaps only: uv run python geodata_to_unity.py --export heightmap # textures only: uv run python geodata_to_unity.py --export textures - Import the PNGs into Unity Terrains using
tile_index.csvfor placement and consistent height scaling (0–65535).
How the export works
- Heightmaps: the pipeline builds
work/dgm.vrtfrom allraw/dgm1/*.tif, computes a global min/max once, and warps each tile footprint toheightmap.out_reswithsrcNodata=-9999anddstNodataset to the global min. PNGs are scaled to[0, 65535]with worldfiles and listed inexport_unity/tile_index.csv. - Orthophotos:
work/dop.vrtis built fromraw/dop20/jp2/*.jp2; the manifest drives the cropping bounds. JPEG tiles are written toexport_unity/ortho_jpg/with matching.jgwworldfiles. If the manifest is missing, the orthophoto export aborts—run the heightmap export first or use--export all. - Archives:
--build-from-archiveexpands every*.zipunderarchive/*into the matchingraw/*directories and copiesarchive/dop20/filelist.txtnext toraw/dop20/for the downloader. - Cleanup: temporary
_tmp.tifand GDAL aux XML files underwork/andraw/dgm1/are removed at the end of the heightmap export; avoid storing non-GDAL metadata in those folders.
Key Commands
- Refresh VRT:
gdalbuildvrt work/dgm.vrt raw/dgm1/*.tif - Run export pipeline:
uv run python geodata_to_unity.py --export all - Inspect an output tile:
gdalinfo export_unity/height_png16/<tile>.png | head - Override config paths: use
--config <path>,--raw-dgm1-path <dir>,--raw-dop20-path <dir>. - Build raws from archives:
uv run python geodata_to_unity.py --build-from-archive --export all(unzipsarchive/*; dop20 filelist stays inarchive/dop20/for the downloader). - Rebuild VRTs after moving data: add
--force-vrt.
Workflow Notes
- The pipeline computes a global min/max from the VRT to scale all tiles consistently; adjust
heightmap.out_resorheightmap.resampleingeodata_config.jsonif your AOI or target resolution changes. _tmp.tiffiles inwork/are transient; you can deletework/to force a clean rebuild.- Keep file names stable to avoid churn in Unity scenes; re-exports overwrite in place.
- Large raw datasets are intentionally excluded from version control—document download sources or scripts instead of committing data.
- Additional inputs: download helper lives in
scripts/dlscript_dop20.shand pulls JP2/J2W/XML orthophotos listed inarchive/dop20/filelist.txt(one URL per line);archive/can hold zipped 3D building tiles for future use. - Handoff to Unity: copy/sync
export_unity/height_png16/andexport_unity/tile_index.csvintoDTrierFlood/Assets/GeoData/before running the Unity-side importer. Keepheightmap.out_resaligned with the importer’s expected resolution (currently 1025).
Orthophotos (textures)
- Ensure DOP assets are present in
raw/dop20/jp2/,raw/dop20/j2w/, andraw/dop20/meta/; usescripts/dlscript_dop20.shto fetch JP2/J2W/XML entries listed inarchive/dop20/filelist.txt(one URL per line). - From
GeoData/, run:This buildsuv run python geodata_to_unity.py --export textureswork/dop.vrtif missing and writesexport_unity/ortho_jpg/<tile>.jpg+.jgwaligned totile_index.csv.- If you see
Computed -srcwin ... falls partially outside source raster extentwarnings, the DOP coverage is slightly smaller than the tile footprint; edge pixels will be filled with NoData/zeros. Add adjacent JP2s or shrink the requested window if you need to avoid the warning. - The download script relies on a Linux/OpenSSL toolchain with system CA bundle at
/etc/ssl/certs/ca-certificates.crt; it builds a trust chain by fetching the geobasis intermediate. macOS/Windows users should either provide a combined CA viaCURL_CA_BUNDLEor download with a browser/wget and place files manually. - Place companion
.j2wand.xmlfiles underraw/dop20/j2w/andraw/dop20/meta/if available; they are not required for the VRT but help provenance.
- If you see
Buildings
LoD2 CityGML tiles can be converted to GLB per tile while preserving roof/wall semantics:
- CityGML → CityJSON:
for f in raw/citygml/lod2/*.gml; do base="$(basename "$f" .gml)" tools/citygml-tools-2.4.0/citygml-tools to-cityjson "$f" \ -o "work/cityjson/${base}.city.json" done - Clean + triangulate:
for f in work/cityjson/*.city.json; do base="$(basename "$f" .city.json)" input_json="$f/$base.json" # citygml-tools writes a .json inside the .city.json folder uv run cjio "$input_json" upgrade triangulate vertices_clean \ save "work/cityjson_tri/${base}.tri.city.json" done - Split roof/wall semantics without reindexing vertices:
uv run python scripts/split_semantics.py - Export GLBs (tile-local coords; place with
export_unity/tile_index.csv):for f in work/cityjson_tri/*.tri.city.json; do base="$(basename "$f" .tri.city.json)" uv run cjio "$f" export --format glb "export_unity/buildings_glb/${base}.glb" done for f in work/cityjson_split/*.roof.city.json; do base="$(basename "$f" .roof.city.json)" uv run cjio "$f" export --format glb "export_unity/buildings_glb_split/${base}_roof.glb" done for f in work/cityjson_split/*.wall.city.json; do base="$(basename "$f" .wall.city.json)" uv run cjio "$f" export --format glb "export_unity/buildings_glb_split/${base}_wall.glb" done - Confirm intermediates/GLBs exist:
uv run python scripts/verify_pipeline.py --mode both
Troubleshooting
- Empty raw directories cause VRT creation to fail fast (
No sources available to build VRT); populate inputs or adjust--raw-*overrides. - If you moved raw data or deleted
work/, add--force-vrtto rebuild VRTs before exporting. - Orthophoto export warnings like
Computed -srcwin ... falls partially outside source raster extentindicate coverage gaps; add neighboring JP2s or accept the NoData edge fill. - If GDAL Python bindings are missing, install system GDAL first and re-run
uv syncsoosgeoimports succeed.