bevy_flora
⚠️ Vibe Coded. This crate was written by an AI agent working from a human's direction. It is covered by tests and by a rendered visual QA loop (
qa/visual_findings.mdin the repository), but it has had no line-by-line human audit. Read it before you trust it.
Parametric, stylized procedural trees for Bevy that grow over time. Pick one of 15 presets or tune every parameter, spawn a component, and watch a seedling grow into a mature tree. The same seed always gives the same tree.

cargo run --release --example capture_growth: the oak preset from age 0 to maturity, one frame per age step.
Compatibility
bevy_flora |
bevy |
Rust |
|---|---|---|
| 0.2 | 0.20 | 1.97.1+ (edition 2024) |
Install
[]
= "0.2"
| feature | default | what it does |
|---|---|---|
serde |
— | Serialize / Deserialize on every parameter type, so trees can be authored in RON or JSON |
The library depends on bevy with default features off (std, bevy_asset, bevy_color, bevy_mesh, bevy_pbr), so it adds no windowing or audio to a build.
Quickstart
Add the plugin and spawn a tree. Growing advances its age every frame until it is mature; leave it off and set TreeAge yourself (the default, f32::INFINITY, is the mature tree).
use *;
use ;
The plugin keeps two child entities on each tree (wood and leaves) and rebuilds their meshes whenever ProceduralTree or TreeAge changes. It sends a TreeGenerated message after each rebuild.
Without the plugin
build_tree is a pure function from parameters and age to CPU meshes and the aged skeleton, so you can bake trees offline, feed your own renderer, or build colliders from the skeleton:
use ;
let params = Pine.params;
let tree = build_tree;
let wood = tree.trunk.clone.into_bevy_mesh; // bevy::mesh::Mesh
let leaves = tree.foliage.into_bevy_mesh;
assert!;
Features
- 15 presets: oak, pine, willow, birch, palm, cypress, bonsai, maple, spruce, poplar, baobab, dragon tree, Japanese maple, dead tree and redwood. Each is a plain
TreeParamsvalue you can edit. - Growth over time. Every branch has a birth age and a growth duration, derived from where it sits on the tree. A tree can be shown at any age, branches thicken after they lengthen, and leaves grow to full size without re-rolling or disappearing as the tree ages.
- Deterministic. Each branch draws randomness from its own seeded stream, so the same
seedgives the same tree on every run, and aging never re-rolls branches or leaves that already exist. - Branch shape: crown envelopes, phyllotaxis, apical dominance, Y-splits, recursive sub-branches, twist, and a gravity bend that sub-branches and leaves follow. Floor avoidance keeps even strongly drooping wood above the ground.
- Closed wood. Branches meet the trunk through flared collars and root segments, forks taper into their halves, and trunk tops end in a flat cap, a cone or a leader branch. Optional pipe-model radii, radius-adaptive ring counts and volume-preserving (Taubin) smoothing that keeps seams, branch ends and twig seats in place.
- Leaves: five styles (crossed planes, single quad, cluster sphere, star burst, needle cluster), three placements (terminal branches, all branches, tip clusters) and four orientations. Leaf cards are leaf-shaped (cut into the geometry, so there is no alpha-mask
discard) and grow out of their twigs, crowns shade as one soft volume through crown-bent normals (normal_bend), and each leaf gets its own brightness through a vertex colour (color_variation). All of it is baked into the mesh, so the stockStandardMaterialis enough and no custom shader is involved. The leaf material is translucent, so back-lit leaves are not black.
Examples
| example | what it shows |
|---|---|
showcase |
An interactive growing tree. Right-drag / wheel orbits, [ ] cycle presets, N reseeds, Space toggles growth, R restarts, M jumps to mature, G rebuilds. |
gallery |
Renders 289 scenarios (every preset at several ages and seeds, forced splits, smoothing and pipe radii on every preset, every leaf style × placement × orientation, every crown shape, parameter extremes) offscreen to four-view PNGs plus a stats.tsv with mesh sanity flags. This is the visual QA harness. --filter <substr> narrows it. |
capture_growth |
Records the clip above as numbered PNG frames. |
How it works
TreeParams → skeleton (a node tree of trunk, leader, primaries, splits and sub-branches) → birth times → the skeleton at a given age → wood mesh and leaf points → MeshData → Bevy Mesh. ARCHITECTURE.md has the details and the invariants (winding, bend, junctions) the meshers rely on.
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.