Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

facett-map3d/examples/flythrough.rs

//! **facett — OSM 3D flight-sim / cinematic flythrough** (`flythrough` example).
//!
//! A standalone eframe/wgpu window that WATCHES a camera fly the extruded OSM 3D city
//! on its own: the buildings rise from real footprints, the GPU depth buffer orders
//! them, and the [`Map3D`] cinematic flythrough ([`Map3D::with_flythrough`]) orbits +
//! cruises + sweeps the skyline — no keyboard needed. Toggle **auto-fly** off to grab
//! the orbit controls yourself.
//!
//! Run (on a display):
//! ```bash
//! DISPLAY=:0 cargo run -p facett-map3d --example flythrough --features wgpu --release
//! ```

// Native-only (opens an eframe window). Empty `main` on wasm so the crate still
// builds for `wasm32-unknown-unknown`.
#[cfg(target_arch = "wasm32")]
fn main() {}

#[cfg(not(target_arch = "wasm32"))]
use app::App;

#[cfg(not(target_arch = "wasm32"))]
mod app {
    use eframe::egui;
    use facett_core::Facet;
    use facett_map::Way;
    use facett_map3d::Map3D;

    /// A deterministic procedural city (a grid of closed, filled building rings) so the
    /// demo runs fixture-free; `from_geometry` frames the densest cluster and the
    /// flythrough flies it. Point a real OSM extract in later via `facett-osm` if wanted.
    pub fn grid_city() -> Vec<Way> {
        let lon0 = 9.50;
        let lat0 = 47.10;
        let cell = 0.0016;
        let n = 10;
        let mut ways = Vec::new();
        let mut id = 1i64;
        let hash = |a: i64, b: i64| -> u32 {
            let mut h = (a.wrapping_mul(73856093) ^ b.wrapping_mul(19349663)) as u32;
            h ^= h >> 13;
            h = h.wrapping_mul(0x9E3779B1);
            h ^ (h >> 16)
        };
        for gy in 0..n {
            for gx in 0..n {
                let h = hash(gx, gy);
                if h % 7 == 0 {
                    continue;
                }
                let cx = lon0 + (gx as f64 + 0.5) * cell;
                let cy = lat0 + (gy as f64 + 0.5) * cell;
                let half = cell * (0.18 + (h % 13) as f64 * 0.012);
                let ring = vec![
                    (cx - half, cy - half),
                    (cx + half, cy - half),
                    (cx + half, cy + half),
                    (cx - half, cy + half),
                    (cx - half, cy - half),
                ];
                let fill = egui::Color32::from_rgb(90 + (h % 60) as u8, 150 + (h % 70) as u8, 210 + (h % 45) as u8);
                let outline = egui::Color32::from_rgb(20, 40, 60);
                ways.push(Way::filled(id, "building", ring, fill, outline, 1.0));
                id += 1;
            }
        }
        ways
    }

    pub struct App {
        map: Map3D,
        autofly: bool,
    }

    impl App {
        pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
            // Install the GPU depth-tested renderer into eframe's wgpu render state.
            if let Some(rs) = cc.wgpu_render_state.as_ref() {
                facett_map3d::gpu::install_renderer(rs);
            }
            let ways = grid_city();
            let map = Map3D::from_geometry("OSM 3D flythrough", &ways).with_gpu(true).with_flythrough(true);
            Self { map, autofly: true }
        }
    }

    impl eframe::App for App {
        // This facett eframe build hands the app a single full-window `Ui` (the same
        // `App::ui` signature `osm3d_demo.rs` uses), so panels lay out with the
        // `Ui`-taking `show` (egui 0.36's name for `show_inside`).
        fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
            // Keep the flight animating even with no input events.
            ui.ctx().request_repaint();

            egui::Panel::top("bar").show(ui, |ui| {
                ui.horizontal_wrapped(|ui| {
                    ui.heading("facett · OSM 3D flight-sim");
                    ui.separator();
                    if ui.checkbox(&mut self.autofly, "auto-fly (cinematic flythrough)").changed() {
                        self.map.set_flythrough(self.autofly);
                    }
                    ui.separator();
                    ui.label(if self.autofly {
                        "watching the camera fly the city — untick auto-fly to take the controls"
                    } else {
                        "drag to orbit · wheel to zoom · re-tick auto-fly to resume the flythrough"
                    });
                });
            });

            egui::CentralPanel::default().show(ui, |ui| {
                facett_core::set_theme(ui.ctx(), facett_core::Theme::sci_fi());
                Facet::ui(&mut self.map, ui);
            });
        }
    }
}

#[cfg(not(target_arch = "wasm32"))]
fn main() -> eframe::Result<()> {
    let native_options = eframe::NativeOptions {
        viewport: eframe::egui::ViewportBuilder::default()
            .with_inner_size([1100.0, 760.0])
            .with_title("facett — OSM 3D flight-sim (cinematic flythrough)"),
        renderer: eframe::Renderer::Wgpu,
        ..Default::default()
    };
    eframe::run_native(
        "facett-flythrough",
        native_options,
        Box::new(|cc| Ok(Box::new(App::new(cc)))),
    )
}