worldgen

git clone https://git.godosa.eu/worldgen

master

raw · 1637 bytes

"""Config O₂ / low-gravity zones: smooth, noise-warped discs in mask units
(O₂ ×(1 + 0.5 v), gravity ×(1 + 0.7 v)), added to the painted masks in the `sketch` stage. Very gradual: at most
≈ 1.9 · |effect| / radius per km (≤ 0.23 O₂ points and ≤ 0.014 g per 30 km for the configured zones)."""
from __future__ import annotations

import numpy as np

from .noise import fbm, name_seed
from .sphere import gc_dist_km, latlon_to_xyz

WARP = 0.2           # outline wobble: distances stretched or shrunk by up to 20 % (low-frequency noise)
WARP_FREQ = 1.0


def smootherstep(t):
    t = np.clip(t, 0.0, 1.0)
    return t * t * t * (t * (6.0 * t - 15.0) + 10.0)


def contribution(xyz, zone: dict, seed: int, radius_km: float):
    """v · (1 − smootherstep(d′ / r)), d′ = d · (1 + WARP · warp): v at the centre, 0 beyond r / (1 − WARP)."""
    xyz = np.asarray(xyz, dtype=np.float64)
    d = gc_dist_km(xyz, latlon_to_xyz(*zone["center"]), radius_km)
    r = float(zone["radius_km"])
    out = np.zeros(len(xyz))
    near = d < r / (1.0 - WARP)
    if near.any():
        w = np.clip(2.0 * fbm(xyz[near], name_seed(seed, zone["name"]), 3, WARP_FREQ), -1.0, 1.0)
        out[near] = zone["v"] * (1.0 - smootherstep(d[near] * (1.0 + WARP * w) / r))
    return out


def masks(xyz, zones: list, seed: int, radius_km: float):
    """(m_o2, m_gravity): the config zones summed (the caller adds the painted masks and clips to [−1, 1])."""
    m = {"o2": np.zeros(len(xyz)), "gravity": np.zeros(len(xyz))}
    for z in zones:
        m[z["field"]] += contribution(xyz, z, seed, radius_km)
    return m["o2"], m["gravity"]