Skip to main content

earth/rendering/
clouds.rs

1#[derive(Debug, Clone, Copy, PartialEq)]
2pub enum CloudType {
3    Cumulus,
4    Stratus,
5    Cirrus,
6    Cumulonimbus,
7    Altocumulus,
8}
9pub struct CloudLayer {
10    pub cloud_type: CloudType,
11    pub base_altitude_m: f64,
12    pub thickness_m: f64,
13    pub coverage: f64,
14    pub density: f64,
15    pub wind_speed_ms: f64,
16    pub wind_direction: [f64; 2],
17}
18impl CloudLayer {
19    pub fn cumulus() -> Self {
20        Self {
21            cloud_type: CloudType::Cumulus,
22            base_altitude_m: 2_000.0,
23            thickness_m: 1_500.0,
24            coverage: 0.4,
25            density: 0.3,
26            wind_speed_ms: 8.0,
27            wind_direction: [1.0, 0.0],
28        }
29    }
30    pub fn stratus() -> Self {
31        Self {
32            cloud_type: CloudType::Stratus,
33            base_altitude_m: 500.0,
34            thickness_m: 500.0,
35            coverage: 0.7,
36            density: 0.5,
37            wind_speed_ms: 5.0,
38            wind_direction: [0.7, 0.7],
39        }
40    }
41    pub fn cirrus() -> Self {
42        Self {
43            cloud_type: CloudType::Cirrus,
44            base_altitude_m: 8_000.0,
45            thickness_m: 1_000.0,
46            coverage: 0.3,
47            density: 0.05,
48            wind_speed_ms: 30.0,
49            wind_direction: [1.0, 0.2],
50        }
51    }
52    pub fn cumulonimbus() -> Self {
53        Self {
54            cloud_type: CloudType::Cumulonimbus,
55            base_altitude_m: 1_000.0,
56            thickness_m: 12_000.0,
57            coverage: 0.15,
58            density: 0.8,
59            wind_speed_ms: 15.0,
60            wind_direction: [0.5, 0.5],
61        }
62    }
63}
64pub struct CloudSystem {
65    pub layers: Vec<CloudLayer>,
66    pub time_offset_s: f64,
67}
68impl CloudSystem {
69    pub fn earth_default() -> Self {
70        Self {
71            layers: vec![
72                CloudLayer::cumulus(),
73                CloudLayer::stratus(),
74                CloudLayer::cirrus(),
75            ],
76            time_offset_s: 0.0,
77        }
78    }
79    pub fn step(&mut self, dt_s: f64) {
80        self.time_offset_s += dt_s;
81    }
82    pub fn sample_density(&self, altitude_m: f64, _lat: f64, _lon: f64) -> f64 {
83        let mut total = 0.0;
84        for layer in &self.layers {
85            let top = layer.base_altitude_m + layer.thickness_m;
86            if altitude_m >= layer.base_altitude_m && altitude_m <= top {
87                let t = (altitude_m - layer.base_altitude_m) / layer.thickness_m;
88                let profile = 4.0 * t * (1.0 - t);
89                total += layer.density * layer.coverage * profile;
90            }
91        }
92        total.min(1.0)
93    }
94}