Skip to content

Commit afcecf1

Browse files
committed
Reorganize, clean up noise
1 parent 7d54803 commit afcecf1

File tree

1 file changed

+130
-131
lines changed

1 file changed

+130
-131
lines changed

core/src/math/noise.rs

Lines changed: 130 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1,111 +1,12 @@
1-
//! Two- and three-dimensional Perlin noise.
1+
//! Procedural noise generation.
22
33
use super::{
44
spline::smoothstep,
55
vary::lerp,
66
vec::{splat, vec2, vec3, Vec2, Vec3, Vector},
77
};
88

9-
/// Gradient vectors for 2D noise.
10-
static GRADS_2: [Vec2; 8] = [
11-
vec2(0.924, 0.383),
12-
vec2(0.383, 0.924),
13-
vec2(-0.383, 0.924),
14-
vec2(-0.924, 0.383),
15-
vec2(-0.924, -0.383),
16-
vec2(-0.383, -0.924),
17-
vec2(0.383, -0.924),
18-
vec2(0.924, -0.383),
19-
];
20-
21-
/// Gradient vectors for 3D noise.
22-
static GRADS_3: [Vec3; 16] = [
23-
//
24-
vec3(0.0, -1.0, -1.0),
25-
vec3(0.0, -1.0, 1.0),
26-
vec3(0.0, 1.0, -1.0),
27-
vec3(0.0, 1.0, 1.0),
28-
//
29-
vec3(-1.0, 0.0, -1.0),
30-
vec3(-1.0, 0.0, 1.0),
31-
vec3(1.0, 0.0, -1.0),
32-
vec3(1.0, 0.0, 1.0),
33-
//
34-
vec3(-1.0, -1.0, 0.0),
35-
vec3(-1.0, 1.0, 0.0),
36-
vec3(1.0, -1.0, 0.0),
37-
vec3(1.0, 1.0, 0.0),
38-
//
39-
vec3(1.0, 1.0, 0.0),
40-
vec3(-1.0, 1.0, 0.0),
41-
vec3(0.0, -1.0, 1.0),
42-
vec3(0.0, -1.0, -1.0),
43-
];
44-
45-
#[rustfmt::skip]
46-
static PERM: [u8; 256] = [
47-
156, 2, 157, 90, 75, 199, 55, 167, 62, 92, 101, 253, 66, 134, 113, 83,
48-
1, 136, 78, 106, 254, 105, 248, 176, 234, 5, 195, 226, 49, 71, 87, 44,
49-
122, 94, 219, 140, 72, 159, 237, 212, 8, 162, 200, 124, 125, 69, 165, 74,
50-
245, 42, 89, 216, 158, 108, 238, 184, 217, 73, 126, 210, 14, 111, 19, 188,
51-
186, 45, 38, 223, 35, 112, 214, 26, 145, 95, 99, 193, 250, 189, 152, 182,
52-
166, 247, 148, 213, 168, 70, 96, 249, 127, 132, 4, 137, 41, 60, 102, 28,
53-
27, 240, 227, 155, 211, 230, 9, 80, 178, 3, 68, 153, 143, 84, 179, 181,
54-
12, 97, 103, 16, 225, 146, 63, 82, 203, 175, 163, 147, 11, 116, 185, 215,
55-
57, 120, 208, 129, 115, 198, 37, 201, 39, 98, 20, 183, 56, 118, 109, 142,
56-
138, 65, 117, 114, 160, 25, 43, 191, 204, 161, 22, 251, 139, 79, 131, 231,
57-
76, 0, 205, 206, 244, 51, 174, 13, 110, 85, 209, 77, 64, 53, 48, 221,
58-
133, 93, 224, 24, 33, 164, 23, 47, 171, 128, 243, 18, 52, 119, 149, 100,
59-
246, 233, 31, 192, 252, 190, 15, 172, 91, 229, 144, 54, 61, 58, 220, 36,
60-
222, 29, 50, 88, 121, 173, 232, 194, 239, 197, 32, 180, 107, 46, 7, 130,
61-
169, 81, 218, 67, 21, 170, 187, 59, 86, 235, 154, 123, 150, 177, 135, 228,
62-
104, 242, 6, 151, 255, 34, 30, 141, 202, 196, 236, 207, 241, 40, 17, 10
63-
];
64-
65-
fn perm(x: i32) -> i32 {
66-
PERM[(x & 0xFF) as usize] as i32
67-
}
68-
69-
fn grad2(x: f32, y: f32) -> Vec2 {
70-
let perm = perm(x as i32 + perm(y as i32));
71-
GRADS_2[perm as usize & 0x7]
72-
}
73-
74-
fn grads2(pt: Vec2) -> [Vec2; 4] {
75-
use super::float::f32;
76-
let [x0, y0] = pt.map(f32::floor).0;
77-
78-
let g00 = grad2(x0, y0);
79-
let g01 = grad2(x0, y0 + 1.0);
80-
let g10 = grad2(x0 + 1.0, y0);
81-
let g11 = grad2(x0 + 1.0, y0 + 1.0);
82-
83-
[g00, g01, g10, g11]
84-
}
85-
86-
fn grad3(x: f32, y: f32, z: f32) -> Vec3 {
87-
let perm = perm(x as i32 + perm(y as i32 + perm(z as i32)));
88-
GRADS_3[perm as usize & 0xF]
89-
}
90-
91-
fn grads3(pt0: Vec3) -> [Vec3; 8] {
92-
use super::float::f32;
93-
let pt1 = pt0 + splat(1.0);
94-
let [x0, y0, z0] = pt0.0;
95-
let [x1, y1, z1] = pt1.0;
96-
97-
let g000 = grad3(x0, y0, z0);
98-
let g001 = grad3(x0, y0, z1);
99-
let g010 = grad3(x0, y1, z0);
100-
let g011 = grad3(x0, y1, z1);
101-
let g100 = grad3(x1, y0, z0);
102-
let g101 = grad3(x1, y0, z1);
103-
let g110 = grad3(x1, y1, z0);
104-
let g111 = grad3(x1, y1, z1);
105-
106-
[g000, g001, g010, g011, g100, g101, g110, g111]
107-
}
108-
9+
/// Returns the Perlin noise value corresponding to the 2D point.
10910
pub fn perlin2(pt: Vec2) -> f32 {
11011
use super::float::f32;
11112
let f = pt - pt.map(f32::floor);
@@ -123,6 +24,10 @@ pub fn perlin2(pt: Vec2) -> f32 {
12324
lerp(t.y(), a, b)
12425
}
12526

27+
/// Returns the Perlin gradient vector corresponding to the 2D point.
28+
///
29+
/// The vector is computed by taking the gradient vectors of all four
30+
/// surrounding grid points and smoothly interpolating between them.
12631
pub fn perlin2v(pt: Vec2) -> Vec2 {
12732
use super::float::f32;
12833
let fract = pt - pt.map(f32::floor);
@@ -134,6 +39,7 @@ pub fn perlin2v(pt: Vec2) -> Vec2 {
13439
lerp(t.y(), a, b)
13540
}
13641

42+
/// Returns the Perlin noise value corresponding to the 3D point.
13743
pub fn perlin3(pt: Vec3) -> f32 {
13844
use super::float::f32;
13945
let pt0 = pt.map(f32::floor);
@@ -163,6 +69,10 @@ pub fn perlin3(pt: Vec3) -> f32 {
16369
lerp(t.z(), z0, z1)
16470
}
16571

72+
/// Returns the Perlin gradient vector corresponding to the 3D point.
73+
///
74+
/// The vector is computed by taking the gradient vectors of all four
75+
/// surrounding grid points and smoothly interpolating between them.
16676
pub fn perlin3v(pt: Vec3) -> Vec3 {
16777
use super::float::f32;
16878
let fract = pt - pt.map(f32::floor);
@@ -178,35 +88,124 @@ pub fn perlin3v(pt: Vec3) -> Vec3 {
17888
lerp(t.z(), z0, z1)
17989
}
18090

91+
fn perm(x: i32) -> i32 {
92+
PERM[(x & 0xFF) as usize] as i32
93+
}
94+
95+
fn grad2(x: f32, y: f32) -> Vec2 {
96+
let perm = perm(x as i32 + perm(y as i32));
97+
GRADS_2[perm as usize & 0x7]
98+
}
99+
100+
fn grads2(pt: Vec2) -> [Vec2; 4] {
101+
use super::float::f32;
102+
let [x0, y0] = pt.map(f32::floor).0;
103+
104+
let g00 = grad2(x0, y0);
105+
let g01 = grad2(x0, y0 + 1.0);
106+
let g10 = grad2(x0 + 1.0, y0);
107+
let g11 = grad2(x0 + 1.0, y0 + 1.0);
108+
109+
[g00, g01, g10, g11]
110+
}
111+
112+
fn grad3(x: f32, y: f32, z: f32) -> Vec3 {
113+
let perm = perm(x as i32 + perm(y as i32 + perm(z as i32)));
114+
GRADS_3[perm as usize & 0xF]
115+
}
116+
117+
fn grads3(pt0: Vec3) -> [Vec3; 8] {
118+
let pt1 = pt0 + splat(1.0);
119+
let [x0, y0, z0] = pt0.0;
120+
let [x1, y1, z1] = pt1.0;
121+
122+
//
123+
// 011 +--------------+ 111
124+
// / | / |
125+
// / | / |
126+
// 010 +--------------+ 110 |
127+
// | | | |
128+
// | +--------|-----+ 101
129+
// | / | /
130+
// | / | /
131+
// 000 +--------------+ 100
132+
//
133+
134+
let g000 = grad3(x0, y0, z0);
135+
let g001 = grad3(x0, y0, z1);
136+
let g010 = grad3(x0, y1, z0);
137+
let g011 = grad3(x0, y1, z1);
138+
let g100 = grad3(x1, y0, z0);
139+
let g101 = grad3(x1, y0, z1);
140+
let g110 = grad3(x1, y1, z0);
141+
let g111 = grad3(x1, y1, z1);
142+
143+
[g000, g001, g010, g011, g100, g101, g110, g111]
144+
}
145+
146+
const A: f32 = 1.237;
147+
const B: f32 = 0.513;
148+
/// Gradient vectors for 2D noise.
149+
static GRADS_2: [Vec2; 8] = [
150+
vec2(A, B),
151+
vec2(B, A),
152+
vec2(-B, A),
153+
vec2(-A, B),
154+
vec2(-A, -B),
155+
vec2(-B, -A),
156+
vec2(B, -A),
157+
vec2(A, -B),
158+
];
159+
160+
/// Gradient vectors for 3D noise.
161+
static GRADS_3: [Vec3; 16] = [
162+
//
163+
vec3(0.0, -1.0, -1.0),
164+
vec3(0.0, -1.0, 1.0),
165+
vec3(0.0, 1.0, -1.0),
166+
vec3(0.0, 1.0, 1.0),
167+
//
168+
vec3(-1.0, 0.0, -1.0),
169+
vec3(-1.0, 0.0, 1.0),
170+
vec3(1.0, 0.0, -1.0),
171+
vec3(1.0, 0.0, 1.0),
172+
//
173+
vec3(-1.0, -1.0, 0.0),
174+
vec3(-1.0, 1.0, 0.0),
175+
vec3(1.0, -1.0, 0.0),
176+
vec3(1.0, 1.0, 0.0),
177+
//
178+
vec3(1.0, 1.0, 0.0),
179+
vec3(-1.0, 1.0, 0.0),
180+
vec3(0.0, -1.0, 1.0),
181+
vec3(0.0, -1.0, -1.0),
182+
];
183+
184+
/// Permutation table for calculating a pseudo-random index for each grid point.
185+
#[rustfmt::skip]
186+
static PERM: [u8; 256] = [
187+
156, 2, 157, 90, 75, 199, 55, 167, 62, 92, 101, 253, 66, 134, 113, 83,
188+
1, 136, 78, 106, 254, 105, 248, 176, 234, 5, 195, 226, 49, 71, 87, 44,
189+
122, 94, 219, 140, 72, 159, 237, 212, 8, 162, 200, 124, 125, 69, 165, 74,
190+
245, 42, 89, 216, 158, 108, 238, 184, 217, 73, 126, 210, 14, 111, 19, 188,
191+
186, 45, 38, 223, 35, 112, 214, 26, 145, 95, 99, 193, 250, 189, 152, 182,
192+
166, 247, 148, 213, 168, 70, 96, 249, 127, 132, 4, 137, 41, 60, 102, 28,
193+
27, 240, 227, 155, 211, 230, 9, 80, 178, 3, 68, 153, 143, 84, 179, 181,
194+
12, 97, 103, 16, 225, 146, 63, 82, 203, 175, 163, 147, 11, 116, 185, 215,
195+
57, 120, 208, 129, 115, 198, 37, 201, 39, 98, 20, 183, 56, 118, 109, 142,
196+
138, 65, 117, 114, 160, 25, 43, 191, 204, 161, 22, 251, 139, 79, 131, 231,
197+
76, 0, 205, 206, 244, 51, 174, 13, 110, 85, 209, 77, 64, 53, 48, 221,
198+
133, 93, 224, 24, 33, 164, 23, 47, 171, 128, 243, 18, 52, 119, 149, 100,
199+
246, 233, 31, 192, 252, 190, 15, 172, 91, 229, 144, 54, 61, 58, 220, 36,
200+
222, 29, 50, 88, 121, 173, 232, 194, 239, 197, 32, 180, 107, 46, 7, 130,
201+
169, 81, 218, 67, 21, 170, 187, 59, 86, 235, 154, 123, 150, 177, 135, 228,
202+
104, 242, 6, 151, 255, 34, 30, 141, 202, 196, 236, 207, 241, 40, 17, 10
203+
];
204+
181205
#[cfg(test)]
182206
mod tests {
183207
use super::*;
184-
use std::dbg;
185-
186-
#[test]
187-
fn perlin2_theo() {
188-
let pt: Vec2 = vec2(9.5, 5.5);
189-
190-
use super::super::float::f32;
191-
let f = pt - pt.map(f32::floor);
192-
let [fx, fy] = f.0;
193-
194-
let [g00, g01, g10, g11]: [Vec2; 4] = [
195-
vec2(0.924, 0.383),
196-
vec2(0.383, -0.924),
197-
vec2(-0.383, 0.924),
198-
vec2(-0.924, -0.383),
199-
];
200-
let d00 = g00.dot(&vec2(fx, fy));
201-
let d01 = g01.dot(&vec2(fx, fy - 1.0));
202-
let d10 = g10.dot(&vec2(fx - 1.0, fy));
203-
let d11 = g11.dot(&vec2(fx - 1.0, fy - 1.0));
204-
205-
let t = f.map(smoothstep);
206-
let (a, b) = lerp(t.x(), (d00, d01), (d10, d11));
207-
208-
dbg!(lerp(t.y(), a, b));
209-
}
208+
use std::eprintln;
210209

211210
#[test]
212211
fn perlin2_statistics() {
@@ -223,8 +222,8 @@ mod tests {
223222
}
224223
avg /= count.pow(2) as f32;
225224

226-
assert_eq!(avg, -0.0004172578);
227-
assert_eq!(min, -0.6612066);
225+
assert_eq!(avg, -0.0005586566);
226+
assert_eq!(min, -0.8853002);
228227
assert_eq!(max, 0.6612066);
229228
}
230229
#[test]
@@ -246,8 +245,8 @@ mod tests {
246245
}
247246
avg /= count.pow(3) as f32;
248247

249-
assert_eq!(avg, -0.0003959533);
248+
assert_eq!(avg, 0.00039595732);
250249
assert_eq!(min, -0.8853568);
251-
assert_eq!(max, 0.87813747);
250+
assert_eq!(max, 0.8853002);
252251
}
253252
}

0 commit comments

Comments
 (0)