1const PERLIN_PERM: [u8; 256] = [
2 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69,
3 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219,
4 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175,
5 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230,
6 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76,
7 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173,
8 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206,
9 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163,
10 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232,
11 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162,
12 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204,
13 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141,
14 128, 195, 78, 66, 215, 61, 156, 180,
15];
16
17fn perlin_fade(t: f64) -> f64 {
18 t * t * t * (t * (t * 6.0 - 15.0) + 10.0)
19}
20
21fn perlin_lerp(a: f64, b: f64, t: f64) -> f64 {
22 a + (b - a) * t
23}
24
25fn perlin_hash(x: i32, y: i32, z: i32) -> u8 {
26 let x = PERLIN_PERM[(x & 255) as usize] as usize;
27 let y = PERLIN_PERM[((x + (y & 255) as usize) & 255) as usize] as usize;
28 PERLIN_PERM[((y + (z & 255) as usize) & 255) as usize]
29}
30
31fn perlin_grad(hash: u8, x: f64, y: f64, z: f64) -> f64 {
32 match hash & 0x0f {
33 0x0 => x + y,
34 0x1 => -x + y,
35 0x2 => x - y,
36 0x3 => -x - y,
37 0x4 => x + z,
38 0x5 => -x + z,
39 0x6 => x - z,
40 0x7 => -x - z,
41 0x8 => y + z,
42 0x9 => -y + z,
43 0xa => y - z,
44 0xb => -y - z,
45 0xc => y + x,
46 0xd => -y + z,
47 0xe => y - x,
48 _ => -y - z,
49 }
50}
51
52pub fn perlin(x: f64, y: f64, z: Option<f64>) -> f64 {
53 let z = z.unwrap_or(0.0);
54
55 let xi0 = x.floor() as i32;
56 let yi0 = y.floor() as i32;
57 let zi0 = z.floor() as i32;
58 let xi1 = xi0 + 1;
59 let yi1 = yi0 + 1;
60 let zi1 = zi0 + 1;
61
62 let xf0 = x - xi0 as f64;
63 let yf0 = y - yi0 as f64;
64 let zf0 = z - zi0 as f64;
65 let xf1 = xf0 - 1.0;
66 let yf1 = yf0 - 1.0;
67 let zf1 = zf0 - 1.0;
68
69 let u = perlin_fade(xf0);
70 let v = perlin_fade(yf0);
71 let w = perlin_fade(zf0);
72
73 let x00 = perlin_lerp(
74 perlin_grad(perlin_hash(xi0, yi0, zi0), xf0, yf0, zf0),
75 perlin_grad(perlin_hash(xi1, yi0, zi0), xf1, yf0, zf0),
76 u,
77 );
78 let x10 = perlin_lerp(
79 perlin_grad(perlin_hash(xi0, yi1, zi0), xf0, yf1, zf0),
80 perlin_grad(perlin_hash(xi1, yi1, zi0), xf1, yf1, zf0),
81 u,
82 );
83 let x01 = perlin_lerp(
84 perlin_grad(perlin_hash(xi0, yi0, zi1), xf0, yf0, zf1),
85 perlin_grad(perlin_hash(xi1, yi0, zi1), xf1, yf0, zf1),
86 u,
87 );
88 let x11 = perlin_lerp(
89 perlin_grad(perlin_hash(xi0, yi1, zi1), xf0, yf1, zf1),
90 perlin_grad(perlin_hash(xi1, yi1, zi1), xf1, yf1, zf1),
91 u,
92 );
93
94 let y0 = perlin_lerp(x00, x10, v);
95 let y1 = perlin_lerp(x01, x11, v);
96 perlin_lerp(y0, y1, w).clamp(-1.0, 1.0)
97}
98
99pub fn quat_mul(a: [f32; 4], b: [f32; 4]) -> [f32; 4] {
100 let (ax, ay, az, aw) = (a[0], a[1], a[2], a[3]);
101 let (bx, by, bz, bw) = (b[0], b[1], b[2], b[3]);
102 [
103 aw * bx + ax * bw + ay * bz - az * by,
104 aw * by - ax * bz + ay * bw + az * bx,
105 aw * bz + ax * by - ay * bx + az * bw,
106 aw * bw - ax * bx - ay * by - az * bz,
107 ]
108}
109
110pub fn quat_conjugate(q: [f32; 4]) -> [f32; 4] {
111 [-q[0], -q[1], -q[2], q[3]]
112}
113
114pub fn quat_rotate_vec3(q: [f32; 4], v: [f32; 3]) -> [f32; 3] {
115 let vq = [v[0], v[1], v[2], 0.0f32];
117 let t = quat_mul(q, vq);
118 let r = quat_mul(t, quat_conjugate(q));
119 [r[0], r[1], r[2]]
120}
121
122pub fn vec3_normalize(v: [f32; 3]) -> [f32; 3] {
123 let len2 = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
124 if len2 <= 0.0 {
125 return [0.0, 0.0, 0.0];
126 }
127 let inv = len2.sqrt().recip();
128 [v[0] * inv, v[1] * inv, v[2] * inv]
129}
130
131pub fn vec3_len(v: [f32; 3]) -> f32 {
132 (v[0] * v[0] + v[1] * v[1] + v[2] * v[2]).sqrt()
133}
134
135pub fn vec3_dot(a: [f32; 3], b: [f32; 3]) -> f32 {
136 a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
137}
138
139pub fn vec3_cross(a: [f32; 3], b: [f32; 3]) -> [f32; 3] {
140 [
141 a[1] * b[2] - a[2] * b[1],
142 a[2] * b[0] - a[0] * b[2],
143 a[0] * b[1] - a[1] * b[0],
144 ]
145}
146
147pub fn vec3_scale(v: [f32; 3], s: f32) -> [f32; 3] {
148 [v[0] * s, v[1] * s, v[2] * s]
149}
150
151pub fn vec3_negate(v: [f32; 3]) -> [f32; 3] {
152 [-v[0], -v[1], -v[2]]
153}
154
155pub fn vec3_sub(a: [f32; 3], b: [f32; 3]) -> [f32; 3] {
156 [a[0] - b[0], a[1] - b[1], a[2] - b[2]]
157}
158
159pub fn vec3_reflect(dir: [f32; 3], plane_normal: [f32; 3]) -> [f32; 3] {
160 let dist = vec3_dot(dir, plane_normal);
161 vec3_sub(dir, vec3_scale(plane_normal, 2.0 * dist))
162}
163
164pub fn vec3_reflect_point(
165 point: [f32; 3],
166 plane_pos: [f32; 3],
167 plane_normal: [f32; 3],
168) -> [f32; 3] {
169 let offset = vec3_sub(point, plane_pos);
170 let dist = vec3_dot(offset, plane_normal);
171 vec3_sub(point, vec3_scale(plane_normal, 2.0 * dist))
172}
173
174pub fn mat4_identity() -> [[f32; 4]; 4] {
175 [
176 [1.0, 0.0, 0.0, 0.0],
177 [0.0, 1.0, 0.0, 0.0],
178 [0.0, 0.0, 1.0, 0.0],
179 [0.0, 0.0, 0.0, 1.0],
180 ]
181}
182
183pub fn mat4_mul(a: [[f32; 4]; 4], b: [[f32; 4]; 4]) -> [[f32; 4]; 4] {
184 let mut out = [[0.0f32; 4]; 4];
185 for c in 0..4 {
186 for r in 0..4 {
187 out[c][r] =
188 a[0][r] * b[c][0] + a[1][r] * b[c][1] + a[2][r] * b[c][2] + a[3][r] * b[c][3];
189 }
190 }
191 out
192}
193
194pub fn mat4_mul_vec4(m: [[f32; 4]; 4], v: [f32; 4]) -> [f32; 4] {
195 [
196 m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0] * v[3],
197 m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1] * v[3],
198 m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2] * v[3],
199 m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3] * v[3],
200 ]
201}
202
203pub fn vec3_add(a: [f32; 3], b: [f32; 3]) -> [f32; 3] {
204 [a[0] + b[0], a[1] + b[1], a[2] + b[2]]
205}
206
207pub fn vec3_lerp(a: [f32; 3], b: [f32; 3], t: f32) -> [f32; 3] {
208 vec3_add(a, vec3_scale(vec3_sub(b, a), t))
209}
210
211pub fn quat_normalize(q: [f32; 4]) -> [f32; 4] {
212 let len2 = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3];
213 if len2 < 1e-12 {
214 return [0.0, 0.0, 0.0, 1.0];
215 }
216 let inv = len2.sqrt().recip();
217 [q[0] * inv, q[1] * inv, q[2] * inv, q[3] * inv]
218}
219
220pub fn quat_rotation_y(yaw: f32) -> [f32; 4] {
221 let half = yaw * 0.5;
222 [0.0, half.sin(), 0.0, half.cos()]
223}
224
225pub fn quat_nlerp(a: [f32; 4], b: [f32; 4], t: f32) -> [f32; 4] {
228 let dot = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
229 let b = if dot < 0.0 {
230 [-b[0], -b[1], -b[2], -b[3]]
231 } else {
232 b
233 };
234 quat_normalize([
235 a[0] + (b[0] - a[0]) * t,
236 a[1] + (b[1] - a[1]) * t,
237 a[2] + (b[2] - a[2]) * t,
238 a[3] + (b[3] - a[3]) * t,
239 ])
240}
241
242pub fn shortest_arc_quat(from: [f32; 3], to: [f32; 3]) -> [f32; 4] {
244 let d = vec3_dot(from, to);
245 if d < -0.9999 {
246 let perp = if from[0].abs() < 0.9 {
247 [1.0, 0.0, 0.0]
248 } else {
249 [0.0, 1.0, 0.0]
250 };
251 let axis = vec3_normalize(vec3_cross(from, perp));
252 return [axis[0], axis[1], axis[2], 0.0];
253 }
254 let c = vec3_cross(from, to);
255 quat_normalize([c[0], c[1], c[2], 1.0 + d])
256}
257
258pub fn mat_to_quat(m: [[f32; 4]; 4]) -> [f32; 4] {
260 fn col_len(m: [[f32; 4]; 4], c: usize) -> f32 {
261 (m[c][0] * m[c][0] + m[c][1] * m[c][1] + m[c][2] * m[c][2])
262 .sqrt()
263 .max(1e-9)
264 }
265 let s0 = col_len(m, 0).recip();
266 let s1 = col_len(m, 1).recip();
267 let s2 = col_len(m, 2).recip();
268 let r00 = m[0][0] * s0;
269 let r10 = m[0][1] * s0;
270 let r20 = m[0][2] * s0;
271 let r01 = m[1][0] * s1;
272 let r11 = m[1][1] * s1;
273 let r21 = m[1][2] * s1;
274 let r02 = m[2][0] * s2;
275 let r12 = m[2][1] * s2;
276 let r22 = m[2][2] * s2;
277 let trace = r00 + r11 + r22;
278 if trace > 0.0 {
279 let s = 0.5 / (trace + 1.0).sqrt();
280 quat_normalize([(r21 - r12) * s, (r02 - r20) * s, (r10 - r01) * s, 0.25 / s])
281 } else if r00 > r11 && r00 > r22 {
282 let s = 2.0 * (1.0 + r00 - r11 - r22).sqrt();
283 quat_normalize([0.25 * s, (r01 + r10) / s, (r02 + r20) / s, (r21 - r12) / s])
284 } else if r11 > r22 {
285 let s = 2.0 * (1.0 + r11 - r00 - r22).sqrt();
286 quat_normalize([(r01 + r10) / s, 0.25 * s, (r12 + r21) / s, (r02 - r20) / s])
287 } else {
288 let s = 2.0 * (1.0 + r22 - r00 - r11).sqrt();
289 quat_normalize([(r02 + r20) / s, (r12 + r21) / s, 0.25 * s, (r10 - r01) / s])
290 }
291}
292
293pub fn quat_from_axis_angle(axis: [f32; 3], angle_rad: f32) -> [f32; 4] {
294 let axis = vec3_normalize(axis);
295 let (s, c) = (0.5 * angle_rad).sin_cos();
296 [axis[0] * s, axis[1] * s, axis[2] * s, c]
297}
298
299pub fn quat_to_axis_angle(q: [f32; 4]) -> ([f32; 3], f32) {
303 let [x, y, z, w] = q;
304 let len_sq = x * x + y * y + z * z;
305
306 if len_sq < 1e-10 {
307 return ([0.0, 0.0, 1.0], 0.0);
309 }
310
311 let sin_half_angle = len_sq.sqrt();
312 let angle = 2.0 * sin_half_angle.atan2(w);
313 let axis = if sin_half_angle > 1e-6 {
314 [x / sin_half_angle, y / sin_half_angle, z / sin_half_angle]
315 } else {
316 [0.0, 0.0, 1.0]
317 };
318
319 (axis, angle)
320}
321
322pub fn mat4_inverse(m: [[f32; 4]; 4]) -> Option<[[f32; 4]; 4]> {
326 let mut a = [[0.0f32; 8]; 4];
329 for r in 0..4 {
330 for c in 0..4 {
331 a[r][c] = m[c][r];
333 }
334 a[r][4 + r] = 1.0;
335 }
336
337 for i in 0..4 {
338 let mut pivot_row = i;
340 let mut pivot_val = a[i][i].abs();
341 for r in (i + 1)..4 {
342 let v = a[r][i].abs();
343 if v > pivot_val {
344 pivot_val = v;
345 pivot_row = r;
346 }
347 }
348 if pivot_val == 0.0 {
349 return None;
350 }
351 if pivot_row != i {
352 a.swap(i, pivot_row);
353 }
354
355 let inv_pivot = 1.0 / a[i][i];
357 for c in i..8 {
358 a[i][c] *= inv_pivot;
359 }
360
361 for r in 0..4 {
363 if r == i {
364 continue;
365 }
366 let factor = a[r][i];
367 if factor == 0.0 {
368 continue;
369 }
370 for c in i..8 {
371 a[r][c] -= factor * a[i][c];
372 }
373 }
374 }
375
376 let mut inv = [[0.0f32; 4]; 4];
378 for r in 0..4 {
379 for c in 0..4 {
380 inv[c][r] = a[r][4 + c];
381 }
382 }
383 Some(inv)
384}