139 lines
4.1 KiB
Bash
Executable File
139 lines
4.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# End-to-end helper to convert CityGML tiles to tile-local GLBs.
|
|
# Assumes heightmaps/textures are already exported so tile_index.csv exists.
|
|
|
|
set -euo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
|
|
RAW_DIR="${RAW_DIR:-$ROOT/raw/citygml/lod2}"
|
|
CITYJSON_DIR="${CITYJSON_DIR:-$ROOT/work/cityjson}"
|
|
CLEAN_DIR="${CLEAN_DIR:-$ROOT/work/cityjson_clean}"
|
|
TRI_DIR="${TRI_DIR:-$ROOT/work/cityjson_tri}"
|
|
TRI_LOCAL_DIR="${TRI_LOCAL_DIR:-$ROOT/work/cityjson_tri_local}"
|
|
SPLIT_DIR="${SPLIT_DIR:-$ROOT/work/cityjson_split_local}"
|
|
GLB_DIR="${GLB_DIR:-$ROOT/export_unity/buildings_glb}"
|
|
GLB_SPLIT_DIR="${GLB_SPLIT_DIR:-$ROOT/export_unity/buildings_glb_split}"
|
|
TILE_INDEX="${TILE_INDEX:-$ROOT/export_unity/tile_index.csv}"
|
|
|
|
CITYGML_TOOLS="${CITYGML_TOOLS:-$ROOT/tools/citygml-tools-2.4.0/citygml-tools}"
|
|
CJIO_CMD="${CJIO:-uv run cjio}"
|
|
PYTHON_CMD="${PYTHON_CMD:-uv run python}"
|
|
|
|
log() {
|
|
printf '[citygml->glb] %s\n' "$*"
|
|
}
|
|
|
|
resolve_cityjson() {
|
|
local path="$1"
|
|
if [[ -f "$path" ]]; then
|
|
echo "$path"
|
|
return 0
|
|
fi
|
|
if [[ -d "$path" ]]; then
|
|
local base
|
|
base="$(basename "$path" .city.json)"
|
|
if [[ -f "$path/$base.json" ]]; then
|
|
echo "$path/$base.json"
|
|
return 0
|
|
fi
|
|
local first
|
|
first="$(find "$path" -maxdepth 1 -name '*.json' | head -n1 || true)"
|
|
if [[ -n "$first" ]]; then
|
|
echo "$first"
|
|
return 0
|
|
fi
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
if [[ ! -f "$TILE_INDEX" ]]; then
|
|
echo "tile_index.csv missing at $TILE_INDEX; run heightmap export first." >&2
|
|
exit 1
|
|
fi
|
|
|
|
mapfile -t GMLS < <(find "$RAW_DIR" -maxdepth 1 -name 'LoD2_*.gml' | sort)
|
|
if [[ ${#GMLS[@]} -eq 0 ]]; then
|
|
echo "No CityGML tiles found in $RAW_DIR" >&2
|
|
exit 1
|
|
fi
|
|
|
|
mkdir -p "$CITYJSON_DIR" "$CLEAN_DIR" "$TRI_DIR" "$TRI_LOCAL_DIR" "$SPLIT_DIR" "$GLB_DIR" "$GLB_SPLIT_DIR"
|
|
|
|
log "CityGML -> CityJSON (${#GMLS[@]} tiles)"
|
|
for gml in "${GMLS[@]}"; do
|
|
base="$(basename "$gml" .gml)"
|
|
out="$CITYJSON_DIR/${base}.city.json"
|
|
if [[ -e "$out" ]]; then
|
|
log "skip existing $out"
|
|
continue
|
|
fi
|
|
"$CITYGML_TOOLS" to-cityjson "$gml" -o "$out"
|
|
done
|
|
|
|
log "Clean invalid vertices"
|
|
$PYTHON_CMD "$ROOT/scripts/clean_cityjson_vertices.py" --input-dir "$CITYJSON_DIR" --output-dir "$CLEAN_DIR"
|
|
|
|
log "Triangulate"
|
|
mapfile -t CITYJSONS < <(find "$CLEAN_DIR" -maxdepth 1 -name '*.city.json' | sort)
|
|
for path in "${CITYJSONS[@]}"; do
|
|
base="$(basename "$path" .city.json)"
|
|
target="$TRI_DIR/${base}.tri.city.json"
|
|
if [[ -e "$target" ]]; then
|
|
log "skip existing $target"
|
|
continue
|
|
fi
|
|
input_json="$(resolve_cityjson "$path" || true)"
|
|
if [[ -z "$input_json" ]]; then
|
|
log "skip $path (cannot resolve json)"
|
|
continue
|
|
fi
|
|
$CJIO_CMD --ignore_duplicate_keys "$input_json" upgrade triangulate vertices_clean save "$target"
|
|
done
|
|
|
|
log "Rebase to tile-local XY"
|
|
$PYTHON_CMD "$ROOT/scripts/rebase_cityjson_tiles.py" --input-dir "$TRI_DIR" --output-dir "$TRI_LOCAL_DIR" --tile-index "$TILE_INDEX"
|
|
|
|
log "Split semantics (roof/wall)"
|
|
$PYTHON_CMD "$ROOT/scripts/split_semantics.py" --input-dir "$TRI_LOCAL_DIR" --output-dir "$SPLIT_DIR"
|
|
|
|
log "Export GLB (base)"
|
|
mapfile -t TRIS < <(find "$TRI_LOCAL_DIR" -maxdepth 1 -name '*.tri.city.json' | sort)
|
|
for tri in "${TRIS[@]}"; do
|
|
base="$(basename "$tri" .tri.city.json)"
|
|
out="$GLB_DIR/${base}.glb"
|
|
if [[ -e "$out" ]]; then
|
|
log "skip existing $out"
|
|
continue
|
|
fi
|
|
$CJIO_CMD "$tri" export glb "$out"
|
|
done
|
|
|
|
log "Export GLB (roof/wall)"
|
|
mapfile -t ROOFS < <(find "$SPLIT_DIR" -maxdepth 1 -name '*.roof.city.json' | sort)
|
|
for roof in "${ROOFS[@]}"; do
|
|
base="$(basename "$roof" .roof.city.json)"
|
|
out="$GLB_SPLIT_DIR/${base}_roof.glb"
|
|
if [[ -e "$out" ]]; then
|
|
log "skip existing $out"
|
|
continue
|
|
fi
|
|
$CJIO_CMD "$roof" export glb "$out"
|
|
done
|
|
|
|
mapfile -t WALLS < <(find "$SPLIT_DIR" -maxdepth 1 -name '*.wall.city.json' | sort)
|
|
for wall in "${WALLS[@]}"; do
|
|
base="$(basename "$wall" .wall.city.json)"
|
|
out="$GLB_SPLIT_DIR/${base}_wall.glb"
|
|
if [[ -e "$out" ]]; then
|
|
log "skip existing $out"
|
|
continue
|
|
fi
|
|
$CJIO_CMD "$wall" export glb "$out"
|
|
done
|
|
|
|
log "Verify outputs"
|
|
$PYTHON_CMD "$ROOT/scripts/verify_pipeline.py" --mode both --tri-dir "$TRI_LOCAL_DIR" --split-dir "$SPLIT_DIR"
|
|
|
|
log "Done"
|