Full terrain-to-render pipeline at tooling/planet-gen/: - body_definition_parser: reads system index.md → body definitions - planet_simulation: FBM + Voronoi ridges, Whittaker biome classification, D8 river routing, physics-driven craters (atmo × tectonics scaling) - render_heightmap: 4096×2048 cartographic maps with hillshade - planet_renderer: 512×512 globe with terrain UV mapping, clouds, rings - biomes.toml: externalized color/classification tables (single source) - scaffold_bodies: creates per-body index.md with YAML frontmatter - batch: unattended processing with error handling, resume, determinism check Supports all body types: temperate, arid, frozen, volcanic, barren, oceanic, gas giant (banded + ringed), and moons (half-size, grey, cratered). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
327 lines
13 KiB
TOML
327 lines
13 KiB
TOML
# Planet Generator — Biome & Color Configuration
|
||
#
|
||
# Single source of truth for biome classification, color palettes,
|
||
# and rendering parameters. Loaded by planet_simulation.py,
|
||
# render_heightmap.py, and planet_renderer.py.
|
||
#
|
||
# Edit this file to adjust colors without touching Python code.
|
||
|
||
# ─────────────────────────────────────────────────────────────────────
|
||
# Whittaker biome classification table
|
||
#
|
||
# Temperature axis is ABSOLUTE KELVIN — not normalized per-world.
|
||
# Moisture axis is [0, 1].
|
||
# Order matters: first match wins.
|
||
# ─────────────────────────────────────────────────────────────────────
|
||
|
||
[[whittaker]]
|
||
id = 5
|
||
name = "tropical_rainforest"
|
||
temp_lo = 303
|
||
temp_hi = 999
|
||
moist_lo = 0.65
|
||
moist_hi = 1.00
|
||
|
||
[[whittaker]]
|
||
id = 6
|
||
name = "tropical_seasonal"
|
||
temp_lo = 303
|
||
temp_hi = 999
|
||
moist_lo = 0.35
|
||
moist_hi = 0.65
|
||
|
||
[[whittaker]]
|
||
id = 7
|
||
name = "savanna"
|
||
temp_lo = 293
|
||
temp_hi = 999
|
||
moist_lo = 0.18
|
||
moist_hi = 0.35
|
||
|
||
[[whittaker]]
|
||
id = 15
|
||
name = "hot_desert"
|
||
temp_lo = 303
|
||
temp_hi = 999
|
||
moist_lo = 0.00
|
||
moist_hi = 0.18
|
||
|
||
[[whittaker]]
|
||
id = 9
|
||
name = "temperate_deciduous"
|
||
temp_lo = 283
|
||
temp_hi = 308
|
||
moist_lo = 0.55
|
||
moist_hi = 1.00
|
||
|
||
[[whittaker]]
|
||
id = 8
|
||
name = "temperate_grassland"
|
||
temp_lo = 278
|
||
temp_hi = 303
|
||
moist_lo = 0.30
|
||
moist_hi = 0.55
|
||
|
||
[[whittaker]]
|
||
id = 10
|
||
name = "temperate_rainforest"
|
||
temp_lo = 278
|
||
temp_hi = 303
|
||
moist_lo = 0.60
|
||
moist_hi = 1.00
|
||
|
||
[[whittaker]]
|
||
id = 9
|
||
name = "temperate_deciduous_cool"
|
||
temp_lo = 273
|
||
temp_hi = 293
|
||
moist_lo = 0.30
|
||
moist_hi = 0.60
|
||
|
||
[[whittaker]]
|
||
id = 12
|
||
name = "shrubland"
|
||
temp_lo = 278
|
||
temp_hi = 303
|
||
moist_lo = 0.10
|
||
moist_hi = 0.30
|
||
|
||
[[whittaker]]
|
||
id = 14
|
||
name = "subtropical_desert"
|
||
temp_lo = 283
|
||
temp_hi = 308
|
||
moist_lo = 0.00
|
||
moist_hi = 0.18
|
||
|
||
[[whittaker]]
|
||
id = 13
|
||
name = "temperate_desert"
|
||
temp_lo = 273
|
||
temp_hi = 293
|
||
moist_lo = 0.00
|
||
moist_hi = 0.30
|
||
|
||
[[whittaker]]
|
||
id = 11
|
||
name = "boreal_taiga"
|
||
temp_lo = 253
|
||
temp_hi = 278
|
||
moist_lo = 0.40
|
||
moist_hi = 1.00
|
||
|
||
[[whittaker]]
|
||
id = 11
|
||
name = "boreal_dry"
|
||
temp_lo = 253
|
||
temp_hi = 278
|
||
moist_lo = 0.15
|
||
moist_hi = 0.40
|
||
|
||
[[whittaker]]
|
||
id = 16
|
||
name = "tundra"
|
||
temp_lo = 243
|
||
temp_hi = 263
|
||
moist_lo = 0.00
|
||
moist_hi = 1.00
|
||
|
||
[[whittaker]]
|
||
id = 16
|
||
name = "cold_tundra"
|
||
temp_lo = 233
|
||
temp_hi = 253
|
||
moist_lo = 0.20
|
||
moist_hi = 1.00
|
||
|
||
[[whittaker]]
|
||
id = 17
|
||
name = "ice_snow"
|
||
temp_lo = 200
|
||
temp_hi = 243
|
||
moist_lo = 0.00
|
||
moist_hi = 1.00
|
||
|
||
[[whittaker]]
|
||
id = 17
|
||
name = "ice_cold_dry"
|
||
temp_lo = 243
|
||
temp_hi = 273
|
||
moist_lo = 0.00
|
||
moist_hi = 0.15
|
||
|
||
# ─────────────────────────────────────────────────────────────────────
|
||
# Temperature bands per planet class (Kelvin)
|
||
# Fiction wins over physics — temperature is clamped to these bands.
|
||
# ─────────────────────────────────────────────────────────────────────
|
||
|
||
[temperature_bands]
|
||
temperate = [275, 305]
|
||
oceanic = [278, 300]
|
||
forest = [275, 308]
|
||
arid = [295, 340]
|
||
frozen = [210, 265]
|
||
volcanic = [290, 380]
|
||
barren = [180, 380]
|
||
|
||
# ─────────────────────────────────────────────────────────────────────
|
||
# Biome color palette
|
||
#
|
||
# Each biome class has two color modes:
|
||
# cartographic — map colors (National Geographic style, readable)
|
||
# photographic — orbital appearance (dark, muted, realistic)
|
||
#
|
||
# RGB values 0-255.
|
||
# ─────────────────────────────────────────────────────────────────────
|
||
|
||
[biome_colors]
|
||
|
||
# Ocean
|
||
0 = { name = "ocean_deep", cartographic = [ 80, 155, 190], photographic = [ 18, 45, 80] }
|
||
1 = { name = "ocean_mid", cartographic = [110, 185, 215], photographic = [ 28, 72, 115] }
|
||
2 = { name = "ocean_shallow", cartographic = [150, 210, 230], photographic = [ 42, 105, 145] }
|
||
|
||
# Coast / lowland
|
||
3 = { name = "coast", cartographic = [155, 185, 130], photographic = [ 90, 108, 75] }
|
||
4 = { name = "lowland", cartographic = [120, 165, 100], photographic = [ 72, 98, 58] }
|
||
|
||
# Tropical
|
||
5 = { name = "tropical_rainforest", cartographic = [ 50, 140, 65], photographic = [ 12, 38, 18] }
|
||
6 = { name = "tropical_seasonal", cartographic = [ 90, 170, 75], photographic = [ 28, 65, 28] }
|
||
7 = { name = "savanna", cartographic = [175, 210, 105], photographic = [108, 118, 55] }
|
||
|
||
# Temperate
|
||
8 = { name = "temperate_grassland", cartographic = [190, 210, 110], photographic = [118, 128, 62] }
|
||
9 = { name = "temperate_deciduous", cartographic = [ 70, 148, 70], photographic = [ 22, 55, 28] }
|
||
10 = { name = "temperate_rainforest", cartographic = [ 45, 125, 65], photographic = [ 15, 45, 22] }
|
||
11 = { name = "boreal_taiga", cartographic = [ 28, 88, 55], photographic = [ 8, 30, 18] }
|
||
12 = { name = "shrubland", cartographic = [168, 168, 95], photographic = [ 98, 88, 55] }
|
||
|
||
# Desert
|
||
13 = { name = "temperate_desert", cartographic = [215, 200, 155], photographic = [155, 138, 98] }
|
||
14 = { name = "subtropical_desert", cartographic = [210, 165, 85], photographic = [148, 108, 62] }
|
||
15 = { name = "hot_desert", cartographic = [215, 138, 55], photographic = [162, 98, 42] }
|
||
|
||
# Cold
|
||
16 = { name = "tundra", cartographic = [198, 185, 145], photographic = [ 95, 88, 72] }
|
||
17 = { name = "ice_snow", cartographic = [235, 238, 242], photographic = [218, 228, 238] }
|
||
18 = { name = "mountain_rock", cartographic = [148, 135, 120], photographic = [ 88, 80, 72] }
|
||
|
||
# Volcanic
|
||
19 = { name = "lava_field", cartographic = [ 55, 32, 22], photographic = [ 38, 22, 15] }
|
||
|
||
# Exotic / extremophile
|
||
20 = { name = "chemosynthetic_mat", cartographic = [ 45, 88, 52], photographic = [ 18, 38, 22] }
|
||
21 = { name = "thermophilic_field", cartographic = [118, 72, 40], photographic = [ 78, 45, 22] }
|
||
22 = { name = "sulfuric_scrub", cartographic = [148, 130, 58], photographic = [ 98, 85, 35] }
|
||
23 = { name = "cryptobiotic_crust", cartographic = [130, 118, 100], photographic = [ 78, 70, 58] }
|
||
24 = { name = "lithic_pioneer", cartographic = [138, 125, 110], photographic = [ 82, 75, 65] }
|
||
25 = { name = "ash_field", cartographic = [ 68, 58, 52], photographic = [ 42, 35, 30] }
|
||
26 = { name = "ice_shelf", cartographic = [245, 246, 248], photographic = [235, 238, 242] }
|
||
|
||
# Dry terrain (atmosphere gate — non-vegetated)
|
||
27 = { name = "dust_plain", cartographic = [195, 165, 115], photographic = [175, 142, 95] }
|
||
28 = { name = "rocky_highland", cartographic = [175, 145, 105], photographic = [152, 122, 85] }
|
||
29 = { name = "warm_dust", cartographic = [210, 175, 120], photographic = [188, 155, 105] }
|
||
30 = { name = "cold_rock", cartographic = [160, 140, 115], photographic = [135, 118, 95] }
|
||
|
||
# Lunar terrain (grey rock)
|
||
31 = { name = "lunar_highland", cartographic = [165, 165, 162], photographic = [138, 138, 135] }
|
||
32 = { name = "lunar_mare", cartographic = [120, 120, 118], photographic = [100, 100, 98] }
|
||
33 = { name = "lunar_midland", cartographic = [145, 145, 142], photographic = [118, 118, 115] }
|
||
|
||
# ─────────────────────────────────────────────────────────────────────
|
||
# Rendering colors (not biome-specific)
|
||
# ─────────────────────────────────────────────────────────────────────
|
||
|
||
[render_colors]
|
||
river = [ 80, 140, 200]
|
||
coastline = [ 30, 45, 35]
|
||
|
||
# ─────────────────────────────────────────────────────────────────────
|
||
# Star tints — subtle color shift from stellar type
|
||
# Applied multiplicatively to surface lighting.
|
||
# ─────────────────────────────────────────────────────────────────────
|
||
|
||
[star_tints]
|
||
O = [0.90, 0.92, 1.00]
|
||
B = [0.94, 0.96, 1.00]
|
||
A = [0.97, 0.98, 1.00]
|
||
F = [1.00, 0.99, 0.97]
|
||
G = [1.00, 0.97, 0.93]
|
||
K = [1.00, 0.93, 0.85]
|
||
M = [1.00, 0.88, 0.78]
|
||
|
||
# ─────────────────────────────────────────────────────────────────────
|
||
# Atmosphere rim colors per planet class (globe renderer)
|
||
# null = no atmosphere glow
|
||
# ─────────────────────────────────────────────────────────────────────
|
||
|
||
[atmosphere_colors]
|
||
temperate = [0.45, 0.65, 1.00]
|
||
oceanic = [0.40, 0.60, 1.00]
|
||
forest = [0.42, 0.68, 0.80]
|
||
arid = [0.90, 0.72, 0.50]
|
||
martian = [0.82, 0.58, 0.40]
|
||
frozen = [0.75, 0.88, 1.00]
|
||
volcanic = [0.55, 0.40, 0.30]
|
||
|
||
# ─────────────────────────────────────────────────────────────────────
|
||
# Gas giant band palettes (globe renderer)
|
||
# Each palette is a list of RGB band colors.
|
||
# ─────────────────────────────────────────────────────────────────────
|
||
|
||
[gas_palettes]
|
||
jovian = [[0.78, 0.62, 0.44], [0.60, 0.44, 0.30], [0.88, 0.76, 0.60],
|
||
[0.72, 0.55, 0.38], [0.92, 0.84, 0.70], [0.55, 0.40, 0.28]]
|
||
neptunian = [[0.25, 0.45, 0.75], [0.35, 0.58, 0.85], [0.18, 0.35, 0.65],
|
||
[0.42, 0.65, 0.90], [0.20, 0.40, 0.70], [0.50, 0.70, 0.92]]
|
||
saturnian = [[0.82, 0.74, 0.55], [0.75, 0.66, 0.48], [0.88, 0.80, 0.62],
|
||
[0.70, 0.62, 0.44], [0.92, 0.86, 0.68], [0.65, 0.58, 0.42]]
|
||
icy = [[0.78, 0.85, 0.92], [0.70, 0.80, 0.90], [0.85, 0.90, 0.95],
|
||
[0.65, 0.75, 0.88], [0.90, 0.93, 0.97], [0.60, 0.70, 0.85]]
|
||
sulfuric = [[0.88, 0.80, 0.22], [0.80, 0.65, 0.18], [0.92, 0.86, 0.35],
|
||
[0.75, 0.60, 0.15], [0.85, 0.75, 0.28], [0.70, 0.55, 0.12]]
|
||
infernal = [[0.65, 0.18, 0.12], [0.45, 0.12, 0.08], [0.80, 0.25, 0.15],
|
||
[0.55, 0.15, 0.10], [0.72, 0.20, 0.12], [0.38, 0.10, 0.06]]
|
||
|
||
# Locked selection list for deterministic random palette assignment.
|
||
# Order matters — changing this changes which body gets which palette.
|
||
# Only add to the end. Never reorder or remove.
|
||
selection_order = ["jovian", "neptunian", "saturnian", "icy", "sulfuric", "infernal"]
|
||
|
||
# ─────────────────────────────────────────────────────────────────────
|
||
# Crater scaling factors
|
||
# atmosphere: fraction of impactors that survive entry
|
||
# tectonics: fraction of craters preserved (not resurfaced)
|
||
# Final crater count = base_count × atmo_factor × tect_factor
|
||
# ─────────────────────────────────────────────────────────────────────
|
||
|
||
[crater_scaling]
|
||
base_count = 300
|
||
|
||
[crater_scaling.atmosphere]
|
||
none = 1.0
|
||
thin = 0.6
|
||
standard = 0.25
|
||
thick = 0.08
|
||
|
||
[crater_scaling.tectonics]
|
||
none = 1.0
|
||
low = 0.7
|
||
active = 0.3
|
||
extreme = 0.1
|
||
|
||
# ─────────────────────────────────────────────────────────────────────
|
||
# Exotic biome class IDs (modifier stack in compute_biome)
|
||
# ─────────────────────────────────────────────────────────────────────
|
||
|
||
[exotic_classes]
|
||
chemosynthetic_mat = 20
|
||
thermophilic_field = 21
|
||
sulfuric_scrub = 22
|
||
cryptobiotic_crust = 23
|
||
ash_field = 25
|
||
lava_field = 19
|
||
ice_shelf = 26
|