1use std::f64::consts::PI;
2
3use noise::{NoiseFn, Perlin, Seedable};
4use rand::{Rng, SeedableRng};
5use rand_xoshiro::Xoshiro256StarStar;
6
7use crate::pyqie::Pyqie;
8
9pub struct Math {
10 rng: Xoshiro256StarStar,
11 perlin: Perlin,
12}
13
14impl Math {
15 pub fn new() -> Self {
16 let seed = Self::generate_seed();
17 let rng = Xoshiro256StarStar::seed_from_u64(seed as u64);
18 let perlin = Perlin::new().set_seed(seed);
19 Self { rng, perlin }
20 }
21
22 fn generate_seed() -> u32 {
23 let mut rng = rand::thread_rng();
24 rng.gen_range(0..u32::MAX)
25 }
26}
27
28impl Pyqie {
29 pub fn ceil(&self, x: f64) -> i32 {
30 f64::ceil(x) as i32
31 }
32
33 pub fn floor(&self, x: f64) -> i32 {
34 f64::floor(x) as i32
35 }
36
37 pub fn sgn(&self, x: f64) -> f64 {
38 if x > 0.0 {
39 1.0
40 } else if x < 0.0 {
41 -1.0
42 } else {
43 0.0
44 }
45 }
46
47 pub fn sqrt(&self, x: f64) -> f64 {
48 if x == 0.0 {
49 f64::MAX
50 } else {
51 f64::sqrt(x)
52 }
53 }
54
55 pub fn sin(&self, deg: f64) -> f64 {
56 f64::sin(deg * PI / 180.0)
57 }
58
59 pub fn cos(&self, deg: f64) -> f64 {
60 f64::cos(deg * PI / 180.0)
61 }
62
63 pub fn atan2(&self, y: f64, x: f64) -> f64 {
64 f64::atan2(y, x) * 180.0 / PI
65 }
66
67 pub fn rseed(&mut self, seed: u32) {
68 self.math.rng = Xoshiro256StarStar::seed_from_u64(seed as u64);
69 }
70
71 pub fn rndi(&mut self, a: i32, b: i32) -> i32 {
72 let (a, b) = if a < b { (a, b) } else { (b, a) };
73 self.math.rng.gen_range(a..=b)
74 }
75
76 pub fn rndf(&mut self, a: f64, b: f64) -> f64 {
77 let (a, b) = if a < b { (a, b) } else { (b, a) };
78 self.math.rng.gen_range(a..=b)
79 }
80
81 pub fn nseed(&mut self, seed: u32) {
82 self.math.perlin = Perlin::new().set_seed(seed);
83 }
84
85 pub fn noise(&mut self, x: f64, y: f64, z: f64) -> f64 {
86 self.math.perlin.get([x, y, z])
87 }
88}