OverviewThis WebsiteHome LabTrading BotEcosimProcedural Generation
Source Code

src/pages/projects/proc_gen.rs

use leptos::*;
use leptos_meta::{Meta, Title};

use super::data::ALL_PROJECTS;

#[component]
pub fn ProcGen() -> impl IntoView {
    let project = ALL_PROJECTS
        .iter()
        .find(|p| p.slug == "proc-gen")
        .unwrap();
    let skills_view = project
        .skills
        .iter()
        .map(|&s| view! { <li>{s}</li> })
        .collect::<Vec<_>>();

    view! {
        <Title text="Procedural Generation – Peter Pinto"/>
        <Meta name="description" content="A planet-scale procedural generation engine using the H3 hexagonal grid, adaptive LOD refinement, and a trait-based deterministic simulation system built on Bevy."/>
        <div class="page">
            <span class="eyebrow">"Projects"</span>
            <h1>"Procedural " <em style="font-style:italic; color: var(--accent)">"Generation"</em></h1>
            <p class="lead">
                "A planet-scale hexagonal grid engine with adaptive level-of-detail refinement,
                Perlin noise terrain, and a trait-based simulation system — designed for
                deterministic, networked ecosystem simulation."
            </p>

            <ul class="skills-list" style="margin-top: 1.5rem;">
                {skills_view}
            </ul>

            <hr class="divider"/>

            // ── H3 Grid ───────────────────────────────────────────
            <section class="project-section">
                <span class="eyebrow">"Foundation"</span>
                <h2>"H3 Hexagonal Grid"</h2>
                <p>
                    "The planet surface is partitioned using "
                    <a href="https://h3geo.org" target="_blank" rel="noopener noreferrer" class="prose-link">"Uber's H3"</a>
                    " hierarchical hexagonal grid system. Unlike square or triangular grids,
                    H3's hexagons have uniform neighbour distances and no pole singularities —
                    every cell on the sphere has the same geometric relationship to its neighbours.
                    The hierarchy runs from resolution 0 (122 base cells covering the globe) up
                    to resolution 15 (sub-metre cells), where each hex subdivides into 7 children."
                </p>
            </section>

            <hr class="divider"/>

            // ── Adaptive LOD ──────────────────────────────────────
            <section class="project-section">
                <span class="eyebrow">"Rendering"</span>
                <h2>"Adaptive LOD Refinement"</h2>
                <p>
                    "Cell resolution is managed dynamically based on camera proximity. Cells
                    near the camera are in "
                    <code class="inline-code">"Refining"</code>
                    " state — they spawn their 7 children and despawn themselves. Cells the
                    camera moves away from enter "
                    <code class="inline-code">"Coarsening"</code>
                    " state — their parent is respawned and they are removed. The transition
                    is driven by Bevy ECS systems on a custom "
                    <code class="inline-code">"SimulationUpdate"</code>
                    " schedule that runs independently of the render loop."
                </p>
                <p style="margin-top: 1rem;">
                    "The result is a globe that renders only as much geometry as the current
                    viewpoint demands — a low-resolution wireframe from orbit that resolves
                    to fine-grained detail on the ground without ever loading the full grid
                    into memory."
                </p>
            </section>

            <hr class="divider"/>

            // ── Terrain ───────────────────────────────────────────
            <section class="project-section">
                <span class="eyebrow">"World Generation"</span>
                <h2>"Terrain"</h2>
                <p>
                    "Terrain height is sampled using multi-octave Perlin noise from the "
                    <code class="inline-code">"noise"</code>
                    " crate. Each H3 cell's geographic centroid is converted to lat/lng
                    coordinates, which are fed into the noise function to produce a stable,
                    deterministic height value. Higher octaves add fine surface detail without
                    altering coarse topology — this means the terrain is consistent regardless
                    of which resolution level samples it."
                </p>
            </section>

            <hr class="divider"/>

            // ── Simulation ────────────────────────────────────────
            <section class="project-section">
                <span class="eyebrow">"Simulation"</span>
                <h2>"Trait-Based Simulation System"</h2>
                <p>
                    "Simulation logic is plugged in via a "
                    <code class="inline-code">"Simulation"</code>
                    " trait. Each implementation receives a cell's current state and its
                    neighbours' states and returns an updated state. This keeps the simulation
                    logic completely decoupled from the grid management code — swapping in a
                    different ecosystem model is a one-line change."
                </p>
                <p style="margin-top: 1rem;">
                    "When the LOD changes, simulation data is preserved through an
                    aggregate/subdivide pattern: child cells inherit subdivided values from
                    their parent, and when cells coarsen, children aggregate back up to
                    produce a consistent parent state. No simulation history is lost across
                    resolution transitions."
                </p>
            </section>

            <hr class="divider"/>

            // ── Determinism ───────────────────────────────────────
            <section class="project-section">
                <span class="eyebrow">"Design"</span>
                <h2>"Determinism"</h2>
                <p>
                    "Every system that touches simulation state is audited for determinism.
                    HashMaps have been replaced with BTreeMaps where iteration order matters.
                    Bevy query ordering is explicitly controlled via system ordering constraints.
                    A "
                    <code class="inline-code">"DETERMINISM_ANALYSIS.md"</code>
                    " tracks every known nondeterministic pattern and its resolution status —
                    floating-point variance, query iteration order, and hash randomisation
                    are each addressed individually."
                </p>
            </section>
        </div>
    }
}