Final Post – Digital Bonsai

Generating Digital Bonsai: A Journey into Procedural Art Generation

Digital art has always fascinated me, especially when it intersects with the delicate world of generative design. Thus, I want to share my journey of creating a procedural bonsai tree generation system that blends computational creativity with the subtle art of nature.

The Concept: Algorithmic Nature

The project began with a simple yet ambitious goal: to create a digital bonsai that could be generated with a single mouse click. Unlike traditional digital art methods, this approach uses complex algorithms to simulate the organic growth and intricate details of a living tree.

Key Algorithmic Innovations

  1. Bezier Curve Branch Generation: The heart of the system lies in using Bezier curves to create naturally curved branches. By carefully calculating control points, we simulate the unpredictable growth patterns of real trees.
  2. Recursive Branch Creation: Each branch can spawn child branches with decreasing complexity, mimicking how real trees develop their intricate structures.
  3. Procedural Leaf Placement: Leaves aren’t simply placed arbitrarily. The algorithm ensures they’re distributed naturally, with minimal overlap and variation in size and angle.

Technical Challenges

Creating a realistic tree generation system was no small feat. Some of the most significant challenges included:

  • Performance Optimization: Generating complex tree structures with multiple branches and leaves requires careful computational management.
  • Natural Randomness: Ensuring that randomness feels organic and not mechanically generated.
  • Detailed Rendering: Creating subtle details like wood grain, branch tapering, and leaf variations.

Notable Features

Sophisticated Branch Rendering

The Branch class is a marvel of computational design. It doesn’t just draw lines but creates:

  • Gradient-based wood coloration
  • Varying branch widths
  • Subtle wood texture details
  • Smooth, organic branch curves

Environmental Context

The program doesn’t just generate a tree in isolation. It creates a complete scene with:

  • A textured mountain background
  • A detailed ceramic pot
  • A noise-based background that adds depth and atmosphere

Interactive Generation

With a simple mouse click, users can generate entirely unique bonsai trees, making each creation a one-of-a-kind digital artwork.

The Beauty of Procedural Art

What makes this project special is how it bridges computational thinking with artistic expression. Each generated tree is unique, yet follows rules that make it feel natural and alive.

The code uses techniques like:

  • Noise-based color generation
  • Bezier curve mathematics
  • Recursive algorithms
  • Randomness with controlled constraints

Technical Highlights

// Example of branch generation logic 
generateChildBranches(depth) { 
if (depth <= 0) { 
this.generateLeaves(); return; 
} // Probabilistic branch creation 
const rand = random(1); 
const numBranches = rand < 0.02 ? 3 : rand < 0.16 ? 2 : rand < 0.4 ? 1 : 0; 
}

 

This snippet shows how even branch creation follows probabilistic rules, ensuring variety without complete randomness.

Conclusion

Procedural art generation is more than just creating images—it’s about encoding the complexity of natural systems into mathematical and computational frameworks. This bonsai generation system is a testament to how code can capture the essence of organic growth.

Whether you’re a programmer, an artist, or simply someone who appreciates the intersection of technology and nature, I hope this journey through algorithmic bonsai generation has inspired you to see code as a creative medium.

Digital Bonsai

Design Concept

The Digital Bonsai project explores the intersection of traditional Japanese bonsai art and generative design. While physical bonsai takes years of careful cultivation, this digital interpretation allows instant exploration of organic growth patterns while maintaining the meditative qualities of bonsai shaping.

The artistic intention is to create a space where users can experience the joy of bonsai creation without the time investment, while still appreciating the core aesthetic principles of balance, asymmetry, and naturalness that define bonsai art.

Sketch

Mermaid State Diagram

 

stateDiagram-v2
[*] --> Initial: Load Canvas
Initial --> TrunkPlacement: User Click
TrunkPlacement --> BranchGrowth: Generate Trunk
BranchGrowth --> LeafPlacement: Create Branches
LeafPlacement --> Complete: Add Foliage

Complete --> TrunkPlacement: New Click

note right of TrunkPlacement
Click position determines:
- Trunk height
- Growth direction
- Initial thickness
end note

note right of BranchGrowth
Organic branching using:
- Bezier curves
- Width inheritance
- Natural tapering
end note

