Skip to main content

minecraft_mth/
lib.rs

1mod asin_tab;
2mod cos_tab;
3mod sin_table;
4
5use asin_tab::ASIN_TAB;
6use cos_tab::COS_TAB;
7use num_traits::{Euclid, Float, FromPrimitive, Signed};
8use sin_table::SIN;
9
10const PI: f32 = std::f32::consts::PI;
11const PI_64: f64 = std::f64::consts::PI;
12pub const DEG_TO_RAD: f32 = PI / 180.0;
13pub const RAD_TO_DEG: f32 = 180.0 / PI;
14const SIN_SCALE: f64 = 10430.378350470453;
15const ONE_SIXTH: f64 = 0.16666666666666666;
16const FRAC_BIAS: f64 = f64::from_bits(4805340802404319232u64);
17
18pub fn sin(x: f64) -> f32 {
19    let idx = (((x * SIN_SCALE) as i64 as u64) & 65535) as usize;
20    SIN[idx]
21}
22
23pub fn cos(x: f64) -> f32 {
24    let idx = (((x * SIN_SCALE + 16384.0) as i64 as u64) & 65535) as usize;
25    SIN[idx]
26}
27
28pub fn sqrt(x: f32) -> f32 {
29    x.sqrt()
30}
31
32pub fn floor<T: Float>(v: T) -> T {
33    let _ = v;
34    todo!()
35}
36
37pub fn lfloor(v: f64) -> i64 {
38    let _ = v;
39    todo!()
40}
41
42pub fn abs<T: Signed>(v: T) -> T {
43    v.abs()
44}
45
46pub fn ceil<T: Float>(v: T) -> i32 {
47    let _ = v;
48    todo!()
49}
50
51pub fn ceil_long(v: f64) -> i64 {
52    let _ = v;
53    todo!()
54}
55
56pub fn clamp<T: PartialOrd>(value: T, min: T, max: T) -> T {
57    num_traits::clamp(value, min, max)
58}
59
60pub fn clamped_lerp<T: Float>(factor: T, min: T, max: T) -> T {
61    let _ = (factor, min, max);
62    todo!()
63}
64
65pub fn abs_max<T: Signed + PartialOrd>(a: T, b: T) -> T {
66    let abs_a = a.abs();
67    let abs_b = b.abs();
68    if abs_a > abs_b { abs_a } else { abs_b }
69}
70
71pub fn chessboard_distance(x0: i32, z0: i32, x1: i32, z1: i32) -> i32 {
72    abs_max(x1 - x0, z1 - z0)
73}
74
75pub fn floor_div(a: i32, b: i32) -> i32 {
76    a.div_euclid(b)
77}
78
79pub fn equal<T: Float>(a: T, b: T) -> bool {
80    let eps = T::from(1e-5).unwrap();
81    (b - a).abs() < eps
82}
83
84pub fn positive_modulo<T: Euclid>(input: T, r#mod: T) -> T {
85    input.rem_euclid(&r#mod)
86}
87
88pub fn is_miltiple_of(dividend: i32, divisor: i32) -> bool {
89    dividend % divisor == 0
90}
91
92pub fn pack_degrees(angle: f32) -> i8 {
93    (angle * 256.0 / 360.0).floor() as i8
94}
95
96pub fn unpack_degress(rot: i8) -> f32 {
97    rot as f32 * 360.0 / 256.0
98}
99
100pub fn wrap_degrees<T>(angle: T) -> T
101where
102    T: Signed + Copy + FromPrimitive + PartialOrd,
103{
104    let deg180 = T::from_i32(180).unwrap();
105    let deg360 = T::from_i32(360).unwrap();
106    let a: T = angle % deg360;
107
108    match a {
109        x if x >= deg180 => x - deg360,
110        x if x < -deg180 => x + deg360,
111        x => x,
112    }
113}
114
115pub fn degrees_difference(from_angle: f32, to_angle: f32) -> f32 {
116    wrap_degrees(to_angle - from_angle)
117}
118
119pub fn degrees_difference_abs(angle_a: f32, angle_b: f32) -> f32 {
120    degrees_difference(angle_a, angle_b).abs()
121}
122
123pub fn rotate_if_necessary(base_angle: f32, target_angle: f32, max_angle_diff: f32) -> f32 {
124    let _ = (base_angle, target_angle, max_angle_diff);
125    todo!()
126}
127
128pub fn approach(current: f32, target: f32, increment: f32) -> f32 {
129    let _ = (current, target, increment);
130    todo!()
131}
132
133pub fn approach_degress(current: f32, target: f32, increment: f32) -> f32 {
134    let _ = (current, target, increment);
135    todo!()
136}
137
138pub fn get_int(input: &str, default: i32) -> i32 {
139    input.parse::<i32>().unwrap_or(default)
140}
141
142pub fn smallest_encompassing_power_of_two(input: i32) -> i32 {
143    let _ = input;
144    todo!()
145}
146
147pub fn is_power_of_two(input: u32) -> bool {
148    input.is_power_of_two()
149}
150
151pub fn ceillog2(input: u32) -> u32 {
152    if is_power_of_two(input) {
153        log2(input)
154    } else {
155        log2(input) + 1
156    }
157}
158
159pub fn log2(input: u32) -> u32 {
160    input.ilog2()
161}
162
163pub fn frac<T: Float>(num: T) -> T {
164    let _ = num;
165    todo!()
166}
167
168pub fn inverse_lerp<T: Float>(value: T, min: T, max: T) -> T {
169    let _ = (value, min, max);
170    todo!()
171}
172
173pub fn atan2(y: f64, x: f64) -> f64 {
174    let mut x = x;
175    let mut y = y;
176    let d2 = x * x + y * y;
177
178    if d2.is_nan() {
179        return f64::NAN;
180    }
181
182    let neg_y = y < 0.0;
183    if neg_y {
184        y = -y;
185    }
186
187    let neg_x = x < 0.0;
188    if neg_x {
189        x = -x;
190    }
191
192    let steep = y > x;
193    if steep {
194        (x, y) = (y, x)
195    }
196
197    let rinv = fast_inv_sqrt(d2);
198
199    x *= rinv;
200    y *= rinv;
201
202    let yp = FRAC_BIAS + y;
203    let index = yp.to_bits() as usize;
204    let phi = ASIN_TAB[index];
205    let c_phi = COS_TAB[index];
206    let s_phi = yp - FRAC_BIAS;
207
208    let sd = y * c_phi - x * s_phi;
209
210    let d = (6.0 + sd * sd) * sd * ONE_SIXTH;
211
212    let mut theta = phi + d;
213
214    if steep {
215        theta = PI_64 / 2.0 - theta
216    }
217
218    if neg_x {
219        theta = PI_64 - theta
220    }
221
222    if neg_y {
223        theta = -theta
224    }
225
226    theta
227}
228
229pub fn inv_sqrt<T: Float>(x: T) -> T {
230    x.sqrt().recip()
231}
232
233pub fn fast_inv_sqrt(x: f64) -> f64 {
234    let xhalf = 0.5 * x;
235    let mut i = x.to_bits();
236    i = 6910469410427058090_u64 - (i >> 1);
237    let y = f64::from_bits(i);
238
239    y * (1.5 - xhalf * y * y)
240}
241
242pub fn fast_inv_cube_root(x: f32) -> f32 {
243    let _ = x;
244    todo!()
245}
246
247pub fn hsv_to_rgb(hue: f32, saturation: f32, value: f32) -> i32 {
248    let _ = (hue, saturation, value);
249    todo!()
250}
251
252pub fn hsv_to_argb(hue: f32, saturation: f32, value: f32, alpha: i32) -> i32 {
253    let _ = (hue, saturation, value, alpha);
254    todo!()
255}
256
257pub fn lerp_int(alpha1: f32, p0: i32, p1: i32) -> i32 {
258    let _ = (alpha1, p0, p1);
259    todo!()
260}
261
262pub fn lerp_discrete(alpha1: f32, p0: i32, p1: i32) -> i32 {
263    let _ = (alpha1, p0, p1);
264    todo!()
265}
266
267pub fn lerp<T: Float>(alpha1: T, p0: T, p1: T) -> T {
268    p0 + alpha1 * (p1 - p0)
269}
270
271pub fn lerp2(alpha1: f64, alpha2: f64, x00: f64, x10: f64, x01: f64, x11: f64) -> f64 {
272    lerp(alpha2, lerp(alpha1, x00, x10), lerp(alpha1, x01, x11))
273}
274
275#[allow(clippy::too_many_arguments)]
276pub fn lerp3(
277    alpha1: f64,
278    alpha2: f64,
279    alpha3: f64,
280    x000: f64,
281    x100: f64,
282    x010: f64,
283    x110: f64,
284    x001: f64,
285    x101: f64,
286    x011: f64,
287    x111: f64,
288) -> f64 {
289    lerp(
290        alpha3,
291        lerp2(alpha1, alpha2, x000, x100, x010, x110),
292        lerp2(alpha1, alpha2, x001, x101, x011, x111),
293    )
294}
295
296pub fn catmullrom(alpha: f32, p0: f32, p1: f32, p2: f32, p3: f32) -> f32 {
297    let _ = (alpha, p0, p1, p2, p3);
298    todo!()
299}
300
301pub fn smoothstep(x: f64) -> f64 {
302    let _ = x;
303    todo!()
304}
305
306pub fn smoothstep_derivative(x: f64) -> f64 {
307    let _ = x;
308    todo!()
309}
310
311pub fn sign(number: f64) -> i32 {
312    number.signum() as i32
313}
314
315pub fn rot_lerp<T>(a: T, from: T, to: T) -> T
316where
317    T: Signed + Copy + FromPrimitive + PartialOrd + Float,
318{
319    from + a * wrap_degrees(to - from)
320}
321
322pub fn rot_lerp_rad(a: f32, from: f32, to: f32) -> f32 {
323    let diff = (to - from + PI).rem_euclid(2.0 * PI) - PI;
324    from + a * diff
325}
326
327pub fn triangle_wave(index: f32, period: f32) -> f32 {
328    let _ = (index, period);
329    todo!()
330}
331
332pub fn clamped_map<T: Float>(value: T, from_min: T, from_max: T, to_min: T, to_max: T) -> T {
333    clamped_lerp(inverse_lerp(value, from_min, from_max), to_min, to_max)
334}
335
336pub fn map<T: Float>(value: T, from_min: T, from_max: T, to_min: T, to_max: T) -> T {
337    lerp(inverse_lerp(value, from_min, from_max), to_min, to_max)
338}
339
340pub fn round_toward(input: i32, multiple: i32) -> i32 {
341    positive_ceil_div(input, multiple) * multiple
342}
343
344pub fn positive_ceil_div(input: i32, divisor: i32) -> i32 {
345    -floor_div(-input, divisor)
346}
347
348pub fn length_squared<T: Float>(x: T, y: T) -> T {
349    x * x + y * y
350}
351
352pub fn length<T: Float>(x: T, y: T) -> T {
353    length_squared(x, y).sqrt()
354}
355
356pub fn length_squared_3<T: Float>(x: T, y: T, z: T) -> T {
357    x * x + y * y + z * z
358}
359
360pub fn length_3<T: Float>(x: T, y: T, z: T) -> T {
361    length_squared_3(x, y, z).sqrt()
362}
363
364pub fn quantize(value: f64, quantize_resolution: f64) -> f64 {
365    floor(value / quantize_resolution) * quantize_resolution
366}