Compare commits
No commits in common. "main" and "e7b0735bcf76aabbb2023158230ee10b412b868d" have entirely different histories.
main
...
e7b0735bcf
61 changed files with 53 additions and 2834 deletions
229
Cargo.lock
generated
229
Cargo.lock
generated
|
@ -236,7 +236,7 @@ dependencies = [
|
|||
"daggy 0.5.0",
|
||||
"fnv",
|
||||
"instant",
|
||||
"num 0.3.1",
|
||||
"num",
|
||||
"pistoncore-input",
|
||||
"rusttype 0.8.3",
|
||||
]
|
||||
|
@ -1075,7 +1075,7 @@ dependencies = [
|
|||
"gif",
|
||||
"jpeg-decoder",
|
||||
"num-iter",
|
||||
"num-rational 0.3.2",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
"png",
|
||||
"scoped_threadpool",
|
||||
|
@ -1188,12 +1188,6 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a"
|
||||
|
||||
[[package]]
|
||||
name = "line_drawing"
|
||||
version = "0.7.0"
|
||||
|
@ -1587,25 +1581,11 @@ version = "0.3.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f"
|
||||
dependencies = [
|
||||
"num-bigint 0.3.2",
|
||||
"num-complex 0.3.1",
|
||||
"num-bigint",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-rational 0.3.2",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606"
|
||||
dependencies = [
|
||||
"num-bigint 0.4.2",
|
||||
"num-complex 0.4.0",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-rational 0.4.0",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
|
@ -1620,17 +1600,6 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74e768dff5fb39a41b3bcd30bb25cf989706c90d028d1ad71971987aa309d535"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.3.1"
|
||||
|
@ -1640,15 +1609,6 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26873667bbbb7c5182d4a37c1add32cdf09f841af72da53318fdb81543c15085"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
|
@ -1677,19 +1637,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-bigint 0.3.2",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-bigint 0.4.2",
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
@ -1701,7 +1649,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2080,16 +2027,6 @@ dependencies = [
|
|||
"getrandom 0.2.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_distr"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "051b398806e42b9cd04ad9ec8f81e355d0a382c543ac6672c62f5a5b452ef142"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"rand 0.8.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.2.0"
|
||||
|
@ -2411,87 +2348,6 @@ dependencies = [
|
|||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled10"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nannou",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled11"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nannou",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled12"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nannou",
|
||||
"rand_distr",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled13"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nannou",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled14"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nannou",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled15"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nannou",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled16"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nannou",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled17"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nannou",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled18"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nannou",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled19"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nannou",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled2"
|
||||
version = "0.1.0"
|
||||
|
@ -2500,55 +2356,6 @@ dependencies = [
|
|||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled20"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nannou",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled21"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nannou",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled22"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nannou",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled23"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nannou",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled24"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nannou",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled25"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nannou",
|
||||
"num 0.4.0",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled3"
|
||||
version = "0.1.0"
|
||||
|
@ -2581,30 +2388,6 @@ dependencies = [
|
|||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled7"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nannou",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled8"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nannou",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtitled9"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nannou",
|
||||
"utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.74"
|
||||
|
|
|
@ -3,3 +3,7 @@
|
|||
this is a bunch of nannou projects
|
||||
|
||||
i'll add a list with pictures here soon
|
||||
|
||||
you'll notice that the numbers i've put on fedi and the ones here are different :)
|
||||
|
||||
also don't criticize my code pls i'm sensitive and i Will cry
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 2 MiB |
Binary file not shown.
Before Width: | Height: | Size: 5.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.4 KiB |
|
@ -1,8 +0,0 @@
|
|||
[package]
|
||||
name = "subtitled10"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
utils = { path = "../utils" }
|
|
@ -1,171 +0,0 @@
|
|||
use nannou::prelude::*;
|
||||
use utils::*;
|
||||
|
||||
fn main() {
|
||||
nannou::app(model).update(update).simple_window(view).run();
|
||||
}
|
||||
|
||||
// http://paulbourke.net/fractals/clifford/
|
||||
// http://paulbourke.net/fractals/peterdejong/
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum Attractor {
|
||||
Clifford,
|
||||
DeJong,
|
||||
}
|
||||
|
||||
impl Attractor {
|
||||
fn random() -> Self {
|
||||
match random_range(0, 2) {
|
||||
0 => Self::Clifford,
|
||||
_ => Self::DeJong,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
struct Params {
|
||||
a: f32,
|
||||
b: f32,
|
||||
c: f32,
|
||||
d: f32,
|
||||
attractor: Attractor,
|
||||
}
|
||||
struct Model {
|
||||
points: Vec<Vec2>,
|
||||
base_hue: f32,
|
||||
|
||||
/// params for the attractor
|
||||
params: Params,
|
||||
|
||||
// modulation values for each param
|
||||
a_mul: f32,
|
||||
a_add: f32,
|
||||
b_mul: f32,
|
||||
b_add: f32,
|
||||
c_mul: f32,
|
||||
c_add: f32,
|
||||
d_mul: f32,
|
||||
d_add: f32,
|
||||
|
||||
// max range for each param
|
||||
// this would be a const, but acos isn't a const fn
|
||||
min_a: f32,
|
||||
max_a: f32,
|
||||
min_b: f32,
|
||||
max_b: f32,
|
||||
min_c: f32,
|
||||
max_c: f32,
|
||||
min_d: f32,
|
||||
max_d: f32,
|
||||
}
|
||||
|
||||
fn model(_app: &App) -> Model {
|
||||
Model {
|
||||
params: Params {
|
||||
a: 0.0,
|
||||
b: 0.0,
|
||||
c: 0.0,
|
||||
d: 0.0,
|
||||
attractor: Attractor::random(),
|
||||
},
|
||||
|
||||
a_mul: random_range(0.3, 1.0) * random_range(-1.0, 1.0).signum(),
|
||||
b_mul: random_range(0.3, 1.0) * random_range(-1.0, 1.0).signum(),
|
||||
c_mul: random_range(0.3, 1.0) * random_range(-1.0, 1.0).signum(),
|
||||
d_mul: random_range(0.3, 1.0) * random_range(-1.0, 1.0).signum(),
|
||||
|
||||
a_add: random_range(0.3, 2.0),
|
||||
b_add: random_range(0.3, 2.0),
|
||||
c_add: random_range(0.3, 2.0),
|
||||
d_add: random_range(0.3, 2.0),
|
||||
|
||||
// magic numbers from here:
|
||||
// http://paulbourke.net/fractals/clifford/paul_richards/main.cpp
|
||||
min_a: f32::acos(1.6 / 2.0),
|
||||
max_a: f32::acos(1.3 / 2.0),
|
||||
min_b: f32::acos(-0.6 / 2.0),
|
||||
max_b: f32::acos(1.7 / 2.0),
|
||||
min_c: f32::acos(-1.2 / 2.0),
|
||||
max_c: f32::acos(0.5 / 2.0),
|
||||
min_d: f32::acos(1.6 / 2.0),
|
||||
max_d: f32::acos(1.4 / 2.0),
|
||||
|
||||
base_hue: random_range(0., 360.0),
|
||||
points: vec![Vec2::splat(0.1); 10000],
|
||||
}
|
||||
}
|
||||
|
||||
fn advance(
|
||||
Params {
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
attractor,
|
||||
}: Params,
|
||||
point: Vec2,
|
||||
) -> Vec2 {
|
||||
let x = point.x;
|
||||
let y = point.y;
|
||||
|
||||
// clifford attractor
|
||||
// xn+1 = sin(a yn) + c cos(a xn)
|
||||
// yn+1 = sin(b xn) + d cos(b yn)
|
||||
|
||||
// de Jong
|
||||
// xn+1 = sin(a yn) - cos(b xn)
|
||||
// yn+1 = sin(c xn) - cos(d yn)
|
||||
|
||||
match attractor {
|
||||
Attractor::Clifford => vec2(
|
||||
(a * y).sin() + (a * x).cos() * c,
|
||||
(b * x).sin() + (b * y).cos() * d,
|
||||
),
|
||||
Attractor::DeJong => vec2((a * y).sin() - (b * x).cos(), (c * x).sin() - (d * y).cos()),
|
||||
}
|
||||
}
|
||||
|
||||
fn update(app: &App, model: &mut Model, _update: Update) {
|
||||
let t = app.elapsed_frames() as f32 / 60.0;
|
||||
|
||||
// modulate params
|
||||
model.params.a = map_sin(t * model.a_mul + model.a_add, model.min_a, model.max_a);
|
||||
model.params.b = map_sin(t * model.b_mul + model.b_add, model.min_b, model.max_b);
|
||||
model.params.c = map_sin(t * model.c_mul + model.c_add, model.min_c, model.max_c);
|
||||
model.params.d = map_sin(t * model.d_mul + model.d_add, model.min_d, model.max_d);
|
||||
|
||||
// advance all points in list
|
||||
let mut last = model.points.last().unwrap().clone();
|
||||
for v in &mut model.points {
|
||||
last = advance(model.params, last);
|
||||
*v = last;
|
||||
}
|
||||
|
||||
// move base_hue
|
||||
model.base_hue += 0.5;
|
||||
}
|
||||
|
||||
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(BLACK);
|
||||
} else {
|
||||
let win = app.window_rect();
|
||||
draw.rect().wh(win.wh()).color(srgba(0., 0.0, 0.0, 0.02));
|
||||
}
|
||||
|
||||
for &p in &model.points {
|
||||
let h = random_range(model.base_hue, model.base_hue + 60.0) / 360.0;
|
||||
draw.ellipse()
|
||||
.radius(0.2)
|
||||
.xy(150.0 * p)
|
||||
.color(hsla(h.fract(), 1.0, 0.5, 0.1));
|
||||
}
|
||||
|
||||
draw.to_frame(app, &frame).unwrap();
|
||||
utils::record::record(app, &frame);
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
[package]
|
||||
name = "subtitled11"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
utils = { path = "../utils" }
|
|
@ -1,163 +0,0 @@
|
|||
use nannou::prelude::*;
|
||||
|
||||
fn main() {
|
||||
nannou::app(model).update(update).simple_window(view).run();
|
||||
}
|
||||
|
||||
struct Model {
|
||||
automata: Automata,
|
||||
row: usize,
|
||||
cube: Vec<Vec4>,
|
||||
}
|
||||
|
||||
fn model(_app: &App) -> Model {
|
||||
// generate all the points in the cube
|
||||
let mut cube = vec![];
|
||||
let p = [-1.0, 1.0];
|
||||
for &x in &p {
|
||||
for &y in &p {
|
||||
for &z in &p {
|
||||
for &w in &p {
|
||||
cube.push(vec4(x, y, z, w));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Model {
|
||||
automata: Automata::new(),
|
||||
row: 0,
|
||||
cube,
|
||||
}
|
||||
}
|
||||
|
||||
fn update(app: &App, model: &mut Model, _update: Update) {
|
||||
let _t = app.elapsed_frames() as f32 / 60.0;
|
||||
|
||||
if app.elapsed_frames() % 10 == 0 {
|
||||
model.automata.advance();
|
||||
model.row += 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn rot(angle: f32) -> Mat4 {
|
||||
// 4d rotations https://math.stackexchange.com/questions/1402362/rotation-in-4d
|
||||
let m = mat4(
|
||||
vec4(angle.cos(), angle.sin(), 0.0, 0.0),
|
||||
vec4(-angle.sin(), angle.cos(), 0.0, 0.0),
|
||||
vec4(0.0, 0.0, 1.0, 0.0),
|
||||
vec4(0.0, 0.0, 0.0, 1.0),
|
||||
) * mat4(
|
||||
vec4(1.0, 0.0, 0.0, 0.0),
|
||||
vec4(0.0, angle.cos(), angle.sin(), 0.0),
|
||||
vec4(0.0, -angle.sin(), angle.cos(), 0.0),
|
||||
vec4(0.0, 0.0, 0.0, 1.0),
|
||||
);
|
||||
let angle = -angle * 2.0;
|
||||
m * mat4(
|
||||
vec4(1.0, 0.0, 0.0, 0.0),
|
||||
vec4(0.0, 1.0, 0.0, 0.0),
|
||||
vec4(0.0, 0.0, angle.cos(), angle.sin()),
|
||||
vec4(0.0, 0.0, -angle.sin(), angle.cos()),
|
||||
)
|
||||
}
|
||||
|
||||
fn view(app: &App, model: &Model, frame: Frame) {
|
||||
let t = frame.nth() as f32 / 60.0;
|
||||
|
||||
// background
|
||||
|
||||
let draw = app.draw();
|
||||
if frame.nth() == 0 {
|
||||
draw.background().color(SNOW);
|
||||
} else {
|
||||
let win = app.window_rect();
|
||||
draw.rect()
|
||||
.wh(win.wh())
|
||||
.color(srgba(1.0, 250.0 / 255.0, 250.0 / 255.0, 0.01));
|
||||
}
|
||||
|
||||
// draw automata
|
||||
|
||||
let (l, top, w, h) = app.window_rect().l_t_w_h();
|
||||
|
||||
const BALL_SIZE: f32 = 6.0;
|
||||
let cols = w / BALL_SIZE;
|
||||
let rows = h / BALL_SIZE;
|
||||
|
||||
for (i, &b) in model.automata.points.iter().enumerate() {
|
||||
if b && i as f32 <= cols {
|
||||
let x = l + (i as f32 % cols) * BALL_SIZE;
|
||||
let y = top - (model.row as f32 % rows) * BALL_SIZE;
|
||||
let p = vec2(x, y);
|
||||
let h = model.row as f32 / 360.0;
|
||||
draw.ellipse()
|
||||
.radius(BALL_SIZE / 2.0)
|
||||
.xy(p)
|
||||
.color(hsl(h.fract(), 0.5, 0.5));
|
||||
}
|
||||
}
|
||||
|
||||
// draw center square
|
||||
draw.rect().w_h(400.0, 400.0).color(SNOW);
|
||||
|
||||
// draw 4d cube
|
||||
let p: Vec<_> = model
|
||||
.cube
|
||||
.iter()
|
||||
.map(|&v| {
|
||||
// rotate
|
||||
let v = rot(t) * v;
|
||||
// project onto xz plane cause it's the coolest one
|
||||
50.0 * vec2(v.x + v.y, v.z + v.w)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for (i, (&a, &b)) in p
|
||||
.iter()
|
||||
.enumerate()
|
||||
// make all pairs of points
|
||||
.flat_map(|(i, a)| p[i + 1..].iter().map(move |b| (a, b)))
|
||||
.enumerate()
|
||||
{
|
||||
if i % 2 != 0 {
|
||||
draw.line().points(a, b).color(BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
draw.to_frame(app, &frame).unwrap();
|
||||
utils::record::record(app, &frame);
|
||||
}
|
||||
|
||||
struct Automata {
|
||||
points: Vec<bool>,
|
||||
rule: Vec<bool>,
|
||||
}
|
||||
|
||||
impl Automata {
|
||||
fn new() -> Self {
|
||||
let points = (0..200).map(|_| random::<bool>()).collect();
|
||||
let rule = (0..8).map(|_| random::<bool>()).collect();
|
||||
|
||||
Self { points, rule }
|
||||
}
|
||||
|
||||
fn advance(&mut self) {
|
||||
for i in 0..self.points.len() {
|
||||
let i1 = (i + 1) % self.points.len();
|
||||
let im1 = if i == 0 { self.points.len() - 1 } else { i - 1 };
|
||||
let v = (self.points[im1], self.points[i], self.points[i1]);
|
||||
|
||||
self.points[i] = match v {
|
||||
(false, false, false) => self.rule[0],
|
||||
(false, false, true) => self.rule[1],
|
||||
(false, true, false) => self.rule[2],
|
||||
(false, true, true) => self.rule[3],
|
||||
(true, false, false) => self.rule[4],
|
||||
(true, false, true) => self.rule[5],
|
||||
(true, true, false) => self.rule[6],
|
||||
(true, true, true) => self.rule[7],
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
[package]
|
||||
name = "subtitled12"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
rand_distr = "0.4.1"
|
||||
utils = { path = "../utils" }
|
|
@ -1,67 +0,0 @@
|
|||
use nannou::prelude::*;
|
||||
use nannou::rand::prelude::*;
|
||||
use rand_distr::Normal;
|
||||
use utils::*;
|
||||
|
||||
fn main() {
|
||||
nannou::app(model).update(update).simple_window(view).run();
|
||||
}
|
||||
|
||||
struct Model {
|
||||
lines: Vec<Vec<Vec2>>,
|
||||
}
|
||||
|
||||
fn lines(max_width: f32) -> Vec<Vec<Vec2>> {
|
||||
let normal = Normal::new(0.0, 0.2).unwrap();
|
||||
|
||||
(0..20)
|
||||
.map(|_| {
|
||||
let mut line = vec![Vec2::Y];
|
||||
|
||||
// generate the y coordinates for all points
|
||||
let n = random_range(4, 12);
|
||||
let mut ys = (0..n).map(|_| random_range(-1.0, 1.0)).collect::<Vec<_>>();
|
||||
ys.sort_by(|a, b| b.partial_cmp(a).unwrap());
|
||||
|
||||
// make the actual points and add them to the vec
|
||||
for y in ys {
|
||||
let w = map_range(1.0 - y.abs(), 0.0, 1.0, 0.01, max_width);
|
||||
let x = nannou::rand::thread_rng().sample::<f32, _>(normal) * w;
|
||||
line.push(vec2(x, y));
|
||||
}
|
||||
|
||||
line.push(-Vec2::Y);
|
||||
|
||||
line
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn model(_app: &App) -> Model {
|
||||
Model { lines: lines(0.0) }
|
||||
}
|
||||
|
||||
fn update(app: &App, model: &mut Model, _update: Update) {
|
||||
let t = app.elapsed_frames() as f32 / 60.0;
|
||||
|
||||
if app.elapsed_frames() % 2 == 0 {
|
||||
model.lines = lines(map_sin(t, 0.1, 1.0));
|
||||
}
|
||||
}
|
||||
|
||||
fn view(app: &App, model: &Model, frame: Frame) {
|
||||
let _t = frame.nth() as f32 / 60.0;
|
||||
|
||||
let draw = app.draw();
|
||||
draw.background().color(BLACK);
|
||||
|
||||
for line in &model.lines {
|
||||
draw.polyline()
|
||||
.stroke_weight(1.0)
|
||||
.points(line.iter().map(|v| *v * 300.0))
|
||||
.color(PINK);
|
||||
}
|
||||
|
||||
draw.to_frame(app, &frame).unwrap();
|
||||
utils::record::record(app, &frame);
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
[package]
|
||||
name = "subtitled13"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
utils = { path = "../utils" }
|
|
@ -1,94 +0,0 @@
|
|||
use nannou::prelude::*;
|
||||
use utils::*;
|
||||
|
||||
fn main() {
|
||||
nannou::app(model).update(update).simple_window(view).run();
|
||||
}
|
||||
|
||||
struct Model {
|
||||
walkers: Vec<Vec2>,
|
||||
clustered: Vec<Vec2>,
|
||||
}
|
||||
|
||||
fn model(_app: &App) -> Model {
|
||||
Model {
|
||||
walkers: (0..5000).map(|_| vec2_range(-1.0, 1.0) * 300.0).collect(),
|
||||
clustered: vec![Vec2::ZERO],
|
||||
}
|
||||
}
|
||||
|
||||
fn update(app: &App, model: &mut Model, _update: Update) {
|
||||
let _t = app.elapsed_frames() as f32 / 60.0;
|
||||
|
||||
// sort them by x to be a bit more efficient with the collision detection
|
||||
model
|
||||
.clustered
|
||||
.sort_by(|a, b| a.x.partial_cmp(&b.x).unwrap());
|
||||
let clusters = model.clustered.clone();
|
||||
|
||||
let mut to_remove = vec![];
|
||||
for (i, p) in &mut model.walkers.iter_mut().enumerate() {
|
||||
*p += vec2_range(-1.0, 1.0) * 3.5 + 0.5 * vec2(p.y, -p.x).normalize();
|
||||
|
||||
const RAD: f32 = 6.0;
|
||||
for &c in &clusters {
|
||||
// skip the ones outside the x range
|
||||
if c.x < p.x - RAD {
|
||||
continue;
|
||||
}
|
||||
if c.x > p.x + RAD {
|
||||
break;
|
||||
}
|
||||
|
||||
// if it's colliding, make it be a clustered point
|
||||
if p.distance_squared(c) < RAD * RAD {
|
||||
model.clustered.push(*p);
|
||||
to_remove.push(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove the ones that have become clustered
|
||||
// backwards cause otherwise you shift the indexes
|
||||
for i in to_remove.into_iter().rev() {
|
||||
model.walkers.remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
fn view(app: &App, model: &Model, frame: Frame) {
|
||||
let t = frame.nth() as f32 / 60.0;
|
||||
|
||||
let draw = app.draw();
|
||||
|
||||
drawing::draw_soft_bg(&draw, app, SNOW, 1.0);
|
||||
|
||||
for &p in &model.clustered {
|
||||
let v = map_sin(t + (p.x.powi(2) + p.y.powi(2) + t) * 0.00003, -20.0, 20.0);
|
||||
let h = (100.0 + v) / 360.0;
|
||||
draw.ellipse().xy(p).radius(4.0).color(hsl(h, 0.5, 0.5));
|
||||
}
|
||||
|
||||
for &p in &model.walkers {
|
||||
draw.ellipse().xy(p).radius(0.0).color(BLACK);
|
||||
}
|
||||
// use nannou::rand::seq::SliceRandom;
|
||||
// let mut rng = nannou::rand::thread_rng();
|
||||
// let n = (frame.nth() as f32 * 0.7) as usize;
|
||||
// for _ in 0..n {
|
||||
// let a = model.clustered.choose(&mut rng);
|
||||
// let b = model.clustered.choose(&mut rng);
|
||||
// if let (Some(&a), Some(&b)) = (a, b) {
|
||||
// let v = map_sin(t * 2.0 + a.x * a.y, -20.0, 20.0);
|
||||
// let h = (100.0 + v) / 360.0;
|
||||
|
||||
// draw.line()
|
||||
// .stroke_weight(3.0)
|
||||
// .points(a, b)
|
||||
// .color(hsla(h, 0.5, 0.5, 0.04));
|
||||
// }
|
||||
// }
|
||||
|
||||
draw.to_frame(app, &frame).unwrap();
|
||||
utils::record::record(app, &frame);
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
[package]
|
||||
name = "subtitled14"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
utils = { path = "../utils" }
|
|
@ -1,152 +0,0 @@
|
|||
use nannou::prelude::*;
|
||||
// use utils::*;
|
||||
|
||||
// from https://fabiensanglard.net/doom_fire_psx/
|
||||
|
||||
fn main() {
|
||||
nannou::app(model).update(update).simple_window(view).run();
|
||||
}
|
||||
|
||||
struct Model {
|
||||
fire: Vec<Vec<f32>>,
|
||||
colors: Vec<Rgb8>,
|
||||
uwu: wgpu::Texture,
|
||||
}
|
||||
|
||||
const WIDTH: usize = 400;
|
||||
const HEIGHT: usize = 300;
|
||||
const BALL_SIZE: f32 = 3.0;
|
||||
|
||||
fn model(app: &App) -> Model {
|
||||
let fire = vec![vec![0.0; WIDTH]; HEIGHT];
|
||||
|
||||
let colors = vec![
|
||||
(0x07, 0x07, 0x07),
|
||||
(0x1F, 0x07, 0x07),
|
||||
(0x2F, 0x0F, 0x07),
|
||||
(0x47, 0x0F, 0x07),
|
||||
(0x57, 0x17, 0x07),
|
||||
(0x67, 0x1F, 0x07),
|
||||
(0x77, 0x1F, 0x07),
|
||||
(0x8F, 0x27, 0x07),
|
||||
(0x9F, 0x2F, 0x07),
|
||||
(0xAF, 0x3F, 0x07),
|
||||
(0xBF, 0x47, 0x07),
|
||||
(0xC7, 0x47, 0x07),
|
||||
(0xDF, 0x4F, 0x07),
|
||||
(0xDF, 0x57, 0x07),
|
||||
(0xDF, 0x57, 0x07),
|
||||
(0xD7, 0x5F, 0x07),
|
||||
(0xD7, 0x5F, 0x07),
|
||||
(0xD7, 0x67, 0x0F),
|
||||
(0xCF, 0x6F, 0x0F),
|
||||
(0xCF, 0x77, 0x0F),
|
||||
(0xCF, 0x7F, 0x0F),
|
||||
(0xCF, 0x87, 0x17),
|
||||
(0xC7, 0x87, 0x17),
|
||||
(0xC7, 0x8F, 0x17),
|
||||
(0xC7, 0x97, 0x1F),
|
||||
(0xBF, 0x9F, 0x1F),
|
||||
(0xBF, 0x9F, 0x1F),
|
||||
(0xBF, 0xA7, 0x27),
|
||||
(0xBF, 0xA7, 0x27),
|
||||
(0xBF, 0xAF, 0x2F),
|
||||
(0xB7, 0xAF, 0x2F),
|
||||
(0xB7, 0xB7, 0x2F),
|
||||
(0xB7, 0xB7, 0x37),
|
||||
(0xCF, 0xCF, 0x6F),
|
||||
(0xDF, 0xDF, 0x9F),
|
||||
(0xEF, 0xEF, 0xC7),
|
||||
(0xFF, 0xFF, 0xFF),
|
||||
]
|
||||
.into_iter()
|
||||
.map(|c| c.into())
|
||||
.collect();
|
||||
|
||||
let assets = app.assets_path().unwrap();
|
||||
let img_path = assets.join("images").join("blahaj.png");
|
||||
let uwu = wgpu::Texture::from_path(app, img_path).unwrap();
|
||||
|
||||
let mut model = Model { fire, colors, uwu };
|
||||
|
||||
// presimulate fire
|
||||
for _ in 0..400 {
|
||||
advance(app, &mut model);
|
||||
}
|
||||
|
||||
model
|
||||
}
|
||||
|
||||
fn update(app: &App, model: &mut Model, _update: Update) {
|
||||
let _t = app.elapsed_frames() as f32 / 60.0;
|
||||
|
||||
advance(app, model);
|
||||
}
|
||||
|
||||
fn advance(app: &App, model: &mut Model) {
|
||||
let (w, h) = app.window_rect().w_h();
|
||||
|
||||
let cols = (w / BALL_SIZE) as usize;
|
||||
let rows = (h / BALL_SIZE) as usize - 50;
|
||||
|
||||
if app.elapsed_frames() > 200 {
|
||||
for i in 0..cols {
|
||||
model.fire[rows][i] = 0.0;
|
||||
}
|
||||
} else {
|
||||
for i in 0..cols {
|
||||
model.fire[rows][i] = 36.0;
|
||||
}
|
||||
}
|
||||
|
||||
for x in 0..cols {
|
||||
for y in 0..rows {
|
||||
let disp = random_range(0, 2);
|
||||
model.fire[y][(x + disp) % cols] = model.fire[y + 1][x] - random_range(0., 1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn view(app: &App, model: &Model, frame: Frame) {
|
||||
let _t = frame.nth() as f32 / 60.0;
|
||||
|
||||
let draw = app.draw();
|
||||
draw.background().color(BLACK);
|
||||
|
||||
draw.texture(&model.uwu)
|
||||
.w_h(400.0, 282.6)
|
||||
.y((-200.0 + frame.nth() as f32).min(0.0));
|
||||
|
||||
let (l, top, w, h) = app.window_rect().l_t_w_h();
|
||||
|
||||
let cols = w / BALL_SIZE;
|
||||
let rows = h / BALL_SIZE;
|
||||
|
||||
for (i, row) in model.fire.iter().enumerate() {
|
||||
for (j, c) in row.iter().enumerate() {
|
||||
let col_index = c.max(0.0).trunc() as usize % model.colors.len();
|
||||
|
||||
if i as f32 <= rows && j as f32 <= cols && col_index != 0 {
|
||||
let x = l + j as f32 * BALL_SIZE;
|
||||
let y = top - i as f32 * BALL_SIZE;
|
||||
let p = vec2(x, y);
|
||||
let r = BALL_SIZE;
|
||||
// * map_range(i as f32, 0 as f32, rows, 0., 1.0)
|
||||
// * random_range(0.9, 1.1);
|
||||
|
||||
draw.quad()
|
||||
.points(
|
||||
p + r * vec2(1., 1.),
|
||||
p + r * vec2(1., -1.),
|
||||
p + r * vec2(-1., -1.),
|
||||
p + r * vec2(-1., 1.),
|
||||
)
|
||||
.xy(p)
|
||||
.color(model.colors[col_index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw.to_frame(app, &frame).unwrap();
|
||||
utils::record::record(app, &frame);
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
[package]
|
||||
name = "subtitled15"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
utils = { path = "../utils" }
|
Binary file not shown.
|
@ -1,13 +0,0 @@
|
|||
// NOTE: This shader requires being manually compiled to SPIR-V in order to
|
||||
// avoid having downstream users require building shaderc and compiling the
|
||||
// shader themselves. If you update this shader, be sure to also re-compile it
|
||||
// and update `frag.spv`. You can do so using `glslangValidator` with the
|
||||
// following command: `glslangValidator -V shader.frag`
|
||||
|
||||
#version 450
|
||||
|
||||
layout(location = 0) out vec4 f_color;
|
||||
|
||||
void main() {
|
||||
f_color = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
// NOTE: This shader requires being manually compiled to SPIR-V in order to
|
||||
// avoid having downstream users require building shaderc and compiling the
|
||||
// shader themselves. If you update this shader, be sure to also re-compile it
|
||||
// and update `vert.spv`. You can do so using `glslangValidator` with the
|
||||
// following command: `glslangValidator -V shader.vert`
|
||||
|
||||
#version 450
|
||||
|
||||
// maybe change for this https://github.com/castor-software/rethread/blob/69a5746b02c260982a812c52da15ee364bc047e8/code/software-evolution/drift_vis/src/shaders/blur.vert
|
||||
|
||||
layout(location = 0) in vec2 position;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
}
|
Binary file not shown.
|
@ -1,127 +0,0 @@
|
|||
use nannou::prelude::*;
|
||||
|
||||
struct Model {
|
||||
bind_group: wgpu::BindGroup,
|
||||
render_pipeline: wgpu::RenderPipeline,
|
||||
vertex_buffer1: wgpu::Buffer,
|
||||
vertex_buffer2: wgpu::Buffer,
|
||||
}
|
||||
|
||||
// The vertex type that we will use to represent a point on our triangle.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
struct Vertex {
|
||||
position: [f32; 2],
|
||||
}
|
||||
|
||||
// The vertices that make up our triangle.
|
||||
const VERTICES1: [Vertex; 3] = [
|
||||
Vertex {
|
||||
position: [-1.0, -1.0],
|
||||
},
|
||||
Vertex {
|
||||
position: [1.0, 1.0],
|
||||
},
|
||||
Vertex {
|
||||
position: [-1.0, 1.0],
|
||||
},
|
||||
];
|
||||
const VERTICES2: [Vertex; 3] = [
|
||||
Vertex {
|
||||
position: [1.0, -1.0],
|
||||
},
|
||||
Vertex {
|
||||
position: [1.0, 1.0],
|
||||
},
|
||||
Vertex {
|
||||
position: [-1.0, -1.0],
|
||||
},
|
||||
];
|
||||
|
||||
fn main() {
|
||||
nannou::app(model).run();
|
||||
}
|
||||
|
||||
fn model(app: &App) -> Model {
|
||||
let w_id = app.new_window().size(512, 512).view(view).build().unwrap();
|
||||
|
||||
// The gpu device associated with the window's swapchain
|
||||
let window = app.window(w_id).unwrap();
|
||||
let device = window.swap_chain_device();
|
||||
let format = Frame::TEXTURE_FORMAT;
|
||||
let sample_count = window.msaa_samples();
|
||||
|
||||
// Load shader modules.
|
||||
let vs_mod = wgpu::shader_from_spirv_bytes(device, include_bytes!("../shaders/vert.spv"));
|
||||
let fs_mod = wgpu::shader_from_spirv_bytes(device, include_bytes!("../shaders/frag.spv"));
|
||||
|
||||
// Create the vertex buffer.
|
||||
let usage = wgpu::BufferUsage::VERTEX;
|
||||
let vertices_bytes = vertices_as_bytes(&VERTICES1[..]);
|
||||
let vertex_buffer1 = device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: vertices_bytes,
|
||||
usage,
|
||||
});
|
||||
let vertices_bytes = vertices_as_bytes(&VERTICES2[..]);
|
||||
let vertex_buffer2 = device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: vertices_bytes,
|
||||
usage,
|
||||
});
|
||||
|
||||
// Create the render pipeline.
|
||||
let bind_group_layout = wgpu::BindGroupLayoutBuilder::new().build(device);
|
||||
let bind_group = wgpu::BindGroupBuilder::new().build(device, &bind_group_layout);
|
||||
let pipeline_layout = wgpu::create_pipeline_layout(device, None, &[&bind_group_layout], &[]);
|
||||
let render_pipeline = wgpu::RenderPipelineBuilder::from_layout(&pipeline_layout, &vs_mod)
|
||||
.fragment_shader(&fs_mod)
|
||||
.color_format(format)
|
||||
.add_vertex_buffer::<Vertex>(&wgpu::vertex_attr_array![0 => Float32x2])
|
||||
.sample_count(sample_count)
|
||||
.build(device);
|
||||
|
||||
Model {
|
||||
bind_group,
|
||||
vertex_buffer1,
|
||||
vertex_buffer2,
|
||||
render_pipeline,
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the state of your `Model` into the given `Frame` here.
|
||||
fn view(_app: &App, model: &Model, frame: Frame) {
|
||||
// Using this we will encode commands that will be submitted to the GPU.
|
||||
let mut encoder = frame.command_encoder();
|
||||
|
||||
// The render pass can be thought of a single large command consisting of sub commands. Here we
|
||||
// begin a render pass that outputs to the frame's texture. Then we add sub-commands for
|
||||
// setting the bind group, render pipeline, vertex buffers and then finally drawing.
|
||||
let mut render_pass = wgpu::RenderPassBuilder::new()
|
||||
.color_attachment(frame.texture_view(), |color| color)
|
||||
.begin(&mut encoder);
|
||||
render_pass.set_bind_group(0, &model.bind_group, &[]);
|
||||
render_pass.set_pipeline(&model.render_pipeline);
|
||||
render_pass.set_vertex_buffer(0, model.vertex_buffer1.slice(..));
|
||||
|
||||
// We want to draw the whole range of vertices, and we're only drawing one instance of them.
|
||||
let vertex_range = 0..VERTICES1.len() as u32;
|
||||
let instance_range = 0..1;
|
||||
render_pass.draw(vertex_range, instance_range);
|
||||
|
||||
render_pass.set_bind_group(0, &model.bind_group, &[]);
|
||||
render_pass.set_pipeline(&model.render_pipeline);
|
||||
render_pass.set_vertex_buffer(0, model.vertex_buffer2.slice(..));
|
||||
|
||||
// We want to draw the whole range of vertices, and we're only drawing one instance of them.
|
||||
let vertex_range = 0..VERTICES2.len() as u32;
|
||||
let instance_range = 0..1;
|
||||
render_pass.draw(vertex_range, instance_range);
|
||||
|
||||
// Now we're done! The commands we added will be submitted after `view` completes.
|
||||
}
|
||||
|
||||
// See the `nannou::wgpu::bytes` documentation for why this is necessary.
|
||||
fn vertices_as_bytes(data: &[Vertex]) -> &[u8] {
|
||||
unsafe { wgpu::bytes::from_slice(data) }
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
[package]
|
||||
name = "subtitled16"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
utils = { path = "../utils" }
|
|
@ -1,112 +0,0 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use nannou::prelude::*;
|
||||
|
||||
// https://sighack.com/post/flood-fill-art-using-random-walks
|
||||
|
||||
const R: f32 = 2.0;
|
||||
|
||||
fn main() {
|
||||
nannou::app(model).update(update).simple_window(view).run();
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Point {
|
||||
pos: IVec2,
|
||||
color: f32,
|
||||
}
|
||||
|
||||
impl Point {
|
||||
fn new(pos: IVec2, color: f32) -> Self {
|
||||
Self { pos, color }
|
||||
}
|
||||
}
|
||||
|
||||
fn neighbors(point: IVec2) -> Vec<IVec2> {
|
||||
let mut cube = vec![];
|
||||
let p = [-1, 0, 1];
|
||||
for &x in &p {
|
||||
for &y in &p {
|
||||
if (x, y) != (0, 0) {
|
||||
cube.push(ivec2(x, y) + point);
|
||||
}
|
||||
}
|
||||
}
|
||||
cube
|
||||
}
|
||||
|
||||
struct Model {
|
||||
points: Vec<Point>,
|
||||
visits: Vec<Point>,
|
||||
}
|
||||
|
||||
fn model(_app: &App) -> Model {
|
||||
Model {
|
||||
visits: vec![Point::new(IVec2::ZERO, random_range(0.0, 360.0))],
|
||||
points: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
fn update(app: &App, model: &mut Model, _update: Update) {
|
||||
for _ in 0..50 {
|
||||
run(app, model)
|
||||
}
|
||||
}
|
||||
fn run(app: &App, model: &mut Model) {
|
||||
let _t = app.elapsed_frames() as f32 / 60.0;
|
||||
|
||||
// take a random out of the visits list
|
||||
let point = model.visits.remove(random_range(0, model.visits.len()));
|
||||
// visit it and all it's neighbors
|
||||
let neighbors = neighbors(point.pos)
|
||||
.into_iter()
|
||||
.filter(|p| {
|
||||
model.visits.iter().find(|point| point.pos == *p).is_none()
|
||||
&& model.points.iter().find(|point| point.pos == *p).is_none()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
for n in neighbors {
|
||||
model
|
||||
.visits
|
||||
// NOTE: this is where the randomization of the color happens
|
||||
.push(Point::new(n, point.color + random_range(-10.0, 10.0)))
|
||||
}
|
||||
// move it to visited points
|
||||
model.points.push(point);
|
||||
}
|
||||
|
||||
fn view(app: &App, model: &Model, frame: Frame) {
|
||||
let _t = frame.nth() as f32 / 60.0;
|
||||
|
||||
let draw = app.draw();
|
||||
draw.background().color(SNOW);
|
||||
|
||||
for walker in &model.visits {
|
||||
let h = walker.color / 360.0;
|
||||
draw.ellipse()
|
||||
.xy(walker.pos.as_f32() * R * 2.0)
|
||||
.radius(R)
|
||||
.color(hsl(h.fract(), 0.5, 0.7));
|
||||
}
|
||||
for walker in &model.points {
|
||||
let h = walker.color / 360.0;
|
||||
let p = walker.pos.as_f32() * R;
|
||||
draw.quad()
|
||||
.points(
|
||||
p + R * vec2(1., 1.),
|
||||
p + R * vec2(1., -1.),
|
||||
p + R * vec2(-1., -1.),
|
||||
p + R * vec2(-1., 1.),
|
||||
)
|
||||
.xy(p)
|
||||
.color(hsl(h.fract(), 0.5, 0.5));
|
||||
}
|
||||
|
||||
if frame.nth() < 50 {
|
||||
// cause otherwise it goes too fast when recording and it can't save the frames in time lmao
|
||||
std::thread::sleep(Duration::from_millis(5));
|
||||
}
|
||||
|
||||
draw.to_frame(app, &frame).unwrap();
|
||||
utils::record::record(app, &frame);
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
[package]
|
||||
name = "subtitled17"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
utils = { path = "../utils" }
|
|
@ -1,54 +0,0 @@
|
|||
use nannou::prelude::*;
|
||||
use utils::{curves::*, drawing::draw_soft_bg, *};
|
||||
|
||||
const POINTS: usize = 10;
|
||||
const SIZE: f32 = 300.0;
|
||||
|
||||
fn main() {
|
||||
nannou::app(model).update(update).simple_window(view).run();
|
||||
}
|
||||
|
||||
struct Model {
|
||||
curves: Vec<Chaikin>,
|
||||
}
|
||||
|
||||
fn model(_app: &App) -> Model {
|
||||
let curves = (0..10)
|
||||
.map(|_| {
|
||||
Chaikin::new(
|
||||
(0..POINTS)
|
||||
.map(|_| vec2_range(-1., 1.) * SIZE)
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
Model { curves }
|
||||
}
|
||||
|
||||
fn update(app: &App, _model: &mut Model, _update: Update) {
|
||||
let _t = app.elapsed_frames() as f32 / 60.0;
|
||||
}
|
||||
|
||||
fn view(app: &App, model: &Model, frame: Frame) {
|
||||
let t = frame.nth() as f32 / 60.0;
|
||||
|
||||
let draw = app.draw();
|
||||
draw_soft_bg(&draw, app, SNOW, 0.01);
|
||||
|
||||
for (i, curve) in model.curves.iter().enumerate() {
|
||||
let div = map_sin(t * 0.7 + (2 * i) as f32, 0.15, 0.35);
|
||||
let h = map_sin(t * 0.3 + i as f32, 0., 1.);
|
||||
|
||||
draw.polyline().stroke_weight(1.5).points_colored(
|
||||
curve
|
||||
.points(div, 10)
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(i, p)| (p, hsla((h + i as f32 / 10000.0).fract(), 0.5, 0.5, 0.5))),
|
||||
);
|
||||
}
|
||||
|
||||
draw.to_frame(app, &frame).unwrap();
|
||||
utils::record::record(app, &frame);
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
[package]
|
||||
name = "subtitled18"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
utils = { path = "../utils" }
|
|
@ -1,52 +0,0 @@
|
|||
use nannou::prelude::*;
|
||||
use utils::{drawing::draw_soft_bg, *};
|
||||
|
||||
fn main() {
|
||||
nannou::app(model).update(update).simple_window(view).run();
|
||||
}
|
||||
|
||||
struct Model {}
|
||||
|
||||
fn model(_app: &App) -> Model {
|
||||
Model {}
|
||||
}
|
||||
|
||||
fn update(app: &App, _model: &mut Model, _update: Update) {
|
||||
let _t = app.elapsed_frames() as f32 / 60.0;
|
||||
}
|
||||
|
||||
fn view(app: &App, _model: &Model, frame: Frame) {
|
||||
let t = frame.nth() as f32 / 60.0;
|
||||
|
||||
let draw = app.draw();
|
||||
draw_soft_bg(&draw, app, BLACK, 1.0);
|
||||
|
||||
let count = 10;
|
||||
for a in 0..360 {
|
||||
for i in 1..=count {
|
||||
let a = a as f32;
|
||||
let fi = i as f32;
|
||||
|
||||
let r = 1500.0 * (t + 0.01 * a + fi).cos();
|
||||
let r = r.powf(0.9 * fi / count as f32);
|
||||
// alternate directions of spin for each layer
|
||||
let s = if i % 2 == 0 { 1.0 } else { -1.0 } * map_sin(a * fi * fi, 0.1, 1.0);
|
||||
|
||||
let p = r * (s * t + fi + a).sin_cos().to_vec2();
|
||||
|
||||
// jitter
|
||||
let p = p + map_sin(t * 0.3 + TAU * 0.75, 0., 7.0) * vec2_circ();
|
||||
let sat = map_sin(t * 0.3 + TAU * 0.75, 0.4, 0.9);
|
||||
|
||||
let r = map_range(r, 0., 500.0, 0.5, 13.0).sqrt();
|
||||
|
||||
draw.ellipse()
|
||||
.radius(r)
|
||||
.xy(p)
|
||||
.color(hsl(a / 360.0, sat, 0.5));
|
||||
}
|
||||
}
|
||||
|
||||
draw.to_frame(app, &frame).unwrap();
|
||||
utils::record::record(app, &frame);
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
[package]
|
||||
name = "subtitled19"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
utils = { path = "../utils" }
|
|
@ -1,66 +0,0 @@
|
|||
use nannou::prelude::*;
|
||||
use utils::{drawing::draw_soft_bg, *};
|
||||
|
||||
fn main() {
|
||||
nannou::app(model).update(update).simple_window(view).run();
|
||||
}
|
||||
|
||||
struct Walker {
|
||||
pos: Vec2,
|
||||
vel: Vec2,
|
||||
color: f32,
|
||||
}
|
||||
|
||||
struct Model {
|
||||
walkers: Vec<Walker>,
|
||||
}
|
||||
|
||||
fn model(_app: &App) -> Model {
|
||||
Model {
|
||||
walkers: (0..100)
|
||||
.map(|_| Walker {
|
||||
pos: Vec2::ZERO,
|
||||
vel: Vec2::ZERO,
|
||||
color: random_range(0.0, 1.0),
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn update(app: &App, model: &mut Model, _update: Update) {
|
||||
let _t = app.elapsed_frames() as f32 / 60.0;
|
||||
|
||||
for walker in &mut model.walkers {
|
||||
walker.vel += vec2_range(-2.0, 1.0);
|
||||
walker.vel = walker.vel.normalize();
|
||||
|
||||
walker.pos += walker.vel;
|
||||
|
||||
// wrap around the box
|
||||
const SIZE: f32 = 100.0;
|
||||
if walker.pos.x.abs() > SIZE {
|
||||
walker.pos.x = -walker.pos.x;
|
||||
}
|
||||
if walker.pos.y.abs() > SIZE {
|
||||
walker.pos.y = -walker.pos.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn view(app: &App, model: &Model, frame: Frame) {
|
||||
let t = frame.nth() as f32 / 60.0;
|
||||
|
||||
let draw = app.draw();
|
||||
draw_soft_bg(&draw, app, SNOW, 0.01);
|
||||
|
||||
for walker in &model.walkers {
|
||||
let h = (t * 10.0 + walker.color * 50.0) / 360.0;
|
||||
draw.ellipse()
|
||||
.xy(walker.pos)
|
||||
.radius(1.0)
|
||||
.color(hsl(h.fract(), 0.7, 0.5));
|
||||
}
|
||||
|
||||
draw.to_frame(app, &frame).unwrap();
|
||||
utils::record::record(app, &frame);
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
[package]
|
||||
name = "subtitled20"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
utils = { path = "../utils" }
|
|
@ -1,60 +0,0 @@
|
|||
use nannou::prelude::*;
|
||||
use utils::*;
|
||||
|
||||
// based on https://nbickford.wordpress.com/2011/04/03/the-minsky-circle-algorithm/
|
||||
|
||||
fn main() {
|
||||
nannou::app(model).update(update).simple_window(view).run();
|
||||
}
|
||||
|
||||
struct Model {
|
||||
points: Vec<Vec2>,
|
||||
base_hue: f32,
|
||||
}
|
||||
|
||||
fn model(_app: &App) -> Model {
|
||||
Model {
|
||||
points: (0..1000).map(|_| Vec2::ONE * 6.0).collect(),
|
||||
base_hue: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
fn advance(mut point: Vec2, t: f32) -> Vec2 {
|
||||
let d = map_sin(t * 1.1, 0.01, 0.12);
|
||||
let e = (t.sqrt() * 0.01 + 0.3).min(1.1);
|
||||
point.x -= (point.y * d).floor();
|
||||
point.y += (point.x * e).floor();
|
||||
point
|
||||
}
|
||||
|
||||
fn update(app: &App, model: &mut Model, _update: Update) {
|
||||
let t = app.elapsed_frames() as f32 / 60.0;
|
||||
|
||||
// advance all points in list
|
||||
let mut last = model.points.last().unwrap().clone();
|
||||
for v in &mut model.points {
|
||||
last = advance(last, t);
|
||||
*v = last;
|
||||
}
|
||||
|
||||
// move base_hue
|
||||
model.base_hue += random::<f32>();
|
||||
}
|
||||
|
||||
fn view(app: &App, model: &Model, frame: Frame) {
|
||||
let t = frame.nth() as f32 / 60.0;
|
||||
|
||||
let draw = app.draw();
|
||||
drawing::draw_soft_bg(&draw, app, BLACK, 0.01);
|
||||
|
||||
for &p in &model.points {
|
||||
let h = random_range(model.base_hue, model.base_hue + 60.0) / 360.0;
|
||||
draw.ellipse()
|
||||
.radius(map_sin(p.x.powi(3) + p.y.powi(7) + t * 0.1, 1.0, 3.0))
|
||||
.xy(p * 7.0)
|
||||
.color(hsla(h.fract(), 1.0, 0.5, 0.1));
|
||||
}
|
||||
|
||||
draw.to_frame(app, &frame).unwrap();
|
||||
utils::record::record(app, &frame);
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
[package]
|
||||
name = "subtitled21"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
utils = { path = "../utils" }
|
|
@ -1,90 +0,0 @@
|
|||
use nannou::prelude::*;
|
||||
|
||||
fn main() {
|
||||
nannou::app(model)
|
||||
.update(update)
|
||||
.simple_window(view)
|
||||
.size(800, 800)
|
||||
.run();
|
||||
}
|
||||
|
||||
struct Model {}
|
||||
|
||||
const BALL_SIZE: f32 = 3.0;
|
||||
|
||||
fn model(_app: &App) -> Model {
|
||||
Model {}
|
||||
}
|
||||
|
||||
fn update(app: &App, _model: &mut Model, _update: Update) {
|
||||
let _t = app.elapsed_frames() as f32 / 60.0;
|
||||
}
|
||||
|
||||
fn shader(i: usize, j: usize, w: usize, h: usize, t: f32) -> Rgb {
|
||||
let x = i as f32 / w as f32;
|
||||
let y = j as f32 / h as f32;
|
||||
let pos = vec2(x, y);
|
||||
|
||||
creation(pos, t)
|
||||
}
|
||||
|
||||
// https://www.shadertoy.com/view/XsXXDn
|
||||
fn creation(pos: Vec2, t: f32) -> Rgb {
|
||||
let mut l = t;
|
||||
let mut z = t;
|
||||
let mut c = [0.0; 3];
|
||||
|
||||
for i in 0..3 {
|
||||
let mut uv = pos;
|
||||
let mut p = pos;
|
||||
|
||||
p -= Vec2::splat(0.5);
|
||||
z += 0.07;
|
||||
l = p.length();
|
||||
uv += p / l * (z.sin() + 1.) * abs((l * 9. - z * 2.).sin());
|
||||
c[i] = 0.01 / ((vec2(uv.x.fract(), uv.y.fract()) - Vec2::splat(0.5)).abs()).length();
|
||||
}
|
||||
|
||||
srgb(c[0] / l, c[1] / l, c[2] / l)
|
||||
}
|
||||
|
||||
fn view(app: &App, _model: &Model, frame: Frame) {
|
||||
let t = frame.nth() as f32 / 120.0;
|
||||
|
||||
let draw = app.draw();
|
||||
draw.background().color(BLACK);
|
||||
|
||||
let (l, top, w, h) = app.window_rect().l_t_w_h();
|
||||
|
||||
let cols = (w / BALL_SIZE) as usize;
|
||||
let rows = (h / BALL_SIZE) as usize;
|
||||
|
||||
for i in 0..cols {
|
||||
for j in 0..rows {
|
||||
let x = l + j as f32 * BALL_SIZE;
|
||||
let y = top - i as f32 * BALL_SIZE;
|
||||
let p = vec2(x, y)
|
||||
+ (t * 0.4).min(5.0)
|
||||
* 10.0
|
||||
* vec2(
|
||||
(t * 0.7 + (i * j) as f32).sin(),
|
||||
(t * 0.9 + (2 * i * j) as f32).cos(),
|
||||
);
|
||||
|
||||
let color = shader(i, j, cols, rows, t);
|
||||
|
||||
draw.quad()
|
||||
.points(
|
||||
p + BALL_SIZE * vec2(1., 1.),
|
||||
p + BALL_SIZE * vec2(1., -1.),
|
||||
p + BALL_SIZE * vec2(-1., -1.),
|
||||
p + BALL_SIZE * vec2(-1., 1.),
|
||||
)
|
||||
.xy(p)
|
||||
.color(color);
|
||||
}
|
||||
}
|
||||
|
||||
draw.to_frame(app, &frame).unwrap();
|
||||
utils::record::record(app, &frame);
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
[package]
|
||||
name = "subtitled22"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
utils = { path = "../utils" }
|
|
@ -1,99 +0,0 @@
|
|||
use nannou::prelude::*;
|
||||
use utils::{drawing::draw_soft_bg, *};
|
||||
|
||||
fn main() {
|
||||
nannou::app(model).update(update).simple_window(view).run();
|
||||
}
|
||||
|
||||
enum Type {
|
||||
Square,
|
||||
Circle,
|
||||
}
|
||||
struct Shape {
|
||||
size: f32,
|
||||
r: f32,
|
||||
color: f32,
|
||||
t: Type,
|
||||
}
|
||||
|
||||
struct Model {
|
||||
shapes: Vec<Shape>,
|
||||
}
|
||||
|
||||
fn model(_app: &App) -> Model {
|
||||
Model {
|
||||
shapes: (0..1000)
|
||||
.map(|_| {
|
||||
let size = random_range(7.0, 18.0);
|
||||
let r = random_range(100.0, 300.0);
|
||||
let color = (random_range(0.0, 80.0) / 360.0).fract();
|
||||
let t = if random::<f32>() > 0.3 {
|
||||
Type::Circle
|
||||
} else {
|
||||
Type::Square
|
||||
};
|
||||
Shape { size, r, color, t }
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn update(app: &App, _model: &mut Model, _update: Update) {
|
||||
let _t = app.elapsed_frames() as f32 / 60.0;
|
||||
}
|
||||
|
||||
fn view(app: &App, model: &Model, frame: Frame) {
|
||||
let t = frame.nth() as f32 / 60.0;
|
||||
|
||||
let draw = app.draw();
|
||||
draw_soft_bg(&draw, &app, SNOW, 1.03);
|
||||
|
||||
let count = model.shapes.len() as f32;
|
||||
for (i, shape) in model.shapes.iter().enumerate() {
|
||||
let angle = 360.0 * i as f32 / count;
|
||||
let angle = angle + t * map_sin(angle.powi(4), 0.2, 0.7);
|
||||
|
||||
let r = shape.r * map_sin(t + i as f32, 0.5, 1.3);
|
||||
|
||||
let size = shape.size * map_sin(0.004 * t + 2.0 * i as f32, 0.5, 1.5);
|
||||
|
||||
match shape.t {
|
||||
Type::Circle => {
|
||||
let color = (shape.color + 0.01 * t + angle * 0.0001).fract();
|
||||
let color = hsl(color, map_sin(i.pow(3) as f32, 0.4, 0.7), 0.5);
|
||||
|
||||
let p = r * angle.sin_cos().to_vec2();
|
||||
|
||||
draw.ellipse().radius(size).xy(p).color(color);
|
||||
}
|
||||
Type::Square => {
|
||||
let p = r * (-angle).sin_cos().to_vec2();
|
||||
let rotation = t + i as f32;
|
||||
|
||||
let points = vec![
|
||||
vec2(1.0, 1.0),
|
||||
vec2(-1.0, 1.0),
|
||||
vec2(-1.0, -1.0),
|
||||
vec2(1.0, -1.0),
|
||||
]
|
||||
.into_iter()
|
||||
.map(|v| {
|
||||
vec2(
|
||||
v.x * rotation.cos() - v.y * rotation.sin(),
|
||||
v.x * rotation.sin() + v.y * rotation.cos(),
|
||||
)
|
||||
})
|
||||
.map(|v| v * size + p)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
draw.polyline()
|
||||
.stroke_weight(1.5)
|
||||
.points_closed(points)
|
||||
.color(SNOW);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
draw.to_frame(app, &frame).unwrap();
|
||||
utils::record::record(app, &frame);
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
[package]
|
||||
name = "subtitled23"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
utils = { path = "../utils" }
|
|
@ -1,69 +0,0 @@
|
|||
use nannou::prelude::*;
|
||||
use utils::*;
|
||||
|
||||
fn main() {
|
||||
nannou::app(model).update(update).simple_window(view).run();
|
||||
}
|
||||
|
||||
struct Model {
|
||||
points: Vec<Vec2>,
|
||||
base_hue: f32,
|
||||
}
|
||||
|
||||
fn model(_app: &App) -> Model {
|
||||
Model {
|
||||
base_hue: random_range(0., 360.0),
|
||||
points: vec![Vec2::splat(0.1); 10000],
|
||||
}
|
||||
}
|
||||
|
||||
fn advance(point: Vec2, t: f32) -> Vec2 {
|
||||
// pick a random point
|
||||
let count = ((t * 0.125).trunc() as usize % 5) + 3;
|
||||
let mut points = (0..count)
|
||||
.map(|i| (TAU * i as f32 / count as f32).sin_cos().to_vec2())
|
||||
.collect::<Vec<_>>();
|
||||
points.push(Vec2::ZERO);
|
||||
|
||||
let random = points[random_range(0, count)];
|
||||
|
||||
(random + point) * map_cos(t * PI * 0.25, 0.1, 1.0).powf(1.5)
|
||||
}
|
||||
|
||||
fn update(app: &App, model: &mut Model, _update: Update) {
|
||||
let t = app.elapsed_frames() as f32 / 60.0;
|
||||
|
||||
// advance all points in list
|
||||
let mut last = model.points.last().unwrap().clone();
|
||||
for v in &mut model.points {
|
||||
last = advance(last, t);
|
||||
*v = last;
|
||||
}
|
||||
|
||||
// move base_hue
|
||||
model.base_hue += 0.5;
|
||||
}
|
||||
|
||||
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(BLACK);
|
||||
} else {
|
||||
let win = app.window_rect();
|
||||
draw.rect().wh(win.wh()).color(srgba(0., 0.0, 0.0, 0.02));
|
||||
}
|
||||
|
||||
for &p in &model.points {
|
||||
let h = random_range(model.base_hue, model.base_hue + 60.0) / 360.0;
|
||||
draw.ellipse()
|
||||
.radius(0.2)
|
||||
.xy(150.0 * p)
|
||||
.color(hsla(h.fract(), 1.0, 0.5, 0.1));
|
||||
}
|
||||
|
||||
draw.to_frame(app, &frame).unwrap();
|
||||
utils::record::record(app, &frame);
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
[package]
|
||||
name = "subtitled24"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
utils = { path = "../utils" }
|
|
@ -1,67 +0,0 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use nannou::prelude::*;
|
||||
use utils::{
|
||||
lsystems::LSystem,
|
||||
turtle::{Turtle, TurtleAlphabet},
|
||||
};
|
||||
|
||||
fn main() {
|
||||
nannou::app(model)
|
||||
.update(update)
|
||||
.simple_window(view)
|
||||
.size(600, 520)
|
||||
.run();
|
||||
}
|
||||
|
||||
struct Model {}
|
||||
|
||||
fn model(_app: &App) -> Model {
|
||||
Model {}
|
||||
}
|
||||
|
||||
fn update(app: &App, _model: &mut Model, _update: Update) {
|
||||
let _t = app.elapsed_frames() as f32 / 60.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);
|
||||
}
|
||||
|
||||
if frame.nth() % 60 == 0 {
|
||||
let iters = t.trunc() as usize % 10;
|
||||
|
||||
use TurtleAlphabet::*;
|
||||
let mut sys = LSystem::new(
|
||||
vec![Line, Right, Right, Line, Right, Right, Line],
|
||||
Box::new(|i| match i {
|
||||
Line => vec![
|
||||
Line, Right, Right, Line, Right, Right, Line, Right, Right, Move,
|
||||
],
|
||||
Move => vec![Move, Move],
|
||||
a @ _ => vec![a],
|
||||
}),
|
||||
);
|
||||
let h = app.window_rect().h() / 2.0;
|
||||
let w = app.window_rect().w() / 2.0;
|
||||
|
||||
let mut turtle = Turtle::new(vec2(-w, -h), 2.85 * w * 0.5.powi(iters as i32), TAU / 3.0);
|
||||
turtle.rotation = -PI / 4.0;
|
||||
|
||||
let a = sys.nth(iters);
|
||||
turtle.advance_many(&draw, &a);
|
||||
// turtle.advance(&draw, TurtleAlphabet::Line);
|
||||
// turtle.advance(&draw, TurtleAlphabet::Right);
|
||||
// turtle.advance(&draw, TurtleAlphabet::Line);
|
||||
}
|
||||
|
||||
// cause otherwise it goes too fast when recording and it can't save the frames in time lmao
|
||||
std::thread::sleep(Duration::from_millis(5));
|
||||
|
||||
draw.to_frame(app, &frame).unwrap();
|
||||
utils::record::record(app, &frame);
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
[package]
|
||||
name = "subtitled25"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
num = "0.4.0"
|
||||
utils = { path = "../utils" }
|
|
@ -1,50 +0,0 @@
|
|||
use nannou::prelude::*;
|
||||
use num::complex::*;
|
||||
use utils::*;
|
||||
|
||||
fn main() {
|
||||
nannou::app(model)
|
||||
.update(update)
|
||||
.simple_window(view)
|
||||
.size(800, 800)
|
||||
.run();
|
||||
}
|
||||
|
||||
struct Model {}
|
||||
|
||||
const BALL_SIZE: f32 = 3.0;
|
||||
|
||||
fn model(_app: &App) -> Model {
|
||||
Model {}
|
||||
}
|
||||
|
||||
fn update(app: &App, _model: &mut Model, _update: Update) {
|
||||
let _t = app.elapsed_frames() as f32 / 60.0;
|
||||
}
|
||||
|
||||
fn shader(i: usize, j: usize, w: usize, h: usize, t: f32) -> Hsl {
|
||||
let x = (i as f32 / w as f32) - 0.5;
|
||||
let y = (j as f32 / h as f32) - 0.5;
|
||||
let x = x * 7.0;
|
||||
let y = y * 7.0;
|
||||
let mut v = Complex::new(y, x);
|
||||
|
||||
let a = map_sin(t * 0.5, 0.0, TAU);
|
||||
let c = Complex::from_polar(0.7885, a);
|
||||
|
||||
let iters = map_sin(t * 0.1, 10.0, 100.0);
|
||||
|
||||
for i in 0..(iters as usize) {
|
||||
v = v.powi(2) + c;
|
||||
|
||||
if v.norm() > 10.0 {
|
||||
return hsl(i as f32 / iters, 0.5, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
hsl(0.0, 0.0, 0.0)
|
||||
}
|
||||
|
||||
fn view(app: &App, _model: &Model, frame: Frame) {
|
||||
utils::shaders::run(app, frame, BALL_SIZE, shader, vec2)
|
||||
}
|
|
@ -34,7 +34,7 @@ fn view(app: &App, _model: &Model, frame: Frame) {
|
|||
|
||||
let draw = app.draw();
|
||||
|
||||
if frame.nth() == 0 {
|
||||
if frame.nth() == 1 {
|
||||
draw.background().color(BG);
|
||||
} else {
|
||||
let win = app.window_rect();
|
||||
|
|
|
@ -9,25 +9,17 @@ fn main() {
|
|||
|
||||
struct Model {
|
||||
shape: Shapes,
|
||||
count: usize,
|
||||
}
|
||||
|
||||
fn model(_app: &App) -> Model {
|
||||
Model {
|
||||
shape: Shapes::new(0),
|
||||
count: 0,
|
||||
shape: Shapes::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn update(app: &App, model: &mut Model, _update: Update) {
|
||||
if app.elapsed_frames() % 60 == 0 && app.elapsed_frames() > 1 {
|
||||
if model.count >= 20 {
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
model.shape = Shapes::new(random_range(1, 7));
|
||||
|
||||
model.count += 1;
|
||||
if app.elapsed_frames() % 60 == 0 {
|
||||
model.shape = Shapes::new();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,7 +29,7 @@ fn view(app: &App, model: &Model, frame: Frame) {
|
|||
let draw = app.draw();
|
||||
if frame.nth() == 0 {
|
||||
draw.background().color(BLACK);
|
||||
} else if frame.nth() % 60 > 30 {
|
||||
} else if frame.nth() % 60 > 40 {
|
||||
let win = app.window_rect();
|
||||
draw.rect().wh(win.wh()).color(srgba(0.0, 0.0, 0.0, 0.2));
|
||||
}
|
||||
|
|
|
@ -3,115 +3,41 @@ use nannou::prelude::*;
|
|||
pub struct Shapes(Vec<Shape>);
|
||||
impl Shapes {
|
||||
pub fn draw(&self, draw: Draw) {
|
||||
let w = 1.0;
|
||||
|
||||
for shape in &self.0 {
|
||||
match shape {
|
||||
&Shape::Triangle {
|
||||
center,
|
||||
radius,
|
||||
rotation,
|
||||
} => {
|
||||
Shape::Triangle { center, radius } => {
|
||||
let points = vec![vec2(0., 1.), vec2(0.866, -0.5), vec2(-0.866, -0.5)]
|
||||
.into_iter()
|
||||
.map(|v| {
|
||||
vec2(
|
||||
v.x * rotation.cos() - v.y * rotation.sin(),
|
||||
v.x * rotation.sin() + v.y * rotation.cos(),
|
||||
)
|
||||
})
|
||||
.map(|v| v * radius + center)
|
||||
.map(|v| v * *radius + *center)
|
||||
.collect::<Vec<_>>();
|
||||
draw.polyline().weight(w).points_closed(points).color(PINK);
|
||||
draw.polyline().weight(3.).points_closed(points).color(PINK);
|
||||
}
|
||||
Shape::Circle { center, radius, .. } => {
|
||||
Shape::Circle { center, radius } => {
|
||||
draw.ellipse()
|
||||
.radius(*radius)
|
||||
.no_fill()
|
||||
.stroke_weight(w)
|
||||
.stroke_weight(3.)
|
||||
.xy(*center)
|
||||
.stroke_color(PINK);
|
||||
}
|
||||
&Shape::Line {
|
||||
center,
|
||||
radius,
|
||||
rotation,
|
||||
} => {
|
||||
let points = vec![vec2(-1.0, 0.), vec2(1.0, 0.0)]
|
||||
.into_iter()
|
||||
.map(|v| {
|
||||
vec2(
|
||||
v.x * rotation.cos() - v.y * rotation.sin(),
|
||||
v.x * rotation.sin() + v.y * rotation.cos(),
|
||||
)
|
||||
})
|
||||
.map(|v| v * radius + center)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
draw.line()
|
||||
.stroke_weight(w)
|
||||
.start(points[0])
|
||||
.end(points[1])
|
||||
.color(PINK);
|
||||
}
|
||||
Shape::LongLine { center, radius, .. } => {
|
||||
draw.line()
|
||||
.stroke_weight(w)
|
||||
.start(Vec2::ZERO)
|
||||
.end(*center + center.normalize() * *radius)
|
||||
.color(PINK);
|
||||
}
|
||||
&Shape::Square {
|
||||
center,
|
||||
radius,
|
||||
rotation,
|
||||
} => {
|
||||
let points = vec![
|
||||
vec2(1.0, 1.0),
|
||||
vec2(-1.0, 1.0),
|
||||
vec2(-1.0, -1.0),
|
||||
vec2(1.0, -1.0),
|
||||
]
|
||||
.into_iter()
|
||||
.map(|v| {
|
||||
vec2(
|
||||
v.x * rotation.cos() - v.y * rotation.sin(),
|
||||
v.x * rotation.sin() + v.y * rotation.cos(),
|
||||
)
|
||||
})
|
||||
.map(|v| v * radius + center)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
draw.polyline()
|
||||
.stroke_weight(w)
|
||||
.points_closed(points)
|
||||
.color(PINK);
|
||||
}
|
||||
Shape::Line { center, radius } => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(children: usize) -> Self {
|
||||
pub fn new() -> Self {
|
||||
let root = Shape::random(Vec2::ZERO, 100.0);
|
||||
|
||||
let mut vec = vec![];
|
||||
|
||||
for _ in 0..children {
|
||||
for _ in 0..3 {
|
||||
let (c, r) = root.get_random_point_distance();
|
||||
let s = Shape::random(c, r);
|
||||
|
||||
let children = random_range(0, 5.min(children + 2));
|
||||
let children = random_range(0, 3);
|
||||
for _ in 0..children {
|
||||
let (c, r) = s.get_random_point_distance();
|
||||
let s = Shape::random(c, r);
|
||||
|
||||
let children = random_range(0, 3.min(children + 1));
|
||||
for _ in 0..children {
|
||||
let (c, r) = s.get_random_point_distance();
|
||||
let s = Shape::random(c, r);
|
||||
vec.push(s);
|
||||
}
|
||||
|
||||
vec.push(s);
|
||||
}
|
||||
|
||||
|
@ -123,144 +49,58 @@ impl Shapes {
|
|||
}
|
||||
}
|
||||
|
||||
macro_rules! sh {
|
||||
( $($id:ident),* ) => {
|
||||
pub enum Shape {
|
||||
$(
|
||||
$id { center: Vec2, radius: f32, rotation: f32 },
|
||||
)*
|
||||
Triangle { center: Vec2, radius: f32 },
|
||||
Circle { center: Vec2, radius: f32 },
|
||||
Line { center: Vec2, radius: f32 },
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
sh!(Triangle, Circle, Line, LongLine, Square);
|
||||
|
||||
fn random_sq_rot() -> f32 {
|
||||
[0.0, PI / 4.0][random_range(0, 2)]
|
||||
}
|
||||
fn random_tri_rot() -> f32 {
|
||||
[0.0, PI / 3.0][random_range(0, 2)]
|
||||
}
|
||||
fn random_line_rot() -> f32 {
|
||||
[0.0, PI / 3.0, PI / 2.0, PI / 4.0, PI][random_range(0, 4)]
|
||||
}
|
||||
|
||||
impl Shape {
|
||||
fn random(center: Vec2, radius: f32) -> Self {
|
||||
match random_range(0, 5) {
|
||||
0 => Self::tri(center, radius, random_tri_rot()),
|
||||
1 => Self::line(center, radius, random_line_rot()),
|
||||
2 if center.distance(Vec2::ZERO) > 0.01 => Self::long_line(center, radius, 0.0),
|
||||
3 => Self::square(center, radius, random_sq_rot()),
|
||||
_ => Self::circ(center, radius, 0.0),
|
||||
match random_range(0, 3) {
|
||||
0 => Self::tri(center, radius),
|
||||
1 => Self::line(center, radius),
|
||||
_ => Self::circ(center, radius),
|
||||
}
|
||||
}
|
||||
|
||||
fn tri(center: Vec2, radius: f32, rotation: f32) -> Self {
|
||||
Self::Triangle {
|
||||
center,
|
||||
radius,
|
||||
rotation,
|
||||
fn tri(center: Vec2, radius: f32) -> Self {
|
||||
Self::Triangle { center, radius }
|
||||
}
|
||||
fn circ(center: Vec2, radius: f32) -> Self {
|
||||
Self::Circle { center, radius }
|
||||
}
|
||||
fn circ(center: Vec2, radius: f32, rotation: f32) -> Self {
|
||||
Self::Circle {
|
||||
center,
|
||||
radius,
|
||||
rotation,
|
||||
}
|
||||
}
|
||||
fn line(center: Vec2, radius: f32, rotation: f32) -> Self {
|
||||
Self::Line {
|
||||
center,
|
||||
radius,
|
||||
rotation,
|
||||
}
|
||||
}
|
||||
fn long_line(center: Vec2, radius: f32, rotation: f32) -> Self {
|
||||
Self::LongLine {
|
||||
center,
|
||||
radius,
|
||||
rotation,
|
||||
}
|
||||
}
|
||||
fn square(center: Vec2, radius: f32, rotation: f32) -> Self {
|
||||
Self::Square {
|
||||
center,
|
||||
radius,
|
||||
rotation,
|
||||
}
|
||||
fn line(center: Vec2, radius: f32) -> Self {
|
||||
Self::Line { center, radius }
|
||||
}
|
||||
|
||||
fn get_random_point_distance(&self) -> (Vec2, f32) {
|
||||
match self {
|
||||
&Shape::Triangle {
|
||||
center,
|
||||
radius,
|
||||
rotation,
|
||||
} => {
|
||||
Shape::Triangle { center, radius } => {
|
||||
let points = vec![vec2(0., 1.), vec2(0.866, -0.5), vec2(-0.866, -0.5)]
|
||||
.into_iter()
|
||||
.map(|v| {
|
||||
vec2(
|
||||
v.x * rotation.cos() - v.y * rotation.sin(),
|
||||
v.x * rotation.sin() + v.y * rotation.cos(),
|
||||
)
|
||||
})
|
||||
.map(|v| v * radius + center)
|
||||
.map(|v| v * *radius + *center)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let denom = random_range(1.0, 4.0).floor();
|
||||
let denom = random_range(1.0, 5.0).floor();
|
||||
(points[random_range(0, points.len())], radius / denom)
|
||||
}
|
||||
&Shape::Circle { center, radius, .. } => {
|
||||
Shape::Circle { center, radius } => {
|
||||
let point = match random_range(0, 4) {
|
||||
0 => center + Vec2::X * radius,
|
||||
1 => center - Vec2::X * radius,
|
||||
2 => center + Vec2::Y * radius,
|
||||
_ => center - Vec2::Y * radius,
|
||||
0 => *center + Vec2::X * *radius,
|
||||
1 => *center - Vec2::X * *radius,
|
||||
2 => *center + Vec2::Y * *radius,
|
||||
_ => *center - Vec2::Y * *radius,
|
||||
};
|
||||
|
||||
let denom = random_range(1.0, 4.0).floor();
|
||||
let denom = random_range(1.0, 5.0).floor();
|
||||
(point, radius / denom)
|
||||
}
|
||||
&Shape::Line { center, radius, .. } => {
|
||||
let point = match random_range(0, 2) {
|
||||
0 => center - center.normalize() * radius,
|
||||
_ => center + center.normalize() * radius,
|
||||
};
|
||||
Shape::Line { center, radius } => {
|
||||
let point = todo!("one of the two vertices");
|
||||
|
||||
let denom = random_range(1.0, 4.0).floor();
|
||||
let denom = random_range(1.0, 5.0).floor();
|
||||
(point, radius / denom)
|
||||
}
|
||||
&Shape::LongLine { center, radius, .. } => {
|
||||
let denom = random_range(1.0, 4.0).floor();
|
||||
(center + center.normalize() * radius, radius / denom)
|
||||
}
|
||||
&Shape::Square {
|
||||
center,
|
||||
radius,
|
||||
rotation,
|
||||
} => {
|
||||
let points = vec![
|
||||
vec2(1.0, 1.0),
|
||||
vec2(-1.0, 1.0),
|
||||
vec2(-1.0, -1.0),
|
||||
vec2(1.0, -1.0),
|
||||
]
|
||||
.into_iter()
|
||||
.map(|v| {
|
||||
vec2(
|
||||
v.x * rotation.cos() - v.y * rotation.sin(),
|
||||
v.x * rotation.sin() + v.y * rotation.cos(),
|
||||
)
|
||||
})
|
||||
.map(|v| v * radius + center)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let denom = random_range(1.0, 4.0).floor();
|
||||
(points[random_range(0, 4)], radius / denom)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
[package]
|
||||
name = "subtitled7"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
utils = { path = "../utils" }
|
|
@ -1,151 +0,0 @@
|
|||
use nannou::prelude::*;
|
||||
use std::collections::VecDeque;
|
||||
use utils::*;
|
||||
|
||||
fn main() {
|
||||
nannou::app(model).update(update).simple_window(view).run();
|
||||
}
|
||||
|
||||
struct Model {
|
||||
points: VecDeque<(Vec2, (f32, f32))>,
|
||||
}
|
||||
|
||||
const GOLDEN: f32 = 0.618033988;
|
||||
|
||||
fn point(i: usize) -> Vec2 {
|
||||
let theta = i as f32 * TAU * GOLDEN;
|
||||
let r = theta.sqrt();
|
||||
let x = r * theta.cos();
|
||||
let y = r * theta.sin();
|
||||
vec2(x, y)
|
||||
}
|
||||
|
||||
fn color() -> (f32, f32) {
|
||||
(
|
||||
random_range(345.0, 355.0) / 360.0,
|
||||
random_range(75.0, 93.0) / 100.0,
|
||||
)
|
||||
}
|
||||
|
||||
fn model(_app: &App) -> Model {
|
||||
Model {
|
||||
points: (0..2000).map(point).map(|a| (a * 10.0, color())).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn circ(p: Vec2, center: Vec2, r: f32) -> f32 {
|
||||
(p - center).length() - r
|
||||
}
|
||||
|
||||
fn spinny_circles(p: Vec2, t: f32) -> f32 {
|
||||
let mut c = vec![(Vec2::ZERO, 1.0)];
|
||||
|
||||
let mut ext = (0..7)
|
||||
.map(|i| {
|
||||
let v: Vec2 = (t + TAU * i as f32 / 7.0).sin_cos().into();
|
||||
(v * 100.0, 10.0)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
c.append(&mut ext);
|
||||
let mut ext = (0..7)
|
||||
.map(|i| {
|
||||
let v: Vec2 = (-t + TAU * i as f32 / 7.0).sin_cos().into();
|
||||
(v * 250.0, 10.0)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
c.append(&mut ext);
|
||||
|
||||
c.iter()
|
||||
.fold(f32::MAX, |acc, &(c, r)| acc.min(circ(p, c, r)))
|
||||
}
|
||||
|
||||
fn segment(p: Vec2, a: Vec2, b: Vec2) -> f32 {
|
||||
let pa = p - a;
|
||||
let ba = b - a;
|
||||
let h = (pa.dot(ba) / ba.length_squared()).clamp(0.0, 1.0);
|
||||
return (pa - ba * h).length();
|
||||
}
|
||||
fn pentagram(p: Vec2, center: Vec2, t: f32) -> f32 {
|
||||
let points = (0..5)
|
||||
.map(|i| {
|
||||
let v: Vec2 = (-t + TAU * i as f32 / 5.0).sin_cos().into();
|
||||
v * 100.0 - center
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
(0..5)
|
||||
.map(|i| (points[i], points[(i + 2) % 5]))
|
||||
.fold(f32::MAX, |acc, (a, b)| acc.min(segment(p, a, b)))
|
||||
}
|
||||
fn pentagrams(p: Vec2, t: f32) -> f32 {
|
||||
(0..5)
|
||||
.map(|i| {
|
||||
let v: Vec2 = (t / 10.0 + TAU * i as f32 / 5.0).sin_cos().into();
|
||||
let v = v * 330.0;
|
||||
pentagram(p, v, t)
|
||||
})
|
||||
.fold(f32::MAX, |acc, a| acc.min(a))
|
||||
}
|
||||
|
||||
fn f(p: Vec2, t: f32) -> f32 {
|
||||
spinny_circles(p, t).min(pentagrams(p, t))
|
||||
}
|
||||
|
||||
fn norm_f(p: Vec2, t: f32) -> Vec2 {
|
||||
const H: f32 = 0.0001;
|
||||
let k = vec2(1.0, -1.0);
|
||||
return (k * f(p + k * H, t)
|
||||
+ k.yy() * f(p + k.yy() * H, t)
|
||||
+ k.yx() * f(p + k.yx() * H, t)
|
||||
+ k.xx() * f(p + k.xx() * H, t))
|
||||
.normalize();
|
||||
}
|
||||
|
||||
fn update(app: &App, model: &mut Model, _update: Update) {
|
||||
let t = app.elapsed_frames() as f32 / 120.0;
|
||||
for (p, _) in &mut model.points {
|
||||
*p -= norm_f(*p, t) * f(*p, t).signum();
|
||||
}
|
||||
|
||||
if app.elapsed_frames() > 20 {
|
||||
for _ in 0..10 {
|
||||
model
|
||||
.points
|
||||
.push_back((6.0 * point(random_range(0, 1000)), color()));
|
||||
}
|
||||
}
|
||||
|
||||
// remove a bunch of them every once in a while
|
||||
// since we're already not running real time, who cares if we pause for a bit rigth?
|
||||
if app.elapsed_frames() % 200 == 0 {
|
||||
// drain_filter but i'm too lazy for nightly
|
||||
let mut i = 0;
|
||||
while i < model.points.len() {
|
||||
if f(model.points[i].0, t) < 0.0 {
|
||||
model.points.remove(i);
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn view(app: &App, model: &Model, frame: Frame) {
|
||||
let _t = frame.nth() as f32 / 120.0;
|
||||
|
||||
let draw = app.draw();
|
||||
if frame.nth() == 0 {
|
||||
draw.background().color(BLACK);
|
||||
} else {
|
||||
let win = app.window_rect();
|
||||
draw.rect().wh(win.wh()).color(srgba(0., 0.0, 0.0, 0.005));
|
||||
}
|
||||
|
||||
for &(p, (h, l)) in &model.points {
|
||||
draw.ellipse().color(hsl(h, 1.0, l)).xy(p).radius(1.0);
|
||||
}
|
||||
|
||||
draw.to_frame(app, &frame).unwrap();
|
||||
|
||||
utils::record::record(app, &frame);
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
[package]
|
||||
name = "subtitled8"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
utils = { path = "../utils" }
|
|
@ -1,133 +0,0 @@
|
|||
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<Vec2>,
|
||||
offsets: Vec<Vec2>,
|
||||
|
||||
bg: Vec<(Vec2, f32)>,
|
||||
}
|
||||
impl Model {
|
||||
fn points(&self) -> Vec<Vec2> {
|
||||
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::<Vec<_>>();
|
||||
|
||||
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);
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
[package]
|
||||
name = "subtitled9"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
utils = { path = "../utils" }
|
|
@ -1,82 +0,0 @@
|
|||
use nannou::prelude::*;
|
||||
use utils::*;
|
||||
|
||||
fn main() {
|
||||
nannou::app(model).update(update).simple_window(view).run();
|
||||
}
|
||||
|
||||
struct Model {}
|
||||
|
||||
fn model(_app: &App) -> Model {
|
||||
Model {}
|
||||
}
|
||||
|
||||
fn update(_app: &App, _model: &mut Model, _update: Update) {}
|
||||
|
||||
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.01));
|
||||
}
|
||||
|
||||
// okay so this is a bit of a hack
|
||||
// we draw the ones inside and outside the box in two separate passes
|
||||
// on the first one, we draw the ones inside the box, with a box of size 220
|
||||
// then we draw the blank stuff outside of a 200 box
|
||||
// then we draw the points outside the 200 box
|
||||
|
||||
// this is cause otherwise either the colored lines go outside the box,
|
||||
// or the colored lines finish too early
|
||||
// this works and it's still real time so
|
||||
// don't judge me uwu
|
||||
|
||||
// inner draw
|
||||
for i in 0..50 {
|
||||
let r = 1.5;
|
||||
let r2 = r * (50 + i) as f32 / 50.0;
|
||||
let v = vec2((t * r + i as f32).sin(), (t * r2 + (2 * i) as f32).sin()) * 300.0;
|
||||
|
||||
// while inside the box, draw a line to the last point
|
||||
if v.x.abs() < 220.0 && v.y.abs() < 220.0 {
|
||||
let t = t - 1.0 / 60.0;
|
||||
let v_prev = vec2((t * r + i as f32).sin(), (t * r2 + (2 * i) as f32).sin()) * 300.0;
|
||||
|
||||
let h_prev = map_sin((v_prev.x + v_prev.y) / 400.0 + i as f32, 0.0, 1.0);
|
||||
|
||||
draw.line()
|
||||
.stroke_weight(4.0)
|
||||
.points(v, v_prev)
|
||||
.color(hsl(h_prev, 0.5, 0.5));
|
||||
|
||||
let h = map_sin((v.x + v.y) / 400.0 + i as f32, 0.0, 1.0);
|
||||
draw.ellipse().radius(2.0).xy(v).color(hsl(h, 0.5, 0.5));
|
||||
}
|
||||
}
|
||||
|
||||
// draw exterior
|
||||
drawing::draw_exterior(&draw, 200.0, SNOW);
|
||||
|
||||
// outer draw
|
||||
for i in 0..50 {
|
||||
let r = 1.5;
|
||||
let r2 = r * (50 + i) as f32 / 50.0;
|
||||
let v = vec2((t * r + i as f32).sin(), (t * r2 + (2 * i) as f32).sin()) * 300.0;
|
||||
|
||||
if v.x.abs() > 201.0 || v.y.abs() > 201.0 {
|
||||
draw.ellipse().radius(2.0).xy(v).color(BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
draw.to_frame(app, &frame).unwrap();
|
||||
utils::record::record(app, &frame);
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
use nannou::prelude::*;
|
||||
use utils::*;
|
||||
|
||||
fn main() {
|
||||
nannou::app(model).update(update).simple_window(view).run();
|
||||
|
@ -11,18 +10,13 @@ fn model(_app: &App) -> Model {
|
|||
Model {}
|
||||
}
|
||||
|
||||
fn update(app: &App, _model: &mut Model, _update: Update) {
|
||||
let _t = app.elapsed_frames() as f32 / 60.0;
|
||||
}
|
||||
fn update(_app: &App, _model: &mut Model, _update: Update) {}
|
||||
|
||||
fn view(app: &App, _model: &Model, frame: Frame) {
|
||||
let _t = frame.nth() as f32 / 60.0;
|
||||
|
||||
let draw = app.draw();
|
||||
draw.background().color(PLUM);
|
||||
|
||||
draw.ellipse().color(STEELBLUE);
|
||||
|
||||
draw.to_frame(app, &frame).unwrap();
|
||||
utils::record::record(app, &frame);
|
||||
}
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
use nannou::prelude::*;
|
||||
|
||||
pub struct Chaikin {
|
||||
pub points: Vec<Vec2>,
|
||||
}
|
||||
impl Chaikin {
|
||||
pub fn new(points: Vec<Vec2>) -> Self {
|
||||
Self { points }
|
||||
}
|
||||
|
||||
pub fn points(&self, div: f32, n: usize) -> Vec<Vec2> {
|
||||
let mut points = self.points.clone();
|
||||
for _ in 0..n {
|
||||
let first = *points.first().unwrap();
|
||||
let last = *points.last().unwrap();
|
||||
points = points
|
||||
.windows(2)
|
||||
.flat_map(|p| {
|
||||
let a = p[0];
|
||||
let b = p[1];
|
||||
|
||||
[a + div * (b - a), a + (1.0 - div) * (b - a)]
|
||||
})
|
||||
.collect();
|
||||
|
||||
points.insert(0, first);
|
||||
points.push(last);
|
||||
}
|
||||
points
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
use nannou::{color::IntoLinSrgba, draw::properties::ColorScalar, prelude::*};
|
||||
|
||||
pub fn draw_soft_bg(draw: &Draw, app: &App, color: impl IntoLinSrgba<ColorScalar>, alpha: f32) {
|
||||
if app.elapsed_frames() <= 1 {
|
||||
draw.background().color(color);
|
||||
} else {
|
||||
let mut color = color.into_lin_srgba();
|
||||
color.alpha = alpha;
|
||||
|
||||
let win = app.window_rect();
|
||||
draw.rect().wh(win.wh()).color(color);
|
||||
}
|
||||
}
|
||||
|
||||
/// Draws the opposite of a box
|
||||
pub fn draw_exterior(draw: &Draw, size: f32, color: impl IntoLinSrgba<ColorScalar> + Clone) {
|
||||
draw.quad()
|
||||
.points(
|
||||
vec2(size, -1000.0),
|
||||
vec2(size, 1000.0),
|
||||
vec2(1000.0, 1000.0),
|
||||
vec2(1000.0, -1000.0),
|
||||
)
|
||||
.color(color.clone());
|
||||
draw.quad()
|
||||
.points(
|
||||
vec2(-size, -1000.0),
|
||||
vec2(-size, 1000.0),
|
||||
vec2(-1000.0, 1000.0),
|
||||
vec2(-1000.0, -1000.0),
|
||||
)
|
||||
.color(color.clone());
|
||||
draw.quad()
|
||||
.points(
|
||||
vec2(-1000.0, size),
|
||||
vec2(-1000.0, 1000.0),
|
||||
vec2(1000.0, 1000.0),
|
||||
vec2(1000.0, size),
|
||||
)
|
||||
.color(color.clone());
|
||||
draw.quad()
|
||||
.points(
|
||||
vec2(-1000.0, -size),
|
||||
vec2(-1000.0, -1000.0),
|
||||
vec2(1000.0, -1000.0),
|
||||
vec2(1000.0, -size),
|
||||
)
|
||||
.color(color);
|
||||
}
|
|
@ -1,11 +1,5 @@
|
|||
pub mod color;
|
||||
pub mod curves;
|
||||
pub mod drawing;
|
||||
pub mod lsystems;
|
||||
pub mod record;
|
||||
pub mod sequences;
|
||||
pub mod shaders;
|
||||
pub mod turtle;
|
||||
|
||||
use nannou::prelude::*;
|
||||
|
||||
|
@ -20,40 +14,9 @@ pub fn map_cos(v: f32, out_min: f32, out_max: f32) -> f32 {
|
|||
|
||||
pub trait Vec2Extension {
|
||||
fn atan2(self) -> f32;
|
||||
fn yy(self) -> Self;
|
||||
fn yx(self) -> Self;
|
||||
fn xx(self) -> Self;
|
||||
}
|
||||
impl Vec2Extension for Vec2 {
|
||||
fn atan2(self) -> f32 {
|
||||
self.x.atan2(self.y)
|
||||
}
|
||||
fn yy(self) -> Self {
|
||||
vec2(self.y, self.y)
|
||||
}
|
||||
fn yx(self) -> Self {
|
||||
vec2(self.y, self.x)
|
||||
}
|
||||
fn xx(self) -> Self {
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vec2_range(min: f32, max: f32) -> Vec2 {
|
||||
vec2(random_range(min, max), random_range(min, max))
|
||||
}
|
||||
pub fn ivec2_range(min: i32, max: i32) -> IVec2 {
|
||||
ivec2(random_range(min, max), random_range(min, max))
|
||||
}
|
||||
/// returns a random vector in the unit circle
|
||||
pub fn vec2_circ() -> Vec2 {
|
||||
random_range(0., TAU).sin_cos().into()
|
||||
}
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
pub struct LSystem<Alphabet: Clone> {
|
||||
axiom: Vec<Alphabet>,
|
||||
rule: Box<dyn FnMut(Alphabet) -> Vec<Alphabet>>,
|
||||
memo: HashMap<usize, Vec<Alphabet>>,
|
||||
}
|
||||
|
||||
impl<Alphabet: Clone> LSystem<Alphabet> {
|
||||
pub fn new(axiom: Vec<Alphabet>, rule: Box<dyn FnMut(Alphabet) -> Vec<Alphabet>>) -> Self {
|
||||
Self {
|
||||
axiom,
|
||||
rule,
|
||||
memo: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn nth(&mut self, i: usize) -> Vec<Alphabet> {
|
||||
if i == 0 {
|
||||
return self.axiom.clone();
|
||||
}
|
||||
if let Some(a) = self.memo.get(&i) {
|
||||
return a.clone();
|
||||
}
|
||||
|
||||
let last = self.nth(i - 1);
|
||||
|
||||
let mut res = Vec::new();
|
||||
for letter in last {
|
||||
res.extend((self.rule)(letter).into_iter());
|
||||
}
|
||||
|
||||
self.memo.insert(i, res.clone());
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn lsystems() {
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
enum Test {
|
||||
A,
|
||||
B,
|
||||
}
|
||||
use Test::*;
|
||||
|
||||
let mut sys = LSystem::new(
|
||||
vec![A],
|
||||
Box::new(|i| match i {
|
||||
A => vec![A, B],
|
||||
B => vec![A],
|
||||
}),
|
||||
);
|
||||
|
||||
assert_eq!(vec![A], sys.nth(0));
|
||||
assert_eq!(vec![A, B], sys.nth(1));
|
||||
assert_eq!(vec![A, B, A], sys.nth(2));
|
||||
assert_eq!(vec![A, B, A, A, B], sys.nth(3));
|
||||
assert_eq!(vec![A, B, A, A, B, A, B, A], sys.nth(4));
|
||||
}
|
||||
}
|
|
@ -18,7 +18,6 @@ pub fn record(app: &App, frame: &Frame) {
|
|||
// Capture all frames to a directory called `/<path_to_nannou>/nannou/simple_capture`.
|
||||
.join("recordings")
|
||||
.join(app.exe_name().unwrap())
|
||||
.join("frames")
|
||||
// Name each file after the number of the frame.
|
||||
.join(format!("{:03}", frame.nth()))
|
||||
// The extension will be PNG. We also support tiff, bmp, gif, jpeg, webp and some others.
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
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<Item = Vec2> {
|
||||
Self::new(base1)
|
||||
.zip(Self::new(base2))
|
||||
.map(crate::Tup2Extension::to_vec2)
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Halton {
|
||||
type Item = f32;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VanDerCorput {
|
||||
i: usize,
|
||||
base: f32,
|
||||
}
|
||||
impl VanDerCorput {
|
||||
pub fn new(base: f32) -> Self {
|
||||
Self { i: 0, base }
|
||||
}
|
||||
pub fn points(base1: f32, base2: f32) -> impl Iterator<Item = Vec2> {
|
||||
Self::new(base1)
|
||||
.zip(Self::new(base2))
|
||||
.map(crate::Tup2Extension::to_vec2)
|
||||
}
|
||||
}
|
||||
impl Iterator for VanDerCorput {
|
||||
type Item = f32;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let mut q = 0.0;
|
||||
let mut bk = 1.0 / self.base;
|
||||
let mut i = self.i as f32;
|
||||
|
||||
while i > 0.0 {
|
||||
q += (i % self.base) * bk;
|
||||
i /= self.base;
|
||||
bk /= self.base;
|
||||
}
|
||||
|
||||
Some(q)
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
use nannou::prelude::*;
|
||||
|
||||
pub fn run<S, T>(app: &App, frame: Frame, ball_size: f32, shader: S, tile_movement: T)
|
||||
where
|
||||
S: Fn(usize, usize, usize, usize, f32) -> Hsl,
|
||||
T: Fn(f32, f32) -> Vec2,
|
||||
{
|
||||
let t = frame.nth() as f32 / 120.0;
|
||||
|
||||
let draw = app.draw();
|
||||
draw.background().color(BLACK);
|
||||
|
||||
let (l, top, w, h) = app.window_rect().l_t_w_h();
|
||||
|
||||
let cols = (w / ball_size) as usize;
|
||||
let rows = (h / ball_size) as usize;
|
||||
|
||||
for i in 0..cols {
|
||||
for j in 0..rows {
|
||||
let x = l + j as f32 * ball_size;
|
||||
let y = top - i as f32 * ball_size;
|
||||
let p = tile_movement(x, y);
|
||||
|
||||
let color = shader(i, j, cols, rows, t);
|
||||
|
||||
draw.quad()
|
||||
.points(
|
||||
p + ball_size * vec2(1., 1.),
|
||||
p + ball_size * vec2(1., -1.),
|
||||
p + ball_size * vec2(-1., -1.),
|
||||
p + ball_size * vec2(-1., 1.),
|
||||
)
|
||||
.xy(p)
|
||||
.color(color);
|
||||
}
|
||||
}
|
||||
|
||||
draw.to_frame(app, &frame).unwrap();
|
||||
super::record::record(app, &frame);
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
use nannou::prelude::*;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum TurtleAlphabet {
|
||||
Line,
|
||||
Move,
|
||||
Right,
|
||||
Left,
|
||||
Push,
|
||||
Pop,
|
||||
}
|
||||
|
||||
pub struct Turtle {
|
||||
position: Vec2,
|
||||
pub rotation: f32,
|
||||
len: f32,
|
||||
theta: f32,
|
||||
stack: Vec<(Vec2, f32)>,
|
||||
}
|
||||
|
||||
impl Turtle {
|
||||
pub fn new(position: Vec2, len: f32, theta: f32) -> Self {
|
||||
Self {
|
||||
position,
|
||||
rotation: 0.0,
|
||||
len,
|
||||
theta,
|
||||
stack: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn advance(&mut self, draw: &Draw, l: TurtleAlphabet) {
|
||||
match l {
|
||||
TurtleAlphabet::Line | TurtleAlphabet::Move => {
|
||||
let next = self.position + Vec2::ONE.rotate(self.rotation) * self.len;
|
||||
draw.line().points(self.position, next);
|
||||
self.position = next;
|
||||
}
|
||||
// TurtleAlphabet::Move => {
|
||||
// self.position += Vec2::ONE.rotate(self.rotation) * self.len;
|
||||
// }
|
||||
TurtleAlphabet::Right => self.rotation = (self.rotation - self.theta).rem_euclid(TAU),
|
||||
TurtleAlphabet::Left => self.rotation = (self.rotation + self.theta).rem_euclid(TAU),
|
||||
TurtleAlphabet::Push => self.stack.push((self.position, self.rotation)),
|
||||
TurtleAlphabet::Pop => {
|
||||
if let Some((a, b)) = self.stack.pop() {
|
||||
self.position = a;
|
||||
self.rotation = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn advance_many(&mut self, draw: &Draw, l: &[TurtleAlphabet]) {
|
||||
for &l in l {
|
||||
self.advance(draw, l)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,10 +7,8 @@ if [[ -z $1 ]]; then
|
|||
echo "example:"
|
||||
echo -e "\t$0 packagename"
|
||||
else
|
||||
rm -rf "recordings/$1/frames"
|
||||
mkdir -p "recordings/$1/videos"
|
||||
rm -rf "recordings/$1"
|
||||
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"
|
||||
ffmpeg -framerate 60 -i "recordings/$1/%03d.png" -pix_fmt yuv420p "recordings/$1.mp4"
|
||||
echo "done"
|
||||
fi
|
||||
|
|
Loading…
Reference in a new issue