note right of LeafPlacement
Leaf generation at:
- Branch terminals
- Random variations
- Clustered groups
end note

Current Implementation

The base sketch uses a three-class system:

  1. Node class: Handles growth points and branching decisions
  2. Branch class: Manages the organic curves and width inheritance
  3. Leaf class: Controls foliage generation and placement

Key features:

  • Bezier curves for natural branch flow
  • Dynamic width tapering
  • Organic branching patterns
  • Terminal leaf generation
  • Wood texture simulation
  • Smooth joint transitions

Future Improvements

  1. Enhanced Naturalism
    • Bark texture variations
    • Age-based characteristics
    • Growth rings
    • Branch scarring
  2. Environmental Factors
    • Wind effects
    • Gravity influence
    • Light-seeking behavior
    • Season changes
  3. Interactive Features
    • Pruning tools
    • Branch wiring
    • Growth time-lapse
    • Style presets (formal upright, cascade, etc.)

Game of Life +

The Concept

I created an interactive implementation of Conway’s Game of Life with customizable rules and real-time editing capabilities. What makes this version special is its focus on experimentation and accessibility – users can modify the simulation rules while it’s running or pause to edit patterns directly. The interface is designed to be intuitive while offering deep customization options.

Code Highlight

I’m particularly proud of the updateGrid() function, which handles the core cellular automaton logic:

javascript
function updateGrid() {
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
let neighbors = countNeighbors(grid, i, j);
let state = grid[i][j];
// Apply rules
if (state === 0 && neighbors === rules.birthRule) {
nextGrid[i][j] = 1;
} else if (state === 1 && (neighbors >= rules.survivalMin && neighbors <= rules.survivalMax)) {
nextGrid[i][j] = 1;
} else {
nextGrid[i][j] = 0;
}
}
}
}

This code is elegant in its simplicity while being highly flexible. Instead of hardcoding Conway’s traditional rules (birth on 3 neighbors, survival on 2 or 3), it uses variables for birth and survival conditions. This allows users to experiment with different rule sets and discover new patterns. The clean separation between rule checking and grid updating also makes it easy to modify or extend the behavior.

The Sketch

The sketch provides a full-featured cellular automata playground with:

  • Real-time rule modification
  • Custom color selection
  • Variable brush sizes for drawing
  • Grid visualization when paused
  • Clear and random pattern generation
  • A reset button to restore default settings
  • Numerical feedback for all parameters

Reflections and Future Improvements

Working on this project revealed several interesting possibilities for future enhancements:

  1. Pattern Library
    • Add ability to save and load interesting patterns
    • Include a collection of classic Game of Life patterns (gliders, spaceships, etc.)
    • Allow users to share patterns with others
  2. Enhanced Visualization
    • Add cell age visualization (cells could change color based on how long they’ve been alive)
    • Include heat maps showing areas of high activity
    • Add trail effects to show pattern movement
  3. Extended Controls
    • Add speed control for the simulation
    • Implement step-by-step mode for analyzing pattern evolution
    • Add undo/redo functionality for drawing
    • Allow custom grid sizes
  4. Analysis Features
    • Add population graphs showing cell count over time
    • Include pattern detection to identify common structures
    • Add statistics about pattern stability and periodicity

The current implementation provides a solid foundation for exploring cellular automata, but there’s still much room for expansion. The modular design makes it easy to add these features incrementally while maintaining the core functionality.

The most interesting potential improvement would be adding pattern analysis tools. Being able to track population changes and identify stable structures could help users understand how different rules affect pattern evolution. This could make the sketch not just a creative tool, but also a valuable educational resource for studying emergent behavior in cellular automata.

Matter.js Game

For my latest coding project, I combined the p5.js and Matter.js libraries to create an interactive game where the player controls a windmill to catch falling particles. The objective is simple yet addictive: catch as many particles in the moving goal as possible, aiming to reach 30 points before the timer runs out. The game features an interactive timer, a scoring system, and a dynamic win screen that displays the final time. Let’s take a closer look at the concept, code, and potential future improvements.

Concept

This project was inspired by classic arcade games, where the focus is on timing and precision. I wanted to create something that required player control and had a clear objective, so I added a rotating windmill controlled by the arrow keys and a particle-spawning system. The goal moves across the bottom of the screen, and every particle that lands inside scores a point. If the player scores 20 points, they win the game! After winning, the player can restart the game by clicking anywhere on the screen.

