|
8 | 8 | // option. This file may not be copied, modified, or distributed
|
9 | 9 | // except according to those terms.
|
10 | 10 |
|
11 |
| -// Multi-language Perlin noise benchmark. |
12 |
| -// See https://github.com/nsf/pnoise for timings and alternative implementations. |
| 11 | +// Perlin noise benchmark from https://gist.github.com/1170424 |
13 | 12 |
|
14 |
| -use std::f32::consts::PI; |
15 |
| -use std::rand::{Rng, StdRng}; |
| 13 | +use std::f64; |
| 14 | +use std::rand::Rng; |
| 15 | +use std::rand; |
16 | 16 |
|
17 | 17 | struct Vec2 {
|
18 | 18 | x: f32,
|
19 | 19 | y: f32,
|
20 | 20 | }
|
21 | 21 |
|
| 22 | +#[inline(always)] |
22 | 23 | fn lerp(a: f32, b: f32, v: f32) -> f32 { a * (1.0 - v) + b * v }
|
23 | 24 |
|
| 25 | +#[inline(always)] |
24 | 26 | fn smooth(v: f32) -> f32 { v * v * (3.0 - 2.0 * v) }
|
25 | 27 |
|
26 |
| -fn random_gradient<R: Rng>(r: &mut R) -> Vec2 { |
27 |
| - let v = PI * 2.0 * r.gen(); |
28 |
| - Vec2 { x: v.cos(), y: v.sin() } |
| 28 | +fn random_gradient<R:Rng>(r: &mut R) -> Vec2 { |
| 29 | + let v = 2.0 * f64::consts::PI * r.gen(); |
| 30 | + Vec2 { |
| 31 | + x: v.cos() as f32, |
| 32 | + y: v.sin() as f32, |
| 33 | + } |
29 | 34 | }
|
30 | 35 |
|
31 | 36 | fn gradient(orig: Vec2, grad: Vec2, p: Vec2) -> f32 {
|
32 |
| - (p.x - orig.x) * grad.x + (p.y - orig.y) * grad.y |
| 37 | + let sp = Vec2 {x: p.x - orig.x, y: p.y - orig.y}; |
| 38 | + grad.x * sp.x + grad.y * sp.y |
33 | 39 | }
|
34 | 40 |
|
35 | 41 | struct Noise2DContext {
|
36 | 42 | rgradients: [Vec2, ..256],
|
37 |
| - permutations: [i32, ..256], |
| 43 | + permutations: [int, ..256], |
38 | 44 | }
|
39 | 45 |
|
40 | 46 | impl Noise2DContext {
|
41 |
| - fn new() -> Noise2DContext { |
42 |
| - let mut rng = StdRng::new(); |
43 |
| - |
44 |
| - let mut rgradients = [Vec2 { x: 0.0, y: 0.0 }, ..256]; |
45 |
| - for x in rgradients.mut_iter() { |
46 |
| - *x = random_gradient(&mut rng); |
| 47 | + pub fn new() -> Noise2DContext { |
| 48 | + let mut r = rand::rng(); |
| 49 | + let mut rgradients = [ Vec2 { x: 0.0, y: 0.0 }, ..256 ]; |
| 50 | + for i in range(0, 256) { |
| 51 | + rgradients[i] = random_gradient(&mut r); |
47 | 52 | }
|
48 |
| - |
49 |
| - let mut permutations = [0i32, ..256]; |
50 |
| - for (i, x) in permutations.mut_iter().enumerate() { |
51 |
| - *x = i as i32; |
| 53 | + let mut permutations = [ 0, ..256 ]; |
| 54 | + for i in range(0, 256) { |
| 55 | + permutations[i] = i; |
52 | 56 | }
|
53 |
| - rng.shuffle_mut(permutations); |
| 57 | + r.shuffle_mut(permutations); |
54 | 58 |
|
55 |
| - Noise2DContext { rgradients: rgradients, permutations: permutations } |
| 59 | + Noise2DContext { |
| 60 | + rgradients: rgradients, |
| 61 | + permutations: permutations, |
| 62 | + } |
56 | 63 | }
|
57 | 64 |
|
58 |
| - fn get_gradient(&self, x: i32, y: i32) -> Vec2 { |
| 65 | + #[inline(always)] |
| 66 | + pub fn get_gradient(&self, x: int, y: int) -> Vec2 { |
59 | 67 | let idx = self.permutations[x & 255] + self.permutations[y & 255];
|
60 | 68 | self.rgradients[idx & 255]
|
61 | 69 | }
|
62 | 70 |
|
63 |
| - fn get_gradients(&self, x: f32, y: f32) -> ([Vec2, ..4], [Vec2, ..4]) { |
| 71 | + #[inline] |
| 72 | + pub fn get_gradients(&self, |
| 73 | + gradients: &mut [Vec2, ..4], |
| 74 | + origins: &mut [Vec2, ..4], |
| 75 | + x: f32, |
| 76 | + y: f32) { |
64 | 77 | let x0f = x.floor();
|
65 | 78 | let y0f = y.floor();
|
66 |
| - let x1f = x0f + 1.0; |
67 |
| - let y1f = y0f + 1.0; |
68 |
| - |
69 |
| - let x0 = x0f as i32; |
70 |
| - let y0 = y0f as i32; |
| 79 | + let x0 = x0f as int; |
| 80 | + let y0 = y0f as int; |
71 | 81 | let x1 = x0 + 1;
|
72 | 82 | let y1 = y0 + 1;
|
73 | 83 |
|
74 |
| - ([self.get_gradient(x0, y0), self.get_gradient(x1, y0), |
75 |
| - self.get_gradient(x0, y1), self.get_gradient(x1, y1)], |
76 |
| - [Vec2 { x: x0f, y: y0f }, Vec2 { x: x1f, y: y0f }, |
77 |
| - Vec2 { x: x0f, y: y1f }, Vec2 { x: x1f, y: y1f }]) |
| 84 | + gradients[0] = self.get_gradient(x0, y0); |
| 85 | + gradients[1] = self.get_gradient(x1, y0); |
| 86 | + gradients[2] = self.get_gradient(x0, y1); |
| 87 | + gradients[3] = self.get_gradient(x1, y1); |
| 88 | + |
| 89 | + origins[0] = Vec2 {x: x0f + 0.0, y: y0f + 0.0}; |
| 90 | + origins[1] = Vec2 {x: x0f + 1.0, y: y0f + 0.0}; |
| 91 | + origins[2] = Vec2 {x: x0f + 0.0, y: y0f + 1.0}; |
| 92 | + origins[3] = Vec2 {x: x0f + 1.0, y: y0f + 1.0}; |
78 | 93 | }
|
79 | 94 |
|
80 |
| - fn get(&self, x: f32, y: f32) -> f32 { |
| 95 | + #[inline] |
| 96 | + pub fn get(&self, x: f32, y: f32) -> f32 { |
81 | 97 | let p = Vec2 {x: x, y: y};
|
82 |
| - let (gradients, origins) = self.get_gradients(x, y); |
83 |
| - |
| 98 | + let mut gradients = [ Vec2 { x: 0.0, y: 0.0 }, ..4 ]; |
| 99 | + let mut origins = [ Vec2 { x: 0.0, y: 0.0 }, ..4 ]; |
| 100 | + self.get_gradients(&mut gradients, &mut origins, x, y); |
84 | 101 | let v0 = gradient(origins[0], gradients[0], p);
|
85 | 102 | let v1 = gradient(origins[1], gradients[1], p);
|
86 | 103 | let v2 = gradient(origins[2], gradients[2], p);
|
87 | 104 | let v3 = gradient(origins[3], gradients[3], p);
|
88 |
| - |
89 | 105 | let fx = smooth(x - origins[0].x);
|
90 | 106 | let vx0 = lerp(v0, v1, fx);
|
91 | 107 | let vx1 = lerp(v2, v3, fx);
|
92 | 108 | let fy = smooth(y - origins[0].y);
|
93 |
| - |
94 | 109 | lerp(vx0, vx1, fy)
|
95 | 110 | }
|
96 | 111 | }
|
97 | 112 |
|
98 | 113 | fn main() {
|
99 |
| - let symbols = [' ', '░', '▒', '▓', '█', '█']; |
| 114 | + let symbols = [" ", "░", "▒", "▓", "█", "█"]; |
100 | 115 | let mut pixels = [0f32, ..256*256];
|
101 |
| - let n2d = Noise2DContext::new(); |
102 |
| - |
103 |
| - for _ in range(0, 100) { |
| 116 | + let n2d = ~Noise2DContext::new(); |
| 117 | + for _ in range(0, 100u) { |
104 | 118 | for y in range(0, 256) {
|
105 | 119 | for x in range(0, 256) {
|
106 |
| - let v = n2d.get(x as f32 * 0.1, y as f32 * 0.1); |
107 |
| - pixels[y*256+x] = v * 0.5 + 0.5; |
108 |
| - } |
109 |
| - } |
110 |
| - } |
| 120 | + let v = n2d.get( |
| 121 | + x as f32 * 0.1f32, |
| 122 | + y as f32 * 0.1f32 |
| 123 | + ) * 0.5f32 + 0.5f32; |
| 124 | + pixels[y*256+x] = v; |
| 125 | + }; |
| 126 | + }; |
| 127 | + }; |
111 | 128 |
|
112 | 129 | for y in range(0, 256) {
|
113 | 130 | for x in range(0, 256) {
|
114 |
| - let idx = (pixels[y*256+x] / 0.2) as uint; |
115 |
| - print!("{:c}", symbols[idx]); |
| 131 | + print!("{}", symbols[(pixels[y*256+x] / 0.2f32) as int]); |
116 | 132 | }
|
117 |
| - print!("\n"); |
| 133 | + println!(""); |
118 | 134 | }
|
119 | 135 | }
|
0 commit comments