use bevy::color::Color;
use bevy::math::Vec2;
use bevy::reflect::Reflect;
pub use crate::crown::CrownShape;
pub use crate::growth::GrowthParams;
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Reflect)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum TrunkTermination {
#[default]
FlatCap,
PointedTip,
LeaderBranch,
}
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Reflect)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum LeafStyle {
#[default]
CrossedPlanes,
SingleQuad,
ClusterSphere,
StarBurst,
NeedleCluster,
}
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Reflect)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum FoliagePlacement {
#[default]
TerminalBranches,
AllBranches,
TipClusters,
}
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Reflect)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum LeafOrientation {
#[default]
RadialOutward,
FollowBranch,
RandomUpward,
HorizontalSpread,
}
#[derive(Clone, Debug, PartialEq, Reflect)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TrunkParams {
pub height: f32,
pub radius: f32,
pub radial_segments: u32,
pub height_segments: u32,
pub taper: f32,
pub taper_curve: f32,
pub flare: f32,
pub randomness: f32,
pub root_flare_count: u32,
pub root_flare_spread: f32,
pub root_flare_height: f32,
pub termination: TrunkTermination,
pub leader_length: f32,
pub leader_taper: f32,
pub leader_has_branches: bool,
pub twist: f32,
}
impl Default for TrunkParams {
fn default() -> Self {
Self {
height: 5.0,
radius: 0.5,
radial_segments: 8,
height_segments: 4,
taper: 0.3,
taper_curve: 0.5,
flare: 1.0,
randomness: 0.0,
root_flare_count: 0,
root_flare_spread: 0.5,
root_flare_height: 0.15,
termination: TrunkTermination::FlatCap,
leader_length: 0.15,
leader_taper: 0.1,
leader_has_branches: false,
twist: 0.0,
}
}
}
#[derive(Clone, Debug, PartialEq, Reflect)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct BranchParams {
pub start: f32,
pub end: f32,
pub density: f32,
pub length: f32,
pub angle: f32,
pub radius_ratio: f32,
pub taper: f32,
pub phyllotaxis_angle: f32,
pub randomness: f32,
pub up_attraction: f32,
pub recursion: u32,
pub sub_branch_count: u32,
pub sub_branch_scale: f32,
pub length_variation: f32,
pub sub_branch_position_bias: f32,
pub apical_dominance: f32,
pub flatness: f32,
pub angle_curve: f32,
pub crown_angle_variation: f32,
pub twist: f32,
pub gravity_strength: f32,
pub stiffness: f32,
pub break_chance: f32,
pub crown_shape: CrownShape,
pub crown_influence: f32,
pub floor_avoidance: bool,
pub floor_level: f32,
pub min_twig_radius: f32,
}
impl Default for BranchParams {
fn default() -> Self {
Self {
start: 0.3,
end: 0.9,
density: 1.0,
length: 0.4,
angle: 45.0,
radius_ratio: 0.3,
taper: 0.7,
phyllotaxis_angle: 137.5,
randomness: 0.2,
up_attraction: 0.1,
recursion: 1,
sub_branch_count: 2,
sub_branch_scale: 0.5,
length_variation: 0.15,
sub_branch_position_bias: 0.0,
apical_dominance: 0.5,
flatness: 0.0,
angle_curve: 0.0,
crown_angle_variation: 0.0,
twist: 0.0,
gravity_strength: 0.0,
stiffness: 0.5,
break_chance: 0.0,
crown_shape: CrownShape::Cylindrical,
crown_influence: 1.0,
floor_avoidance: true,
floor_level: 0.0,
min_twig_radius: 0.005,
}
}
}
#[derive(Clone, Debug, PartialEq, Reflect)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct SplitParams {
pub enabled: bool,
pub probability: f32,
pub angle: f32,
pub position: f32,
pub radius_threshold: f32,
}
impl Default for SplitParams {
fn default() -> Self {
Self {
enabled: false,
probability: 0.3,
angle: 30.0,
position: 0.5,
radius_threshold: 0.05,
}
}
}
#[derive(Clone, Debug, PartialEq, Reflect)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct MeshParams {
pub smooth_iterations: u32,
pub smooth_factor: f32,
pub adaptive_resolution: bool,
pub resolution_scale: f32,
pub min_radial_segments: u32,
pub max_radial_segments: u32,
pub pipe_radius_enabled: bool,
pub pipe_radius_exponent: f32,
pub pipe_radius_min: f32,
pub collar_enabled: bool,
pub collar_length: f32,
}
impl Default for MeshParams {
fn default() -> Self {
Self {
smooth_iterations: 0,
smooth_factor: 0.5,
adaptive_resolution: false,
resolution_scale: 16.0,
min_radial_segments: 4,
max_radial_segments: 16,
pipe_radius_enabled: false,
pipe_radius_exponent: 2.0,
pipe_radius_min: 0.02,
collar_enabled: true,
collar_length: 1.5,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Reflect)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum LeafScan {
Oak,
Willow,
Birch,
Bonsai,
Maple,
Poplar,
JapaneseMaple,
}
impl LeafScan {
pub const ALL: [LeafScan; 7] = [
LeafScan::Oak,
LeafScan::Willow,
LeafScan::Birch,
LeafScan::Bonsai,
LeafScan::Maple,
LeafScan::Poplar,
LeafScan::JapaneseMaple,
];
}
#[derive(Clone, Debug, PartialEq, Reflect)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct FoliageParams {
pub enabled: bool,
pub style: LeafStyle,
pub placement: FoliagePlacement,
pub orientation: LeafOrientation,
pub density: f32,
pub cluster_size: u32,
pub leaf_size: f32,
pub leaf_size_variation: f32,
pub radius_threshold: f32,
pub height_falloff: f32,
pub droop: f32,
pub rotation_variation: f32,
pub use_crown_density: bool,
pub normal_bend: f32,
pub color_variation: f32,
pub hue_variation: f32,
pub occlusion: f32,
pub color: Color,
pub shading: LeafShading,
pub scan: Option<LeafScan>,
pub autumn: Option<Color>,
}
impl Default for FoliageParams {
fn default() -> Self {
Self {
enabled: true,
style: LeafStyle::CrossedPlanes,
placement: FoliagePlacement::TerminalBranches,
orientation: LeafOrientation::RadialOutward,
density: 3.0,
cluster_size: 4,
leaf_size: 0.3,
leaf_size_variation: 0.15,
radius_threshold: 0.15,
height_falloff: 0.3,
droop: 0.2,
rotation_variation: 0.5,
use_crown_density: true,
normal_bend: 0.8,
color_variation: 0.3,
hue_variation: 0.3,
occlusion: 0.6,
color: Color::srgb(0.133, 0.545, 0.133),
shading: LeafShading::default(),
scan: None,
autumn: None,
}
}
}
#[derive(Clone, Debug, PartialEq, Reflect)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct LeafShading {
pub translucency: f32,
pub transmission_tint: Color,
pub roughness: f32,
pub veins: f32,
pub underside: f32,
}
impl Default for LeafShading {
fn default() -> Self {
Self {
translucency: 1.0,
transmission_tint: Color::srgb(1.0, 0.95, 0.55),
roughness: 0.55,
veins: 0.5,
underside: 0.25,
}
}
}
#[derive(Clone, Debug, PartialEq, Reflect)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct WindResponse {
pub sway: f32,
pub flutter: f32,
pub sway_frequency: f32,
pub flutter_frequency: f32,
}
impl Default for WindResponse {
fn default() -> Self {
Self { sway: 1.0, flutter: 1.0, sway_frequency: 1.0, flutter_frequency: 1.0 }
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Reflect)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum BarkScan {
Oak,
Pine,
Willow,
Birch,
Palm,
Cedar,
Zelkova,
Maple,
KnottedPine,
Sakura,
PalmTree,
Hackberry,
Brown,
Metasequoia,
}
impl BarkScan {
pub const ALL: [BarkScan; 14] = [
BarkScan::Oak,
BarkScan::Pine,
BarkScan::Willow,
BarkScan::Birch,
BarkScan::Palm,
BarkScan::Cedar,
BarkScan::Zelkova,
BarkScan::Maple,
BarkScan::KnottedPine,
BarkScan::Sakura,
BarkScan::PalmTree,
BarkScan::Hackberry,
BarkScan::Brown,
BarkScan::Metasequoia,
];
pub fn tile_size(self) -> Vec2 {
match self {
BarkScan::Oak | BarkScan::Cedar => Vec2::new(1.0, 2.0),
BarkScan::Pine => Vec2::new(2.0, 2.0),
BarkScan::Willow | BarkScan::Brown => Vec2::ONE,
BarkScan::Birch => Vec2::splat(0.6),
BarkScan::Palm => Vec2::splat(1.86),
BarkScan::Zelkova | BarkScan::Maple => Vec2::splat(1.8),
BarkScan::Hackberry => Vec2::new(1.8, 3.6),
BarkScan::KnottedPine => Vec2::splat(1.7),
BarkScan::Sakura => Vec2::splat(1.6),
BarkScan::PalmTree => Vec2::new(1.3, 2.6),
BarkScan::Metasequoia => Vec2::splat(1.94),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Reflect)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct BarkParams {
pub scan: Option<BarkScan>,
pub smooth_below: f32,
pub fissured_above: f32,
}
impl Default for BarkParams {
fn default() -> Self {
Self { scan: None, smooth_below: 0.03, fissured_above: 0.15 }
}
}
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash, Reflect)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum RenderStyle {
#[default]
Natural,
Painterly,
Toon,
}
#[derive(Clone, Debug, PartialEq, Reflect)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TreeParams {
pub seed: i32,
pub trunk: TrunkParams,
pub branches: BranchParams,
pub split: SplitParams,
pub mesh: MeshParams,
pub foliage: FoliageParams,
pub growth: GrowthParams,
pub wind: WindResponse,
pub trunk_color: Color,
pub bark: BarkParams,
pub style: RenderStyle,
}
impl Default for TreeParams {
fn default() -> Self {
Self {
seed: 42,
trunk: TrunkParams::default(),
branches: BranchParams::default(),
split: SplitParams::default(),
mesh: MeshParams::default(),
foliage: FoliageParams::default(),
growth: GrowthParams::default(),
wind: WindResponse::default(),
trunk_color: Color::srgb(0.545, 0.271, 0.075),
bark: BarkParams::default(),
style: RenderStyle::Natural,
}
}
}