Embedded Sketch

https://editor.p5js.org/is2431/sketches/oE836dc9v

Reflection and Future Work

Reflecting on the process, I enjoyed exploring how Matter.js could be used to create physics-based interactions in a p5.js sketch. The windmill mechanism, in particular, felt satisfying to code as it introduced realistic physics to the player’s actions. However, one challenge was balancing interactivity and performance, especially when handling a high number of particles on-screen.

Ideas for Future Improvements

For future iterations, I’d like to explore the following improvements:

  1. Enhanced Visuals: Adding particle effects or animations when a particle hits the goal could add visual excitement to the game.
  2. Power-Ups and Obstacles: Introducing occasional power-ups that temporarily increase the windmill’s rotation speed or make the particles larger, as well as obstacles that reduce the score, could add depth and strategy.
  3. Difficulty Levels: Implementing levels with progressively faster-moving goals or smaller particle sizes would increase the challenge and extend playability.
  4. Mobile Compatibility: Adapting the game for mobile by adding touch-based controls for the windmill could open it up to more users.

I hope you enjoyed this walkthrough of my proje

Free Flowing Flocking System

The Concept

I wanted to create a system that goes beyond traditional boid flocking behavior. The goal was to craft a visual experience that tells a story through motion, tension, and release. The system transitions between free-flowing states and complex mathematical formations, all while maintaining the organic feel of natural flocking behavior.

The particles move through several distinct phases:

  1. Free-flowing exploration
  2. Lissajous curve formations
  3. Logarithmic spiral patterns
  4. Mandala-like circular arrangements
  5. A parametric heart shape with controlled chaos

Each phase has its own character, with carefully tuned parameters for alignment, cohesion, and separation that give it a unique feel while maintaining visual coherence with the whole piece.

Technical Highlight

One of the most challenging aspects was creating smooth transitions when particles wrap around screen edges. Traditional edge wrapping creates jarring visual artifacts – straight lines cutting across the screen. The solution involves calculating the closest position between two particles, considering wrapped positions around screen edges. This ensures smooth flocking behavior even when some particles are on opposite sides of the screen. When combined with history clearing during wrapping, it eliminates the visual artifacts that often plague edge-wrapping systems.

Color and Visual Design

The visual design draws inspiration from natural phenomena – deep sea bioluminescence, sunset plasma, and aurora borealis. Each color scheme transitions smoothly into the next, creating a constantly evolving palette that complements the movement patterns.

The particle trails add a sense of history to the motion, creating organic flowing lines that help viewers understand the system’s evolution. The trail length and opacity are carefully tuned to create a balance between showing motion history and maintaining visual clarity.

Reflections and Future Work

While I’m pleased with the current state of the project, there are several exciting directions for future development:

  1. 3D Extensions: Expanding the system into three dimensions would open up possibilities for more complex formations and viewpoint changes.
  2. Interactive Elements: Adding user interaction through mouse movement or touch could create interesting disruptions in the flocking patterns.
  3. Performance Optimization: While the current system handles 150 particles smoothly, optimizing the spatial partitioning could allow for thousands of particles, creating even more complex emergent patterns.

The most interesting aspect of this project has been finding the sweet spot between chaos and order – allowing enough randomness to keep the system feeling organic while maintaining the mathematical beauty of the formations. It’s a delicate balance that mirrors many natural systems, where simple rules give rise to complex, beautiful behaviors.

Interactive Leader-Follower Flow Field System

Concept & Inspiration

The core idea is to simulate organic movement patterns similar to those found in nature – think schools of fish following a leader, or birds in a murmuration. But rather than just create a basic flocking system, we can add an extra layer of complexity by having the leader influence both its direct followers and the underlying environment (represented by the flow field).

The key elements that make this interesting are:

  1. Dual control modes – users can either directly control the leader or let it wander autonomously
  2. Multi-layered interaction between all elements
  3. Visual representation of movement through light and color

Embedded Sketch

https://editor.p5js.org/is2431/sketches/mMoMzqnax

Technical Highlights

