1use crate::{
2 IndexRef,
3 util::{math::close, sampler::Sampler},
4};
5use common::{match_some, terrain::structure::StructureBlock};
6use std::ops::Range;
7use strum::EnumIter;
8use vek::*;
9
10#[derive(Copy, Clone, Debug, EnumIter)]
11pub enum ForestKind {
12 Palm,
13 Acacia,
14 Baobab,
15 Oak,
16 Chestnut,
17 Cedar,
18 Pine,
19 Redwood,
20 Birch,
21 Mangrove,
22 Giant,
23 Swamp,
24 Frostpine,
25 Dead,
26 Mapletree,
27 Cherry,
28 AutumnTree,
29}
30
31pub struct Environment {
32 pub humid: f32,
33 pub temp: f32,
34 pub near_water: f32,
35}
36
37impl ForestKind {
38 pub fn humid_range(&self) -> Range<f32> {
39 match self {
40 ForestKind::Palm => 0.25..1.4,
41 ForestKind::Acacia => 0.05..0.55,
42 ForestKind::Baobab => 0.2..0.6,
43 ForestKind::Oak => 0.35..1.5,
44 ForestKind::Chestnut => 0.35..1.5,
45 ForestKind::Cedar => 0.275..1.45,
46 ForestKind::Pine => 0.2..1.4,
47 ForestKind::Redwood => 0.6..1.0,
48 ForestKind::Frostpine => 0.2..1.4,
49 ForestKind::Birch => 0.0..0.6,
50 ForestKind::Mangrove => 0.5..1.3,
51 ForestKind::Swamp => 0.5..1.1,
52 ForestKind::Dead => 0.0..1.5,
53 ForestKind::Mapletree => 0.65..1.25,
54 ForestKind::Cherry => 0.45..0.75,
55 ForestKind::AutumnTree => 0.25..0.65,
56 _ => 0.0..0.0,
57 }
58 }
59
60 pub fn temp_range(&self) -> Range<f32> {
61 match self {
62 ForestKind::Palm => 0.4..1.6,
63 ForestKind::Acacia => 0.3..1.6,
64 ForestKind::Baobab => 0.4..0.9,
65 ForestKind::Oak => -0.35..0.45,
66 ForestKind::Chestnut => -0.35..0.45,
67 ForestKind::Cedar => -0.65..0.15,
68 ForestKind::Pine => -0.85..-0.2,
69 ForestKind::Redwood => -0.5..-0.3,
70 ForestKind::Frostpine => -1.8..-0.8,
71 ForestKind::Birch => -0.7..0.25,
72 ForestKind::Mangrove => 0.35..1.6,
73 ForestKind::Swamp => -0.6..0.8,
74 ForestKind::Dead => -1.5..1.0,
75 ForestKind::Mapletree => -0.15..0.25,
76 ForestKind::Cherry => -0.10..0.15,
77 ForestKind::AutumnTree => -0.45..0.05,
78 _ => 0.0..0.0,
79 }
80 }
81
82 pub fn near_water_range(&self) -> Option<Range<f32>> {
83 match_some!(self,
84 ForestKind::Palm => 0.35..1.8,
85 ForestKind::Swamp => 0.5..1.8,
86 )
87 }
88
89 pub fn ideal_proclivity(&self) -> f32 {
91 match self {
92 ForestKind::Palm => 0.4,
93 ForestKind::Acacia => 0.6,
94 ForestKind::Baobab => 0.2,
95 ForestKind::Oak => 1.0,
96 ForestKind::Chestnut => 0.3,
97 ForestKind::Cedar => 0.3,
98 ForestKind::Pine => 1.0,
99 ForestKind::Redwood => 2.5,
100 ForestKind::Frostpine => 1.0,
101 ForestKind::Birch => 0.65,
102 ForestKind::Mangrove => 2.0,
103 ForestKind::Swamp => 1.0,
104 ForestKind::Dead => 0.01,
105 ForestKind::Mapletree => 0.65,
106 ForestKind::Cherry => 12.0,
107 ForestKind::AutumnTree => 125.0,
108 _ => 0.0,
109 }
110 }
111
112 pub fn shrub_density_factor(&self) -> f32 {
113 match self {
114 ForestKind::Palm => 0.2,
115 ForestKind::Acacia => 0.3,
116 ForestKind::Baobab => 0.2,
117 ForestKind::Oak => 0.4,
118 ForestKind::Chestnut => 0.3,
119 ForestKind::Cedar => 0.3,
120 ForestKind::Pine => 0.5,
121 ForestKind::Frostpine => 0.3,
122 ForestKind::Birch => 0.65,
123 ForestKind::Mangrove => 1.0,
124 ForestKind::Swamp => 0.4,
125 ForestKind::Mapletree => 0.4,
126 ForestKind::Cherry => 0.3,
127 ForestKind::AutumnTree => 0.4,
128 _ => 1.0,
129 }
130 }
131
132 pub fn leaf_block(&self) -> StructureBlock {
133 match self {
134 ForestKind::Palm => StructureBlock::PalmLeavesOuter,
135 ForestKind::Acacia => StructureBlock::Acacia,
136 ForestKind::Baobab => StructureBlock::Baobab,
137 ForestKind::Oak => StructureBlock::TemperateLeaves,
138 ForestKind::Chestnut => StructureBlock::Chestnut,
139 ForestKind::Cedar => StructureBlock::PineLeaves,
140 ForestKind::Pine => StructureBlock::PineLeaves,
141 ForestKind::Redwood => StructureBlock::PineLeaves,
142 ForestKind::Birch => StructureBlock::TemperateLeaves,
143 ForestKind::Mangrove => StructureBlock::Mangrove,
144 ForestKind::Giant => StructureBlock::TemperateLeaves,
145 ForestKind::Swamp => StructureBlock::TemperateLeaves,
146 ForestKind::Frostpine => StructureBlock::FrostpineLeaves,
147 ForestKind::Dead => StructureBlock::TemperateLeaves,
148 ForestKind::Mapletree => StructureBlock::MapleLeaves,
149 ForestKind::Cherry => StructureBlock::CherryLeaves,
150 ForestKind::AutumnTree => StructureBlock::AutumnLeaves,
151 }
152 }
153
154 pub fn proclivity(&self, env: &Environment) -> f32 {
155 self.ideal_proclivity()
156 * close(env.humid, self.humid_range())
157 * close(env.temp, self.temp_range())
158 * self.near_water_range().map_or(1.0, |near_water_range| {
159 close(env.near_water, near_water_range)
160 })
161 }
162}
163
164pub fn leaf_color(
165 index: IndexRef,
166 seed: u32,
167 lerp: f32,
168 sblock: &StructureBlock,
169) -> Option<Rgb<u8>> {
170 let ranges = sblock
171 .elim_case_pure(&index.colors.block.structure_blocks)
172 .as_ref()
173 .map(Vec::as_slice)
174 .unwrap_or(&[]);
175
176 ranges
177 .get(crate::util::RandomPerm::new(seed).get(seed) as usize % ranges.len())
178 .map(|range| {
179 Rgb::<f32>::lerp(
180 Rgb::<u8>::from(range.start).map(f32::from),
181 Rgb::<u8>::from(range.end).map(f32::from),
182 lerp,
183 )
184 .map(|e| e as u8)
185 })
186}
187
188pub struct TreeAttr {
191 pub pos: Vec2<i32>,
192 pub seed: u32,
193 pub scale: f32,
194 pub forest_kind: ForestKind,
195 pub inhabited: bool,
196}