Skip to content

Commit 3d0216a

Browse files
committed
More Perlin noise
1 parent 5f40366 commit 3d0216a

File tree

1 file changed

+155
-78
lines changed

1 file changed

+155
-78
lines changed

core/src/math/noise.rs

Lines changed: 155 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,113 @@
1-
use crate::math::spline::smoothstep;
1+
//! Two- and three-dimensional Perlin noise.
22
3-
use super::vary::lerp;
4-
use super::vec::{vec2, Vec2};
3+
use super::{
4+
spline::smoothstep,
5+
vary::lerp,
6+
vec::{splat, vec2, vec3, Vec2, Vec3, Vector},
7+
};
58

6-
static GRADS: [Vec2; 40] = [
7-
vec2(0.981, 0.195),
8-
vec2(0.957, 0.290),
9+
/// Gradient vectors for 2D noise.
10+
static GRADS_2: [Vec2; 8] = [
911
vec2(0.924, 0.383),
10-
vec2(0.882, 0.471),
11-
vec2(0.831, 0.556),
12-
vec2(0.556, 0.831),
13-
vec2(0.471, 0.882),
1412
vec2(0.383, 0.924),
15-
vec2(0.290, 0.957),
16-
vec2(0.195, 0.981),
17-
vec2(-0.195, 0.981),
18-
vec2(-0.290, 0.957),
1913
vec2(-0.383, 0.924),
20-
vec2(-0.471, 0.882),
21-
vec2(-0.556, 0.831),
22-
vec2(-0.634, 0.773),
23-
vec2(-0.882, 0.471),
2414
vec2(-0.924, 0.383),
25-
vec2(-0.957, 0.290),
26-
vec2(-0.981, 0.195),
27-
vec2(-0.981, -0.195),
28-
vec2(-0.957, -0.290),
2915
vec2(-0.924, -0.383),
30-
vec2(-0.882, -0.471),
31-
vec2(-0.831, -0.556),
32-
vec2(-0.556, -0.831),
33-
vec2(-0.471, -0.882),
3416
vec2(-0.383, -0.924),
35-
vec2(-0.290, -0.957),
36-
vec2(-0.195, -0.981),
37-
vec2(0.195, -0.981),
38-
vec2(0.290, -0.957),
3917
vec2(0.383, -0.924),
40-
vec2(0.471, -0.882),
41-
vec2(0.556, -0.831),
42-
vec2(0.831, -0.556),
43-
vec2(0.882, -0.471),
4418
vec2(0.924, -0.383),
45-
vec2(0.957, -0.290),
46-
vec2(0.981, -0.195),
4719
];
4820

49-
fn grad(x: f32, y: f32) -> Vec2 {
50-
GRADS[hash(x as i32, y as i32) % GRADS.len()]
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]
5172
}
5273

