proof_engine/weather/
mod.rs1pub mod atmosphere;
2pub mod precipitation;
3pub mod climate;
4
5pub use atmosphere::*;
6pub use precipitation::*;
7pub use climate::*;
8
9#[derive(Clone, Copy, Debug, Default, PartialEq)]
13pub struct Vec3 {
14 pub x: f32,
15 pub y: f32,
16 pub z: f32,
17}
18
19impl Vec3 {
20 pub const ZERO: Self = Self { x: 0.0, y: 0.0, z: 0.0 };
21 pub fn new(x: f32, y: f32, z: f32) -> Self { Self { x, y, z } }
22 pub fn length(&self) -> f32 { (self.x * self.x + self.y * self.y + self.z * self.z).sqrt() }
23 pub fn normalize(&self) -> Self {
24 let len = self.length();
25 if len < 1e-12 { Self::ZERO } else { Self { x: self.x / len, y: self.y / len, z: self.z / len } }
26 }
27 pub fn dot(&self, other: &Self) -> f32 { self.x * other.x + self.y * other.y + self.z * other.z }
28 pub fn scale(&self, s: f32) -> Self { Self { x: self.x * s, y: self.y * s, z: self.z * s } }
29 pub fn lerp(self, other: Self, t: f32) -> Self {
30 Self { x: self.x + (other.x - self.x) * t, y: self.y + (other.y - self.y) * t, z: self.z + (other.z - self.z) * t }
31 }
32 pub fn add(self, other: Self) -> Self { Self { x: self.x + other.x, y: self.y + other.y, z: self.z + other.z } }
33 pub fn sub(self, other: Self) -> Self { Self { x: self.x - other.x, y: self.y - other.y, z: self.z - other.z } }
34}
35
36impl std::ops::Add for Vec3 {
37 type Output = Self;
38 fn add(self, rhs: Self) -> Self { Self { x: self.x + rhs.x, y: self.y + rhs.y, z: self.z + rhs.z } }
39}
40
41impl std::ops::Sub for Vec3 {
42 type Output = Self;
43 fn sub(self, rhs: Self) -> Self { Self { x: self.x - rhs.x, y: self.y - rhs.y, z: self.z - rhs.z } }
44}
45
46impl std::ops::Mul<f32> for Vec3 {
47 type Output = Self;
48 fn mul(self, rhs: f32) -> Self { Self { x: self.x * rhs, y: self.y * rhs, z: self.z * rhs } }
49}
50
51impl std::ops::AddAssign for Vec3 {
52 fn add_assign(&mut self, rhs: Self) { self.x += rhs.x; self.y += rhs.y; self.z += rhs.z; }
53}
54
55impl std::ops::MulAssign<f32> for Vec3 {
56 fn mul_assign(&mut self, rhs: f32) { self.x *= rhs; self.y *= rhs; self.z *= rhs; }
57}
58
59pub fn lerp(a: f32, b: f32, t: f32) -> f32 {
61 a + (b - a) * t
62}
63
64pub fn smoothstep(edge0: f32, edge1: f32, x: f32) -> f32 {
66 let t = ((x - edge0) / (edge1 - edge0)).clamp(0.0, 1.0);
67 t * t * (3.0 - 2.0 * t)
68}
69
70fn hash_u32(mut x: u32) -> u32 {
72 x = x.wrapping_mul(0x85ebca6b);
73 x ^= x >> 13;
74 x = x.wrapping_mul(0xc2b2ae35);
75 x ^= x >> 16;
76 x
77}
78
79fn hash_2d(ix: i32, iy: i32) -> f32 {
80 let h = hash_u32((ix as u32).wrapping_mul(73856093) ^ (iy as u32).wrapping_mul(19349663));
81 (h & 0x00ff_ffff) as f32 / 0x00ff_ffff as f32
82}
83
84pub fn value_noise_2d(x: f32, y: f32) -> f32 {
86 let ix = x.floor() as i32;
87 let iy = y.floor() as i32;
88 let fx = x - ix as f32;
89 let fy = y - iy as f32;
90 let u = fx * fx * (3.0 - 2.0 * fx);
91 let v = fy * fy * (3.0 - 2.0 * fy);
92
93 let c00 = hash_2d(ix, iy);
94 let c10 = hash_2d(ix + 1, iy);
95 let c01 = hash_2d(ix, iy + 1);
96 let c11 = hash_2d(ix + 1, iy + 1);
97
98 lerp(lerp(c00, c10, u), lerp(c01, c11, u), v)
99}
100
101pub fn fbm_2d(x: f32, y: f32, octaves: u32, lacunarity: f32, gain: f32) -> f32 {
103 let mut sum = 0.0f32;
104 let mut amp = 1.0f32;
105 let mut freq = 1.0f32;
106 let mut max_amp = 0.0f32;
107 for _ in 0..octaves {
108 sum += value_noise_2d(x * freq, y * freq) * amp;
109 max_amp += amp;
110 amp *= gain;
111 freq *= lacunarity;
112 }
113 sum / max_amp
114}