Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
d1309f5
Update raster store refactor plan for DAG changes
adam-ce Aug 14, 2026
75277f8
Capture raster store compatibility baseline
adam-ce Aug 14, 2026
d756a77
Add ignored SF compatibility payloads
adam-ce Aug 14, 2026
4c171c8
Extract shared hierarchy topology
adam-ce Aug 14, 2026
fbc02d0
Add runtime store layouts and codecs
adam-ce Aug 14, 2026
61acb74
Add shared runtime-codec storage core
adam-ce Aug 14, 2026
4ffcdea
Migrate applications to shared storage
adam-ce Aug 14, 2026
3086336
Harden SF storage boundaries
adam-ce Aug 14, 2026
bca0b5c
Remove octree migration shims
adam-ce Aug 14, 2026
ae87580
Remove migration compatibility fixtures
adam-ce Aug 14, 2026
58519bf
Merge branch 'dag-builder' into raster-store
adam-ce Aug 15, 2026
ff2524c
Merge branch 'dag-builder' into raster-store
adam-ce Aug 16, 2026
c1f4bb4
Parameterize golden E2E paths
adam-ce Aug 16, 2026
b90a7a8
Fix stale SF tile ID test
adam-ce Aug 17, 2026
008d478
Add default Zstd envelope compression
adam-ce Aug 17, 2026
f1813e9
Add OpenCV raster conversion API
adam-ce Aug 17, 2026
c7122ab
Migrate octree storage formats to envelopes
adam-ce Aug 17, 2026
e310cf5
Fix unity build and sanitizer symbolization
adam-ce Aug 22, 2026
5a6e953
Update cgltf for writer leak fix
adam-ce Aug 23, 2026
1a1a8d7
Apply renderer code style to raster store changes
adam-ce Aug 23, 2026
6ea8a4a
Fix confirmed raster store review findings
adam-ce Aug 23, 2026
3fbb86b
Serialize shared storage access in parallel builders
adam-ce Aug 25, 2026
b1a2884
Report directory creation failures without throwing
adam-ce Aug 25, 2026
d293327
Validate DAG cross-file cluster counts
adam-ce Aug 25, 2026
a964ff8
List all headers in CMake targets
adam-ce Aug 25, 2026
d8f9290
Compile cgltf implementation outside unity builds
adam-ce Aug 25, 2026
6d1f334
Simplify raster store structure
adam-ce Aug 25, 2026
8a3c043
Merge branch 'main' into raster-store
adam-ce Aug 25, 2026
ba1ef5b
Remove redundant NodePath wrapper
adam-ce Aug 25, 2026
56d3d7d
Consolidate store path layout types
adam-ce Aug 26, 2026
5206d41
Unify project error reporting
adam-ce Aug 26, 2026
05788d6
Simplify unified error propagation
adam-ce Aug 27, 2026
d371927
Simplify glTF exception handling
adam-ce Aug 27, 2026
1663f34
Simplify error reclassification frames
adam-ce Aug 27, 2026
a4ad935
Simplify unified error handling
adam-ce Aug 28, 2026
de98c33
Compile libigl wrappers outside unity builds
adam-ce Aug 28, 2026
204b8e2
Improve Expected error propagation
adam-ce Aug 29, 2026
30d7ec3
Add contextual Error propagation overload
adam-ce Aug 29, 2026
ea52a92
Simplify Error propagation API
adam-ce Aug 29, 2026
29f8b71
docs: add project code style
adam-ce Aug 29, 2026
b0d1b07
Port touched code to project error convention
adam-ce Aug 29, 2026
7288f1e
Port glTF IO to project error convention
adam-ce Aug 29, 2026
422c413
Simplify DAG codec API
adam-ce Aug 31, 2026
78dee9c
remove obsolete refactor docs
adam-ce Aug 31, 2026
a694040
Fix resource exhaustion and temp directory ownership
adam-ce Aug 31, 2026
ec46555
Format new C++ files
adam-ce Aug 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
192 changes: 192 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
---
Language: Cpp
# BasedOnStyle: WebKit
AccessModifierOffset: -4
AlignAfterOpenBracket: DontAlign
AlignArrayOfStructures: None
AlignConsecutiveMacros: None
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignEscapedNewlines: Right
AlignOperands: DontAlign
AlignTrailingComments: false
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortEnumsOnASingleLine: true
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
AttributeMacros:
- __capability
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: All
BreakBeforeConceptDeclarations: true
BreakBeforeBraces: WebKit
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeComma
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 160
CommentPragmas: '^ IWYU pragma:'
QualifierAlignment: Leave
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
PackConstructorInitializers: BinPack
BasedOnStyle: ''
ConstructorInitializerAllOnOneLineOrOnePerLine: false
AllowAllConstructorInitializersOnNextLine: true
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
CaseSensitive: false
- Regex: '.*'
Priority: 1
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseLabels: false
IndentCaseBlocks: false
IndentGotoLabels: true
IndentPPDirectives: None
IndentExternBlock: AfterExternBlock
IndentRequires: false
IndentWidth: 4
IndentWrappedFunctionNames: false
InsertTrailingCommas: None
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
LambdaBodyIndentation: Signature
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: Inner
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 4
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PenaltyIndentedWhitespace: 0
PointerAlignment: Left
PPIndentWidth: -1
ReferenceAlignment: Pointer
ReflowComments: true
RemoveBracesLLVM: false
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes: CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: true
AfterFunctionDefinitionName: false
AfterFunctionDeclarationName: false
AfterIfMacros: true
AfterOverloadedOperator: false
BeforeNonEmptyParentheses: false
SpaceAroundPointerQualifiers: Default
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
BitFieldColonSpacing: Both
Standard: Latest
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 4
UseCRLF: false
UseTab: Never
WhitespaceSensitiveMacros:
- STRINGIZE
- PP_STRINGIZE
- BOOST_PP_STRINGIZE
- NS_SWIFT_NAME
- CF_SWIFT_NAME
...

