1use super::constants::*;
2use crate::core::utils::{
3 math::{Vec2, Vec3, Vec4},
4 ptable::PermutationTable,
5};
6
7pub(crate) fn noise1d(perm: &PermutationTable, point: [f64; 1]) -> f64 {
8 let x = point[0];
9 let x0 = x.floor();
11 let dx = x - x0;
13 let dxs = smoothstep_3(dx);
14 let x0 = x0.rem_euclid(PERMUTATION_TABLE_SIZE as f64) as usize;
16 let sign0 = ((unsafe { perm.hash1d(x0) } % 2) as f64).mul_add(2.0, -1.0);
17 let sign1 = ((unsafe { perm.hash1d(x0 + 1) } % 2) as f64).mul_add(2.0, -1.0);
18 let n0 = sign0 * dx;
20 let n1 = sign1 * (dx - 1.0);
21 lerp(n0, n1, dxs) * 2.0
23}
24
25pub(crate) fn noise2d(perm: &PermutationTable, point: [f64; 2]) -> f64 {
26 let x = Vec2::from(point);
27 let x0 = x.floor();
29 let dx = x - x0;
31 let dxs = dx.map(smoothstep_3);
32 let x0 = x0.cast().rem_euclid(PERMUTATION_TABLE_SIZE);
34 let gi00 = unsafe { perm.hash2d(x0.x, x0.y) } % CORNERPOINT_GRADIENT_LUT_2D_SIZE;
35 let gi01 = unsafe { perm.hash2d(x0.x, x0.y + 1) } % CORNERPOINT_GRADIENT_LUT_2D_SIZE;
36 let gi10 = unsafe { perm.hash2d(x0.x + 1, x0.y) } % CORNERPOINT_GRADIENT_LUT_2D_SIZE;
37 let gi11 = unsafe { perm.hash2d(x0.x + 1, x0.y + 1) } % CORNERPOINT_GRADIENT_LUT_2D_SIZE;
38 let n00 = unsafe { contribution2d(dx.x, dx.y, gi00) };
40 let n01 = unsafe { contribution2d(dx.x, dx.y - 1.0, gi01) };
41 let n10 = unsafe { contribution2d(dx.x - 1.0, dx.y, gi10) };
42 let n11 = unsafe { contribution2d(dx.x - 1.0, dx.y - 1.0, gi11) };
43 let xn0 = lerp(n00, n10, dxs.x);
45 let xn1 = lerp(n01, n11, dxs.x);
46 lerp(xn0, xn1, dxs.y)
47}
48
49pub(crate) fn noise3d(perm: &PermutationTable, point: [f64; 3]) -> f64 {
50 let x = Vec3::from(point);
51 let x0 = x.floor();
53 let dx = x - x0;
55 let dxs = dx.map(smoothstep_3);
56 let x0 = x0.cast().rem_euclid(PERMUTATION_TABLE_SIZE);
58 let gi000 = unsafe { perm.hash3d(x0.x, x0.y, x0.z) } % CORNERPOINT_GRADIENT_LUT_3D_SIZE;
59 let gi001 = unsafe { perm.hash3d(x0.x, x0.y, x0.z + 1) } % CORNERPOINT_GRADIENT_LUT_3D_SIZE;
60 let gi010 = unsafe { perm.hash3d(x0.x, x0.y + 1, x0.z) } % CORNERPOINT_GRADIENT_LUT_3D_SIZE;
61 let gi011 = unsafe { perm.hash3d(x0.x, x0.y + 1, x0.z + 1) } % CORNERPOINT_GRADIENT_LUT_3D_SIZE;
62 let gi100 = unsafe { perm.hash3d(x0.x + 1, x0.y, x0.z) } % CORNERPOINT_GRADIENT_LUT_3D_SIZE;
63 let gi101 = unsafe { perm.hash3d(x0.x + 1, x0.y, x0.z + 1) } % CORNERPOINT_GRADIENT_LUT_3D_SIZE;
64 let gi110 = unsafe { perm.hash3d(x0.x + 1, x0.y + 1, x0.z) } % CORNERPOINT_GRADIENT_LUT_3D_SIZE;
65 let gi111 =
66 unsafe { perm.hash3d(x0.x + 1, x0.y + 1, x0.z + 1) } % CORNERPOINT_GRADIENT_LUT_3D_SIZE;
67 let n000 = unsafe { contribution3d(dx.x, dx.y, dx.z, gi000) };
69 let n001 = unsafe { contribution3d(dx.x, dx.y, dx.z - 1.0, gi001) };
70 let n010 = unsafe { contribution3d(dx.x, dx.y - 1.0, dx.z, gi010) };
71 let n011 = unsafe { contribution3d(dx.x, dx.y - 1.0, dx.z - 1.0, gi011) };
72 let n100 = unsafe { contribution3d(dx.x - 1.0, dx.y, dx.z, gi100) };
73 let n101 = unsafe { contribution3d(dx.x - 1.0, dx.y, dx.z - 1.0, gi101) };
74 let n110 = unsafe { contribution3d(dx.x - 1.0, dx.y - 1.0, dx.z, gi110) };
75 let n111 = unsafe { contribution3d(dx.x - 1.0, dx.y - 1.0, dx.z - 1.0, gi111) };
76 let xn00 = lerp(n000, n100, dxs.x);
78 let xn01 = lerp(n001, n101, dxs.x);
79 let xn10 = lerp(n010, n110, dxs.x);
80 let xn11 = lerp(n011, n111, dxs.x);
81 let yn0 = lerp(xn00, xn10, dxs.y);
82 let yn1 = lerp(xn01, xn11, dxs.y);
83 lerp(yn0, yn1, dxs.z) * 0.6666666666666666
84}
85
86pub(crate) fn noise4d(perm: &PermutationTable, point: [f64; 4]) -> f64 {
87 let x = Vec4::from(point);
88 let x0 = x.floor();
90 let dx = x - x0;
92 let dxs = dx.map(smoothstep_3);
93 let x0 = x0.cast().rem_euclid(PERMUTATION_TABLE_SIZE);
95 let gi0000 = unsafe { perm.hash4d(x0.x, x0.y, x0.z, x0.w) } % CORNERPOINT_GRADIENT_LUT_4D_SIZE;
96 let gi0001 =
97 unsafe { perm.hash4d(x0.x, x0.y, x0.z, x0.w + 1) } % CORNERPOINT_GRADIENT_LUT_4D_SIZE;
98 let gi0010 =
99 unsafe { perm.hash4d(x0.x, x0.y, x0.z + 1, x0.w) } % CORNERPOINT_GRADIENT_LUT_4D_SIZE;
100 let gi0011 =
101 unsafe { perm.hash4d(x0.x, x0.y, x0.z + 1, x0.w + 1) } % CORNERPOINT_GRADIENT_LUT_4D_SIZE;
102 let gi0100 =
103 unsafe { perm.hash4d(x0.x, x0.y + 1, x0.z, x0.w) } % CORNERPOINT_GRADIENT_LUT_4D_SIZE;
104 let gi0101 =
105 unsafe { perm.hash4d(x0.x, x0.y + 1, x0.z, x0.w + 1) } % CORNERPOINT_GRADIENT_LUT_4D_SIZE;
106 let gi0110 =
107 unsafe { perm.hash4d(x0.x, x0.y + 1, x0.z + 1, x0.w) } % CORNERPOINT_GRADIENT_LUT_4D_SIZE;
108 let gi0111 = unsafe { perm.hash4d(x0.x, x0.y + 1, x0.z + 1, x0.w + 1) }
109 % CORNERPOINT_GRADIENT_LUT_4D_SIZE;
110 let gi1000 =
111 unsafe { perm.hash4d(x0.x + 1, x0.y, x0.z, x0.w) } % CORNERPOINT_GRADIENT_LUT_4D_SIZE;
112 let gi1001 =
113 unsafe { perm.hash4d(x0.x + 1, x0.y, x0.z, x0.w + 1) } % CORNERPOINT_GRADIENT_LUT_4D_SIZE;
114 let gi1010 =
115 unsafe { perm.hash4d(x0.x + 1, x0.y, x0.z + 1, x0.w) } % CORNERPOINT_GRADIENT_LUT_4D_SIZE;
116 let gi1011 = unsafe { perm.hash4d(x0.x + 1, x0.y, x0.z + 1, x0.w + 1) }
117 % CORNERPOINT_GRADIENT_LUT_4D_SIZE;
118 let gi1100 =
119 unsafe { perm.hash4d(x0.x + 1, x0.y + 1, x0.z, x0.w) } % CORNERPOINT_GRADIENT_LUT_4D_SIZE;
120 let gi1101 = unsafe { perm.hash4d(x0.x + 1, x0.y + 1, x0.z, x0.w + 1) }
121 % CORNERPOINT_GRADIENT_LUT_4D_SIZE;
122 let gi1110 = unsafe { perm.hash4d(x0.x + 1, x0.y + 1, x0.z + 1, x0.w) }
123 % CORNERPOINT_GRADIENT_LUT_4D_SIZE;
124 let gi1111 = unsafe { perm.hash4d(x0.x + 1, x0.y + 1, x0.z + 1, x0.w + 1) }
125 % CORNERPOINT_GRADIENT_LUT_4D_SIZE;
126 let n0000 = unsafe { contribution4d(dx.x, dx.y, dx.z, dx.w, gi0000) };
128 let n0001 = unsafe { contribution4d(dx.x, dx.y, dx.z, dx.w - 1.0, gi0001) };
129 let n0010 = unsafe { contribution4d(dx.x, dx.y, dx.z - 1.0, dx.w, gi0010) };
130 let n0011 = unsafe { contribution4d(dx.x, dx.y, dx.z - 1.0, dx.w - 1.0, gi0011) };
131 let n0100 = unsafe { contribution4d(dx.x, dx.y - 1.0, dx.z, dx.w, gi0100) };
132 let n0101 = unsafe { contribution4d(dx.x, dx.y - 1.0, dx.z, dx.w - 1.0, gi0101) };
133 let n0110 = unsafe { contribution4d(dx.x, dx.y - 1.0, dx.z - 1.0, dx.w, gi0110) };
134 let n0111 = unsafe { contribution4d(dx.x, dx.y - 1.0, dx.z - 1.0, dx.w - 1.0, gi0111) };
135 let n1000 = unsafe { contribution4d(dx.x - 1.0, dx.y, dx.z, dx.w, gi1000) };
136 let n1001 = unsafe { contribution4d(dx.x - 1.0, dx.y, dx.z, dx.w - 1.0, gi1001) };
137 let n1010 = unsafe { contribution4d(dx.x - 1.0, dx.y, dx.z - 1.0, dx.w, gi1010) };
138 let n1011 = unsafe { contribution4d(dx.x - 1.0, dx.y, dx.z - 1.0, dx.w - 1.0, gi1011) };
139 let n1100 = unsafe { contribution4d(dx.x - 1.0, dx.y - 1.0, dx.z, dx.w, gi1100) };
140 let n1101 = unsafe { contribution4d(dx.x - 1.0, dx.y - 1.0, dx.z, dx.w - 1.0, gi1101) };
141 let n1110 = unsafe { contribution4d(dx.x - 1.0, dx.y - 1.0, dx.z - 1.0, dx.w, gi1110) };
142 let n1111 = unsafe { contribution4d(dx.x - 1.0, dx.y - 1.0, dx.z - 1.0, dx.w - 1.0, gi1111) };
143 let xn000 = lerp(n0000, n1000, dxs.x);
145 let xn001 = lerp(n0001, n1001, dxs.x);
146 let xn010 = lerp(n0010, n1010, dxs.x);
147 let xn011 = lerp(n0011, n1011, dxs.x);
148 let xn100 = lerp(n0100, n1100, dxs.x);
149 let xn101 = lerp(n0101, n1101, dxs.x);
150 let xn110 = lerp(n0110, n1110, dxs.x);
151 let xn111 = lerp(n0111, n1111, dxs.x);
152 let yn00 = lerp(xn000, xn100, dxs.y);
153 let yn01 = lerp(xn001, xn101, dxs.y);
154 let yn10 = lerp(xn010, xn110, dxs.y);
155 let yn11 = lerp(xn011, xn111, dxs.y);
156 let zn0 = lerp(yn00, yn10, dxs.z);
157 let zn1 = lerp(yn01, yn11, dxs.z);
158 lerp(zn0, zn1, dxs.w) * 0.6664701256514842
159}
160
161#[inline]
162fn smoothstep_3(t: f64) -> f64 {
163 t * t * (t * (-2.0) + 3.0)
164}
165
166#[inline]
167fn lerp(a: f64, b: f64, t: f64) -> f64 {
168 a + t * (b - a)
169}
170
171unsafe fn contribution2d(x: f64, y: f64, gi: usize) -> f64 {
172 unsafe {
173 let gradient = CORNERPOINT_GRADIENT_LUT_2D.get_unchecked(gi);
174 gradient.get_unchecked(0) * x + gradient.get_unchecked(1) * y
175 }
176}
177
178unsafe fn contribution3d(x: f64, y: f64, z: f64, gi: usize) -> f64 {
179 unsafe {
180 let gradient = CORNERPOINT_GRADIENT_LUT_3D.get_unchecked(gi);
181 gradient.get_unchecked(0) * x
182 + gradient.get_unchecked(1) * y
183 + gradient.get_unchecked(2) * z
184 }
185}
186
187unsafe fn contribution4d(x: f64, y: f64, z: f64, w: f64, gi: usize) -> f64 {
188 unsafe {
189 let gradient = CORNERPOINT_GRADIENT_LUT_4D.get_unchecked(gi);
190 gradient.get_unchecked(0) * x
191 + gradient.get_unchecked(1) * y
192 + gradient.get_unchecked(2) * z
193 + gradient.get_unchecked(3) * w
194 }
195}