1use rt::fx::{cvttd64, maxsd, minsd};
16
17const LO: f64 = -1073741824.0;
18const HI: f64 = 1073741824.0;
19const C1: u32 = 0x8DA6B343;
20const C2: u32 = 0xD8163841;
21const C3: u32 = 0xCB1AB31F;
22const C4: u32 = 0x165667B1;
23
24static GTAB: [[f64; 2]; 16] = [
25 [1.3870398453221475, 0.275899379282943],
26 [1.1758756024193588, 0.78569495838710213],
27 [0.78569495838710235, 1.1758756024193588],
28 [0.27589937928294311, 1.3870398453221475],
29 [-0.27589937928294295, 1.3870398453221475],
30 [-0.7856949583871019, 1.1758756024193588],
31 [-1.1758756024193588, 0.78569495838710213],
32 [-1.3870398453221475, 0.2758993792829435],
33 [-1.3870398453221475, -0.27589937928294317],
34 [-1.1758756024193591, -0.7856949583871019],
35 [-0.78569495838710213, -1.1758756024193588],
36 [-0.27589937928294361, -1.3870398453221473],
37 [0.27589937928294306, -1.3870398453221475],
38 [0.78569495838710168, -1.1758756024193591],
39 [1.1758756024193588, -0.78569495838710213],
40 [1.3870398453221473, -0.27589937928294367],
41];
42
43#[inline(always)]
44fn fmix(mut h: u32) -> u32 {
45 h ^= h >> 16;
46 h = h.wrapping_mul(0x85EBCA6B);
47 h ^= h >> 13;
48 h = h.wrapping_mul(0xC2B2AE35);
49 h ^ (h >> 16)
50}
51
52#[inline(always)]
54fn floor64(x: f64) -> (i64, f64) {
55 let mut t = cvttd64(x);
56 if t as f64 > x {
57 t -= 1;
58 }
59 (t, x - t as f64)
60}
61
62#[inline(always)]
63fn fade(f: f64) -> f64 {
64 (((f * 6.0 - 15.0) * f + 10.0) * f) * f * f
65}
66
67#[inline(always)]
68fn grad(h: u32, dx: f64, dy: f64) -> f64 {
69 let g = >AB[(h & 15) as usize];
70 g[0] * dx + g[1] * dy
71}
72
73pub fn perlin(x: f64, y: f64, seed: u32, stream: u32) -> f64 {
75 let (ix, fx) = floor64(minsd(maxsd(x, LO), HI));
76 let (iy, fy) = floor64(minsd(maxsd(y, LO), HI));
77 let k = seed.wrapping_mul(C3) ^ stream.wrapping_mul(C4);
78 let x0 = (ix as u32).wrapping_mul(C1);
79 let x1 = x0.wrapping_add(C1);
80 let y0 = (iy as u32).wrapping_mul(C2);
81 let y1 = y0.wrapping_add(C2);
82 let u = fade(fx);
83 let v = fade(fy);
84 let g00 = grad(fmix(x0 ^ y0 ^ k), fx, fy);
85 let g10 = grad(fmix(x1 ^ y0 ^ k), fx - 1.0, fy - 0.0);
86 let a = g00 + (g10 - g00) * u;
87 let g01 = grad(fmix(x0 ^ y1 ^ k), fx - 0.0, fy - 1.0);
88 let g11 = grad(fmix(x1 ^ y1 ^ k), fx - 1.0, fy - 1.0);
89 let b = g01 + (g11 - g01) * u;
90 a + (b - a) * v
91}
92
93pub struct PerlinRow {
95 pub n: usize,
96 pub x0: i32,
97 pub step: i32,
98 pub abs: bool,
99 pub seed: u32,
100 pub stream: u32,
101 pub inv: f64,
102 pub ofsx: f64,
103 pub y: f64,
104 pub amp: f64,
105}
106
107pub fn perlin_row(r: &PerlinRow, acc: &mut [f64]) {
110 let (iy, fy) = floor64(minsd(maxsd(r.y, LO), HI));
111 let fy1 = fy - 1.0;
112 let v = fade(fy);
113 let y0 = (iy as u32).wrapping_mul(C2);
114 let y1 = y0.wrapping_add(C2);
115 let k = r.seed.wrapping_mul(C3) ^ r.stream.wrapping_mul(C4);
116 let (mut a0, mut b0, mut a1, mut b1) = ([0f64; 2], [0f64; 2], [0f64; 2], [0f64; 2]);
117 let mut cached: Option<u32> = None;
118 let mut xi = r.x0;
119 for a in acc.iter_mut().take(r.n) {
120 let x = minsd(maxsd(xi as f64 * r.inv + r.ofsx, LO), HI);
121 let (ix, fx) = floor64(x);
122 if cached != Some(ix as u32) {
123 cached = Some(ix as u32);
124 let x0 = (ix as u32).wrapping_mul(C1);
125 let x1 = x0.wrapping_add(C1);
126 let g00 = >AB[(fmix(x0 ^ y0 ^ k) & 15) as usize];
127 let g01 = >AB[(fmix(x0 ^ y1 ^ k) & 15) as usize];
128 let g10 = >AB[(fmix(x1 ^ y0 ^ k) & 15) as usize];
129 let g11 = >AB[(fmix(x1 ^ y1 ^ k) & 15) as usize];
130 a0 = [g00[0], g01[0]];
131 b0 = [g00[1] * fy, g01[1] * fy1];
132 a1 = [g10[0], g11[0]];
133 b1 = [g10[1] * fy, g11[1] * fy1];
134 }
135 let p = [fx * a0[0] + b0[0], fx * a0[1] + b0[1]];
136 let fxm = fx - 1.0;
137 let q = [fxm * a1[0] + b1[0], fxm * a1[1] + b1[1]];
138 let u = fade(fx);
139 let ab = [p[0] + (q[0] - p[0]) * u, p[1] + (q[1] - p[1]) * u];
140 let mut nv = ab[0] + (ab[1] - ab[0]) * v;
141 if r.abs {
142 nv = f64::from_bits(nv.to_bits() & 0x7FFF_FFFF_FFFF_FFFF);
143 }
144 *a += nv * r.amp;
145 xi = xi.wrapping_add(r.step);
146 }
147}