Skip to content

Hacker Guide

Ziv edited this page Jun 1, 2026 · 1 revision

Raytiles Architecture Diagram

Component Overview

graph TB
    subgraph PublicAPI["📦 Public API"]
        Streamer["🎬 streamer<br/>(Main Orchestrator)<br/>- update: camera→tiles<br/>- draw: render tiles<br/>- ground_height: O(1) query"]
    end

    subgraph ConfigStructs["⚙️ Configuration Objects"]
        WC["world_config<br/>- anchor_x/z_tile<br/>- base_zoom / max_zoom<br/>- tile_size<br/>- skirt_overlap"]
        SC["streaming_config<br/>- rendering_radius<br/>- thresholds per zoom<br/>- update_distance_sq<br/>- upload budget"]
        RC["rendering_config<br/>- fog color/distance<br/>- ambient light<br/>- sun direction/scale<br/>- height/normals scale"]
        PC["pool_config<br/>- download_threads<br/>- cache paths<br/>- tile URLs<br/>- TLS settings"]
    end

    subgraph InternalComponents["🔧 Internal Components"]
        TR["tiles_renderer<br/>- Owns tile_shader<br/>- Owns material<br/>- Draws tiles with lighting"]
        TM["tiles_manager<br/>- Manages tile lifecycle<br/>- Owns pool<br/>- Frustum culling<br/>- LOD subdivision"]
        Pool["pool (workers)<br/>- 4+ worker threads<br/>- Download manager<br/>- Cache I/O<br/>- Image decoding"]
    end

    subgraph ShaderComponents["🎨 Shader & Rendering"]
        TS["tile_shader<br/>- Displacement mapping<br/>- Normal mapping<br/>- Fog blending<br/>- Lighting (sun+ambient)"]
        Mat["Material<br/>(raylib)<br/>- Shader binding<br/>- Texture units<br/>- Uniform state"]
    end

    subgraph TileLifecycle["🔄 Tile States"]
        DK["desired_keys<br/>Set of tiles needed"]
        LT["loading_tile<br/>- 3x futures<br/>- tx/tz position<br/>- stb_image decode"]
        LDT["loaded_tile<br/>- GPU textures<br/>- CPU heightmap<br/>- Mesh (vertex buf)"]
    end

    subgraph DataStructures["📊 Data Structures"]
        TK["tile_key<br/>zoom, x, z"]
        TV["tile_value<br/>size, threshold, mesh"]
        TImage["raylib Image<br/>(texture, heightmap,<br/>normals)"]
    end

    subgraph ExternalDeps["📚 External Dependencies"]
        Raylib["raylib<br/>- Window / GL context<br/>- Image / Shader<br/>- Camera / Matrix"]
        STBI["stb_image<br/>- PNG decode<br/>(reentrant)<br/>- runs in worker"]
        httplib["httplib<br/>- HTTPS downloads<br/>- Keep-alive<br/>(main thread only)"]
    end

    %% Connections: Streamer to Configs
    Streamer -->|takes| WC
    Streamer -->|takes| SC
    Streamer -->|takes| RC
    Streamer -->|takes| PC

    %% Connections: Streamer to Internal
    Streamer -->|owns| TR
    Streamer -->|owns| TM

    %% Connections: Internal to Internal
    TR -->|uses| TS
    TR -->|owns| Mat
    TM -->|owns| Pool

    %% Connections: to Tile States
    TM -->|maintains| DK
    TM -->|manages| LT
    TM -->|promotes to| LDT

    %% Connections: Tile Lifecycle
    DK -->|triggers| LT
    LT -->|future resolves| LDT

    %% Connections: Data Structures
    TK -->|used by| TM
    TV -->|used by| TM
    LT -->|contains| TImage
    LDT -->|contains| TImage

    %% Connections: Shader and Rendering
    TS -->|used by| Mat
    TR -->|renders| LDT

    %% Connections: External Dependencies
    Streamer -->|requires| Raylib
    TR -->|uses| Raylib
    Pool -->|uses| STBI
    Pool -->|uses| httplib
    Raylib -->|provides| TImage

    %% Styling
    classDef publicStyle fill:#90EE90,stroke:#2d5016,stroke-width:2px,color:#000
    classDef configStyle fill:#87CEEB,stroke:#003d99,stroke-width:2px,color:#000
    classDef internalStyle fill:#FFB6C1,stroke:#8b0000,stroke-width:2px,color:#000
    classDef shaderStyle fill:#FFE4B5,stroke:#8b4513,stroke-width:2px,color:#000
    classDef tileStyle fill:#DDA0DD,stroke:#4b0082,stroke-width:2px,color:#000
    classDef dataStyle fill:#F0E68C,stroke:#556b2f,stroke-width:2px,color:#000
    classDef externalStyle fill:#D3D3D3,stroke:#404040,stroke-width:2px,color:#000

    class Streamer publicStyle
    class WC,SC,RC,PC configStyle
    class TR,TM,Pool internalStyle
    class TS,Mat shaderStyle
    class DK,LT,LDT tileStyle
    class TK,TV,TImage dataStyle
    class Raylib,STBI,httplib externalStyle
