Initial commit
commit
2ce3eb8195
|
@ -0,0 +1,2 @@
|
||||||
|
frames/
|
||||||
|
out.mp4
|
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
Cargo.lock
|
|
@ -0,0 +1,7 @@
|
||||||
|
[package]
|
||||||
|
name = "sketch_enby_circles"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
sketchlib = { path = "../sketchlib" }
|
|
@ -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();
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
/target
|
||||||
|
|
||||||
|
# ffmpeg -framerate 60 -i recordings/%05d.png -pix_fmt yuv420p recording.mp4
|
||||||
|
/recordings
|
||||||
|
/recording.mp4
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,7 @@
|
||||||
|
[package]
|
||||||
|
name = "sketch_gravity"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
sketchlib = { path = "../sketchlib" }
|
|
@ -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();
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
Cargo.lock
|
|
@ -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"
|
|
@ -0,0 +1,8 @@
|
||||||
|
pub use nannou;
|
||||||
|
pub use once_cell;
|
||||||
|
pub use rayon;
|
||||||
|
|
||||||
|
pub mod palettes;
|
||||||
|
pub mod recording;
|
||||||
|
|
||||||
|
pub mod prelude;
|
|
@ -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),
|
||||||
|
]
|
||||||
|
});
|
|
@ -0,0 +1,4 @@
|
||||||
|
pub use nannou::prelude::*;
|
||||||
|
pub use rayon::prelude::*;
|
||||||
|
|
||||||
|
pub use crate::recording::*;
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue