earth/rendering/
clouds.rs1#[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}