

use nannou::prelude::*;
use nannou::noise::{ NoiseFn, Perlin };
struct Model {
particles: Vec<Particle>,
noise: Perlin,
}
struct Particle {
pos: Vec2,
vel: Vec2,
col: Hsla,
}
fn main() {
nannou::app(model).update(update).run();
}
fn model(app: &App) -> Model {
app.new_window().size(800, 800).view(view).build().unwrap();
// ์ด๊ธฐ ์
์ ์์ฑ
let particles = (0..2000)
.map(|_| {
let x = random_range(-400.0, 400.0);
let y = random_range(-400.0, 400.0);
Particle {
pos: vec2(x, y),
vel: Vec2::ZERO,
col: hsla(0.0, 0.0, 1.0, 0.15), // ํ์ดํธ, ๋ฐํฌ๋ช
}
})
.collect();
Model {
particles,
noise: Perlin::new(),
}
}
fn update(app: &App, model: &mut Model, _update: Update) {
let time = (app.elapsed_frames() as f64) * 0.005;
for p in model.particles.iter_mut() {
// ๋
ธ์ด์ฆ ๊ธฐ๋ฐ ํ๋ฆ์ฅ
let angle =
(
model.noise.get([(p.pos.x as f64) * 0.004, (p.pos.y as f64) * 0.004, time]) as f32 //์ธ๋ฐํจ
) * TAU;
let dir = vec2(angle.cos(), angle.sin()) * 1.0; //๋์ผ๋ฉด ์ฑ๊ฒจ์ง
p.vel = dir;
p.pos += p.vel;
// ํ๋ฉด ๋ฐ์ผ๋ก ๋๊ฐ๋ฉด ๋ฆฌ์
if p.pos.length() > 300.0 {
p.pos = vec2(random_range(-100.0, 100.0), random_range(-100.0, 100.0));
}
// ์
์ ์์์ ํ์ดํธ ์ ์ง (์ถํ ์๋ ๊ธฐ๋ฐ์ผ๋ก ๋ณ๊ฒฝ ๊ฐ๋ฅ)
p.col = hsla(0.0, 0.0, 1.0, 0.05);
}
}
fn view(app: &App, model: &Model, frame: Frame) {
let draw = app.draw();
// ์ฒซ ํ๋ ์์์๋ง ๋ฐฐ๊ฒฝ ์ด๊ธฐํ (์์ฃผ ์ด๋์ด ๋ฐฐ๊ฒฝ)
if app.elapsed_frames() == 1 {
draw.background().color(hsla(0.0, 0.0, 0.02, 1.0));
}
for p in &model.particles {
draw.ellipse().x_y(p.pos.x, p.pos.y).w_h(1.0, 1.0).color(p.col);
}
draw.to_frame(app, &frame).unwrap();
}
// nannou ํ๋ ์์ํฌ์ prelude ๋ชจ๋์ ๊ฐ์ ธ์ต๋๋ค.
// prelude๋ Nannou๋ฅผ ์ฌ์ฉํ๋ ๋ฐ ํ์ํ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ํ์
, ํธ๋ ์, ํจ์๋ค์ ํฌํจํ๊ณ ์์ด
// ๋งค๋ฒ ๊ฐ๋ณ์ ์ผ๋ก use ์ ์ธ์ ํ์ง ์์๋ ํธ๋ฆฌํ๊ฒ ์ฌ์ฉํ ์ ์๊ฒ ํด์ค๋๋ค.
use nannou::prelude::*;
// nannou์์ ์ ๊ณตํ๋ ๋
ธ์ด์ฆ ํจ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
// NoiseFn ํธ๋ ์์ ๋
ธ์ด์ฆ ๊ฐ์ ์์ฑํ๋ ํจ์(get)๋ฅผ ์ ์ํ๊ณ ,
// Perlin์ Perlin ๋
ธ์ด์ฆ ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌํํ ๊ตฌ์กฐ์ฒด์
๋๋ค.
use nannou::noise::{ NoiseFn, Perlin };
// ์ ํ๋ฆฌ์ผ์ด์
์ ์ ์ฒด ์ํ(State)๋ฅผ ์ ์ฅํ ๊ตฌ์กฐ์ฒด์
๋๋ค.
// Model์ Nannou ์ฑ์ ๋ฐ์ดํฐ ๋ชจ๋ธ ์ญํ ์ ํ๋ฉฐ, ์ฑ์ด ์คํ๋๋ ๋์ ๊ณ์ ์ ์ง๋ฉ๋๋ค.
struct Model {
// ํ๋ฉด์ ๊ทธ๋ ค์ง ๋ชจ๋ ํํฐํด(์
์)๋ค์ ๋ด์๋ ๋ฒกํฐ(๋์ ๋ฐฐ์ด)์
๋๋ค.
particles: Vec<Particle>,
// Perlin ๋
ธ์ด์ฆ๋ฅผ ์์ฑํ๊ธฐ ์ํ ์ธ์คํด์ค์
๋๋ค. ์ด ๋
ธ์ด์ฆ๋ฅผ ์ด์ฉํด ํํฐํด์ ์์ง์์ ์ ์ดํฉ๋๋ค.
noise: Perlin,
}
// ๊ฐ๋ณ ํํฐํด(์
์)์ ์์ฑ์ ์ ์ํ๋ ๊ตฌ์กฐ์ฒด์
๋๋ค.
struct Particle {
// ํํฐํด์ ํ์ฌ ์์น๋ฅผ ๋ํ๋ด๋ 2์ฐจ์ ๋ฒกํฐ(x, y)์
๋๋ค.
pos: Vec2,
// ํํฐํด์ ์๋์ ๋ฐฉํฅ์ ๋ํ๋ด๋ 2์ฐจ์ ๋ฒกํฐ์
๋๋ค.
vel: Vec2,
// ํํฐํด์ ์์์ ๋ํ๋
๋๋ค. HSLA(์์, ์ฑ๋, ๋ช
๋, ํฌ๋ช
๋) ๋ชจ๋ธ์ ์ฌ์ฉํฉ๋๋ค.
col: Hsla,
}
// ํ๋ก๊ทธ๋จ์ ์ง์
์ (Entry Point)์
๋๋ค.
fn main() {
// nannou ์ ํ๋ฆฌ์ผ์ด์
์ ์ค์ ํ๊ณ ์คํํฉ๋๋ค.
// model ํจ์๋ฅผ ํตํด ์ด๊ธฐ ๋ชจ๋ธ์ ์ค์ ํ๊ณ ,
// update ํจ์๋ฅผ ํตํด ๋งค ํ๋ ์ ๋ชจ๋ธ์ ์ํ๋ฅผ ๊ฐฑ์ ํ๋ฉฐ,
// run()์ ํธ์ถํ์ฌ ์ฑ์ ๋ฉ์ธ ๋ฃจํ๋ฅผ ์์ํฉ๋๋ค.
nannou::app(model).update(update).run();
}
// ์ ํ๋ฆฌ์ผ์ด์
์ด ์ฒ์ ์์๋ ๋ ํ ๋ฒ๋ง ํธ์ถ๋๋ ์ด๊ธฐํ ํจ์์
๋๋ค.
// ์ฑ์ ์ด๊ธฐ ์ํ(Model)๋ฅผ ์ค์ ํ๊ณ ๋ฐํํฉ๋๋ค.
fn model(app: &App) -> Model {
// ์ ์ฐฝ์ ์์ฑํ๊ณ , ๊ฐ๋ก 800, ์ธ๋ก 800 ํฝ์
ํฌ๊ธฐ๋ก ์ค์ ํฉ๋๋ค.
// view ํจ์๋ฅผ ์ด ์ฐฝ์ ๊ทธ๋ฆฌ๊ธฐ ์ฝ๋ฐฑ์ผ๋ก ์ง์ ํ๊ณ , ์ต์ข
์ ์ผ๋ก ์ฐฝ์ ๋น๋ํฉ๋๋ค.
app.new_window().size(800, 800).view(view).build().unwrap();
// 2000๊ฐ์ ํํฐํด์ ์์ฑํ์ฌ ๋ฒกํฐ์ ์ ์ฅํฉ๋๋ค.
let particles = (0..2000)
.map(|_| { // _ ๋ ๋ฐ๋ณต ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ์ง ์๊ฒ ๋ค๋ ์๋ฏธ์
๋๋ค.
// ์ฐฝ ํฌ๊ธฐ(-400 ~ 400) ๋ด์์ ๋ฌด์์ x, y ์ขํ๋ฅผ ์์ฑํฉ๋๋ค.
let x = random_range(-400.0, 400.0);
let y = random_range(-400.0, 400.0);
// Particle ๊ตฌ์กฐ์ฒด๋ฅผ ์์ฑํ์ฌ ๋ฐํํฉ๋๋ค.
Particle {
// ์์์ ์์ฑํ ๋ฌด์์ ์ขํ๋ฅผ ์ด๊ธฐ ์์น๋ก ์ค์ ํฉ๋๋ค.
pos: vec2(x, y),
// ์ด๊ธฐ ์๋๋ 0์ผ๋ก ์ค์ ํฉ๋๋ค.
vel: Vec2::ZERO,
// ์ด๊ธฐ ์์์ ํฐ์(๋ช
๋ 1.0)์ ์ฝ๊ฐ์ ํฌ๋ช
๋(0.15)๋ฅผ ์ค๋๋ค.
col: hsla(0.0, 0.0, 1.0, 0.15),
}
})
.collect(); // map์ ํตํด ์์ฑ๋ ๋ชจ๋ Particle๋ค์ Vec<Particle> ์ปฌ๋ ์
์ผ๋ก ๋ชจ์๋๋ค.
// ์ต์ข
์ ์ผ๋ก ์์ฑ๋ Model ๊ตฌ์กฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค.
Model {
// ์์์ ์์ฑํ ํํฐํด ๋ฒกํฐ๋ฅผ ๋ชจ๋ธ์ ์ํ๋ก ์ ์ฅํฉ๋๋ค.
particles,
// ์๋ก์ด Perlin ๋
ธ์ด์ฆ ์์ฑ๊ธฐ๋ฅผ ์ด๊ธฐํํ์ฌ ๋ชจ๋ธ์ ์ ์ฅํฉ๋๋ค.
noise: Perlin::new(),
}
}
// ๋งค ํ๋ ์๋ง๋ค ํธ์ถ๋์ด ์ ํ๋ฆฌ์ผ์ด์
์ ์ํ(Model)๋ฅผ ๊ฐฑ์ ํ๋ ํจ์์
๋๋ค.
// ํํฐํด์ ์์น, ์๋, ์์ ๋ฑ์ ๊ณ์ฐํ๊ณ ๋ณ๊ฒฝํ๋ ๋ก์ง์ด ๋ด๊น๋๋ค.
fn update(app: &App, model: &mut Model, _update: Update) {
// ์ฑ์ด ์์๋ ํ ๊ฒฝ๊ณผํ ํ๋ ์ ์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์๊ฐ ๊ฐ์ ๊ณ์ฐํฉ๋๋ค.
// ์ด ์๊ฐ ๊ฐ์ Perlin ๋
ธ์ด์ฆ์ z์ถ ์
๋ ฅ์ผ๋ก ์ฌ์ฉ๋์ด, ์๊ฐ์ ๋ฐ๋ผ ํ๋ฆ์ฅ์ด ๊ณ์ ๋ณํ๊ฒ ๋ง๋ญ๋๋ค.
// 0.005๋ฅผ ๊ณฑํด ์๊ฐ์ ํ๋ฆ ์๋๋ฅผ ์กฐ์ ํฉ๋๋ค.
let time = (app.elapsed_frames() as f64) * 0.005;
// ๋ชจ๋ธ์ ์ ์ฅ๋ ๋ชจ๋ ํํฐํด์ ์ํํ๋ฉฐ ๊ฐ ํํฐํด์ ์ํ๋ฅผ ์
๋ฐ์ดํธํฉ๋๋ค.
// iter_mut()๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ ํํฐํด์ ๊ฐ์ ์ง์ ์์ ํ ์ ์๋๋ก ํฉ๋๋ค.
for p in model.particles.iter_mut() {
// Perlin ๋
ธ์ด์ฆ๋ฅผ ์ฌ์ฉํ์ฌ ํ์ฌ ํํฐํด ์์น์ ์๊ฐ(x, y, z)์ ํด๋นํ๋ ๋
ธ์ด์ฆ ๊ฐ์ ์ป์ต๋๋ค.
// ์ด ๋
ธ์ด์ฆ ๊ฐ์ -1.0์์ 1.0 ์ฌ์ด์ ๊ฐ์ ๊ฐ์ง๋๋ค.
// ์์น ๊ฐ์ 0.004๋ฅผ ๊ณฑํ์ฌ ๋
ธ์ด์ฆ ๊ณต๊ฐ์ ์ค์ผ์ผ์ ์กฐ์ ํฉ๋๋ค. ์ด ๊ฐ์ด ์์์๋ก ๋ถ๋๋ฝ๊ณ ๊ฑฐ๋ํ ํ๋ฆ์ด, ํด์๋ก ์๊ธ์๊ธํ ํ๋ฆ์ด ๋ง๋ค์ด์ง๋๋ค.
let noise_val = model.noise.get([(p.pos.x as f64) * 0.004, (p.pos.y as f64) * 0.004, time]) as f32;
// ๋
ธ์ด์ฆ ๊ฐ(-1.0 ~ 1.0)์ ๊ฐ๋(0 ~ 2ฯ)๋ก ๋ณํํฉ๋๋ค.
// TAU๋ 2 * PI ์ ๊ฐ์ ์์์
๋๋ค.
let angle = noise_val * TAU;
// ๊ณ์ฐ๋ ๊ฐ๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐฉํฅ ๋ฒกํฐ๋ฅผ ๋ง๋ญ๋๋ค.
// ์ด ๋ฒกํฐ๋ ํํฐํด์ด ๋ค์ ํ๋ ์์ ๋์๊ฐ ๋ฐฉํฅ์ ๊ฒฐ์ ํฉ๋๋ค.
// ๋ค์ ๊ณฑํด์ง๋ ๊ฐ(1.0)์ ํํฐํด์ ์๋ ฅ์ ์กฐ์ ํฉ๋๋ค. ์ด ๊ฐ์ ํค์ฐ๋ฉด ํํฐํด์ด ๋ ๋นจ๋ฆฌ ์์ง์
๋๋ค.
let dir = vec2(angle.cos(), angle.sin()) * 1.0;
// ํํฐํด์ ์๋๋ฅผ ์์์ ๊ณ์ฐํ ๋ฐฉํฅ ๋ฒกํฐ๋ก ์
๋ฐ์ดํธํฉ๋๋ค.
p.vel = dir;
// ํํฐํด์ ํ์ฌ ์์น์ ์๋๋ฅผ ๋ํ์ฌ ๋ค์ ์์น๋ฅผ ๊ณ์ฐํฉ๋๋ค.
p.pos += p.vel;
// ํํฐํด์ด ํน์ ๊ฒฝ๊ณ(์ค์ฌ์ผ๋ก๋ถํฐ์ ๊ฑฐ๋ฆฌ 300.0)๋ฅผ ๋ฒ์ด๋ฌ๋์ง ํ์ธํฉ๋๋ค.
// length()๋ ์์ (0,0)์ผ๋ก๋ถํฐ์ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ์ฐํฉ๋๋ค.
if p.pos.length() > 300.0 {
// ๊ฒฝ๊ณ๋ฅผ ๋ฒ์ด๋ฌ๋ค๋ฉด, ํํฐํด์ ํ๋ฉด ์ค์ ๊ทผ์ฒ์ ์๋ก์ด ๋ฌด์์ ์์น๋ก ๋ฆฌ์
ํฉ๋๋ค.
// ์ด๋ ๊ฒ ํจ์ผ๋ก์จ ํํฐํด๋ค์ด ๊ณ์ํด์ ํ๋ฉด ์ค์ ์์ญ์์ ํ๋ฆ์ ๋ง๋ค์ด๋
๋๋ค.
p.pos = vec2(random_range(-100.0, 100.0), random_range(-100.0, 100.0));
}
// ํํฐํด์ ์์์ ํฐ์(๋ช
๋ 1.0)์ผ๋ก ์ค์ ํ๊ณ , ๋งค์ฐ ๋ฎ์ ํฌ๋ช
๋(0.05)๋ฅผ ์ ์ฉํฉ๋๋ค.
// ๋ฐฐ๊ฒฝ์ ์ง์ฐ์ง ์๊ณ ๊ณ์ ๋ง๊ทธ๋ฆฌ๊ธฐ ๋๋ฌธ์, ๋ฎ์ ํฌ๋ช
๋๋ ํํฐํด์ ์ด๋ ๊ถค์ ์ ๋ถ๋๋ฌ์ด ์ ์ฒ๋ผ ๋ณด์ด๊ฒ ํ๋ ํจ๊ณผ๋ฅผ ์ค๋๋ค.
p.col = hsla(0.0, 0.0, 1.0, 0.05);
}
}
// update ํจ์๊ฐ ํธ์ถ๋ ํ, ๋งค ํ๋ ์๋ง๋ค ํ๋ฉด์ ๊ทธ๋ฆผ์ ๊ทธ๋ฆฌ๋ ํจ์์
๋๋ค.
fn view(app: &App, model: &Model, frame: Frame) {
// ๊ทธ๋ฆฌ๊ธฐ๋ฅผ ์ํ Draw ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
let draw = app.draw();
// ์ฑ์ ์ฒซ ๋ฒ์งธ ํ๋ ์์์๋ง ์คํ๋๋ ๋ธ๋ก์
๋๋ค.
if app.elapsed_frames() == 1 {
// ๋ฐฐ๊ฒฝ์ ์์ฃผ ์ด๋์ด ์์ผ๋ก ํ ๋ฒ๋ง ์น ํฉ๋๋ค.
// ์ดํ ํ๋ ์์์๋ ๋ฐฐ๊ฒฝ์ ๋ค์ ์น ํ์ง ์๊ธฐ ๋๋ฌธ์, ํํฐํด์ด ์์ง์ด๋ ๊ถค์ ์ด ๊ทธ๋๋ก ํ๋ฉด์ ๋์ ๋ฉ๋๋ค.
// ์ด๊ฒ์ด ์ด ์ํธ์ํฌ์ ํต์ฌ ์๊ฐ ํจ๊ณผ์
๋๋ค.
draw.background().color(hsla(0.0, 0.0, 0.02, 1.0));
}
// ๋ชจ๋ธ์ ๋ชจ๋ ํํฐํด๋ค์ ์ํํฉ๋๋ค.
for p in &model.particles {
// ๊ฐ ํํฐํด์ ํ๋ฉด์ ๊ทธ๋ฆฝ๋๋ค.
draw.ellipse() // ํ์(์)์ ๊ทธ๋ฆฌ๋ ํจ์
.x_y(p.pos.x, p.pos.y) // ํํฐํด์ ์์น์
.w_h(1.0, 1.0) // ๊ฐ๋ก, ์ธ๋ก 1.0 ํฝ์
ํฌ๊ธฐ๋ก
.color(p.col); // ํํฐํด์ ์์(ํฌ๋ช
๋๊ฐ ํฌํจ๋ ํฐ์)์ผ๋ก ๊ทธ๋ฆฝ๋๋ค.
}
// ์ง๊ธ๊น์ง ๊ทธ๋ฆฐ ๋ชจ๋ ๋ด์ฉ์ ํ๋ ์์ ์ต์ข
์ ์ผ๋ก ์ ์ฉํ์ฌ ํ๋ฉด์ ํ์ํฉ๋๋ค.
draw.to_frame(app, &frame).unwrap();
}
// Nannou ์ฝ๋๋ฅผ Processing์ผ๋ก ํฌํ
ํ ๋ฒ์ ์
๋๋ค.
// 2000๊ฐ์ ํํฐํด์ด 3D ๋
ธ์ด์ฆ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์์ฑ๋ ํ๋ฆ์ฅ(flow field)์ ๋ฐ๋ผ ์์ง์
๋๋ค.
// ํํฐํด๋ค์ ๋ด์ ArrayList
ArrayList<Particle> particles;
// ๋
ธ์ด์ฆ์ 3๋ฒ์งธ ์ฐจ์์ผ๋ก ์ฌ์ฉ๋ ์๊ฐ ๋ณ์
float time = 0;
// ํํฐํด ํด๋์ค ์ ์
// Nannou์ 'struct Particle'์ ํด๋นํฉ๋๋ค.
class Particle {
PVector pos; // ์์น (position)
PVector vel; // ์๋ (velocity)
// ์์ฑ์ (Constructor)
Particle(float x, float y) {
pos = new PVector(x, y);
vel = new PVector(0, 0); // ์ด๊ธฐ ์๋๋ 0
}
// ํํฐํด์ ์ํ๋ฅผ ์
๋ฐ์ดํธํ๋ ๋ฉ์๋
void update() {
// 3D Perlin ๋
ธ์ด์ฆ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋(angle)๋ฅผ ๊ณ์ฐํฉ๋๋ค.
// Nannou ์ฝ๋์ model.noise.get(...) * TAU ๋ถ๋ถ์ ํด๋นํฉ๋๋ค.
// pos.x * 0.004, pos.y * 0.004๋ ๋
ธ์ด์ฆ ์ค์ผ์ผ(๋ํ
์ผ)์ ๊ฒฐ์ ํฉ๋๋ค.
float angle = noise(pos.x * 0.004f, pos.y * 0.004f, time) * TWO_PI;
// ๊ณ์ฐ๋ ๊ฐ๋๋ก๋ถํฐ ๋ฐฉํฅ ๋ฒกํฐ(velocity)๋ฅผ ์์ฑํฉ๋๋ค.
vel = PVector.fromAngle(angle);
// ์์น์ ์๋๋ฅผ ๋ํด ํํฐํด์ ์ด๋์ํต๋๋ค.
pos.add(vel);
// ํํฐํด์ด ํน์ ๋ฐ๊ฒฝ(300)์ ๋ฒ์ด๋๋ฉด ์ค์ ๊ทผ์ฒ์ ์๋ก์ด ๋ฌด์์ ์์น๋ก ๋ฆฌ์
ํฉ๋๋ค.
// Nannou ์ฝ๋์ p.pos.length() > 300.0 ๋ถ๋ถ์ ํด๋นํฉ๋๋ค.
if (pos.mag() > 300) {
pos.set(random(-100, 100), random(-100, 100));
}
}
// ํํฐํด์ ํ๋ฉด์ ๊ทธ๋ฆฌ๋ ๋ฉ์๋
void display() {
// 1x1 ํฌ๊ธฐ์ ์ ์ ๊ทธ๋ฆฝ๋๋ค.
// Nannou ์ฝ๋์ draw.ellipse().w_h(1.0, 1.0)์ ํด๋นํฉ๋๋ค.
point(pos.x, pos.y);
}
}
// ์ด๊ธฐ ์ค์ ์ ์ํ setup() ํจ์
// Nannou์ model() ํจ์์ ์ ์ฌํ ์ญํ ์ ํฉ๋๋ค.
void setup() {
size(800, 800);
// ํํฐํด ArrayList ์ด๊ธฐํ
particles = new ArrayList<Particle>();
// 2000๊ฐ์ ํํฐํด ์์ฑ
for (int i = 0; i < 2000; i++) {
float x = random(-400, 400);
float y = random(-400, 400);
particles.add(new Particle(x, y));
}
// Nannou ์ฝ๋์์ ์ฒซ ํ๋ ์์๋ง ๋ฐฐ๊ฒฝ์ ๊ทธ๋ฆฌ๋ ๊ฒ๊ณผ ๋์ผํ ํจ๊ณผ๋ฅผ ์ค๋๋ค.
// ์ด๋์ด ํ์(R:5, G:5, B:5)์ผ๋ก ๋ฐฐ๊ฒฝ์ ํ ๋ฒ๋ง ์น ํด, ํํฐํด์ ๊ถค์ ์ด ๊ณ์ ๋จ๋๋ก ํฉ๋๋ค.
// hsla(0.0, 0.0, 0.02, 1.0)๋ ์ฝ RGB(5, 5, 5)์ ํด๋นํฉ๋๋ค.
background(5);
}
// ๋งค ํ๋ ์๋ง๋ค ํธ์ถ๋๋ draw() ํจ์
// Nannou์ update()์ view() ํจ์์ ์ญํ ์ ๋ชจ๋ ์ํํฉ๋๋ค.
void draw() {
// Nannou์ ๊ฐ์ด (0,0)์ ํ๋ฉด ์ค์์ผ๋ก ์ฌ์ฉํ๊ธฐ ์ํด ์ขํ๊ณ๋ฅผ ์ด๋์ํต๋๋ค.
translate(width / 2, height / 2);
// ์๊ฐ ๋ณ์ ์
๋ฐ์ดํธ
// Nannou์ (app.elapsed_frames() as f64) * 0.005 ๋ถ๋ถ์ ํด๋นํฉ๋๋ค.
time += 0.005;
// ํํฐํด์ ์์๊ณผ ๋๊ป ์ค์
// hsla(0.0, 0.0, 1.0, 0.05)๋ ํฐ์์ ์ํ๊ฐ 0.05๋ฅผ ์๋ฏธํฉ๋๋ค.
// Processing์ ์ํ๊ฐ์ 0-255 ๋ฒ์์ด๋ฏ๋ก 0.05 * 255 โ 13์ผ๋ก ๋ณํํฉ๋๋ค.
stroke(255, 13);
strokeWeight(1);
// ๋ชจ๋ ํํฐํด์ ๋ํด update์ display๋ฅผ ํธ์ถํฉ๋๋ค.
for (Particle p : particles) {
p.update();
p.display();
}
}
Nannou(Rust)์ Processing(Java)์ ๊ตฌ์กฐ์ ๋ฌธ๋ฒ์ด ๋ค๋ฅด๋ฏ๋ก, ๋ช ๊ฐ์ง ํต์ฌ์ ์ธ ๋ณํ ํฌ์ธํธ๋ฅผ ์ดํดํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
Nannou๋ model (์ด๊ธฐํ), update (์ํ ๋ณ๊ฒฝ), view (๊ทธ๋ฆฌ๊ธฐ) ํจ์๋ก ๋ช
ํํ๊ฒ ์ญํ ์ด ๋ถ๋ฆฌ๋์ด ์์ต๋๋ค.
Processing์ setup() (์ด๊ธฐํ)๊ณผ draw() (๋งค ํ๋ ์ ์ํ ๋ณ๊ฒฝ ๋ฐ ๊ทธ๋ฆฌ๊ธฐ) ํจ์๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ๋ฐ๋ผ์ Nannou์ update์ view ๋ก์ง์ด ๋ชจ๋ Processing์ draw() ํจ์ ์์ ํฌํจ๋ฉ๋๋ค.
Rust์ ๋ฐ์ดํฐ ๋ฌถ์์ธ struct Particle์ Java์ ๊ฐ์ฒด์งํฅ class Particle๋ก ๋ณํ๋์์ต๋๋ค.
ํํฐํด ๋ชฉ๋ก์ ์ ์ฅํ๋ Rust์ ๋์ ๋ฐฐ์ด Vec<Particle>์ Java์ ArrayList<Particle>๋ก ๋์ฒด๋์์ต๋๋ค. ๊ธฐ๋ฅ์ ์ผ๋ก ๊ฑฐ์ ๋์ผํ ์ญํ ์ ํฉ๋๋ค.
Nannou๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์๋์ฐ์ ์ค์์ด (0, 0) ์ ๋๋ค.
Processing์ ๊ธฐ๋ณธ์ ์ผ๋ก ์๋์ฐ์ ์ข์ธก ์๋จ์ด (0, 0) ์ ๋๋ค.
์๋ณธ๊ณผ ๋์ผํ ์๊ฐ์ ๊ฒฐ๊ณผ๋ฌผ์ ์ป๊ธฐ ์ํด Processing์ draw() ํจ์ ์์ ๋ถ๋ถ์ translate(width / 2, height / 2);๋ฅผ ์ถ๊ฐํ์ฌ ์ขํ๊ณ์ ์์ ์ ํ๋ฉด ์ค์์ผ๋ก ์ด๋์์ผฐ์ต๋๋ค.
Vec2๋ Processing์ ๋ด์ฅ ๋ฒกํฐ ํด๋์ค์ธ PVector๋ก ๋์ฒด๋์์ต๋๋ค. PVector๋ ์์น, ์๋ ๋ฑ์ ๋ค๋ฃจ๋ ๋ฐ ํ์ํ ๋ค์ํ ๋ฉ์๋(add, mag, fromAngle ๋ฑ)๋ฅผ ์ ๊ณตํ์ฌ ๋งค์ฐ ํธ๋ฆฌํฉ๋๋ค.Nannou์์๋ Perlin ๋
ธ์ด์ฆ ๊ฐ์ฒด๋ฅผ ์ง์ ์์ฑํด์ ์ฌ์ฉํ์ง๋ง, Processing์ noise() ํจ์๋ฅผ ๋ด์ฅํ๊ณ ์์ด ๋ณ๋์ ๊ฐ์ฒด ์์ฑ ์์ด ๋ฐ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
์๋ณธ ์ฝ๋์ 3์ฐจ์ ๋
ธ์ด์ฆ noise.get([x, y, time])๋ Processing์ noise(x, y, time)์ผ๋ก ๊ฐ๋จํ๊ฒ ๋ณํ๋ฉ๋๋ค.
๊ถค์ ํจ๊ณผ: Nannou ์ฝ๋์์๋ ์ฒซ ํ๋ ์์๋ง draw.background()๋ฅผ ํธ์ถํ์ฌ ํํฐํด์ ๊ถค์ ์ด ๊ณ์ ๋จ๋๋ก ํ์ต๋๋ค. Processing์์๋ background()๋ฅผ draw()๊ฐ ์๋ setup()์ ํ ๋ฒ๋ง ํธ์ถํ์ฌ ๋์ผํ ํจ๊ณผ๋ฅผ ๊ตฌํํ์ต๋๋ค.
์์ ํํ: Nannou์ hsla(h, s, l, a) ์์๊ฐ์ 0.0์์ 1.0 ์ฌ์ด์ ์ค์๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์๋ณธ์ hsla(0.0, 0.0, 1.0, 0.05)๋ '์ฑ๋ 0, ๋ฐ๊ธฐ 100%'์ด๋ฏ๋ก ํฐ์์ด๋ฉฐ, ์ํ(ํฌ๋ช
๋)๋ 5%์
๋๋ค. ์ด๋ฅผ Processing์ stroke(gray, alpha)๋ก ๋ณํํ์ต๋๋ค. ์์์ 255 (ํฐ์), ์ํ๊ฐ์ 0.05 * 255, ์ฆ ์ฝ 13์ด ๋ฉ๋๋ค.