Created
October 19, 2012 20:42
-
-
Save bstrie/3920608 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct Vec2 { | |
x: f32, | |
y: f32, | |
} | |
#[inline(always)] | |
fn lerp(a: f32, b: f32, v: f32) -> f32 { | |
a * (1f32 - v) + b * v | |
} | |
#[inline(always)] | |
fn smooth(v: f32) -> f32 { | |
v * v * (3f32 - 2f32 * v) | |
} | |
#[inline(always)] | |
fn random_gradient(r: rand::Rng) -> Vec2 { | |
let v = r.gen_float() * float::consts::pi * 2.0; | |
Vec2{ | |
x: float::cos(v) as f32, | |
y: float::sin(v) as f32, | |
} | |
} | |
#[inline(always)] | |
fn gradient(orig: Vec2, grad: Vec2, p: Vec2) -> f32 { | |
let sp = Vec2{x: p.x - orig.x, y: p.y - orig.y}; | |
grad.x * sp.x + grad.y + sp.y | |
} | |
struct Noise2DContext { | |
rgradients: ~[Vec2], | |
permutations: ~[int], | |
} | |
#[inline(always)] | |
fn Noise2DContext() -> ~Noise2DContext { | |
let r = rand::Rng(); | |
let rgradients = do vec::from_fn(256) |_i| { random_gradient(r) }; | |
let mut permutations = do vec::from_fn(256) |i| { i as int }; | |
r.shuffle_mut(permutations); | |
~Noise2DContext{ | |
rgradients: move rgradients, | |
permutations: move permutations, | |
} | |
} | |
impl Noise2DContext { | |
#[inline(always)] | |
fn get_gradient(x: int, y: int) -> Vec2 { | |
let idx = self.permutations[x & 255] + self.permutations[y & 255]; | |
self.rgradients[idx & 255] | |
} | |
#[inline(always)] | |
fn get_gradients(gradients: &[mut Vec2 * 4], origins: &[mut Vec2 * 4], x: f32, y: f32) { | |
let x0f = float::floor(x as libc::c_double) as f32; | |
let y0f = float::floor(y as libc::c_double) as f32; | |
let x0 = x0f as int; | |
let y0 = y0f as int; | |
let x1 = x0 + 1; | |
let y1 = y0 + 1; | |
gradients[0] = self.get_gradient(x0, y0); | |
gradients[1] = self.get_gradient(x1, y0); | |
gradients[2] = self.get_gradient(x0, y1); | |
gradients[3] = self.get_gradient(x1, y1); | |
origins[0] = Vec2{x: x0f + 0f32, y: y0f + 0f32}; | |
origins[1] = Vec2{x: x0f + 1f32, y: y0f + 0f32}; | |
origins[2] = Vec2{x: x0f + 0f32, y: y0f + 1f32}; | |
origins[3] = Vec2{x: x0f + 1f32, y: y0f + 1f32}; | |
} | |
#[inline(always)] | |
fn get(x: f32, y: f32) -> f32 { | |
let p = Vec2{x: x, y: y}; | |
let gradients: [mut Vec2 * 4] = [mut | |
Vec2{x:0f32, y:0f32}, | |
Vec2{x:0f32, y:0f32}, | |
Vec2{x:0f32, y:0f32}, | |
Vec2{x:0f32, y:0f32}, | |
]; | |
let origins: [mut Vec2 * 4] = [mut | |
Vec2{x:0f32, y:0f32}, | |
Vec2{x:0f32, y:0f32}, | |
Vec2{x:0f32, y:0f32}, | |
Vec2{x:0f32, y:0f32}, | |
]; | |
self.get_gradients(&gradients, &origins, x, y); | |
let v0 = gradient(origins[0], gradients[0], p); | |
let v1 = gradient(origins[1], gradients[1], p); | |
let v2 = gradient(origins[2], gradients[2], p); | |
let v3 = gradient(origins[3], gradients[3], p); | |
let fx = smooth(x - origins[0].x); | |
let vx0 = lerp(v0, v1, fx); | |
let vx1 = lerp(v2, v3, fx); | |
let fy = smooth(y - origins[0].y); | |
lerp(vx0, vx1, fy) | |
} | |
} | |
fn main() { | |
let symbols = [" ", "░", "▒", "▓", "█", "█"]; | |
let pixels = vec::to_mut(vec::from_elem(256*256, 0f32)); | |
let n2d = Noise2DContext(); | |
for 100.times { | |
for int::range(0, 256) |y| { | |
for int::range(0, 256) |x| { | |
let v = n2d.get( | |
x as f32 * 0.1f32, | |
y as f32 * 0.1f32 | |
) * 0.5f32 + 0.5f32; | |
pixels[y*256+x] = v; | |
}; | |
}; | |
}; | |
// for int::range(0, 256) |y| { | |
// for int::range(0, 256) |x| { | |
// io::print(symbols[pixels[y*256+x] / 0.2f32 as int]); | |
// } | |
// io::println(""); | |
// } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment