Initial commit

main
Charlotte Som 2021-09-02 03:54:38 +01:00
commit 2ce3eb8195
14 changed files with 3191 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
frames/
out.mp4

2
01_enby_circles/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
Cargo.lock

View File

@ -0,0 +1,7 @@
[package]
name = "sketch_enby_circles"
version = "0.1.0"
edition = "2018"
[dependencies]
sketchlib = { path = "../sketchlib" }

View File

@ -0,0 +1,84 @@
use sketchlib::nannou;
use sketchlib::nannou::color::Alpha;
use sketchlib::nannou::glam::Vec3Swizzles;
use sketchlib::prelude::*;
const PHI_MINUS_ONE_TIMES_PI: f32 = 1.94161103873;
fn main() {
nannou::app(model)
.size(1260, 1260)
.update(update)
.simple_window(view)
.run();
}
struct Point {
pos: Vec3,
}
struct Model {
points: Vec<Point>,
}
fn model(_app: &App) -> Model {
let mut points = vec![];
let mut theta = 0.0;
for r in 0..512 {
let r = 50.0 * (r as f32).sqrt();
points.push(Point {
pos: (r * theta.cos(), r * theta.sin(), 0.0).into(),
});
theta += PHI_MINUS_ONE_TIMES_PI;
}
Model { points }
}
fn update(app: &App, model: &mut Model, _update: Update) {
let dt = delta_t(app) as f32;
let t = absolute_t(app) as f32;
model.points.par_iter_mut().enumerate().for_each(|(i, b)| {
let i = i as f32;
b.pos.x += (t * PI + i).cos() * 35.0 * dt;
b.pos.y += (t * PI + i).sin() * 35.0 * dt;
});
}
fn view(app: &App, model: &Model, frame: Frame) {
// let t = app.duration.since_start.as_secs_f64();
const BG_COL: Srgb<u8> = BLACK;
let draw = app.draw();
if frame.nth() == 0 {
draw.background().color(BG_COL);
} else {
let window_rect = app.window_rect();
draw.rect()
.xy(window_rect.xy())
.wh(window_rect.wh())
.color(Alpha {
color: BG_COL,
alpha: 0.02,
});
}
// let draw = draw.scale(0.01);
for (i, point) in model.points.iter().enumerate() {
let trans_flag = *sketchlib::palettes::NON_BINARY_FLAG;
draw.ellipse()
.color(trans_flag[i % trans_flag.len()])
.radius(10.0)
.xy(point.pos.xy());
}
draw.to_frame(app, &frame).unwrap();
dump_frame(app, &frame).unwrap();
}

5
02_gravity/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
/target
# ffmpeg -framerate 60 -i recordings/%05d.png -pix_fmt yuv420p recording.mp4
/recordings
/recording.mp4

2881
02_gravity/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

7
02_gravity/Cargo.toml Normal file
View File

@ -0,0 +1,7 @@
[package]
name = "sketch_gravity"
version = "0.1.0"
edition = "2018"
[dependencies]
sketchlib = { path = "../sketchlib" }

118
02_gravity/src/main.rs Normal file
View File

