add 22, 23, 24,
parent
5e0d3b3ca0
commit
92214054f9
|
@ -2470,6 +2470,30 @@ dependencies = [
|
|||
"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 = "subtitled3"
|
||||
version = "0.1.0"
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "subtitled22"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
utils = { path = "../utils" }
|
|
@ -0,0 +1,99 @@
|
|||
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);
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "subtitled23"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
utils = { path = "../utils" }
|
|
@ -0,0 +1,68 @@
|
|||
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 points = (0..count)
|
||||
.map(|i| (TAU * i as f32 / count as f32).sin_cos().to_vec2())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
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);
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "subtitled24"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
nannou = "0.17"
|
||||
utils = { path = "../utils" }
|
|
@ -0,0 +1,67 @@
|
|||
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,8 +1,10 @@
|
|||
pub mod color;
|
||||
pub mod curves;
|
||||
pub mod drawing;
|
||||
pub mod lsystems;
|
||||
pub mod record;
|
||||
pub mod sequences;
|
||||
pub mod turtle;
|
||||
|
||||
use nannou::prelude::*;
|
||||
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
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));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
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)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue