pixeltree

Crates.iopixeltree
lib.rspixeltree
version0.2.1
created_at2025-07-24 04:56:47.910595+00
updated_at2025-07-24 04:56:47.910595+00
descriptionA high-performance procedural 2D tree generator for pixel-art games, built with Bevy. Generate beautiful, wind-animated trees with automatic LOD and spatial culling.
homepage
repositoryhttps://github.com/notarikon-nz/pixeltree_rust
max_upload_size
id1765512
size155,603
Matt Orsborn (notarikon-nz)

documentation

README

PixelTree 🌳

A high-performance procedural 2D tree generator for pixel-art games, built with Bevy. Generate beautiful, wind-animated trees with automatic LOD and spatial culling.

Rust Bevy License: MIT

Features

Performance First

  • Zero-cost abstractions with minimal dependencies
  • Parallel generation using Rayon for forests
  • Spatial indexing for efficient culling of off-screen trees
  • Pre-computed wind tables eliminate per-frame trigonometry
  • Memory-optimized leaf data structures with ~40% less memory usage

Procedural Generation

  • Deterministic generation - same position always yields same tree
  • Customizable parameters - height, width, branching, leaf density
  • Multiple tree templates - Default, Pine, Oak, Willow
  • Stack-based branch generation - no recursion overhead

Game-Ready

  • Automatic LOD system with 4 detail levels
  • Wind animation with customizable strength and turbulence
  • GPU instancing support for rendering thousands of trees
  • Compact serialization for save files and networking

Quick Start

use bevy::prelude::*;
use pixeltree::*;

fn main() {
    App::new()
        .add_plugins((DefaultPlugins, PixelTreePlugin))
        .add_systems(Startup, setup)
        .run();
}

fn setup(
    mut commands: Commands,
    mut spatial_index: ResMut<TreeSpatialIndex>,
) {
    // Spawn a single tree
    let params = GenerationParams {
        height_range: (80.0, 120.0),
        wind_params: WindParams {
            strength: 2.0,
            frequency: 1.5,
            turbulence: 0.3,
            direction: Vec2::new(1.0, 0.0),
        },
        ..default()
    };
    
    spawn_tree(
        &mut commands, 
        Vec3::new(0.0, 0.0, 0.0), 
        params,
        &mut spatial_index,
    );
}

Advanced Usage

Generate a Forest

// Generate 100 trees in parallel
let positions: Vec<Vec2> = (0..100)
    .map(|i| Vec2::new(
        (i % 10) as f32 * 50.0 - 250.0,
        (i / 10) as f32 * 50.0 - 250.0,
    ))
    .collect();

spawn_forest(&mut commands, positions, params, &mut spatial_index);

Deterministic Generation

// Trees at the same position will always look identical
let tree = generate_tree_deterministic(
    Vec2::new(100.0, 50.0), 
    &params
);

Custom Tree Templates

let params = GenerationParams {
    template: TreeTemplate::Pine,
    height_range: (100.0, 150.0),
    branch_angle_variance: 25.0, // More upright branches
    ..default()
};

Query Visible Trees

fn render_visible_trees(
    spatial_index: Res<TreeSpatialIndex>,
    camera: Query<&Transform, With<Camera>>,
) {
    let camera_pos = camera.single().translation.truncate();
    let view_bounds = Rect::from_center_size(camera_pos, Vec2::splat(500.0));
    
    let visible_trees = spatial_index.get_visible_trees(view_bounds);
    // Only process visible trees...
}

Cargo Dependencies

[dependencies]
bevy = "0.16.1"
rand = "0.8"
serde = { version = "1.0", features = ["derive"] }
rayon = "1.7"

License

MIT License - see LICENSE for details.

Commit count: 0

cargo fmt