One of the most elegant parts of the system is how it combines multiple forces to create natural-looking movement. Each follower vehicle considers:

  • The flow field’s direction
  • The leader’s predicted future position
  • Separation from nearby vehicles

By carefully balancing these forces (with weights of 1.0, 2.0, and 1.5 respectively), I created movement that feels organic rather than mechanical. The followers don’t just mindlessly chase the leader – they flow around each other while generally moving in the desired direction.

The dynamic flow field is another crucial element. Rather than staying static, it gradually aligns itself with the leader’s movement. This creates a beautiful effect where the leader appears to “part the waters” as it moves through space, influencing not just its direct followers but the entire environment.

Visual Design

The visual aesthetic emphasizes the fluid, organic nature of the system through:

  • Glowing particles that intensify with speed
  • Color gradients that shift based on movement
  • Fading trails that show movement history
  • Additive blending for light-like effects

Future Improvements

While the current system creates engaging visuals, there’s room for expansion:

    1. Behavioral Enhancements:
      • Multiple leaders with different influences
      • Mood states affecting swarm behavior
      • Predator-prey relationships
      • Environmental obstacles
    2. Visual Improvements:
      • Particle systems for more dynamic effects
      • Interactive environment modifications
      • Force visualization options
    3. Performance Optimization:
      • Spatial partitioning for collision detection
      • WebGL implementation
    4. Interactive Features:
      • System parameter controls
      • Drawing tools for obstacles
      • Interactive mood controls

Reflection

The most fascinating aspect of this project is how simple rules can create complex, organic-looking behavior. Each vehicle follows basic physics and a few steering behaviors, yet together they create flowing patterns that feel alive and natural.

The balance between chaos and order is crucial – too much structure makes it mechanical, too little makes it random. Finding that sweet spot where the movement feels both purposeful and unpredictable was one of the most rewarding aspects of the project.

This system could be adapted for various applications:

  • Generative art installations
  • Educational visualizations of complex systems
  • Interactive music visualizations
  • Game mechanics based on emergent behavior

The code provides a foundation for experimenting with swarm behavior, flow fields, and interactive visualizations. Each component can be modified or enhanced independently, making it a great starting point for further exploration.

Generating Voronoi Cells with a Noise Overlay

Project Concept and Design

The goal of this project was to create an interactive Voronoi diagram that responds dynamically to user input and produces aesthetically compelling outputs by adding generative noise. The idea stemmed from the desire to visualize Voronoi patterns, which are generated by partitioning a canvas into regions based on the distance to a set of given points. Each point acts as a “cell center,” and the area around it forms its own unique region.

The primary objectives of the project were to:

  1. Develop an interactive tool that allows users to generate and explore Voronoi diagrams.
  2. Implement different visual variations using color noise and dynamic borders.
  3. Introduce a mechanism for rendering high-quality SVG exports, so users can save and share their creations.

https://photos.app.goo.gl/9BCq82kGNhyzQprz9

Click the screen to put down a cell. WARNING: Cell generation takes time.

 

Key Components and Design Decisions

  1. Concept of Voronoi Diagrams: Voronoi diagrams divide a plane into cells based on the distance to a set of points. Each point is the “seed” of a cell, and the cell comprises all the points closer to that seed than to any other. By using the Euclidean distance between each point on the canvas and each seed, I determined which cell a given pixel belonged to. This was implemented in the code using nested loops iterating over every pixel on the canvas.
  2. User Interactivity: To make the program interactive, I incorporated mouse-based interaction. Users can click anywhere on the canvas to add new cell centers, which dynamically redraws the entire Voronoi diagram. This way, users can create and explore different patterns based on the arrangement of cell centers.
  3. Generative Art Techniques: Instead of filling each Voronoi cell with a solid color, I wanted to experiment with visual noise to give a more organic feel. I used Perlin noise (noise()) to create outlines reminiscent of a height map. This produces a grainy texture that adds depth and uniqueness to each cell while retaining the overall Voronoi structure.
  4. Border Detection: One of the most critical visual elements in Voronoi diagrams is the border between cells. I implemented a pixel-based edge detection by comparing each pixel’s color with its right and lower neighbors. If the colors differed, it indicated a boundary, and I set that pixel’s color to black to create crisp, clear borders.

