Blooming Maze – A Mass–Spring Driven Maze Flower

By Yuyuan Cao
🏆 Highlight Submission

Description

This piece starts with a full-screen black-background white maze. As time passes, the maze’s lines gradually converge to the shape of a flower.

The flower is formed by


Pipeline & Features

1. Image preprocessing (from A1)

In main.cpp the program loads flower_color_80.png with stb_image. Reused A1 image functions:

These are used to convert the flower image to grayscale / HSV and create a mask that marks which pixels belong to the flower vs. background. The mask is downsampled into a per-cell weight array cell_w indicating “how much this maze cell belongs to the flower”.

2. Procedural maze generation

In main.cpp I implement a DFS-based maze generator with a Cell struct and carve_maze(…). This creates a perfect 80×80 maze (one connected component, no cycles). Each cell stores four walls (N,E,S,W) used for later rendering.

3. Mass–spring grid (inspired by A8)

Instead of using the A8 helper functions, I write a simplified mass–spring system directly in main.cpp:

Springs:

Flower attraction:

attract_force = attract_factor node_w (target_pos - current_pos);

attract_factor increases smoothly from 0 to 1 over 120 frames (smoothstep), so the flower gradually emerges.

4. Dynamic maze line rendering

Each maze wall samples nearby cell_w to get a wall weight w_strength. When drawing a wall in draw_wall(…) in main.cpp:

const int MAX_EXTRA = 3; double extra = w_strength MAX_EXTRA attract_factor; int thickness = 1 + (int)std::round(extra);


5. Animation & Output

The main loop generates NUM_FRAMES images (frame_000.png … frame_119.png) using stb_image_write. After rendering all frames, the program automatically calls:

ffmpeg -y -framerate 30 -i frame_%03d.png -pix_fmt yuv420p piece.mp4

The final deliverable for the assignment is piece.mp4.


5. Acknowledgements

CSC317 Assignment 1 starter code

stb libraries

Flower source image

ffmpeg