1 // Perlin noise benchmark from https://gist.github.com/1170424
5 use std::rand::{Rng, RngUtil};
14 fn lerp(a: f32, b: f32, v: f32) -> f32 { a * (1.0 - v) + b * v }
17 fn smooth(v: f32) -> f32 { v * v * (3.0 - 2.0 * v) }
19 fn random_gradient<R:Rng>(r: &mut R) -> Vec2 {
20 let v = 2.0 * float::consts::pi * r.gen();
27 fn gradient(orig: Vec2, grad: Vec2, p: Vec2) -> f32 {
28 let sp = Vec2 {x: p.x - orig.x, y: p.y - orig.y};
29 grad.x * sp.x + grad.y + sp.y
32 struct Noise2DContext {
33 rgradients: [Vec2, ..256],
34 permutations: [int, ..256],
38 pub fn new() -> Noise2DContext {
39 let mut r = rand::rng();
40 let mut rgradients = [ Vec2 { x: 0.0, y: 0.0 }, ..256 ];
41 for i in range(0, 256) {
42 rgradients[i] = random_gradient(&mut r);
44 let mut permutations = [ 0, ..256 ];
45 for i in range(0, 256) {
48 r.shuffle_mut(permutations);
51 rgradients: rgradients,
52 permutations: permutations,
57 pub fn get_gradient(&self, x: int, y: int) -> Vec2 {
58 let idx = self.permutations[x & 255] + self.permutations[y & 255];
59 self.rgradients[idx & 255]
63 pub fn get_gradients(&self,
64 gradients: &mut [Vec2, ..4],
65 origins: &mut [Vec2, ..4],
75 gradients[0] = self.get_gradient(x0, y0);
76 gradients[1] = self.get_gradient(x1, y0);
77 gradients[2] = self.get_gradient(x0, y1);
78 gradients[3] = self.get_gradient(x1, y1);
80 origins[0] = Vec2 {x: x0f + 0.0, y: y0f + 0.0};
81 origins[1] = Vec2 {x: x0f + 1.0, y: y0f + 0.0};
82 origins[2] = Vec2 {x: x0f + 0.0, y: y0f + 1.0};
83 origins[3] = Vec2 {x: x0f + 1.0, y: y0f + 1.0};
87 pub fn get(&self, x: f32, y: f32) -> f32 {
88 let p = Vec2 {x: x, y: y};
89 let mut gradients = [ Vec2 { x: 0.0, y: 0.0 }, ..4 ];
90 let mut origins = [ Vec2 { x: 0.0, y: 0.0 }, ..4 ];
91 self.get_gradients(&mut gradients, &mut origins, x, y);
92 let v0 = gradient(origins[0], gradients[0], p);
93 let v1 = gradient(origins[1], gradients[1], p);
94 let v2 = gradient(origins[2], gradients[2], p);
95 let v3 = gradient(origins[3], gradients[3], p);
96 let fx = smooth(x - origins[0].x);
97 let vx0 = lerp(v0, v1, fx);
98 let vx1 = lerp(v2, v3, fx);
99 let fy = smooth(y - origins[0].y);
105 let symbols = [" ", "░", "▒", "▓", "█", "█"];
106 let mut pixels = [0f32, ..256*256];
107 let n2d = ~Noise2DContext::new();
109 for y in range(0, 256) {
110 for x in range(0, 256) {
120 for y in range(0, 256) {
121 for x in range(0, 256) {
122 print(symbols[(pixels[y*256+x] / 0.2f32) as int]);