Project Development and Challenges

  1. Implementing Voronoi Calculations Efficiently: The first major hurdle was the efficiency of the Voronoi generation. Each pixel needs to be classified based on its distance to all cell centers, which scales poorly as more cells are added. I attempted optimizations, such as limiting the range of cells to check based on a maximum radius, but these did not yield significant performance improvements.
  2. Handling Color Transitions with Noise: Initially, I experimented with applying noise to the entire canvas indiscriminately, but this made it difficult to distinguish cell boundaries. I resolved this by using a lower noise scale and blending the cell color with a base color (white) to reduce visual clutter while retaining a natural texture.
  3. Anti-Aliasing and Edge Smoothing: A key issue was achieving smooth edges, especially along cell borders. I attempted to implement anti-aliasing by blending pixel colors based on their distance to the border, but this proved difficult within p5.js’s pixel-based drawing environment. Ultimately, I increased the pixelDensity() to minimize aliasing artifacts.

The Most Complex and Frightening Part

The most daunting part of this project was optimizing the Voronoi generation algorithm. Due to the pixelwise nature of the computation, the performance dropped rapidly as the number of cells increased. To minimize this risk, I conducted experiments with various distance calculation optimizations, such as bounding box checks and region partitioning, but none provided a breakthrough solution. Ultimately, I accepted that the current implementation, while not perfectly optimized, is still effective for typical canvas sizes and cell counts.

What I Would Do Differently

If I had more time, I would:

  1. Implement a more efficient Voronoi generation using a Fortune’s Algorithm, which scales better than pixel-based methods.
  2. Experiment with different visualizations, such as using curves or gradient fills for cell interiors.
  3. Create a more advanced edge detection algorithm that produces smoother, anti-aliased borders without compromising on performance.

Final Thoughts

This project pushed my understanding of generative art and computational geometry. By exploring different variations and solving various challenges, I was able to produce a compelling, interactive system that not only generates Voronoi diagrams but also serves as a tool for artistic exploration. Though there are areas for improvement, I am satisfied with the current state of the program and look forward to iterating on it further in the future.

Ripple Cubes

https://editor.p5js.org/is2431/sketches/FM0-hjygj

 

Description of the Code

This p5.js sketch creates a 3D cube grid with a dynamic ripple effect. Each cube’s vertical position oscillates based on its distance from the center, while its color changes according to its depth (z coordinate). The concept is inspired by natural wave patterns, where the ripple effect imitates waves traveling through the surface, and color gradients add depth perception to the 3D space. The visual result is a dynamic, pulsating cube, creating an engaging, hypnotic effect.

Functions and Organization

The program organizes the core logic in the draw() function, which is responsible for rendering each frame of the sketch. The ripple effect is achieved through a combination of sin() and dist() functions to compute the oscillation offsets, and the color fill is managed by mapping the z values to RGB values.

Variable and Function Naming

  • w stands for the width of each cube, ensuring the ripple and grid are proportional.
  • rippleHeight controls the amplitude of the waves.
  • cols and rows are used for calculating how many cubes fill the canvas based on the grid spacing.

Reflection and Future Improvements

I’m proud of how well the ripple effect integrates with the 3D rendering and color mapping. However, future improvements could involve adding user interactivity, allowing control over ripple speed, amplitude, or even camera rotation. Another potential idea could be integrating sound, where the ripple responds to external audio input or ambient sounds, enhancing the immersive experience.

The sketch could also evolve into more complex 3D shapes, expanding from simple cubes to spheres or even irregular polygons, to add variety and depth to the visual.

 

Attractors

Concept and Inspiration:

Clifford attractors are fascinating mathematical objects that produce intricate patterns when iteratively calculated. I was inspired by the work of Paul Bourke who uses similar concepts to create mesmerizing visuals.

Code Breakdown:

class Attractor {
  constructor() {
    // Generate random parameters for the attractor equation
    this.a = random(-2, 2);
    this.b = random(-2, 2);
    this.c = random(0.5, 2);
    this.d = random(0.5, 2);
    this.pos = createVector(0, 0); // Initial position

    // Assign two random colors for interpolation
    this.color1 = color(random(255), random(255), random(255));
    this.color2 = color(random(255), random(255), random(255));
  }

