diff --git a/src/bin/lorenz/main.rs b/src/bin/lorenz/main.rs new file mode 100644 index 0000000..d466cba --- /dev/null +++ b/src/bin/lorenz/main.rs @@ -0,0 +1,99 @@ +use std::env::args; +use std::io::stdout; +use std::io::Write; +use std::iter::repeat; +use std::thread::sleep; +use std::time::Duration; + +use pixelfoo::color::Color; + +type Frame = Vec>; + +fn send(w: &mut T, f: &Frame) -> std::io::Result<()> { + for l in f { + for c in l { + w.write_all(&c.rgb())?; + } + } + w.flush() +} + +const DEFAULT_ARG: usize = 10; +fn main() -> std::io::Result<()> { + let args = args().collect::>(); + eprintln!("executing {}", args[0]); + + let x_size = args[1].parse::().unwrap(); + let y_size = args[2].parse::().unwrap(); + let arg = args[3].parse::().unwrap_or(DEFAULT_ARG); + eprintln!("screen size {}x{}, arg {}", x_size, y_size, arg); + + let t_frame = 0.040; // s + let delay = Duration::new(0, (1_000_000_000.0 * t_frame) as u32); + + // Background color. + let c0 = Color::new(0, 0, 80); + let [r0, g0, b0] = c0.rgb(); + + let c1 = Color::new(0, 255, 80); + + let mut frame = repeat(repeat(c0).take(x_size).collect::>()) + .take(y_size) + .collect::>(); + + let x0 = (x_size as f64) / 2.0; + let y0 = (y_size as f64) / 2.0; + + let xc = 0.0; + let zc = 26.0; + let x_scale = 2.0; + let z_scale = 1.0; + + let dt = 0.005; + let a = 10.0; + let b = 27.0; + let c = 8.0 / 3.0; + + let mut x = 1.0; + let mut y = 0.0; + let mut z = zc; + + loop { + //eprintln!("{:10.3} {:10.3} {:10.3}", x, y, z); + + // Decay towards the background color. + for row in &mut frame { + for pixel in row { + let [mut r, mut g, mut b] = pixel.rgb(); + if r > r0 { + r -= 1; + } + if g > g0 { + g -= 1; + } + if b > b0 { + b -= 1; + } + *pixel = Color::new(r, g, b); + } + } + + for _ in 0..arg { + x += dt * a * (y - x); + y += dt * (x * (b - z) - y); + z += dt * (x * y - c * z); + + let xf = (x_scale * (x - xc) + x0).round(); + let yf = (z_scale * (z - zc) + y0).round(); + if xf >= 0.0 && xf < x_size as f64 && yf >= 0.0 && yf < y_size as f64 { + frame[yf as usize][xf as usize] = c1; + } + } + + let mut buf = Vec::with_capacity(x_size * y_size * 3); + send(&mut buf, &frame)?; + stdout().write_all(&buf)?; + stdout().flush()?; + sleep(delay); + } +}