Tile Wave

Tile wave made with Nannou.

Tile Wave
0:00
/

Tile wave made with Nannou.

use nannou::noise::*;
use nannou::prelude::*;

fn main() {
    nannou::app(model).run();
}

struct Model {
    cols: u32,
    rows: u32,
    noise: Perlin,
    z_dist: f32,
}

fn model(app: &App) -> Model {
    let width = 400;
    let height = 400;
    let scale = 40;
    app.new_window().size(width, height).view(view).build().unwrap();
    let cols = width / scale;
    let rows = height / scale;
    let mut noise = Perlin::new();
    noise = noise.set_seed(1);

    Model {
        cols,
        rows,
        noise,
        z_dist: 200.0,
    }
}

fn view(app: &App, model: &Model, frame: Frame) {
    frame.clear(BLACK);
    let win = app.main_window();
    let win_r = win.rect();

    let draw = app.draw();
    let mut yoff = 0.0;
    let zoff = (app.time + 600.0) / 2.0;
    let cell_size = (win_r.right() - win_r.left()) / model.cols as f32;
    let mut tris = Vec::new();

    for col in 0..model.cols {
        let mut xoff = 0.0;
        for row in 0..model.rows {
            let random = model.noise.get([xoff as f64, yoff as f64, zoff as f64]) as f32 * -model.z_dist;
            let start_x = map_range(col as f32, 0.0, model.cols as f32, win_r.left(), win_r.right());
            let start_y = map_range(row as f32, 0.0, model.rows as f32, win_r.bottom(), win_r.top());

            let a = pt3(start_x, start_y, random);
            let b = pt3(start_x + cell_size, start_y, random);
            let c = pt3(start_x + cell_size, start_y + cell_size, random);
            let d = pt3(start_x, start_y + cell_size, random);
            geom::Quad([a, b, c, d]).triangles_iter().for_each(|t| {
                tris.push(t);
            });

            xoff += 0.1;
        }

        yoff += 0.1;
    }

    let tris_colored = tris.iter().map(|tri| {
        return tri.map_vertices(|v| {
            let r = map_range(v[2], 0.0, -model.z_dist, 0.6, 0.9);
            let color = hsl(r, 1.0, 0.5);
            (v, color)
        });
    });

    draw.mesh()
        .tris_colored(tris_colored)
        .x_radians(0.5)
        .y_radians(clamp(app.time.sin(), -0.2, 0.2));

    draw.to_frame(app, &frame).unwrap();
    
    if frame.nth() < 300 {
        let file_path = captured_frame_path(app, &frame);
        app.main_window().capture_frame(file_path);
    }
}

fn captured_frame_path(app: &App, frame: &Frame) -> std::path::PathBuf {
    app.project_path()
        .expect("failed to locate `project_path`")
        .join("frames")
        .join(format!("{:04}", frame.nth()))
        .with_extension("png")
}