7 changes: 7 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Agent instructions

This is the alpine-terrain-builder project.

Follow the project [code style](docs/code-style.md).

Before committing, run `git ls-files --eol --cached --others --exclude-standard` and verify that each changed text file's working-tree line endings (`w/...`) agree with the line endings required by its Git attributes (`attr/...`). Fix unintended mixed or mismatched line endings before committing.
93 changes: 1 addition & 92 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,94 +1,3 @@
# alpine-terrain-builder

## Overview

This repository contains the following tools:

1. [tile_downloader](src/tile_downloader) for downloading orthophoto tiles, which are used for texturing the generated meshes.
2. [terrainbuilder](src/terrainbuilder/) for building the highest quality meshes from the downloaded orthophoto tiles and a heightmap dataset.
3. [terrainmerger](src/terrainmerger/) for building a LOD hierarchy from the highest quality meshes by merging them upwards.
4. [terrainconvert](src/terrainconvert/) for converting .tile files into .glb files.

### Core Library
[terrainlib](src/terrainlib/) contains classes common to all the tools above.

### Scripts
The tools typically only handle one tile per command which makes it infeasible to run them manually for a whole region due to the sheer amount of tiles. Therefore, we've created the following python scripts, which automate calling the relevant tools for a specified regions:

1. [batch-builder.py](batch-builder.py) calls [terrainbuilder](src/terrainbuilder/) for all tiles in the specified region.
2. [batch-merger.py](batch-merger.py) calls [terrainmerger](src/terrainmerger/) for all tiles in the specified region.
3. [batch-converter.py](batch-converter.py) calls [terrainconvert](src/terrainconvert/) for all .tile files in the specified directory and its subdirectories.

## Example Workflow

In this example, we'll show how to build the hierarchy for Vienna's city center (Zoom: 13, X: 4468, Y:2840).

### 1. Downloading tiles
Tile coordinates always use the Google/Mapbox/XYZ convention internally: the origin is north-west, X grows east, and Y grows south. Google Maps, Mapbox, OpenStreetMap, and most XYZ services use the common URL order `{zoom}/{x}/{y}`.

The `basemap` and `gataki` providers select their complete URL pattern and Y direction automatically. Both currently use downward Y with the URL order `{zoom}/{y}/{x}`. The `basemap` provider downloads the basemap.at orthophoto, and the Gataki mirror uses:

`https://gataki.cg.tuwien.ac.at/raw/basemap/tiles/{zoom}/{y}/{x}.jpeg`

Example for the root tile: https://gataki.cg.tuwien.ac.at/raw/basemap/tiles/13/2840/4468.jpeg

For another service, pass a quoted `--url` pattern containing `{zoom}`, `{x}`, and `{y}`. Placeholder placement selects URL coordinate order. Custom URLs default to downward Y; use `--url-y-direction up` for legacy TMS. Downloaded files always use the common Google/Mapbox layout `{zoom}/{x}/{y}.jpeg`, independently of the remote URL.

The following command downloads the mirror's `{zoom}/{y}/{x}` URLs and writes the root tile to `./tiles/13/4468/2840.jpeg`:

```
./tile-downloader --provider gataki --zoom 13 --x 4468 --y 2840 --max-zoom-level 19
```

