๐Ÿ”ฎ :: Perlin Noise Flow 1

BamgasiJMยท2025๋…„ 9์›” 17์ผ

Nannou <Generative Art>

๋ชฉ๋ก ๋ณด๊ธฐ
14/55
post-thumbnail

๐Ÿ“ Rust Code

use nannou::noise::{NoiseFn, Perlin};
use nannou::prelude::*;

// ํŒŒํ‹ฐํด(๋ผ์ธ์˜ ์‹œ์ž‘์  ์—ญํ• ์„ ํ•˜๋Š” ์ ) ๊ตฌ์กฐ์ฒด
struct Particle {
    position: Vec2, // ํ˜„์žฌ ์œ„์น˜
    history: Vec<Vec2>, // ์ด๋™ ๊ถค์ ์„ ์ €์žฅ
}

struct Model {
    particles: Vec<Particle>, // ํŒŒํ‹ฐํด ์ง‘ํ•ฉ
    perlin: Perlin,           // Perlin Noise ํ•จ์ˆ˜
}

fn main() {
    nannou::app(model).update(update).run();
}

// ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜
fn model(app: &App) -> Model {
    // 800 x 800 ์œˆ๋„์šฐ ์ƒ์„ฑ
    app.new_window()
        .size(800, 800)
        .view(view)
        .build()
        .unwrap();

    let mut particles = Vec::new();
    let perlin = Perlin::new();

    // ๋žœ๋คํ•˜๊ฒŒ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํŒŒํ‹ฐํด์„ ์ƒ์„ฑ
    for _ in 0..2000 {
        let x = random_range(-400.0, 400.0);
        let y = random_range(-400.0, 400.0);
        particles.push(Particle {
            position: vec2(x, y),
            history: Vec::new(),
        });
    }

    Model { particles, perlin }
}

// ๋งค ํ”„๋ ˆ์ž„๋งˆ๋‹ค ์—…๋ฐ์ดํŠธ
// ๊ฐ ํŒŒํ‹ฐํด์ด noise ํ•„๋“œ์˜ ๋ฐฉํ–ฅ์„ ๋”ฐ๋ผ ์กฐ๊ธˆ์”ฉ ์›€์ง์ด๊ณ , ๊ทธ ๊ถค์ ์„ history์— ์ €์žฅ
fn update(app: &App, model: &mut Model, _update: Update) {
    let time = app.elapsed_frames() as f64 * 0.01;

    for particle in model.particles.iter_mut() {
        // Perlin noise๋ฅผ ์ด์šฉํ•ด ๋ฐฉํ–ฅ ๊ณ„์‚ฐ
        // ์ขŒํ‘œ์™€ ์‹œ๊ฐ„๊ฐ’์„ ์ž…๋ ฅ๋ฐ›์•„ -1.0 ~ 1.0 ์‚ฌ์ด์˜ ๊ฐ’์„ ๋ฐ˜ํ™˜
        let noise_val = model
            .perlin
            .get([particle.position.x as f64 * 0.02, particle.position.y as f64 * 0.02, time]);

        // noise_val (-1 ~ 1)์„ ๊ฐ๋„๋กœ ๋ณ€ํ™˜
        let angle = map_range(noise_val, -1.0, 1.0, 0.0, TAU);

        // ๋ฐฉํ–ฅ ๋ฒกํ„ฐ
        let direction = vec2(angle.cos(), angle.sin());

        // ์†๋„
        let step = 5.0;

        // ์œ„์น˜ ์—…๋ฐ์ดํŠธ
        particle.position += direction * step;

        // history์— ์œ„์น˜ ์ €์žฅ (๊ธธ์ด๋ฅผ ์ œํ•œ)
        particle.history.push(particle.position);
        if particle.history.len() > 50 {
            particle.history.remove(0);
        }
    }
}

// ํ™”๋ฉด ๊ทธ๋ฆฌ๊ธฐ
// ์ €์žฅ๋œ ๊ถค์ ์„ polyline์œผ๋กœ ์ด์–ด์„œ ๋ผ์ธ ์•„ํŠธ๋ฅผ ๊ทธ๋ฆผ
fn view(app: &App, model: &Model, frame: Frame) {
    let draw = app.draw();

    // ๋งค ํ”„๋ ˆ์ž„ ๋ฐฐ๊ฒฝ์„ ์•„์ฃผ ์‚ด์ง ํˆฌ๋ช…ํ•˜๊ฒŒ ๋ฎ์–ด์„œ "์ž”์ƒ ํšจ๊ณผ" ๋งŒ๋“ค๊ธฐ
    draw.rect()
        .wh(app.window_rect().wh())
        .color(srgba(0.0, 0.0, 0.0, 0.05));

    // ํŒŒํ‹ฐํด์˜ ๊ถค์ ์„ ๋ผ์ธ์œผ๋กœ ๊ทธ๋ฆผ
    for particle in &model.particles {
        if particle.history.len() > 1 {
            draw.polyline()
                .weight(0.5)
                .points(particle.history.clone())
                .color(WHITE);
        }
    }

    draw.to_frame(app, &frame).unwrap();
}

profile
Coding Art with Blender / oF / Processing / p5.js / nannou

0๊ฐœ์˜ ๋Œ“๊ธ€