53-
fn fnv(bytes: &[u8]) -> u64 {
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(pt: Vec3) -> [Vec3; 8] {
92+
use super::float::f32;
93+
let pt0 = pt.map(f32::floor);
94+
let pt1 = pt0 + splat(1.0);
95+
let [x0, y0, z0] = pt0.0;
96+
let [x1, y1, z1] = pt1.0;
97+
98+
let g000 = grad3(x0, y0, z0);
99+
let g001 = grad3(x0, y0, z1);
100+
let g010 = grad3(x0, y1, z0);
101+
let g011 = grad3(x0, y1, z1);
102+
let g100 = grad3(x1, y0, z0);
103+
let g101 = grad3(x1, y0, z1);
104+
let g110 = grad3(x1, y1, z0);
105+
let g111 = grad3(x1, y1, z1);
106+
107+
[g000, g001, g010, g011, g100, g101, g110, g111]
108+
}
109+
110+
fn _fnv(bytes: &[u8]) -> u64 {
54111
const FNV_OFFSET_BASIS: u64 = 14695981039346656037;
55112
const FNV_PRIME: u64 = 1099511628211;
56113

@@ -62,60 +119,80 @@ fn fnv(bytes: &[u8]) -> u64 {
62119
hash
63120
}
64121

65-
fn hash(x: i32, y: i32) -> usize {
66-
let val = (x as u32 as u64) << 32 | (y as u32 as u64);
67-
fnv(&val.to_le_bytes()) as usize
68-
}
69-
70122
pub fn perlin2(pt: Vec2) -> f32 {
71123
use super::float::f32;
124+
let f = pt - pt.map(f32::floor);
125+
let [fx, fy] = f.0;
72126

73-
let [x0, y0] = pt.map(f32::floor).0;
74-
75-
let fx = pt.x() - x0;
76-
let fy = pt.y() - y0;
77-
78-
let g00 = grad(x0, y0);
79-
let g01 = grad(x0, y0 + 1.0);
80-
let g10 = grad(x0 + 1.0, y0);
81-
let g11 = grad(x0 + 1.0, y0 + 1.0);
127+
let [g00, g01, g10, g11] = grads2(pt);
82128

83129
let d00 = g00.dot(&vec2(fx, fy));
84130
let d01 = g01.dot(&vec2(fx, fy - 1.0));
85131
let d10 = g10.dot(&vec2(fx - 1.0, fy));
86132
let d11 = g11.dot(&vec2(fx - 1.0, fy - 1.0));
87133

88-
let a = lerp(smoothstep(fx), d00, d10);
89-
let b = lerp(smoothstep(fx), d01, d11);
90-
91-
lerp(smoothstep(fy), a, b)
134+
let t = f.map(smoothstep);
135+
let (a, b) = lerp(t.x(), (d00, d01), (d10, d11));
136+
lerp(t.y(), a, b)
92137
}
93138

94-
#[cfg(test)]
95-
mod tests {
96-
use std::{print, println};
139+
pub fn perlin2v(pt: Vec2) -> Vec2 {
140+
use super::float::f32;
141+
let fract = pt - pt.map(f32::floor);
97142

98-
use super::*;
99-
use crate::math::{polar, turns};
143+
let [g00, g01, g10, g11] = grads2(pt);
100144

101-
#[test]
102-
fn test() {
103-
for i in -10..=10 {
104-
for j in -10..=10 {
105-
print!("{:2} ", hash(i, j) % 2);
106-
}
107-
println!();
108-
}
145+
let t = fract.map(smoothstep);
146+
let (a, b) = lerp(t.x(), (g00, g01), (g10, g11));
147+
lerp(t.y(), a, b)
148+
}
109149

110-
for i in 0..64 {
111-
let a = turns(i as f32 / 64.0);
150+
pub fn perlin3(pt: Vec3) -> f32 {
151+
use super::float::f32;
152+
let pt0 = pt.map(f32::floor);
153+
let f = pt - pt0;
154+
let i_f: Vec3 = f - splat(1.0);
155+
156+
let [fx, fy, fz] = f.0;
157+
let [ifx, ify, ifz] = i_f.0;
158+
159+
let [g000, g001, g010, g011, g100, g101, g110, g111] = grads3(pt);
160+
161+
let d000 = g000.dot(&vec3(fx, fy, fz));
162+
let d001 = g001.dot(&vec3(fx, fy, ifz));
163+
let d010 = g010.dot(&vec3(fx, ify, fz));
164+
let d011 = g011.dot(&vec3(fx, ify, ifz));
165+
let d100 = g100.dot(&vec3(ifx, fy, fz));
166+
let d101 = g101.dot(&vec3(ifx, fy, ifz));
167+
let d110 = g110.dot(&vec3(ifx, ify, fz));
168+
let d111 = g111.dot(&vec3(ifx, ify, ifz));
169+
170+
let t: Vec3 = f.map(smoothstep);
171+
172+
let x0 = Vector::<_, ()>::new([d000, d010, d001, d011]);
173+
let x1 = Vector::<_, ()>::new([d100, d110, d101, d111]);
174+
let [y0, y1, y2, y3] = lerp(t.x(), x0, x1).0;
175+
let (z0, z1) = lerp(t.y(), (y0, y2), (y1, y3));
176+
lerp(t.z(), z0, z1)
177+
}
112178

113-
let p = polar(1.0, a);
114-
let v = p.to_cart();
179+
pub fn perlin3v(pt: Vec3) -> Vec3 {
180+
use super::float::f32;
181+
let fract = pt - pt.map(f32::floor);
115182

116-
println!("vec2({:.3}, {:.3}),", v.x(), v.y());
117-
}
183+
let [g000, g001, g010, g011, g100, g101, g110, g111] = grads3(pt);
118184

119-
panic!()
120-
}
185+
let t: Vec3 = fract.map(smoothstep);
186+
187+
let x0 = ((g000, g010), (g001, g011));
188+
let x1 = ((g100, g110), (g101, g111));
189+
let ((y0, y1), (y2, y3)) = lerp(t.x(), x0, x1);
190+
let (z0, z1) = lerp(t.y(), (y0, y2), (y1, y3));
191+
lerp(t.z(), z0, z1)
192+
}
193+
194+
#[cfg(test)]
195+
mod tests {
196+
use super::*;
197+
// TODO
121198
}

0 commit comments

Comments
 (0)