Terrain Tile Format
Terrain is stored as a directory of square tiles: one Terrain.json manifest plus one .riff file per tile.
Terrain.json
Section titled “Terrain.json”{ "origin": { "latitude": 35.3826, "longitude": -83.4954 }, "tileDimension": 500, "heightmapResolution": 513, "tiles": [ { "x": 0, "y": 0, "min": 600, "max": 667 } ]}| Field | Meaning |
|---|---|
origin | Latitude/longitude of world position (0, 0), the south-west corner of tile (0, 0). |
tileDimension | Tile edge length in meters. |
heightmapResolution | Height samples per tile edge. Defaults to 513 when absent. |
tiles[].x, tiles[].y | Tile position. x increases east (+X), y increases north (+Z). |
tiles[].min, tiles[].max | The tile’s height range in meters. Must match the tile’s RHGI chunk. |
Leave tileDimension (500) and heightmapResolution (513) as the game writes them. Other values are untested, and changing either in an existing tile set does not convert its tiles.
Tile (x, y) covers world X from x * tileDimension to (x + 1) * tileDimension, and world Z over the same range using y. Positions may be negative.
Each tile is stored as tile_XXX_YYY.riff, with the position zero-padded to at least three digits, for example tile_004_012.riff or tile_-001_000.riff.
RIFF container
Section titled “RIFF container”Tiles are standard RIFF files. All integers are little-endian.
| Offset | Size | Value |
|---|---|---|
| 0 | 4 | RIFF |
| 4 | 4 | int32 size of everything after this field |
| 8 | 4 | Form type RRT0 |
| 12 | … | Chunks |
Each chunk is a 4-byte ASCII id, an int32 payload size, then the payload. A payload with an odd size is followed by one pad byte, which the size does not include.
Chunks may appear in any order. Readers should skip chunks they do not recognize.
Texture chunks
Section titled “Texture chunks”RHGT and RBIO hold rasters with this payload layout:
| Offset | Size | Value |
|---|---|---|
| 0 | 4 | Pixel format: R16 , R8 , RFLT, RGBA, RGB , or RBC4 (BC4 block-compressed) |
| 4 | 4 | int32 width |
| 8 | 4 | int32 height |
| 12 | … | Pixels, rows packed with no padding |
Pixel (x, y) is at index y * width + x. Row 0 is the south edge and column 0 is the west edge.
Chunks
Section titled “Chunks”RHGI — height info
Section titled “RHGI — height info”12 bytes:
| Offset | Type | Value |
|---|---|---|
| 0 | int32 | Tile format version: 0 = no biome raster, 1 = has RBIO |
| 4 | int32 | Minimum height, meters |
| 8 | int32 | Maximum height, meters |
RHGT — heights
Section titled “RHGT — heights”R16, heightmapResolution x heightmapResolution (513 x 513). Each sample is an unsigned 16-bit value scaled linearly between the RHGI min and max:
height = sample / 65535 * (max - min) + minsample = round((height - min) / (max - min) * 65535)Samples sit on the tile’s grid vertices. The first and last rows and columns lie exactly on the tile edges, so neighboring tiles share their edge samples, and those samples should be equal.
The game also reads RFLT heights (32-bit float meters, min/max ignored), but always writes R16.
RBIO — biome raster
Section titled “RBIO — biome raster”R8, 256 x 256. Each texel is a biome class code covering 1/256 of the tile, sampled at the texel center. The values are categories, so the chunk must stay R8. Block compression or interpolation produces codes that don’t exist.
The codes currently in use are listed below. Fetched land cover data is mapped to the family codes (multiples of 10). Dirt and Gravel are written by biome painting in the Map Editor. Ballast is applied at runtime by map features and is not normally stored in tiles.
| Code | Biome | Status |
|---|---|---|
| 0 | Unknown (no data) | No vegetation |
| 10 | Water | Supported |
| 20 | Bare | Placeholder sparse grass only |
| 21 | Ballast | Ballast texture, no vegetation |
| 22 | Dirt | Dirt texture, no vegetation |
| 23 | Gravel | Gravel texture, no vegetation |
| 30 | Grass | Supported |
| 40 | Shrub | Supported |
| 50 | Trees | Supported |
| 60 | Wetland | Placeholder vegetation |
| 70 | Crops | Placeholder vegetation |
| 80 | Built | No vegetation |
| 90 | Ice | Not supported; for permanent ice/glaciers |
Codes are grouped in families of 10, with variations in the units digit. Codes 128 and above are reserved for asset packs.
© 2026 Giraffe Lab LLC. All rights reserved.