1use crate::{
2 IndexRef,
3 util::{math::close, sampler::Sampler},
4};
5use common::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 self {
84 ForestKind::Palm => Some(0.35..1.8),
85 ForestKind::Swamp => Some(0.5..1.8),
86 _ => None,
87 }
88 }
89
90 pub fn ideal_proclivity(&self) -> f32 {
92 match self {
93 ForestKind::Palm => 0.4,
94 ForestKind::Acacia => 0.6,
95 ForestKind::Baobab => 0.2,
96 ForestKind::Oak => 1.0,
97 ForestKind::Chestnut => 0.3,
98 ForestKind::Cedar => 0.3,
99 ForestKind::Pine => 1.0,
100 ForestKind::Redwood => 2.5,
101 ForestKind::Frostpine => 1.0,
102 ForestKind::Birch => 0.65,
103 ForestKind::Mangrove => 2.0,
104 ForestKind::Swamp => 1.0,
105 ForestKind::Dead => 0.01,
106 ForestKind::Mapletree => 0.65,
107 ForestKind::Cherry => 12.0,
108 ForestKind::AutumnTree => 125.0,
109 _ => 0.0,
110 }
111 }
112
113 pub fn shrub_density_factor(&self) -> f32 {
114 match self {
115 ForestKind::Palm => 0.2,
116 ForestKind::Acacia => 0.3,
117 ForestKind::Baobab => 0.2,
118 ForestKind::Oak => 0.4,
119 ForestKind::Chestnut => 0.3,
120 ForestKind::Cedar => 0.3,
121 ForestKind::Pine => 0.5,
122 ForestKind::Frostpine => 0.3,
123 ForestKind::Birch => 0.65,
124 ForestKind::Mangrove => 1.0,
125 ForestKind::Swamp => 0.4,
126 ForestKind::Mapletree => 0.4,
127 ForestKind::Cherry => 0.3,
128 ForestKind::AutumnTree => 0.4,
129 _ => 1.0,
130 }
131 }
132
133 pub fn leaf_block(&self) -> StructureBlock {
134 match self {
135 ForestKind::Palm => StructureBlock::PalmLeavesOuter,
136 ForestKind::Acacia => StructureBlock::Acacia,
137 ForestKind::Baobab => StructureBlock::Baobab,
138 ForestKind::Oak => StructureBlock::TemperateLeaves,
139 ForestKind::Chestnut => StructureBlock::Chestnut,
140 ForestKind::Cedar => StructureBlock::PineLeaves,
141 ForestKind::Pine => StructureBlock::PineLeaves,
142 ForestKind::Redwood => StructureBlock::PineLeaves,
143 ForestKind::Birch => StructureBlock::TemperateLeaves,
144 ForestKind::Mangrove => StructureBlock::Mangrove,
145 ForestKind::Giant => StructureBlock::TemperateLeaves,
146 ForestKind::Swamp => StructureBlock::TemperateLeaves,
147 ForestKind::Frostpine => StructureBlock::FrostpineLeaves,
148 ForestKind::Dead => StructureBlock::TemperateLeaves,
149 ForestKind::Mapletree => StructureBlock::MapleLeaves,
150 ForestKind::Cherry => StructureBlock::CherryLeaves,
151 ForestKind::AutumnTree => StructureBlock::AutumnLeaves,
152 }
153 }
154
155 pub fn proclivity(&self, env: &Environment) -> f32 {
156 self.ideal_proclivity()
157 * close(env.humid, self.humid_range())
158 * close(env.temp, self.temp_range())
159 * self.near_water_range().map_or(1.0, |near_water_range| {
160 close(env.near_water, near_water_range)
161 })
162 }
163}
164
165pub fn leaf_color(
166 index: IndexRef,
167 seed: u32,
168 lerp: f32,
169 sblock: &StructureBlock,
170) -> Option<Rgb<u8>> {
171 let ranges = sblock
172 .elim_case_pure(&index.colors.block.structure_blocks)
173 .as_ref()
174 .map(Vec::as_slice)
175 .unwrap_or(&[]);
176
177 ranges
178 .get(crate::util::RandomPerm::new(seed).get(seed) as usize % ranges.len())
179 .map(|range| {
180 Rgb::<f32>::lerp(
181 Rgb::<u8>::from(range.start).map(f32::from),
182 Rgb::<u8>::from(range.end).map(f32::from),
183 lerp,
184 )
185 .map(|e| e as u8)
186 })
187}
188
189pub struct TreeAttr {
192 pub pos: Vec2<i32>,
193 pub seed: u32,
194 pub scale: f32,
195 pub forest_kind: ForestKind,
196 pub inhabited: bool,
197}