]> git.lizzy.rs Git - rust.git/blob - src/test/bench/noise.rs
auto merge of #8350 : dim-an/rust/fix-struct-match, r=pcwalton
[rust.git] / src / test / bench / noise.rs
1 // Perlin noise benchmark from https://gist.github.com/1170424
2
3 use std::float;
4 use std::int;
5 use std::rand::{Rng, RngUtil};
6 use std::rand;
7
8 struct Vec2 {
9     x: f32,
10     y: f32,
11 }
12
13 #[inline(always)]
14 fn lerp(a: f32, b: f32, v: f32) -> f32 { a * (1.0 - v) + b * v }
15
16 #[inline(always)]
17 fn smooth(v: f32) -> f32 { v * v * (3.0 - 2.0 * v) }
18
19 fn random_gradient<R:Rng>(r: &mut R) -> Vec2 {
20     let v = 2.0 * float::consts::pi * r.gen();
21     Vec2 {
22         x: v.cos() as f32,
23         y: v.sin() as f32,
24     }
25 }
26
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
30 }
31
32 struct Noise2DContext {
33     rgradients: [Vec2, ..256],
34     permutations: [int, ..256],
35 }
36
37 impl Noise2DContext {
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);
43         }
44         let mut permutations = [ 0, ..256 ];
45         for i in range(0, 256) {
46             permutations[i] = i;
47         }
48         r.shuffle_mut(permutations);
49
50         Noise2DContext {
51             rgradients: rgradients,
52             permutations: permutations,
53         }
54     }
55
56     #[inline(always)]
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]
60     }
61
62     #[inline]
63     pub fn get_gradients(&self,
64                          gradients: &mut [Vec2, ..4],
65                          origins: &mut [Vec2, ..4],
66                          x: f32,
67                          y: f32) {
68         let x0f = x.floor();
69         let y0f = y.floor();
70         let x0 = x0f as int;
71         let y0 = y0f as int;
72         let x1 = x0 + 1;
73         let y1 = y0 + 1;
74
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);
79
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};
84     }
85
86     #[inline]
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);
100         lerp(vx0, vx1, fy)
101     }
102 }
103
104 fn main() {
105     let symbols = [" ", "░", "▒", "▓", "█", "█"];
106     let mut pixels = [0f32, ..256*256];
107     let n2d = ~Noise2DContext::new();
108     for _ in range(0, 100u) {
109         for y in range(0, 256) {
110             for x in range(0, 256) {
111                 let v = n2d.get(
112                     x as f32 * 0.1f32,
113                     y as f32 * 0.1f32
114                 ) * 0.5f32 + 0.5f32;
115                 pixels[y*256+x] = v;
116             };
117         };
118     };
119
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]);
123         }
124         println("");
125     }
126 }