@ -0,0 +1,118 @@
use sketchlib::nannou;
use sketchlib::prelude::*;
fn main() {
nannou::app(model)
.size(1260, 1260)
.update(update)
.simple_window(view)
.run();
}
#[derive(Clone)]
struct Body {
pos: DVec2,
vel: DVec2,
mass: i64,
color: Rgb,
}
struct Model {
bodies: Vec<Body>,
}
fn model(_app: &App) -> Model {
let mut bodies = Vec::new();
const MASS_SUN: i64 = 50000000000000000;
bodies.push(Body {
pos: (0.0, 0.0).into(),
vel: (0.0, 0.0).into(),
mass: MASS_SUN,
color: rgb(1.0, 1.0, 1.0),
});
const G: f64 = 6.67408e-11;
let palette = &[
rgb(85.0 / 255.0, 205.0 / 255.0, 252.0 / 255.0),
rgb(1.0, 1.0, 1.0),
rgb(247.0 / 255.0, 168.0 / 255.0, 184.0 / 255.0),
];
let mut theta = 0.0;
for i in 1..=256 {
let r = 25.0 + 5.0 * i as f64;
let m = 50000000000u64 / i;
let curr_color = palette[i as usize % palette.len()];
let speed = (G * MASS_SUN as f64 / r).sqrt();
println!("{}", speed);
bodies.push(Body {
pos: (r * theta.cos(), r * theta.sin()).into(),
vel: (speed * theta.sin(), speed * -theta.cos()).into(),
mass: m as i64,
color: curr_color,
});
theta += 1.94161103873;
}
Model { bodies }
}
fn update(app: &App, model: &mut Model, _update: Update) {
const G: f64 = 6.67408e-11;
let bodies = model.bodies.clone();
let delta_t = delta_t(&app);
model
.bodies
.par_iter_mut()
.enumerate()
.for_each(|(i, body)| {
let mut acc: DVec2 = (0.0, 0.0).into();
bodies.iter().enumerate().for_each(|(j, other_body)| {
if i == j {
return;
}
let delta = other_body.pos - body.pos;
let dist_sq = body.pos.distance_squared(other_body.pos);
if dist_sq <= (body.mass as f64).log10() {
return;
}
let acceleration = G * other_body.mass as f64 / dist_sq;
acc += delta * acceleration / dist_sq.sqrt();
});
body.vel += acc * delta_t;
body.pos += body.vel * delta_t;
});
}
fn view(app: &App, model: &Model, frame: Frame) {
// let t = app.duration.since_start.as_secs_f64();
let draw = app.draw().scale(1.0);
draw.background().color(BLACK);
for body in model.bodies.iter() {
let diameter = (body.mass as f32).log10() * 2.0; // should be proportional to cuberoot but this is so we can actually see the small ones
draw.ellipse()
.w_h(diameter, diameter)
.xy(body.pos.as_f32())
.color(body.color);
}
draw.to_frame(app, &frame).unwrap();
dump_frame(app, &frame).unwrap();
}

2
sketchlib/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
Cargo.lock

10
sketchlib/Cargo.toml Normal file
View File

@ -0,0 +1,10 @@
[package]
name = "sketchlib"
version = "0.1.0"
edition = "2018"
[dependencies]
nannou = "0.17.1"
once_cell = "1.8.0"
rayon = "1.5.1"

8
sketchlib/src/lib.rs Normal file
View File

@ -0,0 +1,8 @@
pub use nannou;
pub use once_cell;
pub use rayon;
pub mod palettes;
pub mod recording;
pub mod prelude;

20
sketchlib/src/palettes.rs Normal file
View File

@ -0,0 +1,20 @@
use once_cell::sync::Lazy;
use crate::prelude::*;
pub const TRANS_FLAG: Lazy<[Rgb; 3]> = Lazy::new(|| {
[
rgb(85.0 / 255.0, 205.0 / 255.0, 252.0 / 255.0),
rgb(1.0, 1.0, 1.0),
rgb(247.0 / 255.0, 168.0 / 255.0, 184.0 / 255.0),
]
});
pub const NON_BINARY_FLAG: Lazy<[Rgb; 4]> = Lazy::new(|| {
[
rgb(1.0, 244.0 / 255.0, 48.0 / 255.0),
rgb(1.0, 1.0, 1.0),
rgb(156.0 / 255.0, 89.0 / 255.0, 209.0 / 255.0),
rgb(0.2, 0.2, 0.2),
]
});

4
sketchlib/src/prelude.rs Normal file
View File

@ -0,0 +1,4 @@
pub use nannou::prelude::*;
pub use rayon::prelude::*;
pub use crate::recording::*;

View File

@ -0,0 +1,41 @@
use std::error::Error;
use nannou::prelude::*;
use once_cell::sync::Lazy;
const FPS: f64 = 60.0;
static RECORDING: Lazy<bool> = Lazy::new(|| std::env::args().any(|s| s == "--record"));
pub fn dump_frame(app: &App, frame: &Frame) -> Result<(), Box<dyn Error>> {
if !*RECORDING {
return Ok(());
}
let path = app
.project_path()?
.join("frames")
.join(format!("{:05}", frame.nth()))
.with_extension("png");
println!("-> {:05} {:.3}", frame.nth(), absolute_t(app));
app.main_window().capture_frame(path);
Ok(())
}
pub fn delta_t(app: &App) -> f64 {
if *RECORDING {
1.0 / FPS
} else {
app.duration.since_prev_update.as_secs_f64()
}
}
pub fn absolute_t(app: &App) -> f64 {
if *RECORDING {
(app.elapsed_frames() as f64) / FPS
} else {
app.duration.since_start.as_secs_f64()
}
}