From 99dddfde579d67a713a702c8ef9fecd1001136e8 Mon Sep 17 00:00:00 2001 From: annieversary Date: Tue, 24 Aug 2021 20:41:36 +0200 Subject: [PATCH] subtitled #8 --- Cargo.lock | 8 ++ crates/subtitled8/Cargo.toml | 8 ++ crates/subtitled8/src/main.rs | 133 ++++++++++++++++++++++++++++++++++ crates/utils/src/lib.rs | 9 +++ crates/utils/src/sequences.rs | 36 +++++++++ record.sh | 2 +- 6 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 crates/subtitled8/Cargo.toml create mode 100644 crates/subtitled8/src/main.rs create mode 100644 crates/utils/src/sequences.rs diff --git a/Cargo.lock b/Cargo.lock index 9b67520..8df08da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2396,6 +2396,14 @@ dependencies = [ "utils", ] +[[package]] +name = "subtitled8" +version = "0.1.0" +dependencies = [ + "nannou", + "utils", +] + [[package]] name = "syn" version = "1.0.74" diff --git a/crates/subtitled8/Cargo.toml b/crates/subtitled8/Cargo.toml new file mode 100644 index 0000000..9e5a005 --- /dev/null +++ b/crates/subtitled8/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "subtitled8" +version = "0.1.0" +edition = "2018" + +[dependencies] +nannou = "0.17" +utils = { path = "../utils" } diff --git a/crates/subtitled8/src/main.rs b/crates/subtitled8/src/main.rs new file mode 100644 index 0000000..838dcb1 --- /dev/null +++ b/crates/subtitled8/src/main.rs @@ -0,0 +1,133 @@ +use nannou::prelude::*; +use utils::*; + +fn main() { + nannou::app(model).update(update).simple_window(view).run(); +} + +const POINTS: usize = 10; +const NUM: usize = 200; + +struct Model { + points: Vec, + offsets: Vec, + + bg: Vec<(Vec2, f32)>, +} +impl Model { + fn points(&self) -> Vec { + self.points + .windows(2) + .flat_map(|p| { + let a = p[0]; + let b = p[1]; + (0..NUM).map(move |i| { + let i = i as f32 / NUM as f32; + (1.0 - i) * a + i * b + }) + }) + .zip(self.offsets.iter()) + .map(|(a, &b)| a + b) + .collect() + } +} + +fn model(_app: &App) -> Model { + let points = (0..POINTS) + .map(|_| vec2(random_range(-1., 1.), random_range(-1., 1.)) * 200.0) + .collect::>(); + + let offsets = vec![Vec2::ZERO; NUM * POINTS]; + + let bg = sequences::Halton::points(2.0, 3.0) + .take(10000) + .map(|v| (v - Vec2::splat(0.5)) * 1100.0) + .filter(|v| v.x.abs() > 220.0 || v.y.abs() > 220.0) + .map(|v| (v, 0.5)) + .collect(); + + Model { + points, + offsets, + bg, + } +} + +fn update(app: &App, model: &mut Model, _update: Update) { + let t = app.elapsed_frames() as f32 / 60.0; + + for p in &mut model.offsets { + *p *= 0.95; + *p += 0.3 * vec2(random_range(-1.0, 1.0), random_range(-1.0, 1.0)); + } + + for (i, p) in model.points.iter_mut().enumerate() { + let a = i as f32 * 0.1; + p.x = (t * a + i as f32).sin(); + p.y = (t * 1.3 * a + i as f32).cos(); + *p *= 200.0; + } + + for (i, p) in model.bg.iter_mut().enumerate() { + p.1 = (t * 2.0 + i as f32).sin() + 1.0; + } +} + +fn view(app: &App, model: &Model, frame: Frame) { + let _t = frame.nth() as f32 / 60.0; + + let draw = app.draw(); + if frame.nth() == 0 { + draw.background().color(SNOW); + } else { + // we only want fading on the inner box, + // outside of it we want a hard reset + + let win = app.window_rect(); + draw.rect() + .wh(win.wh()) + .color(srgba(1.0, 250.0 / 255.0, 250.0 / 255.0, 0.001)); + + draw.quad() + .points( + vec2(220.0, -1000.0), + vec2(220.0, 1000.0), + vec2(1000.0, 1000.0), + vec2(1000.0, -1000.0), + ) + .color(SNOW); + draw.quad() + .points( + vec2(-220.0, -1000.0), + vec2(-220.0, 1000.0), + vec2(-1000.0, 1000.0), + vec2(-1000.0, -1000.0), + ) + .color(SNOW); + draw.quad() + .points( + vec2(-1000.0, 220.0), + vec2(-1000.0, 1000.0), + vec2(1000.0, 1000.0), + vec2(1000.0, 220.0), + ) + .color(SNOW); + draw.quad() + .points( + vec2(-1000.0, -220.0), + vec2(-1000.0, -1000.0), + vec2(1000.0, -1000.0), + vec2(1000.0, -220.0), + ) + .color(SNOW); + } + + draw.polyline().points(model.points()).color(BLACK); + + for &(p, r) in &model.bg { + draw.ellipse().xy(p).radius(r).color(BLACK); + } + + draw.to_frame(app, &frame).unwrap(); + utils::record::record(app, &frame); +} diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs index f8f8b37..8c7fa7c 100644 --- a/crates/utils/src/lib.rs +++ b/crates/utils/src/lib.rs @@ -1,5 +1,6 @@ pub mod color; pub mod record; +pub mod sequences; use nannou::prelude::*; @@ -32,3 +33,11 @@ impl Vec2Extension for Vec2 { vec2(self.x, self.x) } } +pub trait Tup2Extension { + fn to_vec2(self) -> Vec2; +} +impl Tup2Extension for (f32, f32) { + fn to_vec2(self) -> Vec2 { + self.into() + } +} diff --git a/crates/utils/src/sequences.rs b/crates/utils/src/sequences.rs new file mode 100644 index 0000000..8c8abfb --- /dev/null +++ b/crates/utils/src/sequences.rs @@ -0,0 +1,36 @@ +use nannou::prelude::*; + +pub struct Halton { + i: usize, + base: f32, +} + +impl Halton { + pub fn new(base: f32) -> Self { + Self { i: 0, base } + } + + pub fn points(base1: f32, base2: f32) -> impl Iterator { + Self::new(base1) + .zip(Self::new(base2)) + .map(crate::Tup2Extension::to_vec2) + } +} + +impl Iterator for Halton { + type Item = f32; + + fn next(&mut self) -> Option { + let mut f = 1.0; + let mut r = 0.0; + let mut index = self.i as f32; + + while index > 0.0 { + f /= self.base; + r += f * (index % self.base); + index = (index / self.base).floor(); + } + self.i += 1; + Some(r) + } +} diff --git a/record.sh b/record.sh index 8d95db9..09280e5 100755 --- a/record.sh +++ b/record.sh @@ -7,7 +7,7 @@ if [[ -z $1 ]]; then echo "example:" echo -e "\t$0 packagename" else - rm -rf "recordings/frames/$1" + rm -rf "recordings/$1/frames" cargo run --release --package $1 -- -record filename="video$(( $(find recordings/$1/videos -type f -exec basename -s .mp4 {} \; | sed 's/^video//' | sort -n | tail -n1) + 1)).mp4" ffmpeg -framerate 60 -i "recordings/$1/frames/%03d.png" -pix_fmt yuv420p "recordings/$1/videos/$filename"