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