  update() {
    // Calculate the next position based on the attractor equation
    let xNext = sin(this.a * this.pos.y) + this.c * cos(this.a * this.pos.x);
    let yNext = sin(this.b * this.pos.x) + this.d * cos(this.b * this.pos.y);
    this.pos.set(xNext, yNext);
  }

  show() {
    // Map the attractor's position to screen coordinates
    let xScreen = map(this.pos.x, -3, 3, 0, width);
    let yScreen = map(this.pos.y, -3, 3, 0, height);

    // Interpolate between the two colors based on position magnitude
    let lerpAmount = map(this.pos.mag(), 0, 5, 0, 1);
    let lerpedColor = lerpColor(this.color1, this.color2, lerpAmount);

    stroke(lerpedColor); // Set the stroke color
    point(xScreen, yScreen); // Draw a point at the calculated position
  }
}

let attractors = [];

function setup() {
  createCanvas(400, 400);
  background(220);

  // Create an array of attractors
  for (let i = 0; i < 5; i++) {
    attractors.push(new Attractor());
  }
}

function draw() {
  background(220, 10); // Fade the background slightly

  for (let attractor of attractors) {
    for (let i = 0; i < 100; i++) {
      attractor.update();
      attractor.show();
    }
  }
}

function mousePressed() {
  if (mouseButton === LEFT) {
    attractors = []; // Clear existing attractors
    for (let i = 0; i < 5; i++) {
      attractors.push(new Attractor());
    }
  }
}

Highlight:

I’m particularly proud of the show() function, which handles the color interpolation based on the attractor’s position. This creates a smooth transition between two randomly generated colors, adding depth and visual interest to the patterns.

Embedded Sketch: (click screen to render new art)

Reflection and Future Work:

This project was a fun exploration of generative art and p5.js.

Future improvements:

  • User Interaction: Allow users to interact with the sketch by changing parameters or adding new attractors.

  • Animation: Introduce animation to the attractors, making them move or change over time.

Problems Encountered:

  • Visual Fidelity: Finding a good balance of colors was challenging. As well, when rendering, the images come out very grainy. I must experiment further to see if that can be improved

  • Performance: With a large number of attractors, the sketch can become slow. I might explore optimization techniques to improve performance.

Overall, this project was a rewarding experience that allowed me to learn more about generative art and p5.js.

Works cited:

Clifford Attractors : r/p5js (reddit.com)

Clifford Attractors (paulbourke.net)

Week 2 Sketch

Concept:

I recently took on the challenge of simulating the motion of a falling feather in nature using p5.js. The goal was to go beyond a simple straight-down fall and imbue the feather with a sense of personality through its movement, all while controlling it solely through acceleration. I envisioned a feather that gently drifts and rocks side to side as it descends, mimicking the playful dance of a real feather caught in a gentle breeze.

Code Highlight:

One of the aspects I’m particularly proud of is how I implemented the rocking motion coupled with a horizontal boost:

// Apply wind force (horizontal acceleration) with Perlin noise and angle influence
let windDirection = noise(noiseOffset) * 2 - 1; // -1 to 1
featherAx = windForce * windDirection + abs(sin(featherAngle)) * 0.5 * windDirection;

This snippet shows how the feather’s horizontal acceleration (featherAx) is influenced not just by random wind (using Perlin noise) but also by its current angle (featherAngle). The abs(sin(featherAngle)) term provides a boost in the direction of the rotation, making the feather sway more pronouncedly as it rocks. This simple addition significantly enhances the visual appeal and realism of the motion.

Embedded Sketch:

Reflection and Future Work:

I’m quite pleased with how this simulation turned out. The feather’s motion feels natural and captures the essence of its lightness and susceptibility to air currents. However, there’s always room for improvement! Here are some ideas for future exploration:

  • More Realistic Feather Shape: The current U-shape is a simplification. Implementing a more detailed feather shape, perhaps with multiple segments, could add visual interest.

  • Interaction with Wind: It would be interesting to allow the user to interact with the wind, perhaps by blowing on the feather through a microphone or using the mouse to create gusts.

  • 3D Simulation: Extending the simulation to 3D space could open up new possibilities for exploring the feather’s movement in a more immersive environment.

  • Multiple Feathers: Simulating multiple feathers interacting with each other and the wind could create a mesmerizing visual experience.