For example, a custom Google/Mapbox URL can be selected with `--url 'https://example.test/{zoom}/{x}/{y}.jpeg'`.

### 2. Download heightmap dataset
The meshes are built from a heightmap dataset, therefore we need to download one. For this example we'll only use a small part of the complete dataset for the whole of austria (available at https://gataki.cg.tuwien.ac.at/raw/Oe_2020/, 268 GB to 1.1 TB). The part we're gonna use contains Vienna's city center and it is available at https://gataki.cg.tuwien.ac.at/raw/vienna/innenstadt_gs_1m_mgi.tif (228 MB).

![Vienna city center heightmap](readme_img/innenstadt_gs_1m_mgi.jpg)

### 3. Building reference meshes
The following command will build reference meshes for the root tile `13/4468/2840` at the target zoom level `19` from the tile textures in `./tiles/` and the dataset `./innenstadt_gs_1m_mgi.tif` and output them in the folder `./meshes`. The SRS used is `EPSG:3857`, as the [demo renderer](https://github.com/polskus/renderer-alpinite) expects coordinates in the WebMercator (EPSG:3857) system.

```
python3 batch-builder.py --terrainbuilder ./terrainbuilder --tile 13 4468 2840 --target-zoom 19 --output-dir ./meshes -- --textures ./tiles/ --dataset ./innenstadt_gs_1m_mgi.tif --mesh-srs EPSG:3857
```

### 4. Building tile hierarchy by merging and simplifying reference meshes
The following command will build the LOD hierarchy from the reference meshes generated in the previous step at `./meshes` and output simplified GLB/GLTF files at `./hierarchy/{zoom}/{Y}/{X}.simplified.glb`.

> [!WARNING]
> This process is very time intensive and may end up taking hours depending on the region size!

```
python3 batch-merger.py --terrainmerger ./terrainmerger --root-tile 13 4468 2840 --max-zoom 19 --input-dir ./meshes --output-dir ./hierarchy
```

### 5. Converting missing meshes from .TILE to .GLB
Due to the separation of concerns in step `3. Building reference meshes` the tilebuilder does not output .GLB files, and in step `4. Building tile hierarchy by merging and simplifying reference meshes` the terrainmerger only outputs simplified GLB files for the next higher level. Therefore, there are no GLB files present for the highest zoom level `19`. Fortunately, there is the terrainconvert tool, which enables the conversion between .TILE and .GLB files without simplification.
The following command runs a script, which checks if there is a `*.simplified.glb` file for every `*.tile` present.

> [!NOTE]
> Even though we name the converted GLB files using the suffix `.simplified.glb`, there is no simplification happening during the conversion. This naming is only used for consistency's sake, as the terrainmerger creates GLB files with this suffix and the [demo renderer](https://github.com/polskus/renderer-alpinite) expects a consistent naming scheme. You could also, in theory, rename the whole hierarchy to just use `*.glb`, make the relevant change in the [demo renderer](https://github.com/polskus/renderer-alpinite) and it would work too.

```
python3 batch-converter.py --terrainconverter ./terrainconvert --dir ./hierarchy/19 --suffix .simplified
```

### 6. Deployment
To make the tiles accessible to the [demo renderer](https://github.com/polskus/renderer-alpinite) just serve the final hierarchy via a http(s) server, which the computer running the [demo renderer](https://github.com/polskus/renderer-alpinite) can access. The default URL format used by the [demo renderer](https://github.com/polskus/renderer-alpinite) is `/{zoom}/{Y}/{X}.simplified.glb`.

See [Modifying the tile server URL](https://github.com/polskus/renderer-alpinite/blob/main/README.md#modifying-the-tile-server-url) for information on how to change the server URL, file structure and suffix.

## building
In order to build, you need to install:

- fmt (https://fmt.dev/latest/index.html)
- GDAL 3 (https://gdal.org/)
- glm (https://github.com/g-truc/glm)
- catch2 (version 2.x) (https://github.com/catchorg/Catch2/tree/v2.x)
- FreeImage
- tbb (intel threading building blocks)

sudo apt-get install libcgal-dev libopencv-dev libfmt-dev libglm-dev libgdal-dev catch2 libfreeimage-dev libtbb-dev libcurl4-openssl-dev
(libgmp-dev libmpfr-dev libsqlite3-dev)
See the project [code style](docs/code-style.md) before contributing.
2 changes: 1 addition & 1 deletion cmake/SetupGDAL.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function(alp_setup_gdal)
-DBUILD_TESTING=OFF
-DGEOS_BUILD_DEVELOPER=OFF
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
)
)

alp_setup_cmake_project(gdal
URL https://github.com/OSGeo/gdal.git
Expand Down
Loading