Loading

Per-Frame Update Loop

sequenceDiagram
    participant App as Application
    participant S as streamer
    participant TM as tiles_manager
    participant Pool as pool
    participant TR as tiles_renderer
    participant GPU as GPU

    App->>S: update(camera, offset)
    activate S
    S->>TM: compute desired tiles (LOD/frustum)
    activate TM
    TM->>Pool: request new downloads
    activate Pool
    Pool-->>TM: futures (shared_future<Image>)
    deactivate Pool
    TM->>TM: poll finished futures
    TM->>GPU: upload ready tiles (budget capped)
    note over GPU: max_uploads_per_frame<br/>upload_budget_sec
    deactivate TM
    deactivate S

    App->>S: draw()
    activate S
    S->>TR: render tiles in frustum
    activate TR
    TR->>GPU: bind shader + textures
    TR->>GPU: render loaded_tile meshes
    deactivate TR
    deactivate S

    App->>S: ground_height(pos)
    activate S
    S->>TM: find loaded_tile at pos
    TM->>TM: pixel read from<br/>CPU heightmap buffer
    S-->>App: altitude (O(1))
    deactivate S
Loading

Component Responsibilities

Component Responsibility Key Methods
streamer Main entry point, orchestrates update/draw cycle, caches frame state update(), draw(), ground_height(), set_*()
tiles_manager Tile lifecycle (desired→loading→loaded), LOD/frustum, GPU upload scheduling update(), post_process(), promoted_tiles()
tiles_renderer Shader binding, material state, tile mesh rendering draw(), debug(), set_*()
pool Background downloads, cache I/O, stb_image decode, future resolution request_image(), worker_loop()
tile_shader Displacement mapping, normal maps, lighting, fog, skirts shader program compilation
world_config Immutable world topology (anchor, zoom range, tile size, skirt overlap)
streaming_config LOD thresholds, update gating, upload budget, frustum planes
rendering_config Runtime shader uniforms (fog, lighting, drama factors)
pool_config URL/cache templates, worker thread count, TLS settings

Data Flow: Tile Acquisition

1. desired_keys (set of tile_key)
   ↓
2. pool::request_image() for each tile
   ├── cache hit → immediate Image
   └── cache miss → HTTPS download
   ↓
3. shared_future<Image> (3 per tile: tx, hm, nl)
   ↓
4. Poll futures in tiles_manager::post_process()
   ├── texture → UnloadImage + GPU upload
   ├── heightmap → adopt into raii::image (keep CPU copy)
   └── normals → UnloadImage + GPU upload
   ↓
5. loaded_tile ⊂ rendering_tiles
   ↓
6. tiles_renderer::draw() renders in frustum
   ↓
7. ground_height() reads CPU heightmap buffer (O(1))

Key Invariants

  • Window first: InitWindow() must exist before constructing streamer
  • Thread safety: Pool workers never call raylib functions (stb_image only)
  • GPU upload on main thread: Only streamer/tiles_manager can upload to GPU
  • Zoom range: Every zoom in [base_zoom, max_zoom] needs entries in both thresholds and skirt_overlap
  • Tile coordinate order:
    • Esri texture: zoom/y/x (intentional swap)
    • Mapzen heightmap/normals: zoom/x/y (standard)
  • Large-world shifting: Camera in user space, streamer converts to absolute via world_offset
  • Heightmap format: Mapzen Terrarium (RGB encoding of altitude)

Configuration Relationships

graph LR
    A["world_config"] -->|base/max_zoom| B["streaming_config"]
    A -->|tile_size| C["tiles_manager"]
    A -->|anchor| C
    B -->|thresholds| C
    B -->|upload budget| C
    C -->|rendering_config| D["tiles_renderer"]
    D -->|shader uniforms| E["tile_shader"]
    A -->|pool_config| F["pool"]
    C -->|pool| F
Loading

Clone this wiki locally